diff options
Diffstat (limited to 'drivers/thunderbolt/usb4.c')
-rw-r--r-- | drivers/thunderbolt/usb4.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index 1515eff8cc3e..9860b49d7a2b 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -1113,6 +1113,45 @@ int usb4_port_hotplug_enable(struct tb_port *port) return tb_port_write(port, &val, TB_CFG_PORT, ADP_CS_5, 1); } +/** + * usb4_port_reset() - Issue downstream port reset + * @port: USB4 port to reset + * + * Issues downstream port reset to @port. + */ +int usb4_port_reset(struct tb_port *port) +{ + int ret; + u32 val; + + if (!port->cap_usb4) + return -EINVAL; + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); + if (ret) + return ret; + + val |= PORT_CS_19_DPR; + + ret = tb_port_write(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); + if (ret) + return ret; + + fsleep(10000); + + ret = tb_port_read(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); + if (ret) + return ret; + + val &= ~PORT_CS_19_DPR; + + return tb_port_write(port, &val, TB_CFG_PORT, + port->cap_usb4 + PORT_CS_19, 1); +} + static int usb4_port_set_configured(struct tb_port *port, bool configured) { int ret; @@ -2819,8 +2858,10 @@ static int usb4_dp_port_wait_and_clear_cm_ack(struct tb_port *port, usleep_range(50, 100); } while (ktime_before(ktime_get(), end)); - if (val & ADP_DP_CS_8_DR) + if (val & ADP_DP_CS_8_DR) { + tb_port_warn(port, "timeout waiting for DPTX request to clear\n"); return -ETIMEDOUT; + } ret = tb_port_read(port, &val, TB_CFG_PORT, port->cap_adap + ADP_DP_CS_2, 1); |