summaryrefslogtreecommitdiffstats
path: root/drivers/thunderbolt/retimer.c
diff options
context:
space:
mode:
authorRajmohan Mani <rajmohan.mani@intel.com>2021-04-01 17:42:38 +0200
committerMika Westerberg <mika.westerberg@linux.intel.com>2021-06-01 09:53:31 +0200
commit3fb10ea4ce86d4d06622be894099c59872e92c57 (patch)
tree9fbeb49811791a1a415272603300868a78a65102 /drivers/thunderbolt/retimer.c
parentthunderbolt: Add additional USB4 port operations for retimer access (diff)
downloadlinux-3fb10ea4ce86d4d06622be894099c59872e92c57.tar.xz
linux-3fb10ea4ce86d4d06622be894099c59872e92c57.zip
thunderbolt: Add support for retimer NVM upgrade when there is no link
With help from platform firmware (ACPI) it is possible to power on retimers even when there is no USB4 link (e.g nothing is connected to the USB4 ports). This allows us to bring the USB4 sideband up so that we can access retimers and upgrade their NVM firmware. If the platform has support for this, we expose two additional attributes under USB4 ports: offline and rescan. These can be used to bring the port offline, rescan for the retimers and put the port online again. The retimer NVM upgrade itself works the same way than with cable connected. 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> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/thunderbolt/retimer.c')
-rw-r--r--drivers/thunderbolt/retimer.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c
index 2e5188fb1150..05af0feefe84 100644
--- a/drivers/thunderbolt/retimer.c
+++ b/drivers/thunderbolt/retimer.c
@@ -401,19 +401,18 @@ static struct tb_retimer *tb_port_find_retimer(struct tb_port *port, u8 index)
/**
* tb_retimer_scan() - Scan for on-board retimers under port
* @port: USB4 port to scan
+ * @add: If true also registers found retimers
*
- * Tries to enumerate on-board retimers connected to @port. Found
- * retimers are registered as children of @port. Does not scan for cable
- * retimers for now.
+ * Brings the sideband into a state where retimers can be accessed.
+ * Then Tries to enumerate on-board retimers connected to @port. Found
+ * retimers are registered as children of @port if @add is set. Does
+ * not scan for cable retimers for now.
*/
-int tb_retimer_scan(struct tb_port *port)
+int tb_retimer_scan(struct tb_port *port, bool add)
{
u32 status[TB_MAX_RETIMER_INDEX + 1] = {};
int ret, i, last_idx = 0;
- if (!port->cap_usb4)
- return 0;
-
/*
* Send broadcast RT to make sure retimer indices facing this
* port are set.
@@ -423,6 +422,13 @@ int tb_retimer_scan(struct tb_port *port)
return ret;
/*
+ * Enable sideband channel for each retimer. We can do this
+ * regardless whether there is device connected or not.
+ */
+ for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++)
+ usb4_port_retimer_set_inbound_sbtx(port, i);
+
+ /*
* Before doing anything else, read the authentication status.
* If the retimer has it set, store it for the new retimer
* device instance.
@@ -453,10 +459,10 @@ int tb_retimer_scan(struct tb_port *port)
rt = tb_port_find_retimer(port, i);
if (rt) {
put_device(&rt->dev);
- } else {
+ } else if (add) {
ret = tb_retimer_add(port, i, status[i]);
if (ret && ret != -EOPNOTSUPP)
- return ret;
+ break;
}
}