in usb4.c [367:436]
int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags)
{
struct tb_port *port;
u64 route = tb_route(sw);
u32 val;
int ret;
/*
* Enable wakes coming from all USB4 downstream ports (from
* child routers). For device routers do this also for the
* upstream USB4 port.
*/
tb_switch_for_each_port(sw, port) {
if (!tb_port_is_null(port))
continue;
if (!route && tb_is_upstream_port(port))
continue;
if (!port->cap_usb4)
continue;
ret = tb_port_read(port, &val, TB_CFG_PORT,
port->cap_usb4 + PORT_CS_19, 1);
if (ret)
return ret;
val &= ~(PORT_CS_19_WOC | PORT_CS_19_WOD | PORT_CS_19_WOU4);
if (tb_is_upstream_port(port)) {
val |= PORT_CS_19_WOU4;
} else {
bool configured = val & PORT_CS_19_PC;
if ((flags & TB_WAKE_ON_CONNECT) && !configured)
val |= PORT_CS_19_WOC;
if ((flags & TB_WAKE_ON_DISCONNECT) && configured)
val |= PORT_CS_19_WOD;
if ((flags & TB_WAKE_ON_USB4) && configured)
val |= PORT_CS_19_WOU4;
}
ret = tb_port_write(port, &val, TB_CFG_PORT,
port->cap_usb4 + PORT_CS_19, 1);
if (ret)
return ret;
}
/*
* Enable wakes from PCIe, USB 3.x and DP on this router. Only
* needed for device routers.
*/
if (route) {
ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1);
if (ret)
return ret;
val &= ~(ROUTER_CS_5_WOP | ROUTER_CS_5_WOU | ROUTER_CS_5_WOD);
if (flags & TB_WAKE_ON_USB3)
val |= ROUTER_CS_5_WOU;
if (flags & TB_WAKE_ON_PCIE)
val |= ROUTER_CS_5_WOP;
if (flags & TB_WAKE_ON_DP)
val |= ROUTER_CS_5_WOD;
ret = tb_sw_write(sw, &val, TB_CFG_SWITCH, ROUTER_CS_5, 1);
if (ret)
return ret;
}
return 0;
}