thunderbolt: Implement TMU time disruption for Intel Titan Ridge
authorGil Fine <gil.fine@intel.com>
Fri, 17 Dec 2021 01:16:41 +0000 (03:16 +0200)
committerMika Westerberg <mika.westerberg@linux.intel.com>
Wed, 22 Dec 2021 14:13:14 +0000 (17:13 +0300)
Intel Titan Ridge based routers have slightly different flow for time
disruption than USB4 compliant routers. This makes it work on Titan
Ridge too. Needed to enable link low power states on Titan Ridge.

Signed-off-by: Gil Fine <gil.fine@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
drivers/thunderbolt/switch.c
drivers/thunderbolt/tb.h
drivers/thunderbolt/tb_regs.h
drivers/thunderbolt/tmu.c

index c242a027698d8bcae1ebd0c2c1c7cd9df36d78a3..c79074f83442848f238c570a215041326914c89c 100644 (file)
@@ -2228,6 +2228,10 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, struct device *parent,
        if (ret > 0)
                sw->cap_plug_events = ret;
 
+       ret = tb_switch_find_vse_cap(sw, TB_VSE_CAP_TIME2);
+       if (ret > 0)
+               sw->cap_vsec_tmu = ret;
+
        ret = tb_switch_find_vse_cap(sw, TB_VSE_CAP_LINK_CONTROLLER);
        if (ret > 0)
                sw->cap_lc = ret;
index 78b884abd7225c6fa4f520a7438ee478f7b4eb4a..f416e4dcda766e2edb1ec5dcfad9838f6dce043d 100644 (file)
@@ -138,6 +138,7 @@ enum tb_clx {
  * @link_usb4: Upstream link is USB4
  * @generation: Switch Thunderbolt generation
  * @cap_plug_events: Offset to the plug events capability (%0 if not found)
+ * @cap_vsec_tmu: Offset to the TMU vendor specific capability (%0 if not found)
  * @cap_lc: Offset to the link controller capability (%0 if not found)
  * @is_unplugged: The switch is going away
  * @drom: DROM of the switch (%NULL if not found)
@@ -189,6 +190,7 @@ struct tb_switch {
        bool link_usb4;
        unsigned int generation;
        int cap_plug_events;
+       int cap_vsec_tmu;
        int cap_lc;
        bool is_unplugged;
        u8 *drom;
index 50a567e31fda8bc401a5a2669fd981374adfcdd2..2469eb34528d5140d26fda656a4ec8ac5352aad8 100644 (file)
@@ -446,6 +446,10 @@ struct tb_regs_hop {
        u32 unknown3:3; /* set to zero */
 } __packed;
 
+/* TMU Thunderbolt 3 registers */
+#define TB_TIME_VSEC_3_CS_26           0x1a
+#define TB_TIME_VSEC_3_CS_26_TD                BIT(22)
+
 /* Common link controller registers */
 #define TB_LC_DESC                     0x02
 #define TB_LC_DESC_NLC_MASK            GENMASK(3, 0)
index 37048dab5b567b795d0600c353c8214f0e74df37..8392d1352c986760b1e8fea5c6a7c96500437931 100644 (file)
@@ -152,21 +152,27 @@ static int tb_port_tmu_time_sync_enable(struct tb_port *port)
 
 static int tb_switch_tmu_set_time_disruption(struct tb_switch *sw, bool set)
 {
+       u32 val, offset, bit;
        int ret;
-       u32 val;
 
-       ret = tb_sw_read(sw, &val, TB_CFG_SWITCH,
-                        sw->tmu.cap + TMU_RTR_CS_0, 1);
+       if (tb_switch_is_usb4(sw)) {
+               offset = sw->tmu.cap + TMU_RTR_CS_0;
+               bit = TMU_RTR_CS_0_TD;
+       } else {
+               offset = sw->cap_vsec_tmu + TB_TIME_VSEC_3_CS_26;
+               bit = TB_TIME_VSEC_3_CS_26_TD;
+       }
+
+       ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, offset, 1);
        if (ret)
                return ret;
 
        if (set)
-               val |= TMU_RTR_CS_0_TD;
+               val |= bit;
        else
-               val &= ~TMU_RTR_CS_0_TD;
+               val &= ~bit;
 
-       return tb_sw_write(sw, &val, TB_CFG_SWITCH,
-                          sw->tmu.cap + TMU_RTR_CS_0, 1);
+       return tb_sw_write(sw, &val, TB_CFG_SWITCH, offset, 1);
 }
 
 /**