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>
This commit is contained in:
parent
54d59ef7b7
commit
d8774f6899
|
@ -239,9 +239,14 @@ config PRERAM_CBMEM_CONSOLE_SIZE
|
|||
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.
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ romstage-y += reset.c
|
|||
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
|
||||
|
|
|
@ -104,7 +104,28 @@ static int send_pmc_req(int cmd_type, const struct pmc_ipc_buffer *req,
|
|||
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 @@ static int send_pmc_connect_request(int port, struct tcss_mux mux_data)
|
|||
|
||||
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 @@ static int send_pmc_connect_request(int port, struct tcss_mux mux_data)
|
|||
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 @@ static int send_pmc_safe_mode_request(int port, struct tcss_mux mux_data)
|
|||
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 @@ static int send_pmc_dp_hpd_request(int port, struct tcss_mux mux_data)
|
|||
|
||||
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 @@ static int send_pmc_dp_mode_request(int port, struct tcss_mux mux_data)
|
|||
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 @@ static int send_pmc_dp_mode_request(int port, struct tcss_mux mux_data)
|
|||
}
|
||||
|
||||
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 @@ static int send_pmc_dp_mode_request(int port, struct tcss_mux mux_data)
|
|||
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;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
int ret;
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -462,7 +462,7 @@ void platform_fsp_multi_phase_init_cb(uint32_t phase_index)
|
|||
/* 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:
|
||||
|
|
|
@ -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 @@ enum pmc_ipc_command_type {
|
|||
#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 @@ struct tcss_mux {
|
|||
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);
|
||||
|
|
Loading…
Reference in New Issue