From 6026b703e8f61bf9c395bb286fa3b46956ce0496 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 14 Jan 2021 16:44:17 +0200 Subject: [PATCH] thunderbolt: Add wake from DisplayPort Latest USB4 spec added a new wake bit for DisplayPort so add this to the driver when runtime suspending. This way wake up the domain when a new monitor is plugged in to any of the device routers. Also do the same for pre-USB4 devices through the link controller registers as documented in chapter 13 of the USB4 spec. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/lc.c | 6 ++++-- drivers/thunderbolt/switch.c | 3 ++- drivers/thunderbolt/tb.h | 1 + drivers/thunderbolt/tb_regs.h | 3 +++ drivers/thunderbolt/usb4.c | 6 ++++-- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/thunderbolt/lc.c b/drivers/thunderbolt/lc.c index bc67173..c178f0d 100644 --- a/drivers/thunderbolt/lc.c +++ b/drivers/thunderbolt/lc.c @@ -208,8 +208,8 @@ static int tb_lc_set_wake_one(struct tb_switch *sw, unsigned int offset, if (ret) return ret; - ctrl &= ~(TB_LC_SX_CTRL_WOC | TB_LC_SX_CTRL_WOD | TB_LC_SX_CTRL_WOP | - TB_LC_SX_CTRL_WOU4); + ctrl &= ~(TB_LC_SX_CTRL_WOC | TB_LC_SX_CTRL_WOD | TB_LC_SX_CTRL_WODPC | + TB_LC_SX_CTRL_WODPD | TB_LC_SX_CTRL_WOP | TB_LC_SX_CTRL_WOU4); if (flags & TB_WAKE_ON_CONNECT) ctrl |= TB_LC_SX_CTRL_WOC | TB_LC_SX_CTRL_WOD; @@ -217,6 +217,8 @@ static int tb_lc_set_wake_one(struct tb_switch *sw, unsigned int offset, ctrl |= TB_LC_SX_CTRL_WOU4; if (flags & TB_WAKE_ON_PCIE) ctrl |= TB_LC_SX_CTRL_WOP; + if (flags & TB_WAKE_ON_DP) + ctrl |= TB_LC_SX_CTRL_WODPC | TB_LC_SX_CTRL_WODPD; return tb_sw_write(sw, &ctrl, TB_CFG_SWITCH, offset + TB_LC_SX_CTRL, 1); } diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index e73cd29..4d4bc50 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -2844,7 +2844,8 @@ void tb_switch_suspend(struct tb_switch *sw, bool runtime) if (runtime) { /* Trigger wake when something is plugged in/out */ flags |= TB_WAKE_ON_CONNECT | TB_WAKE_ON_DISCONNECT; - flags |= TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE; + flags |= TB_WAKE_ON_USB4; + flags |= TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE | TB_WAKE_ON_DP; } else if (device_may_wakeup(&sw->dev)) { flags |= TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE; } diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index d9d1adc..60a987c 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -347,6 +347,7 @@ struct tb_path { #define TB_WAKE_ON_USB4 BIT(2) #define TB_WAKE_ON_USB3 BIT(3) #define TB_WAKE_ON_PCIE BIT(4) +#define TB_WAKE_ON_DP BIT(5) /** * struct tb_cm_ops - Connection manager specific operations vector diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h index 626751e..113d790 100644 --- a/drivers/thunderbolt/tb_regs.h +++ b/drivers/thunderbolt/tb_regs.h @@ -195,6 +195,7 @@ struct tb_regs_switch_header { #define ROUTER_CS_5_SLP BIT(0) #define ROUTER_CS_5_WOP BIT(1) #define ROUTER_CS_5_WOU BIT(2) +#define ROUTER_CS_5_WOD BIT(3) #define ROUTER_CS_5_C3S BIT(23) #define ROUTER_CS_5_PTO BIT(24) #define ROUTER_CS_5_UTO BIT(25) @@ -458,6 +459,8 @@ struct tb_regs_hop { #define TB_LC_SX_CTRL 0x96 #define TB_LC_SX_CTRL_WOC BIT(1) #define TB_LC_SX_CTRL_WOD BIT(2) +#define TB_LC_SX_CTRL_WODPC BIT(3) +#define TB_LC_SX_CTRL_WODPD BIT(4) #define TB_LC_SX_CTRL_WOU4 BIT(5) #define TB_LC_SX_CTRL_WOP BIT(6) #define TB_LC_SX_CTRL_L1C BIT(16) diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index c0a14bf..7e8b5ca 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -413,7 +413,7 @@ int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) } /* - * Enable wakes from PCIe and USB 3.x on this router. Only + * Enable wakes from PCIe, USB 3.x and DP on this router. Only * needed for device routers. */ if (route) { @@ -421,11 +421,13 @@ int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) if (ret) return ret; - val &= ~(ROUTER_CS_5_WOP | ROUTER_CS_5_WOU); + 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) -- 2.7.4