Furquan Shaikh has submitted this change. ( https://review.coreboot.org/c/coreboot/+/51194 )
Change subject: soc/intel/tigerlake: Enable TCSS Muxes to disconnect mode during boot ......................................................................
soc/intel/tigerlake: Enable TCSS Muxes to disconnect mode during boot
TCSS muxes being left uninitialized during boot is causing some USB3 devices to downgrade to USB2 speed. To properly configure the Type C ports the muxes should be set to disconnected state during boot so that the port mapping of USB2/3 devices is properly setup prior to Kernel initializing devices.
BUG=b:180426950 BRANCH=firmware-volteer-13672.B TEST= Connected USB3 storage device and rebooted the system multiple times to verify that devices were no longer downgrading to USB2 speed.
Change-Id: I4352072a4a7d6ccb1364b38377831f3c22ae8fb4 Signed-off-by: Brandon Breitenstein brandon.breitenstein@intel.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/51194 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Furquan Shaikh furquan@google.com --- M src/soc/intel/tigerlake/Kconfig M src/soc/intel/tigerlake/Makefile.inc M src/soc/intel/tigerlake/early_tcss.c M src/soc/intel/tigerlake/fsp_params.c M src/soc/intel/tigerlake/include/soc/early_tcss.h 5 files changed, 123 insertions(+), 58 deletions(-)
Approvals: build bot (Jenkins): Verified Furquan Shaikh: Looks good to me, approved
diff --git a/src/soc/intel/tigerlake/Kconfig b/src/soc/intel/tigerlake/Kconfig index e179914..afebc0f 100644 --- a/src/soc/intel/tigerlake/Kconfig +++ b/src/soc/intel/tigerlake/Kconfig @@ -239,9 +239,14 @@ hex default 0x2000
+config EARLY_TCSS + bool "Enable early TCSS device Init" + help + Sets up USB2/3 port mapping in TCSS MUX and sets MUX to disconnect state + config EARLY_TCSS_DISPLAY - bool "Enable early TCSS display" - depends on RUN_FSP_GOP + bool "Enable early TCSS display" if EARLY_TCSS + depends on EARLY_TCSS && RUN_FSP_GOP help Enable displays to be detected over Type-C ports during boot.
diff --git a/src/soc/intel/tigerlake/Makefile.inc b/src/soc/intel/tigerlake/Makefile.inc index 0e61627..25aa3f9 100644 --- a/src/soc/intel/tigerlake/Makefile.inc +++ b/src/soc/intel/tigerlake/Makefile.inc @@ -30,7 +30,7 @@ ramstage-y += acpi.c ramstage-y += chip.c ramstage-y += cpu.c -ramstage-$(CONFIG_EARLY_TCSS_DISPLAY) += early_tcss.c +ramstage-$(CONFIG_EARLY_TCSS) += early_tcss.c ramstage-y += elog.c ramstage-y += espi.c ramstage-y += finalize.c diff --git a/src/soc/intel/tigerlake/early_tcss.c b/src/soc/intel/tigerlake/early_tcss.c index cdc90ad..e32c29f 100644 --- a/src/soc/intel/tigerlake/early_tcss.c +++ b/src/soc/intel/tigerlake/early_tcss.c @@ -104,7 +104,28 @@ return -1; }
-static int send_pmc_connect_request(int port, struct tcss_mux mux_data) +static int send_pmc_disconnect_request(int port, const struct tcss_port_map *port_map) +{ + uint32_t cmd; + struct pmc_ipc_buffer req = { 0 }; + struct pmc_ipc_buffer rsp; + + cmd = tcss_make_conn_cmd(PMC_IPC_TCSS_DISC_REQ_RES, port_map->usb3_port, + port_map->usb2_port, 0, 0, 0, 0); + + req.buf[0] = cmd; + + printk(BIOS_DEBUG, "port C%d DISC req: usage %d usb3 %d usb2 %d\n", + port, + GET_TCSS_CD_FIELD(USAGE, cmd), + GET_TCSS_CD_FIELD(USB3, cmd), + GET_TCSS_CD_FIELD(USB2, cmd)); + + return send_pmc_req(CONNECT_REQ, &req, &rsp, PMC_IPC_DISC_REQ_SIZE); +} + +static int send_pmc_connect_request(int port, const struct tcss_mux_info *mux_data, + const struct tcss_port_map *port_map) { uint32_t cmd; struct pmc_ipc_buffer req = { 0 }; @@ -112,12 +133,12 @@
cmd = tcss_make_conn_cmd( PMC_IPC_TCSS_CONN_REQ_RES, - mux_data.usb3_port, - mux_data.usb2_port, - mux_data.ufp, - mux_data.polarity, - mux_data.polarity, - mux_data.acc); + port_map->usb3_port, + port_map->usb2_port, + mux_data->ufp, + mux_data->polarity, + mux_data->polarity, + mux_data->acc);
req.buf[0] = cmd;
@@ -135,13 +156,14 @@ return send_pmc_req(CONNECT_REQ, &req, &rsp, PMC_IPC_CONN_REQ_SIZE); }
-static int send_pmc_safe_mode_request(int port, struct tcss_mux mux_data) +static int send_pmc_safe_mode_request(int port, const struct tcss_mux_info *mux_data, + const struct tcss_port_map *port_map) { uint32_t cmd; struct pmc_ipc_buffer req = { 0 }; struct pmc_ipc_buffer rsp;
- cmd = tcss_make_safe_mode_cmd(PMC_IPC_TCSS_SAFE_MODE_REQ_RES, mux_data.usb3_port); + cmd = tcss_make_safe_mode_cmd(PMC_IPC_TCSS_SAFE_MODE_REQ_RES, port_map->usb3_port);
req.buf[0] = cmd;
@@ -153,7 +175,8 @@ return send_pmc_req(SAFE_REQ, &req, &rsp, PMC_IPC_SAFE_REQ_SIZE); }
-static int send_pmc_dp_hpd_request(int port, struct tcss_mux mux_data) +static int send_pmc_dp_hpd_request(int port, const struct tcss_mux_info *mux_data, + const struct tcss_port_map *port_map) { struct pmc_ipc_buffer req = { 0 }; struct pmc_ipc_buffer rsp; @@ -161,26 +184,29 @@
cmd = tcss_make_hpd_mode_cmd( PMC_IPC_TCSS_HPD_REQ_RES, - mux_data.usb3_port, - mux_data.hpd_lvl, - mux_data.hpd_irq); + port_map->usb3_port, + mux_data->hpd_lvl, + mux_data->hpd_irq);
req.buf[0] = cmd;
return send_pmc_req(HPD_REQ, &req, &rsp, PMC_IPC_HPD_REQ_SIZE); + }
-static int send_pmc_dp_mode_request(int port, struct tcss_mux mux_data) +static int send_pmc_dp_mode_request(int port, const struct tcss_mux_info *mux_data, + const struct tcss_port_map *port_map) { uint32_t cmd; uint8_t dp_mode; int ret; + struct pmc_ipc_buffer req = { 0 }; struct pmc_ipc_buffer rsp;
cmd = tcss_make_alt_mode_cmd_buf_0( PMC_IPC_TCSS_ALTMODE_REQ_RES, - mux_data.usb3_port, + port_map->usb3_port, PMC_IPC_DP_MODE);
req.buf[0] = cmd; @@ -191,7 +217,7 @@ GET_TCSS_ALT_FIELD(USB3, cmd), GET_TCSS_ALT_FIELD(MODE, cmd));
- switch (mux_data.dp_mode) { + switch (mux_data->dp_mode) { case MODE_DP_PIN_A: dp_mode = 1; break; @@ -216,8 +242,8 @@ }
cmd = tcss_make_alt_mode_cmd_buf_1( - mux_data.polarity, - mux_data.cable, + mux_data->polarity, + mux_data->cable, 0, /* ufp is not supported in DP ALT Mode request */ dp_mode);
@@ -235,46 +261,66 @@ if (ret) return ret;
- send_pmc_dp_hpd_request(port, mux_data); + send_pmc_dp_hpd_request(port, mux_data, port_map); return 0; }
-static void update_tcss_mux(int port, struct tcss_mux mux_data) +static void tcss_init_mux(int port, const struct tcss_port_map *port_map) { - int ret = 0; + int ret;
- /* check if mux has a DP device */ - if (mux_data.dp) { - ret = send_pmc_connect_request(port, mux_data); - if (ret) { - printk(BIOS_ERR, "Port %d connect request failed\n", port); - return; - } - ret = send_pmc_safe_mode_request(port, mux_data); - if (ret) { - printk(BIOS_ERR, "Port %d safe mode request failed\n", port); - return; - } - - ret = send_pmc_dp_mode_request(port, mux_data); - } - + ret = send_pmc_disconnect_request(port, port_map); if (ret) - printk(BIOS_ERR, "Port C%d mux set failed with error %d\n", port, ret); + printk(BIOS_ERR, "Failed to setup port:%d to initial state\n", port); }
-void tcss_early_configure(void) +static void tcss_configure_dp_mode(const struct tcss_port_map *port_map, size_t num_ports) { - const struct tcss_mux *mux_info; - size_t num_ports; - int i; + int ret; + size_t i; + const struct tcss_mux_info *mux_info; + const struct tcss_port_map *port_info;
if (!display_init_required()) return;
- mux_info = mainboard_tcss_fill_mux_info(&num_ports); + for (i = 0; i < num_ports; i++) { + mux_info = mainboard_tcss_get_mux_info(i); + port_info = &port_map[i]; + + if (!mux_info->dp) + continue; + + ret = send_pmc_connect_request(i, mux_info, port_info); + if (ret) { + printk(BIOS_ERR, "Port %zd connect request failed\n", i); + continue; + } + ret = send_pmc_safe_mode_request(i, mux_info, port_info); + if (ret) { + printk(BIOS_ERR, "Port %zd safe mode request failed\n", i); + continue; + } + + ret = send_pmc_dp_mode_request(i, mux_info, port_info); + if (ret) + printk(BIOS_ERR, "Port C%zd mux set failed with error %d\n", i, ret); + } +} + +void tcss_early_configure(void) +{ + const struct tcss_port_map *port_map; + size_t num_ports; + size_t i; + + port_map = mainboard_tcss_get_port_info(&num_ports); + if (port_map == NULL) + return;
for (i = 0; i < num_ports; i++) - update_tcss_mux(i, mux_info[i]); + tcss_init_mux(i, &port_map[i]);
+ if (CONFIG(EARLY_TCSS_DISPLAY)) + tcss_configure_dp_mode(port_map, num_ports); } diff --git a/src/soc/intel/tigerlake/fsp_params.c b/src/soc/intel/tigerlake/fsp_params.c index c5501b7..1d57002 100644 --- a/src/soc/intel/tigerlake/fsp_params.c +++ b/src/soc/intel/tigerlake/fsp_params.c @@ -462,7 +462,7 @@ /* TCSS specific initialization here */ printk(BIOS_DEBUG, "FSP MultiPhaseSiInit %s/%s called\n", __FILE__, __func__); - if (CONFIG(EARLY_TCSS_DISPLAY)) + if (CONFIG(EARLY_TCSS)) tcss_early_configure(); break; default: diff --git a/src/soc/intel/tigerlake/include/soc/early_tcss.h b/src/soc/intel/tigerlake/include/soc/early_tcss.h index 8b5d802..e366c9d 100644 --- a/src/soc/intel/tigerlake/include/soc/early_tcss.h +++ b/src/soc/intel/tigerlake/include/soc/early_tcss.h @@ -5,10 +5,12 @@ #define PMC_IPC_USBC_SUBCMD_ID 0x0 #define PMC_IPC_CMD 0x0 #define PMC_IPC_TCSS_CONN_REQ_RES 0x0 +#define PMC_IPC_TCSS_DISC_REQ_RES 0x1 #define PMC_IPC_TCSS_SAFE_MODE_REQ_RES 0x2 #define PMC_IPC_TCSS_ALTMODE_REQ_RES 0x3 #define PMC_IPC_TCSS_HPD_REQ_RES 0x4 #define PMC_IPC_CONN_REQ_SIZE 2 +#define PMC_IPC_DISC_REQ_SIZE 2 #define PMC_IPC_ALT_REQ_SIZE 8 #define PMC_IPC_SAFE_REQ_SIZE 1 #define PMC_IPC_HPD_REQ_SIZE 2 @@ -61,6 +63,8 @@ #define TCSS_HPD_IRQ_SHIFT 13 #define TCSS_HPD_IRQ_MASK 0x01
+#define MAX_TYPE_C_PORTS 4 + #define TCSS_CD_FIELD(name, val) \ (((val) & TCSS_CD_##name##_MASK) << TCSS_CD_##name##_SHIFT)
@@ -112,7 +116,7 @@ #define MODE_DP_PIN_F BIT(5)
/* struct to hold all tcss_mux related variables */ -struct tcss_mux { +struct tcss_mux_info { bool dp; /* DP connected */ bool usb; /* USB connected */ bool cable; /* Activ/Passive Cable */ @@ -122,18 +126,28 @@ bool ufp; bool acc; uint8_t dp_mode; /* DP Operation Mode */ - uint8_t usb3_port; /* USB2 Port Number */ - uint8_t usb2_port; /* USB3 Port Number */ +}; + +struct tcss_port_map { + uint8_t usb2_port; /* USB2 Port Number */ + uint8_t usb3_port; /* USB3 Port Number */ };
void tcss_early_configure(void);
/* - * Mainboard method to setup any mux configuration needed for early TCSS operations. - * This function will need to obtain any mux data needed to forward to IOM/PMC. - * Since the mux data may be stored differently by different mainboards this - * must be defined by the mainboard with its specific mux data stored in a struct tcss_mux - * as defined above. - * Returns completed tcss_mux structure + * Mainboard method to setup any mux config needed for early TCSS display operations. + * This function will need to obtain any mux data needed to forward to IOM/PMC + * Since the mux data may be stored differently by different mainboards this function + * must be defined by mainboard with its specific mux data stored in a tcss_mux_info + * struct as defined above. + * Returns completed tcss_mux_info structure for the specified port */ -const struct tcss_mux *mainboard_tcss_fill_mux_info(size_t *num_ports); +const struct tcss_mux_info *mainboard_tcss_get_mux_info(int port); + +/* + * Mainboard method to get only the port information to initialize the muxes to + * disconnect mode during boot. + * returns tscc_port_map of all ports on system + */ +const struct tcss_port_map *mainboard_tcss_get_port_info(size_t *num_ports);