summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
authorWai-Hong Tam <waihong@google.com>2019-08-01 17:16:10 -0700
committerCommit Bot <commit-bot@chromium.org>2020-04-30 20:50:50 +0000
commit1c20734dddc2237f9219e85a8e6ef65bebc42eee (patch)
tree21fbae323274aeff9a903e4019e83e756244d1c6 /board
parent1f692079b7ff0fd9f3bc1b0f0b7cd1a6b473b8d9 (diff)
downloadchrome-ec-1c20734dddc2237f9219e85a8e6ef65bebc42eee.tar.gz
servo_v4: Support DP alt-mode
This is the initial change to support DP alt-mode, with some TODO items to make some settings more configurable for testing. DP alt-mode is only enabled when * servo v4 is configured dts-mode disabled, like through the command 'dut-control servo_v4_dts_mode:off', and * a monitor is plugged to the mini-DP port (for minimizing the impact to PD FAFT). The realtime HPD monitoring is the following patch. There is a bug (b/140900633) in servo v4 hardware that only 2-lane DP works. BRANCH=servo BUG=b:137219603 TEST=Configured to disable dts-mode, plugged the DP cable to monitor, plugged the Type-C cable to DUT, the external monitor worked. Change-Id: I129754afe1b13fe349d472de4ee6bcec3fd8b854 Signed-off-by: Wai-Hong Tam <waihong@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1868924
Diffstat (limited to 'board')
-rw-r--r--board/servo_v4/board.c9
-rw-r--r--board/servo_v4/board.h5
-rw-r--r--board/servo_v4/usb_pd_policy.c202
3 files changed, 210 insertions, 6 deletions
diff --git a/board/servo_v4/board.c b/board/servo_v4/board.c
index bf1c51e267..0cd5af7f24 100644
--- a/board/servo_v4/board.c
+++ b/board/servo_v4/board.c
@@ -12,6 +12,10 @@
#include "gpio.h"
#include "hooks.h"
#include "i2c.h"
+/* Just want the .h file for PS8742 definitions, not the large object file. */
+#define CONFIG_USB_MUX_PS8742
+#include "ps8740.h"
+#undef CONFIG_USB_MUX_PS8742
#include "queue_policies.h"
#include "registers.h"
#include "spi.h"
@@ -427,10 +431,9 @@ static void board_init(void)
gpio_set_flags(GPIO_DUT_HUB_USB_RESET_L, GPIO_OUT_HIGH);
/*
- * Write USB3 Mode to PS8742 USB/DP Mux.
- * 0x0:disable 0x20:enable.
+ * Disable USB3 mode in PS8742 USB/DP Mux.
*/
- i2c_write8(1, 0x10, 0x0, 0x0);
+ i2c_write8(I2C_PORT_MASTER, PS8740_I2C_ADDR0_FLAG, PS8740_REG_MODE, 0);
/* Enable uservo USB by default. */
init_ioexpander();
diff --git a/board/servo_v4/board.h b/board/servo_v4/board.h
index 298ccd28ce..3362c40ef6 100644
--- a/board/servo_v4/board.h
+++ b/board/servo_v4/board.h
@@ -42,6 +42,10 @@
#define CONFIG_USB_PID 0x501b
#define CONFIG_USB_CONSOLE
#define CONFIG_USB_UPDATE
+#define CONFIG_USB_BCD_DEV 0x0001 /* v 0.01 */
+
+#define CONFIG_USB_PD_IDENTITY_HW_VERS 1
+#define CONFIG_USB_PD_IDENTITY_SW_VERS 1
#define CONFIG_USB_SELF_POWERED
@@ -114,6 +118,7 @@
#define CONFIG_USB_PD_TCPMV1
#define CONFIG_CMD_PD
#define CONFIG_USB_PD_CUSTOM_PDO
+#define CONFIG_USB_PD_ALT_MODE
#define CONFIG_USB_PD_DUAL_ROLE
#define CONFIG_USB_PD_DYNAMIC_SRC_CAP
#define CONFIG_USB_PD_INTERNAL_COMP
diff --git a/board/servo_v4/usb_pd_policy.c b/board/servo_v4/usb_pd_policy.c
index 23814a1d64..1e2927e3b0 100644
--- a/board/servo_v4/usb_pd_policy.c
+++ b/board/servo_v4/usb_pd_policy.c
@@ -11,6 +11,10 @@
#include "hooks.h"
#include "host_command.h"
#include "i2c.h"
+/* Just want the .h file for PS8742 definitions, not the large object file. */
+#define CONFIG_USB_MUX_PS8742
+#include "ps8740.h"
+#undef CONFIG_USB_MUX_PS8742
#include "registers.h"
#include "system.h"
#include "task.h"
@@ -757,6 +761,201 @@ __override void pd_check_dr_role(int port,
/* ----------------- Vendor Defined Messages ------------------ */
+const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */
+ 1, /* 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_U31_GEN1 /* USB SS support */);
+
+static int svdm_response_identity(int port, uint32_t *payload)
+{
+ /*
+ * TODO(b/137219603): Make whether servo supports DP alt-mode
+ * configurable, like through a console command.
+ *
+ * This version is to check if a monitor is plugged to the mini-DP port
+ * to decide if DP alt-mode is supported or not. So no alt-mode
+ * supported if no monitor is plugged before plugging the servo Type-C
+ * cable to DUT. This way doesn't affect PD FAFT results.
+ */
+ int dp_supported = gpio_get_level(GPIO_DP_HPD);
+
+ if (dp_supported) {
+ 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;
+ } else {
+ return 0;
+ }
+}
+
+static int svdm_response_svids(int port, uint32_t *payload)
+{
+ payload[1] = VDO_SVID(USB_SID_DISPLAYPORT, 0);
+ return 2;
+}
+
+#define MODE_CNT 1
+#define OPOS 1
+
+/*
+ * The Type-C demux PS8742 supports pin assignment C, D, and E. Response the DP
+ * capabilities with supporting all of them.
+ *
+ * TODO(b/137219603): Make this pin assignment and plug/receptacle configurable
+ * by a console command that some tests can check different dongle behaviors.
+ */
+const uint32_t vdo_dp_mode[MODE_CNT] = {
+ VDO_MODE_DP(0, /* UFP pin cfg supported: none */
+ MODE_DP_PIN_C | MODE_DP_PIN_D | MODE_DP_PIN_E, /* DFP pin */
+ 1, /* no usb2.0 signalling in AMode */
+ CABLE_PLUG, /* Its a plug */
+ MODE_DP_V13, /* DPv1.3 Support, no Gen2 */
+ MODE_DP_SNK) /* Its a sink only */
+};
+
+static int svdm_response_modes(int port, uint32_t *payload)
+{
+ /* CCD uses the SBU lines; don't enable DP when dts-mode enabled */
+ if (!(cc_config & CC_DISABLE_DTS))
+ return 0; /* 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;
+}
+
+static int is_typec_dp_muxed(void)
+{
+ int value;
+
+ i2c_read8(I2C_PORT_MASTER, PS8740_I2C_ADDR0_FLAG, PS8740_REG_MODE,
+ &value);
+ return value & PS8740_MODE_DP_ENABLED ? 1 : 0;
+}
+
+static void set_typec_mux(int pin_cfg)
+{
+ int value;
+
+ switch (pin_cfg) {
+ case 0:
+ value = 0;
+ CPRINTS("PinCfg:off");
+ break;
+ case MODE_DP_PIN_C:
+ value = PS8740_MODE_DP_ENABLED;
+ CPRINTS("PinCfg:C");
+ break;
+ case MODE_DP_PIN_D:
+ value = PS8740_MODE_DP_ENABLED | PS8740_MODE_USB_ENABLED;
+ CPRINTS("PinCfg:D");
+ break;
+ case MODE_DP_PIN_E:
+ value = PS8740_MODE_DP_ENABLED | PS8740_MODE_CE_DP_ENABLED;
+ CPRINTS("PinCfg:E");
+ break;
+ default:
+ CPRINTS("PinCfg not supported: %d", pin_cfg);
+ return;
+ }
+ if (value && cc_config & CC_POLARITY)
+ value |= PS8740_MODE_POLARITY_INVERTED;
+ i2c_write8(I2C_PORT_MASTER, PS8740_I2C_ADDR0_FLAG, PS8740_REG_MODE,
+ value);
+}
+
+static int dp_status(int port, uint32_t *payload)
+{
+ int opos = PD_VDO_OPOS(payload[0]);
+ int hpd = gpio_get_level(GPIO_DP_HPD);
+
+ if (opos != OPOS)
+ return 0; /* NAK */
+
+ /*
+ * TODO(b/137219603): Make the Multi-Function Preferred bit
+ * configurable by a console command.
+ */
+ payload[1] = VDO_DP_STATUS(0, /* IRQ_HPD */
+ hpd, /* HPD_HI|LOW */
+ 0, /* request exit DP */
+ 0, /* request exit USB */
+ 1, /* MF pref */
+ is_typec_dp_muxed(),
+ 0, /* power low */
+ 0x2);
+ return 2;
+}
+
+static int dp_config(int port, uint32_t *payload)
+{
+ if (PD_DP_CFG_DPON(payload[1]))
+ set_typec_mux(PD_DP_CFG_PIN(payload[1]));
+
+ return 1;
+}
+
+/* Whether alternate mode has been entered or not */
+static int alt_mode;
+
+static int svdm_enter_mode(int port, uint32_t *payload)
+{
+ /* SID & mode request is valid */
+ if ((PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) ||
+ (PD_VDO_OPOS(payload[0]) != OPOS))
+ return 0; /* NAK */
+
+ alt_mode = OPOS;
+ return 1;
+}
+
+int pd_alt_mode(int port, uint16_t svid)
+{
+ if (svid == USB_SID_DISPLAYPORT)
+ return alt_mode;
+
+ return 0;
+}
+
+static int svdm_exit_mode(int port, uint32_t *payload)
+{
+ if (PD_VDO_VID(payload[0]) == USB_SID_DISPLAYPORT)
+ set_typec_mux(0);
+
+ alt_mode = 0;
+
+ return 1; /* Must return ACK */
+}
+
+static struct amode_fx dp_fx = {
+ .status = &dp_status,
+ .config = &dp_config,
+};
+
+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,
+};
+
__override int pd_custom_vdm(int port, int cnt, uint32_t *payload,
uint32_t **rpayload)
{
@@ -780,12 +979,9 @@ __override int pd_custom_vdm(int port, int cnt, uint32_t *payload,
return 0;
}
-
-
__override const struct svdm_amode_fx supported_modes[] = {};
__override const int supported_modes_cnt = ARRAY_SIZE(supported_modes);
-
static void print_cc_mode(void)
{
/* Get current CCD status */