summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2015-06-15 16:55:08 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-06-24 00:04:42 +0000
commit5aadcd90d8ecb79d15dae6d5f0b4567a678e8d8c (patch)
tree6b3720be9d091a6beecdaf5a254cbe047a94dada
parent43db8410667de672369c794fd9b16e40fcded85c (diff)
downloadchrome-ec-5aadcd90d8ecb79d15dae6d5f0b4567a678e8d8c.tar.gz
Add board for USB PD chip evaluation
Base board configuration to evaluate USB PD interface chip by connecting them a STM32F072 Discovery board. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BRANCH=none BUG=chrome-os-partner:41497 TEST=Flash the STM32F072 discovery using the following command: make flash BOARD=pdeval-stm32f072 then connect to the EC console through the USB port. Change-Id: Ie3f5dcd04c077be49fbacc020f7af4f298039e8a Reviewed-on: https://chromium-review.googlesource.com/277713 Tested-by: Alec Berg <alecaberg@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Alec Berg <alecaberg@chromium.org> Commit-Queue: Alec Berg <alecaberg@chromium.org>
l---------board/pdeval-stm32f072/Makefile1
-rw-r--r--board/pdeval-stm32f072/PD_evaluation.md91
-rw-r--r--board/pdeval-stm32f072/board.c55
-rw-r--r--board/pdeval-stm32f072/board.h94
-rw-r--r--board/pdeval-stm32f072/build.mk13
-rw-r--r--board/pdeval-stm32f072/ec.tasklist24
-rw-r--r--board/pdeval-stm32f072/gpio.inc34
-rw-r--r--board/pdeval-stm32f072/openocd-flash.cfg19
-rw-r--r--board/pdeval-stm32f072/usb_pd_policy.c334
9 files changed, 665 insertions, 0 deletions
diff --git a/board/pdeval-stm32f072/Makefile b/board/pdeval-stm32f072/Makefile
new file mode 120000
index 0000000000..94aaae2c4d
--- /dev/null
+++ b/board/pdeval-stm32f072/Makefile
@@ -0,0 +1 @@
+../../Makefile \ No newline at end of file
diff --git a/board/pdeval-stm32f072/PD_evaluation.md b/board/pdeval-stm32f072/PD_evaluation.md
new file mode 100644
index 0000000000..1b47e02d4f
--- /dev/null
+++ b/board/pdeval-stm32f072/PD_evaluation.md
@@ -0,0 +1,91 @@
+USB PD chip evaluation configuration
+====================================
+
+This board configuration implements a USB Power Delivery TCPM
+in order to evaluate various TCPC chips.
+The code tries to follow the preliminary USB PD interface standard but for TCPC chip implementing proprietary I2C protocol, a new TCPM file can be implemented as explained in the [Updating the code](#Updating the code) section below.
+
+Building
+--------
+
+### ChromiumOS chroot
+
+All the following instructions have been verified in a ChromiumOS chroot.
+You can find how to set one up on the Chromium development wiki:
+[http://dev.chromium.org/chromium-os/quick-start-guide](http://dev.chromium.org/chromium-os/quick-start-guide)
+
+### Build the TCPM code
+
+`cd src/platform/ec`
+
+`make BOARD=pdeval-stm32f072`
+
+
+Updating the code
+-----------------
+
+### TCPC Communication code
+
+Please duplicate [`common/usb_pd_tcpm.c`](../../common/usb_pd_tcpm.c) into `common/usb_pd_tcpm_<vendor>.c`.
+Then update the control logic through I2C there.
+
+### Board configuration
+
+In [board/pdeval-stm32f072/board.h](board.h), you can update `CONFIG_USB_PD_PORT_COUNT` to the actual number of ports on your board.
+You also need to create/delete the corresponding `PD_Cx` tasks in [board/pdeval-stm32f072/ec.tasklist](ec.tasklist).
+
+By default, the firmware is using I2C1 with SCL/SDA on pins PB6 and PB7, running with a 100kHz clock.
+To change the pins or speed, you need to edit `i2c_ports` in [board/pdeval-stm32f072/board.c](board.c), update `I2C_PORT_TCPC` in [board/pdeval-stm32f072/board.h](board.h) with the right controller number, and change the pin mux in [board/pdeval-stm32f072/gpio.inc](gpio.inc).
+
+An interrupt line, PA1, is configured to be used for the TCPC to get the attention of the TCPM. The GPIO is configured to trigger an interrupt on the falling edge and will call `tcpc_alert()` which will determine the cause of the interrupt and take action. The GPIO can be changed in [board/pdeval-stm32f072/gpio.inc](gpio.inc).
+
+Flashing and Running
+--------------------
+
+### Flashing the firmware binary
+
+To flash through JTAG with OpenOCD, you can just run:
+
+`sudo make flash BOARD=pdeval-stm32f072`
+
+Note: you need to do that with your USB mini-B cable is connected to the **USB ST-LINK** plug on the discovery board.
+
+### Connecting to the firmware console
+
+Connect a USB cable to the **USB USER** mini-B receptacle on the board.
+`lsusb` should show you a device with the following ID : 18d1:500f
+
+You can get a console over USB by issuing the following command on a Linux computer:
+
+`echo '18d1 500f' | sudo tee /sys/bus/usb-serial/drivers/generic/new_id`
+
+Testing
+-------
+
+Currently, the TCPM is expecting to have a GPIO to detect VBUS, but to minimize the HW setup with the discovery board the alternative is to fake VBUS detection using either the **USER** button on the discovery board, or the `vbus` console command, both of which toggle the state of VBUS detected. For example, to make get a PD contract with a power adapter, plug in the adapter and then toggle VBUS on. When a PD contract above 6V is made, LED5 on the discovery board will light. To disconnect, toggle VBUS off.
+
+EC command line commands
+
+- `help` List all available EC console commands
+- `vbus` Toggle VBUS on/off
+- `pd <port> state` Print PD protocol state information
+
+Known Issues
+------------
+
+1. This doc is not written yet ...
+
+2. You might need a ChromeOS chroot ...
+
+Troubleshooting
+---------------
+
+1. OpenOCD is not finding the device.
+
+ 1. Check that your USB mini-B cable is connected to the **USB ST-LINK** plug on the discovery board.
+ 2. What color is the LD1 LED on the board ?
+
+2. You got black smoke
+
+ 1. Time to buy a new one.
+
diff --git a/board/pdeval-stm32f072/board.c b/board/pdeval-stm32f072/board.c
new file mode 100644
index 0000000000..e0cdb7d970
--- /dev/null
+++ b/board/pdeval-stm32f072/board.c
@@ -0,0 +1,55 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+/* STM32F072-discovery board based USB PD evaluation configuration */
+
+#include "common.h"
+#include "ec_version.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "host_command.h"
+#include "i2c.h"
+#include "registers.h"
+#include "task.h"
+#include "usb.h"
+#include "usb_pd.h"
+#include "util.h"
+
+void button_event(enum gpio_signal signal);
+
+void alert_event(enum gpio_signal signal)
+{
+ /* Exchange status with PD MCU. */
+ host_command_pd_send_status(PD_CHARGE_NO_CHANGE);
+}
+
+#include "gpio_list.h"
+
+const void *const usb_strings[] = {
+ [USB_STR_DESC] = usb_string_desc,
+ [USB_STR_VENDOR] = USB_STRING_DESC("Google Inc."),
+ [USB_STR_PRODUCT] = USB_STRING_DESC("PDeval-stm32f072"),
+ [USB_STR_VERSION] = USB_STRING_DESC(CROS_EC_VERSION32),
+ [USB_STR_CONSOLE_NAME] = USB_STRING_DESC("Shell"),
+};
+
+BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT);
+
+/* Initialize board. */
+static void board_init(void)
+{
+ gpio_enable_interrupt(GPIO_USER_BUTTON);
+ gpio_enable_interrupt(GPIO_PD_MCU_INT);
+}
+DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
+
+void board_reset_pd_mcu(void)
+{
+}
+
+/* I2C ports */
+const struct i2c_port_t i2c_ports[] = {
+ {"tcpc", I2C_PORT_TCPC, 100 /* kHz */, GPIO_I2C0_SCL, GPIO_I2C0_SDA}
+};
+const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
diff --git a/board/pdeval-stm32f072/board.h b/board/pdeval-stm32f072/board.h
new file mode 100644
index 0000000000..99f1e93ee0
--- /dev/null
+++ b/board/pdeval-stm32f072/board.h
@@ -0,0 +1,94 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* STM32F072-discovery board based USB PD evaluation configuration */
+
+#ifndef __BOARD_H
+#define __BOARD_H
+
+/* 48 MHz SYSCLK clock frequency */
+#define CPU_CLOCK 48000000
+
+/* the UART console is on USART2 (PA14/PA15) */
+#undef CONFIG_UART_CONSOLE
+#define CONFIG_UART_CONSOLE 2
+
+/* Optional features */
+#define CONFIG_HW_CRC
+#define CONFIG_I2C
+#define CONFIG_STM_HWTIMER32
+/* USB Power Delivery configuration */
+#define CONFIG_USB_POWER_DELIVERY
+#define CONFIG_USB_PD_ALT_MODE
+#define CONFIG_USB_PD_ALT_MODE_DFP
+#define CONFIG_USB_PD_CUSTOM_VDM
+#define CONFIG_USB_PD_DUAL_ROLE
+#define CONFIG_USB_PD_PORT_COUNT 2
+#define CONFIG_USB_PD_TCPM_TCPCI
+
+/* start as a sink */
+#define PD_DEFAULT_STATE PD_STATE_SNK_DISCONNECTED
+
+/* fake board specific type-C power constants */
+#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */
+#define PD_POWER_SUPPLY_TURN_OFF_DELAY 250000 /* us */
+
+/* Define typical operating power and max power */
+#define PD_OPERATING_POWER_MW 15000
+#define PD_MAX_POWER_MW 60000
+#define PD_MAX_CURRENT_MA 3000
+#define PD_MAX_VOLTAGE_MV 20000
+
+/* I2C master port connected to the TCPC */
+#define I2C_PORT_TCPC 0
+#define I2C_PORT_PD_MCU 0
+
+/* Timer selection */
+
+/* USB Configuration */
+#define CONFIG_USB
+#define CONFIG_USB_PID 0x500f
+#define CONFIG_USB_CONSOLE
+
+/* USB interface indexes (use define rather than enum to expand them) */
+#define USB_IFACE_CONSOLE 0
+#define USB_IFACE_COUNT 1
+
+/* USB endpoint indexes (use define rather than enum to expand them) */
+#define USB_EP_CONTROL 0
+#define USB_EP_CONSOLE 1
+#define USB_EP_COUNT 2
+
+#undef CONFIG_WATCHDOG_HELP
+#undef CONFIG_LID_SWITCH
+
+/*
+ * Allow dangerous commands all the time, since we don't have a write protect
+ * switch.
+ */
+#define CONFIG_SYSTEM_UNLOCKED
+
+#ifndef __ASSEMBLER__
+
+/* Timer selection */
+#define TIM_CLOCK32 2
+
+#include "gpio_signal.h"
+
+/* USB string indexes */
+enum usb_strings {
+ USB_STR_DESC = 0,
+ USB_STR_VENDOR,
+ USB_STR_PRODUCT,
+ USB_STR_VERSION,
+ USB_STR_CONSOLE_NAME,
+
+ USB_STR_COUNT
+};
+
+void board_reset_pd_mcu(void);
+
+#endif /* !__ASSEMBLER__ */
+#endif /* __BOARD_H */
diff --git a/board/pdeval-stm32f072/build.mk b/board/pdeval-stm32f072/build.mk
new file mode 100644
index 0000000000..ef1346d534
--- /dev/null
+++ b/board/pdeval-stm32f072/build.mk
@@ -0,0 +1,13 @@
+# -*- makefile -*-
+# Copyright 2015 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Board specific files build
+
+# the IC is STmicro STM32F072RBT6
+CHIP:=stm32
+CHIP_FAMILY:=stm32f0
+CHIP_VARIANT:=stm32f07x
+
+board-y=board.o usb_pd_policy.o
diff --git a/board/pdeval-stm32f072/ec.tasklist b/board/pdeval-stm32f072/ec.tasklist
new file mode 100644
index 0000000000..fd87fc0237
--- /dev/null
+++ b/board/pdeval-stm32f072/ec.tasklist
@@ -0,0 +1,24 @@
+/* Copyright (c) 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * List of enabled tasks in the priority order
+ *
+ * The first one has the lowest priority.
+ *
+ * For each task, use the macro TASK_ALWAYS(n, r, d, s) for base tasks and
+ * TASK_NOTEST(n, r, d, s) for tasks that can be excluded in test binaries,
+ * where :
+ * 'n' in the name of the task
+ * 'r' in the main routine of the task
+ * 'd' in an opaque parameter passed to the routine at startup
+ * 's' is the stack size in bytes; must be a multiple of 8
+ */
+#define CONFIG_TASK_LIST \
+ TASK_ALWAYS(HOOKS, hook_task, NULL, TASK_STACK_SIZE) \
+ TASK_NOTEST(PDCMD, pd_command_task,NULL, TASK_STACK_SIZE) \
+ TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE) \
+ TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_ALWAYS(PD_C1, pd_task, NULL, LARGER_TASK_STACK_SIZE)
diff --git a/board/pdeval-stm32f072/gpio.inc b/board/pdeval-stm32f072/gpio.inc
new file mode 100644
index 0000000000..b3026102e2
--- /dev/null
+++ b/board/pdeval-stm32f072/gpio.inc
@@ -0,0 +1,34 @@
+/* -*- mode:c -*-
+ *
+ * Copyright (c) 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Inputs with interrupt handlers are first for efficiency */
+GPIO_INT(USER_BUTTON, PIN(A, 0), GPIO_INT_FALLING, button_event)
+GPIO_INT(PD_MCU_INT, PIN(A, 1), GPIO_INT_FALLING, alert_event)
+
+/* Outputs */
+GPIO(LED_U, PIN(C, 6), GPIO_OUT_LOW)
+GPIO(LED_D, PIN(C, 7), GPIO_OUT_LOW)
+GPIO(LED_L, PIN(C, 8), GPIO_OUT_LOW)
+GPIO(LED_R, PIN(C, 9), GPIO_OUT_LOW)
+
+/*
+ * I2C pins should be configured as inputs until I2C module is
+ * initialized. This will avoid driving the lines unintentionally.
+ */
+GPIO(I2C0_SCL, PIN(B, 6), GPIO_INPUT)
+GPIO(I2C0_SDA, PIN(B, 7), GPIO_INPUT)
+GPIO(I2C1_SCL, PIN(B, 13), GPIO_INPUT)
+GPIO(I2C1_SDA, PIN(B, 14), GPIO_INPUT)
+
+/* Unimplemented signals which we need to emulate for now */
+UNIMPLEMENTED(ENTERING_RW)
+UNIMPLEMENTED(WP_L)
+
+ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_USART, 0) /* USART1: PA09/PA10 */
+ALTERNATE(PIN_MASK(A, 0xC000), 1, MODULE_UART, 0) /* USART2: PA14/PA15 */
+ALTERNATE(PIN_MASK(B, 0x00c0), 1, MODULE_I2C, 0) /* I2C MASTER:PB6/7 */
+ALTERNATE(PIN_MASK(B, 0x6000), 5, MODULE_I2C, 0) /* I2C MASTER:PB13/14 */
diff --git a/board/pdeval-stm32f072/openocd-flash.cfg b/board/pdeval-stm32f072/openocd-flash.cfg
new file mode 100644
index 0000000000..d1b847a741
--- /dev/null
+++ b/board/pdeval-stm32f072/openocd-flash.cfg
@@ -0,0 +1,19 @@
+# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source [find board/stm32f0discovery.cfg]
+
+# For flashing, force the board into reset on connect, this ensures that
+# code running on the core can't interfere with programming.
+reset_config connect_assert_srst
+
+gdb_port 0
+tcl_port 0
+telnet_port 0
+init
+reset init
+flash write_image erase $BUILD_DIR/ec.bin 0x08000000
+reset halt
+resume
+shutdown
diff --git a/board/pdeval-stm32f072/usb_pd_policy.c b/board/pdeval-stm32f072/usb_pd_policy.c
new file mode 100644
index 0000000000..35762bde39
--- /dev/null
+++ b/board/pdeval-stm32f072/usb_pd_policy.c
@@ -0,0 +1,334 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "common.h"
+#include "console.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "registers.h"
+#include "system.h"
+#include "task.h"
+#include "timer.h"
+#include "util.h"
+#include "usb_pd.h"
+
+#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
+
+#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP)
+
+/* Used to fake VBUS presence since no GPIO is available to read VBUS */
+static int vbus_present;
+
+const uint32_t pd_src_pdo[] = {
+ PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS),
+};
+const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo);
+
+const uint32_t pd_snk_pdo[] = {
+ PDO_FIXED(5000, 500, PDO_FIXED_FLAGS),
+ PDO_BATT(5000, 20000, 15000),
+ PDO_VAR(5000, 20000, 3000),
+};
+const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
+
+int pd_is_valid_input_voltage(int mv)
+{
+ return 1;
+}
+
+int pd_check_requested_voltage(uint32_t rdo)
+{
+ int max_ma = rdo & 0x3FF;
+ int op_ma = (rdo >> 10) & 0x3FF;
+ int idx = rdo >> 28;
+ uint32_t pdo;
+ uint32_t pdo_ma;
+
+ if (!idx || idx > pd_src_pdo_cnt)
+ return EC_ERROR_INVAL; /* Invalid index */
+
+ /* check current ... */
+ pdo = pd_src_pdo[idx - 1];
+ pdo_ma = (pdo & 0x3ff);
+ if (op_ma > pdo_ma)
+ return EC_ERROR_INVAL; /* too much op current */
+ if (max_ma > pdo_ma)
+ return EC_ERROR_INVAL; /* too much max current */
+
+ CPRINTF("Requested %d V %d mA (for %d/%d mA)\n",
+ ((pdo >> 10) & 0x3ff) * 50, (pdo & 0x3ff) * 10,
+ ((rdo >> 10) & 0x3ff) * 10, (rdo & 0x3ff) * 10);
+
+ return EC_SUCCESS;
+}
+
+void pd_transition_voltage(int idx)
+{
+ /* No-operation: we are always 5V */
+}
+
+int pd_set_power_supply_ready(int port)
+{
+ /* Turn on the "up" LED when we output VBUS */
+ gpio_set_level(GPIO_LED_U, 1);
+ CPRINTS("Power supply ready/%d", port);
+ return EC_SUCCESS; /* we are ready */
+}
+
+void pd_power_supply_reset(int port)
+{
+ /* Turn off the "up" LED when we shutdown VBUS */
+ gpio_set_level(GPIO_LED_U, 0);
+ /* Disable VBUS */
+ CPRINTS("Disable VBUS", port);
+}
+
+void pd_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage)
+{
+ CPRINTS("USBPD current limit port %d max %d mA %d mV",
+ port, max_ma, supply_voltage);
+ /* do some LED coding of the power we can sink */
+ if (max_ma) {
+ if (supply_voltage > 6500)
+ gpio_set_level(GPIO_LED_R, 1);
+ else
+ gpio_set_level(GPIO_LED_L, 1);
+ } else {
+ gpio_set_level(GPIO_LED_L, 0);
+ gpio_set_level(GPIO_LED_R, 0);
+ }
+}
+
+void typec_set_input_current_limit(int port, uint32_t max_ma,
+ uint32_t supply_voltage)
+{
+ CPRINTS("TYPEC current limit port %d max %d mA %d mV",
+ port, max_ma, supply_voltage);
+ gpio_set_level(GPIO_LED_R, !!max_ma);
+}
+
+void button_event(enum gpio_signal signal)
+{
+ vbus_present = !vbus_present;
+ CPRINTS("VBUS %d", vbus_present);
+}
+
+static int command_vbus_toggle(int argc, char **argv)
+{
+ vbus_present = !vbus_present;
+ CPRINTS("VBUS %d", vbus_present);
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(vbus, command_vbus_toggle,
+ "",
+ "Toggle VBUS detected",
+ NULL);
+
+int pd_snk_is_vbus_provided(int port)
+{
+ return vbus_present;
+}
+
+int pd_board_checks(void)
+{
+ return EC_SUCCESS;
+}
+
+int pd_check_power_swap(int port)
+{
+ /*
+ * Allow power swap as long as we are acting as a dual role device,
+ * otherwise assume our role is fixed (not in S0 or console command
+ * to fix our role).
+ */
+ return pd_get_dual_role() == PD_DRP_TOGGLE_ON ? 1 : 0;
+}
+
+int pd_check_data_swap(int port, int data_role)
+{
+ /* Always allow data swap */
+ return 1;
+}
+
+void pd_execute_data_swap(int port, int data_role)
+{
+}
+
+void pd_check_pr_role(int port, int pr_role, int flags)
+{
+}
+
+void pd_check_dr_role(int port, int dr_role, int flags)
+{
+}
+/* ----------------- Vendor Defined Messages ------------------ */
+const struct svdm_response svdm_rsp = {
+ .identity = NULL,
+ .svids = NULL,
+ .modes = NULL,
+};
+
+int pd_custom_vdm(int port, int cnt, uint32_t *payload,
+ uint32_t **rpayload)
+{
+ int cmd = PD_VDO_CMD(payload[0]);
+ uint16_t dev_id = 0;
+ int is_rw;
+
+ /* make sure we have some payload */
+ if (cnt == 0)
+ return 0;
+
+ switch (cmd) {
+ case VDO_CMD_VERSION:
+ /* guarantee last byte of payload is null character */
+ *(payload + cnt - 1) = 0;
+ CPRINTF("version: %s\n", (char *)(payload+1));
+ break;
+ case VDO_CMD_READ_INFO:
+ case VDO_CMD_SEND_INFO:
+ /* copy hash */
+ if (cnt == 7) {
+ dev_id = VDO_INFO_HW_DEV_ID(payload[6]);
+ is_rw = VDO_INFO_IS_RW(payload[6]);
+
+ CPRINTF("DevId:%d.%d SW:%d RW:%d\n",
+ HW_DEV_ID_MAJ(dev_id),
+ HW_DEV_ID_MIN(dev_id),
+ VDO_INFO_SW_DBG_VER(payload[6]),
+ is_rw);
+ } else if (cnt == 6) {
+ /* really old devices don't have last byte */
+ pd_dev_store_rw_hash(port, dev_id, payload + 1,
+ SYSTEM_IMAGE_UNKNOWN);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_USB_PD_ALT_MODE_DFP
+static int dp_flags[CONFIG_USB_PD_PORT_COUNT];
+
+static void svdm_safe_dp_mode(int port)
+{
+ /* make DP interface safe until configure */
+ dp_flags[port] = 0;
+ /* board_set_usb_mux(port, TYPEC_MUX_NONE, pd_get_polarity(port)); */
+}
+
+static int svdm_enter_dp_mode(int port, uint32_t mode_caps)
+{
+ /* Only enter mode if device is DFP_D capable */
+ if (mode_caps & MODE_DP_SNK) {
+ svdm_safe_dp_mode(port);
+ return 0;
+ }
+
+ return -1;
+}
+
+static int svdm_dp_status(int port, uint32_t *payload)
+{
+ int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ payload[0] = VDO(USB_SID_DISPLAYPORT, 1,
+ CMD_DP_STATUS | VDO_OPOS(opos));
+ payload[1] = VDO_DP_STATUS(0, /* HPD IRQ ... not applicable */
+ 0, /* HPD level ... not applicable */
+ 0, /* exit DP? ... no */
+ 0, /* usb mode? ... no */
+ 0, /* multi-function ... no */
+ (!!(dp_flags[port] & DP_FLAGS_DP_ON)),
+ 0, /* power low? ... no */
+ (!!(dp_flags[port] & DP_FLAGS_DP_ON)));
+ return 2;
+};
+
+static int svdm_dp_config(int port, uint32_t *payload)
+{
+ int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT);
+ /* board_set_usb_mux(port, TYPEC_MUX_DP, pd_get_polarity(port)); */
+ payload[0] = VDO(USB_SID_DISPLAYPORT, 1,
+ CMD_DP_CONFIG | VDO_OPOS(opos));
+ payload[1] = VDO_DP_CFG(MODE_DP_PIN_E, /* pin mode */
+ 1, /* DPv1.3 signaling */
+ 2); /* UFP connected */
+ return 2;
+};
+
+static void svdm_dp_post_config(int port)
+{
+ dp_flags[port] |= DP_FLAGS_DP_ON;
+ if (!(dp_flags[port] & DP_FLAGS_HPD_HI_PENDING))
+ return;
+}
+
+static int svdm_dp_attention(int port, uint32_t *payload)
+{
+ /* ack */
+ return 1;
+}
+
+static void svdm_exit_dp_mode(int port)
+{
+ svdm_safe_dp_mode(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,
+ .enter = &svdm_enter_dp_mode,
+ .status = &svdm_dp_status,
+ .config = &svdm_dp_config,
+ .post_config = &svdm_dp_post_config,
+ .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);
+#endif /* CONFIG_USB_PD_ALT_MODE_DFP */