thunderbolt: Add wake from DisplayPort
authorMika Westerberg <mika.westerberg@linux.intel.com>
Thu, 14 Jan 2021 14:44:17 +0000 (16:44 +0200)
committerMika Westerberg <mika.westerberg@linux.intel.com>
Mon, 31 May 2021 11:39:52 +0000 (14:39 +0300)
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 <mika.westerberg@linux.intel.com>
drivers/thunderbolt/lc.c
drivers/thunderbolt/switch.c
drivers/thunderbolt/tb.h
drivers/thunderbolt/tb_regs.h
drivers/thunderbolt/usb4.c

index bc67173..c178f0d 100644 (file)
@@ -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);
 }
index e73cd29..4d4bc50 100644 (file)
@@ -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;
        }
index d9d1adc..60a987c 100644 (file)
@@ -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
index 626751e..113d790 100644 (file)
@@ -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)
index c0a14bf..7e8b5ca 100644 (file)
@@ -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)