summaryrefslogtreecommitdiffstats
path: root/drivers/thunderbolt/tb.c
diff options
context:
space:
mode:
authorRajmohan Mani <rajmohan.mani@intel.com>2019-12-17 13:33:43 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-12-18 15:41:15 +0100
commitcf29b9afb121494a7aa12dae6eebf81347e0313b (patch)
treee179d5b083d5df965ccc3d119002ddda458958e6 /drivers/thunderbolt/tb.c
parentthunderbolt: Make tb_switch_find_cap() available to other files (diff)
downloadlinux-cf29b9afb121494a7aa12dae6eebf81347e0313b.tar.xz
linux-cf29b9afb121494a7aa12dae6eebf81347e0313b.zip
thunderbolt: Add support for Time Management Unit
Time Management Unit (TMU) is included in each USB4 router. It is used to synchronize time across the USB4 fabric. By default when USB4 router is plugged to the domain, its TMU is turned off. This differs from Thunderbolt (1, 2 and 3) devices whose TMU is by default configured to bi-directional HiFi mode. Since time synchronization is needed for proper Display Port tunneling this means we need to configure the TMU on USB4 compliant devices. The USB4 spec allows some flexibility on how the TMU can be configured. This makes it possible to enable link power management states (CLx) in certain topologies, where for example DP tunneling is not used. TMU can also be re-configured dynamicaly depending on types of tunnels created over the USB4 fabric. In this patch we simply configure the TMU to be in bi-directional HiFi mode. This way we can tunnel any kind of traffic without need to perform complex steps to re-configure the domain dynamically. We can add more fine-grained TMU configuration later on when we start enabling CLx states. Signed-off-by: Rajmohan Mani <rajmohan.mani@intel.com> Co-developed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Link: https://lore.kernel.org/r/20191217123345.31850-8-mika.westerberg@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/thunderbolt/tb.c')
-rw-r--r--drivers/thunderbolt/tb.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index 6b99dcd1790c..e446624dd3e7 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -158,6 +158,25 @@ static void tb_scan_xdomain(struct tb_port *port)
}
}
+static int tb_enable_tmu(struct tb_switch *sw)
+{
+ int ret;
+
+ /* If it is already enabled in correct mode, don't touch it */
+ if (tb_switch_tmu_is_enabled(sw))
+ return 0;
+
+ ret = tb_switch_tmu_disable(sw);
+ if (ret)
+ return ret;
+
+ ret = tb_switch_tmu_post_time(sw);
+ if (ret)
+ return ret;
+
+ return tb_switch_tmu_enable(sw);
+}
+
static void tb_scan_port(struct tb_port *port);
/**
@@ -257,6 +276,9 @@ static void tb_scan_port(struct tb_port *port)
if (tb_switch_lane_bonding_enable(sw))
tb_sw_warn(sw, "failed to enable lane bonding\n");
+ if (tb_enable_tmu(sw))
+ tb_sw_warn(sw, "failed to enable TMU\n");
+
tb_scan_switch(sw);
}
@@ -709,6 +731,7 @@ static void tb_handle_hotplug(struct work_struct *work)
tb_sw_set_unplugged(port->remote->sw);
tb_free_invalid_tunnels(tb);
tb_remove_dp_resources(port->remote->sw);
+ tb_switch_tmu_disable(port->remote->sw);
tb_switch_lane_bonding_disable(port->remote->sw);
tb_switch_remove(port->remote->sw);
port->remote = NULL;
@@ -855,6 +878,8 @@ static int tb_start(struct tb *tb)
return ret;
}
+ /* Enable TMU if it is off */
+ tb_switch_tmu_enable(tb->root_switch);
/* Full scan to discover devices added before the driver was loaded. */
tb_scan_switch(tb->root_switch);
/* Find out tunnels created by the boot firmware */
@@ -886,6 +911,9 @@ static void tb_restore_children(struct tb_switch *sw)
{
struct tb_port *port;
+ if (tb_enable_tmu(sw))
+ tb_sw_warn(sw, "failed to restore TMU configuration\n");
+
tb_switch_for_each_port(sw, port) {
if (!tb_port_has_remote(port))
continue;