aboutsummaryrefslogtreecommitdiff
path: root/drivers/thunderbolt/usb4.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-09-30 13:44:59 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-09-30 13:44:59 +0200
commitbffcd14facbdc25ba4da9993cc7811b55b50b6e8 (patch)
treebaaa96dcf297dcdf1c52dc979ee2355d2907fa38 /drivers/thunderbolt/usb4.c
parenta62e6791476a5d07abb8dec9afc2c6d0f65f7e4e (diff)
parent5d2569cb4a65c373896ec0217febdf88739ed295 (diff)
Merge tag 'thunderbolt-for-v6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt into usb-next
Mika writes: "thunderbolt: Changes for v6.1 merge window This includes following Thunderbolt/USB4 changes for the v6.1 merge window: - Support for Intel Meteor Lake integrated Thunderbolt/USB4 controller - Support for ASMedia USB4 controller NVM firmware upgrade - Receiver lane margining support - Few fixes and cleanups. All these have been in linux-next with no reported issues." * tag 'thunderbolt-for-v6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt: thunderbolt: Explicitly enable lane adapter hotplug events at startup thunderbolt: Use dev_err_probe() thunderbolt: Convert to use sysfs_emit()/sysfs_emit_at() APIs thunderbolt: Fix spelling mistake "simultaneusly" -> "simultaneously" thunderbolt: debugfs: Fix spelling mistakes in seq_puts text thunderbolt: Add support for ASMedia NVM image format thunderbolt: Move vendor specific NVM handling into nvm.c thunderbolt: Provide tb_retimer_nvm_read() analogous to tb_switch_nvm_read() thunderbolt: Rename and make nvm_read() available for other files thunderbolt: Extend NVM version fields to 32-bits thunderbolt: Allow NVM upgrade of USB4 host routers thunderbolt: Add support for receiver lane margining thunderbolt: Add helper to check if CL states are enabled on port thunderbolt: Pass CL state bitmask to tb_port_clx_supported() thunderbolt: Move port CL state functions into correct place in switch.c thunderbolt: Move tb_xdomain_parent() to tb.h thunderbolt: Add support for Intel Meteor Lake thunderbolt: Add comment where Thunderbolt 4 PCI IDs start thunderbolt: Add DP OUT resource when DP tunnel is discovered
Diffstat (limited to 'drivers/thunderbolt/usb4.c')
-rw-r--r--drivers/thunderbolt/usb4.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c
index 3a2e7126db9d..38c10c30e6cf 100644
--- a/drivers/thunderbolt/usb4.c
+++ b/drivers/thunderbolt/usb4.c
@@ -1046,6 +1046,26 @@ int usb4_port_unlock(struct tb_port *port)
return tb_port_write(port, &val, TB_CFG_PORT, ADP_CS_4, 1);
}
+/**
+ * usb4_port_hotplug_enable() - Enables hotplug for a port
+ * @port: USB4 port to operate on
+ *
+ * Enables hot plug events on a given port. This is only intended
+ * to be used on lane, DP-IN, and DP-OUT adapters.
+ */
+int usb4_port_hotplug_enable(struct tb_port *port)
+{
+ int ret;
+ u32 val;
+
+ ret = tb_port_read(port, &val, TB_CFG_PORT, ADP_CS_5, 1);
+ if (ret)
+ return ret;
+
+ val &= ~ADP_CS_5_DHP;
+ return tb_port_write(port, &val, TB_CFG_PORT, ADP_CS_5, 1);
+}
+
static int usb4_port_set_configured(struct tb_port *port, bool configured)
{
int ret;
@@ -1384,6 +1404,126 @@ bool usb4_port_clx_supported(struct tb_port *port)
return !!(val & PORT_CS_18_CPS);
}
+/**
+ * usb4_port_margining_caps() - Read USB4 port marginig capabilities
+ * @port: USB4 port
+ * @caps: Array with at least two elements to hold the results
+ *
+ * Reads the USB4 port lane margining capabilities into @caps.
+ */
+int usb4_port_margining_caps(struct tb_port *port, u32 *caps)
+{
+ int ret;
+
+ ret = usb4_port_sb_op(port, USB4_SB_TARGET_ROUTER, 0,
+ USB4_SB_OPCODE_READ_LANE_MARGINING_CAP, 500);
+ if (ret)
+ return ret;
+
+ return usb4_port_sb_read(port, USB4_SB_TARGET_ROUTER, 0,
+ USB4_SB_DATA, caps, sizeof(*caps) * 2);
+}
+
+/**
+ * usb4_port_hw_margin() - Run hardware lane margining on port
+ * @port: USB4 port
+ * @lanes: Which lanes to run (must match the port capabilities). Can be
+ * %0, %1 or %7.
+ * @ber_level: BER level contour value
+ * @timing: Perform timing margining instead of voltage
+ * @right_high: Use Right/high margin instead of left/low
+ * @results: Array with at least two elements to hold the results
+ *
+ * Runs hardware lane margining on USB4 port and returns the result in
+ * @results.
+ */
+int usb4_port_hw_margin(struct tb_port *port, unsigned int lanes,
+ unsigned int ber_level, bool timing, bool right_high,
+ u32 *results)
+{
+ u32 val;
+ int ret;
+
+ val = lanes;
+ if (timing)
+ val |= USB4_MARGIN_HW_TIME;
+ if (right_high)
+ val |= USB4_MARGIN_HW_RH;
+ if (ber_level)
+ val |= (ber_level << USB4_MARGIN_HW_BER_SHIFT) &
+ USB4_MARGIN_HW_BER_MASK;
+
+ ret = usb4_port_sb_write(port, USB4_SB_TARGET_ROUTER, 0,
+ USB4_SB_METADATA, &val, sizeof(val));
+ if (ret)
+ return ret;
+
+ ret = usb4_port_sb_op(port, USB4_SB_TARGET_ROUTER, 0,
+ USB4_SB_OPCODE_RUN_HW_LANE_MARGINING, 2500);
+ if (ret)
+ return ret;
+
+ return usb4_port_sb_read(port, USB4_SB_TARGET_ROUTER, 0,
+ USB4_SB_DATA, results, sizeof(*results) * 2);
+}
+
+/**
+ * usb4_port_sw_margin() - Run software lane margining on port
+ * @port: USB4 port
+ * @lanes: Which lanes to run (must match the port capabilities). Can be
+ * %0, %1 or %7.
+ * @timing: Perform timing margining instead of voltage
+ * @right_high: Use Right/high margin instead of left/low
+ * @counter: What to do with the error counter
+ *
+ * Runs software lane margining on USB4 port. Read back the error
+ * counters by calling usb4_port_sw_margin_errors(). Returns %0 in
+ * success and negative errno otherwise.
+ */
+int usb4_port_sw_margin(struct tb_port *port, unsigned int lanes, bool timing,
+ bool right_high, u32 counter)
+{
+ u32 val;
+ int ret;
+
+ val = lanes;
+ if (timing)
+ val |= USB4_MARGIN_SW_TIME;
+ if (right_high)
+ val |= USB4_MARGIN_SW_RH;
+ val |= (counter << USB4_MARGIN_SW_COUNTER_SHIFT) &
+ USB4_MARGIN_SW_COUNTER_MASK;
+
+ ret = usb4_port_sb_write(port, USB4_SB_TARGET_ROUTER, 0,
+ USB4_SB_METADATA, &val, sizeof(val));
+ if (ret)
+ return ret;
+
+ return usb4_port_sb_op(port, USB4_SB_TARGET_ROUTER, 0,
+ USB4_SB_OPCODE_RUN_SW_LANE_MARGINING, 2500);
+}
+
+/**
+ * usb4_port_sw_margin_errors() - Read the software margining error counters
+ * @port: USB4 port
+ * @errors: Error metadata is copied here.
+ *
+ * This reads back the software margining error counters from the port.
+ * Returns %0 in success and negative errno otherwise.
+ */
+int usb4_port_sw_margin_errors(struct tb_port *port, u32 *errors)
+{
+ int ret;
+
+ ret = usb4_port_sb_op(port, USB4_SB_TARGET_ROUTER, 0,
+ USB4_SB_OPCODE_READ_SW_MARGIN_ERR, 150);
+ if (ret)
+ return ret;
+
+ return usb4_port_sb_read(port, USB4_SB_TARGET_ROUTER, 0,
+ USB4_SB_METADATA, errors, sizeof(*errors));
+}
+
static inline int usb4_port_retimer_op(struct tb_port *port, u8 index,
enum usb4_sb_opcode opcode,
int timeout_msec)