From 97486e981ffb865f8845af3c24d5fb19f1ea37e8 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 9 Jan 2022 13:51:31 +0100 Subject: thunderbolt: Remove useless DMA-32 fallback configuration As stated in [1], dma_set_mask() with a 64-bit mask never fails if dev->dma_mask is non-NULL. So, if it fails, the 32 bits case will also fail for the same reason. Simplify code and remove some dead code accordingly. While at it, include directly instead on relying on indirect inclusion. [1]: https://lkml.org/lkml/2021/6/7/398 Signed-off-by: Christophe JAILLET Signed-off-by: Mika Westerberg --- drivers/thunderbolt/nhi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index c73da0532be4..4a582183f675 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1229,8 +1230,6 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&nhi->lock); res = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); - if (res) - res = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); if (res) { dev_err(&pdev->dev, "failed to set DMA mask\n"); return res; -- cgit From 3eddfc121f90e174253031594b354e5764f8a318 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 27 Oct 2021 13:29:09 +0300 Subject: thunderbolt: Disable LTTPR on Intel Titan Ridge Intel Titan Ridge does not disable AUX timers when it gets SET_CONFIG with SET_LTTPR_MODE set which makes DP tunneling to fail. For this reason disable LTTPR on Titan Ridge device side. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/tb_regs.h | 1 + drivers/thunderbolt/tunnel.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h index a74f4878d3e7..9693a6ec5950 100644 --- a/drivers/thunderbolt/tb_regs.h +++ b/drivers/thunderbolt/tb_regs.h @@ -389,6 +389,7 @@ struct tb_regs_port_header { #define DP_COMMON_CAP_1_LANE 0x0 #define DP_COMMON_CAP_2_LANES 0x1 #define DP_COMMON_CAP_4_LANES 0x2 +#define DP_COMMON_CAP_LTTPR_NS BIT(27) #define DP_COMMON_CAP_DPRX_DONE BIT(31) /* PCIe adapter registers */ diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index a473cc7d9a8d..118742ec93ed 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -580,6 +580,16 @@ static int tb_dp_xchg_caps(struct tb_tunnel *tunnel) out_dp_cap = tb_dp_cap_set_lanes(out_dp_cap, new_lanes); } + /* + * Titan Ridge does not disable AUX timers when it gets + * SET_CONFIG with SET_LTTPR_MODE set. This causes problems with + * DP tunneling. + */ + if (tb_route(out->sw) && tb_switch_is_titan_ridge(out->sw)) { + out_dp_cap |= DP_COMMON_CAP_LTTPR_NS; + tb_port_dbg(out, "disabling LTTPR\n"); + } + return tb_port_write(in, &out_dp_cap, TB_CFG_PORT, in->cap_adap + DP_REMOTE_CAP, 1); } -- cgit From f1d5ec3e0eabaf961ed16516bf35e24b48cda483 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 7 Jan 2022 12:59:01 +0200 Subject: thunderbolt: Add missing device ID to tb_switch_is_alpine_ridge() tb_switch_is_alpine_ridge() is missing device ID for Intel Alpine Ridge dual port version so add this. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/tb.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 74d3b14f004e..44e36498b261 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -855,6 +855,7 @@ static inline bool tb_switch_is_alpine_ridge(const struct tb_switch *sw) if (sw->config.vendor_id == PCI_VENDOR_ID_INTEL) { switch (sw->config.device_id) { case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE: + case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE: case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_LP_BRIDGE: case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_BRIDGE: case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_BRIDGE: -- cgit From 30a4eca69b76c0ed5a2f34dd2a3e195c9bf6bed1 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 7 Jan 2022 13:00:47 +0200 Subject: thunderbolt: Add internal xHCI connect flows for Thunderbolt 3 devices Both Alpine Ridge and Titan Ridge require special flows in order to activate the internal xHCI controller when there is USB device connected to the downstream type-C port. This implements the missing flows for both. Signed-off-by: Mika Westerberg --- drivers/thunderbolt/lc.c | 110 ++++++++++++++++++++++++++++++++++++++++++ drivers/thunderbolt/switch.c | 71 ++++++++++++++++++++++++++- drivers/thunderbolt/tb.c | 11 +++++ drivers/thunderbolt/tb.h | 7 +++ drivers/thunderbolt/tb_regs.h | 8 +++ 5 files changed, 206 insertions(+), 1 deletion(-) diff --git a/drivers/thunderbolt/lc.c b/drivers/thunderbolt/lc.c index 53495a38b4eb..633970fbe9b0 100644 --- a/drivers/thunderbolt/lc.c +++ b/drivers/thunderbolt/lc.c @@ -217,6 +217,116 @@ bool tb_lc_is_clx_supported(struct tb_port *port) return !!(val & TB_LC_LINK_ATTR_CPS); } +/** + * tb_lc_is_usb_plugged() - Is there USB device connected to port + * @port: Device router lane 0 adapter + * + * Returns true if the @port has USB type-C device connected. + */ +bool tb_lc_is_usb_plugged(struct tb_port *port) +{ + struct tb_switch *sw = port->sw; + int cap, ret; + u32 val; + + if (sw->generation != 3) + return false; + + cap = find_port_lc_cap(port); + if (cap < 0) + return false; + + ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, cap + TB_LC_CS_42, 1); + if (ret) + return false; + + return !!(val & TB_LC_CS_42_USB_PLUGGED); +} + +/** + * tb_lc_is_xhci_connected() - Is the internal xHCI connected + * @port: Device router lane 0 adapter + * + * Returns true if the internal xHCI has been connected to @port. + */ +bool tb_lc_is_xhci_connected(struct tb_port *port) +{ + struct tb_switch *sw = port->sw; + int cap, ret; + u32 val; + + if (sw->generation != 3) + return false; + + cap = find_port_lc_cap(port); + if (cap < 0) + return false; + + ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, cap + TB_LC_LINK_REQ, 1); + if (ret) + return false; + + return !!(val & TB_LC_LINK_REQ_XHCI_CONNECT); +} + +static int __tb_lc_xhci_connect(struct tb_port *port, bool connect) +{ + struct tb_switch *sw = port->sw; + int cap, ret; + u32 val; + + if (sw->generation != 3) + return -EINVAL; + + cap = find_port_lc_cap(port); + if (cap < 0) + return cap; + + ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, cap + TB_LC_LINK_REQ, 1); + if (ret) + return ret; + + if (connect) + val |= TB_LC_LINK_REQ_XHCI_CONNECT; + else + val &= ~TB_LC_LINK_REQ_XHCI_CONNECT; + + return tb_sw_write(sw, &val, TB_CFG_SWITCH, cap + TB_LC_LINK_REQ, 1); +} + +/** + * tb_lc_xhci_connect() - Connect internal xHCI + * @port: Device router lane 0 adapter + * + * Tells LC to connect the internal xHCI to @port. Returns %0 on success + * and negative errno in case of failure. Can be called for Thunderbolt 3 + * routers only. + */ +int tb_lc_xhci_connect(struct tb_port *port) +{ + int ret; + + ret = __tb_lc_xhci_connect(port, true); + if (ret) + return ret; + + tb_port_dbg(port, "xHCI connected\n"); + return 0; +} + +/** + * tb_lc_xhci_disconnect() - Disconnect internal xHCI + * @port: Device router lane 0 adapter + * + * Tells LC to disconnect the internal xHCI from @port. Can be called + * for Thunderbolt 3 routers only. + */ +void tb_lc_xhci_disconnect(struct tb_port *port) +{ + __tb_lc_xhci_connect(port, false); + tb_port_dbg(port, "xHCI disconnected\n"); +} + static int tb_lc_set_wake_one(struct tb_switch *sw, unsigned int offset, unsigned int flags) { diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index d026e305fe5d..b5fb3e76ed09 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -1528,7 +1528,13 @@ static int tb_plug_events_active(struct tb_switch *sw, bool active) case PCI_DEVICE_ID_INTEL_PORT_RIDGE: break; default: - data |= 4; + /* + * Skip Alpine Ridge, it needs to have vendor + * specific USB hotplug event enabled for the + * internal xHCI to work. + */ + if (!tb_switch_is_alpine_ridge(sw)) + data |= TB_PLUG_EVENTS_USB_DISABLE; } } else { data = data | 0x7c; @@ -3689,3 +3695,66 @@ int tb_switch_pcie_l1_enable(struct tb_switch *sw) /* Write to Upstream PCIe bridge #0 aka Up0 */ return tb_switch_pcie_bridge_write(sw, 0, 0x143, 0x0c5806b1); } + +/** + * tb_switch_xhci_connect() - Connect internal xHCI + * @sw: Router whose xHCI to connect + * + * Can be called to any router. For Alpine Ridge and Titan Ridge + * performs special flows that bring the xHCI functional for any device + * connected to the type-C port. Call only after PCIe tunnel has been + * established. The function only does the connect if not done already + * so can be called several times for the same router. + */ +int tb_switch_xhci_connect(struct tb_switch *sw) +{ + bool usb_port1, usb_port3, xhci_port1, xhci_port3; + struct tb_port *port1, *port3; + int ret; + + port1 = &sw->ports[1]; + port3 = &sw->ports[3]; + + if (tb_switch_is_alpine_ridge(sw)) { + usb_port1 = tb_lc_is_usb_plugged(port1); + usb_port3 = tb_lc_is_usb_plugged(port3); + xhci_port1 = tb_lc_is_xhci_connected(port1); + xhci_port3 = tb_lc_is_xhci_connected(port3); + + /* Figure out correct USB port to connect */ + if (usb_port1 && !xhci_port1) { + ret = tb_lc_xhci_connect(port1); + if (ret) + return ret; + } + if (usb_port3 && !xhci_port3) + return tb_lc_xhci_connect(port3); + } else if (tb_switch_is_titan_ridge(sw)) { + ret = tb_lc_xhci_connect(port1); + if (ret) + return ret; + return tb_lc_xhci_connect(port3); + } + + return 0; +} + +/** + * tb_switch_xhci_disconnect() - Disconnect internal xHCI + * @sw: Router whose xHCI to disconnect + * + * The opposite of tb_switch_xhci_connect(). Disconnects xHCI on both + * ports. + */ +void tb_switch_xhci_disconnect(struct tb_switch *sw) +{ + if (sw->generation == 3) { + struct tb_port *port1 = &sw->ports[1]; + struct tb_port *port3 = &sw->ports[3]; + + tb_lc_xhci_disconnect(port1); + tb_port_dbg(port1, "disconnected xHCI\n"); + tb_lc_xhci_disconnect(port3); + tb_port_dbg(port3, "disconnected xHCI\n"); + } +} diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index cbd0ad85ffb1..9beb47b31c75 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -1054,6 +1054,8 @@ static int tb_disconnect_pci(struct tb *tb, struct tb_switch *sw) if (WARN_ON(!tunnel)) return -ENODEV; + tb_switch_xhci_disconnect(sw); + tb_tunnel_deactivate(tunnel); list_del(&tunnel->list); tb_tunnel_free(tunnel); @@ -1099,6 +1101,9 @@ static int tb_tunnel_pci(struct tb *tb, struct tb_switch *sw) if (tb_switch_pcie_l1_enable(sw)) tb_sw_warn(sw, "failed to enable PCIe L1 for Titan Ridge\n"); + if (tb_switch_xhci_connect(sw)) + tb_sw_warn(sw, "failed to connect xHCI\n"); + list_add_tail(&tunnel->list, &tcm->tunnel_list); return 0; } @@ -1256,12 +1261,18 @@ static void tb_handle_hotplug(struct work_struct *work) tb_port_unconfigure_xdomain(port); } else if (tb_port_is_dpout(port) || tb_port_is_dpin(port)) { tb_dp_resource_unavailable(tb, port); + } else if (!port->port) { + tb_sw_dbg(sw, "xHCI disconnect request\n"); + tb_switch_xhci_disconnect(sw); } else { tb_port_dbg(port, "got unplug event for disconnected port, ignoring\n"); } } else if (port->remote) { tb_port_dbg(port, "got plug event for connected port, ignoring\n"); + } else if (!port->port && sw->authorized) { + tb_sw_dbg(sw, "xHCI connect request\n"); + tb_switch_xhci_connect(sw); } else { if (tb_port_is_null(port)) { tb_port_dbg(port, "hotplug: scanning\n"); diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index 44e36498b261..b6fcd8d45324 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -988,6 +988,9 @@ int tb_switch_mask_clx_objections(struct tb_switch *sw); int tb_switch_pcie_l1_enable(struct tb_switch *sw); +int tb_switch_xhci_connect(struct tb_switch *sw); +void tb_switch_xhci_disconnect(struct tb_switch *sw); + int tb_wait_for_port(struct tb_port *port, bool wait_if_unplugged); int tb_port_add_nfc_credits(struct tb_port *port, int credits); int tb_port_clear_counter(struct tb_port *port, int counter); @@ -1082,6 +1085,10 @@ int tb_lc_configure_xdomain(struct tb_port *port); void tb_lc_unconfigure_xdomain(struct tb_port *port); int tb_lc_start_lane_initialization(struct tb_port *port); bool tb_lc_is_clx_supported(struct tb_port *port); +bool tb_lc_is_usb_plugged(struct tb_port *port); +bool tb_lc_is_xhci_connected(struct tb_port *port); +int tb_lc_xhci_connect(struct tb_port *port); +void tb_lc_xhci_disconnect(struct tb_port *port); int tb_lc_set_wake(struct tb_switch *sw, unsigned int flags); int tb_lc_set_sleep(struct tb_switch *sw); bool tb_lc_lane_bonding_possible(struct tb_switch *sw); diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h index 9693a6ec5950..70795a2aa9bb 100644 --- a/drivers/thunderbolt/tb_regs.h +++ b/drivers/thunderbolt/tb_regs.h @@ -463,6 +463,8 @@ struct tb_regs_hop { #define TMU_ADP_CS_6_DISABLE_TMU_OBJ_CL2 BIT(3) /* Plug Events registers */ +#define TB_PLUG_EVENTS_USB_DISABLE BIT(2) + #define TB_PLUG_EVENTS_PCIE_WR_DATA 0x1b #define TB_PLUG_EVENTS_PCIE_CMD 0x1c #define TB_PLUG_EVENTS_PCIE_CMD_DW_OFFSET_MASK GENMASK(9, 0) @@ -502,6 +504,9 @@ struct tb_regs_hop { #define TB_LC_POWER 0x740 /* Link controller registers */ +#define TB_LC_CS_42 0x2a +#define TB_LC_CS_42_USB_PLUGGED BIT(31) + #define TB_LC_PORT_ATTR 0x8d #define TB_LC_PORT_ATTR_BE BIT(12) @@ -522,4 +527,7 @@ struct tb_regs_hop { #define TB_LC_LINK_ATTR 0x97 #define TB_LC_LINK_ATTR_CPS BIT(18) +#define TB_LC_LINK_REQ 0xad +#define TB_LC_LINK_REQ_XHCI_CONNECT BIT(31) + #endif -- cgit From 7f7b571becf3731dfa9aa50bed420e0c988e511d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 1 Feb 2022 20:12:30 +0100 Subject: thunderbolt: Replace acpi_bus_get_device() Replace acpi_bus_get_device() that is going to be dropped with acpi_fetch_acpi_dev(). No intentional functional impact. Signed-off-by: Rafael J. Wysocki Signed-off-by: Mika Westerberg --- drivers/thunderbolt/acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/thunderbolt/acpi.c b/drivers/thunderbolt/acpi.c index 79b5abf9d042..c89daac0ad8c 100644 --- a/drivers/thunderbolt/acpi.c +++ b/drivers/thunderbolt/acpi.c @@ -14,15 +14,15 @@ static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data, void **return_value) { + struct acpi_device *adev = acpi_fetch_acpi_dev(handle); struct fwnode_reference_args args; struct fwnode_handle *fwnode; struct tb_nhi *nhi = data; - struct acpi_device *adev; struct pci_dev *pdev; struct device *dev; int ret; - if (acpi_bus_get_device(handle, &adev)) + if (!adev) return AE_OK; fwnode = acpi_fwnode_handle(adev); -- cgit From e87491a9fd4e33eaf18ef69d8295bb07b31452b2 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 3 Mar 2022 07:13:24 -0600 Subject: thunderbolt: Retry DROM reads for more failure scenarios Currently DROM reads are only retried in the case that parsing failed. However if the size or CRC fails, then there should also be a retry. This helps with reading the DROM on TBT3 devices connected to AMD Yellow Carp which will sometimes fail on the first attempt. Signed-off-by: Mario Limonciello Signed-off-by: Mika Westerberg --- drivers/thunderbolt/eeprom.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c index 470885e6f1c8..10cdbcb55df9 100644 --- a/drivers/thunderbolt/eeprom.c +++ b/drivers/thunderbolt/eeprom.c @@ -553,9 +553,9 @@ static int tb_drom_parse(struct tb_switch *sw) crc = tb_crc8((u8 *) &header->uid, 8); if (crc != header->uid_crc8) { tb_sw_warn(sw, - "DROM UID CRC8 mismatch (expected: %#x, got: %#x), aborting\n", + "DROM UID CRC8 mismatch (expected: %#x, got: %#x)\n", header->uid_crc8, crc); - return -EINVAL; + return -EILSEQ; } if (!sw->uid) sw->uid = header->uid; @@ -654,6 +654,7 @@ int tb_drom_read(struct tb_switch *sw) sw->drom = kzalloc(size, GFP_KERNEL); if (!sw->drom) return -ENOMEM; +read: res = tb_drom_read_n(sw, 0, sw->drom, size); if (res) goto err; @@ -662,7 +663,11 @@ parse: header = (void *) sw->drom; if (header->data_len + TB_DROM_DATA_START != size) { - tb_sw_warn(sw, "drom size mismatch, aborting\n"); + tb_sw_warn(sw, "drom size mismatch\n"); + if (retries--) { + msleep(100); + goto read; + } goto err; } @@ -683,11 +688,9 @@ parse: /* If the DROM parsing fails, wait a moment and retry once */ if (res == -EILSEQ && retries--) { - tb_sw_warn(sw, "parsing DROM failed, retrying\n"); + tb_sw_warn(sw, "parsing DROM failed\n"); msleep(100); - res = tb_drom_read_n(sw, 0, sw->drom, size); - if (!res) - goto parse; + goto read; } if (!res) -- cgit From a283de3ec646f19b09f3c8e4c8f57c0e017c9b2b Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 3 Mar 2022 07:13:25 -0600 Subject: thunderbolt: Do not resume routers if UID is not set Routers might not have a UID set if the DROM read failed during initialization previously. Normally upon resume the UID is re-read to confirm it's the same device connected. * If the DROM read failed during init but then succeeded during resume it could either be a new device or faulty device * If the DROM read failed during init and also failed during resume it might be a different device plugged in all together. Detect this situation and prevent re-using the same configuration in these cirucmstances. Signed-off-by: Mario Limonciello Signed-off-by: Mika Westerberg --- drivers/thunderbolt/switch.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index b5fb3e76ed09..294518af4ee4 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -2980,6 +2980,10 @@ int tb_switch_resume(struct tb_switch *sw) return err; } + /* We don't have any way to confirm this was the same device */ + if (!sw->uid) + return -ENODEV; + if (tb_switch_is_usb4(sw)) err = usb4_switch_read_uid(sw, &uid); else -- cgit From 6915812bbd109787ebdb865561dc9164d4b01f56 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 3 Mar 2022 07:13:26 -0600 Subject: thunderbolt: Do not make DROM read success compulsory The USB4 specification doesn't make any requirements that reading a device router's DROM is needed for the operation of the device. Other connection manager solutions don't necessarily read it or gate the usability of the device on whether it was read. So make failures when reading the DROM show warnings but not fail the initialization of the router. Signed-off-by: Mario Limonciello Signed-off-by: Mika Westerberg --- drivers/thunderbolt/switch.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 294518af4ee4..ac87e8b50e52 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -2784,10 +2784,8 @@ int tb_switch_add(struct tb_switch *sw) /* read drom */ ret = tb_drom_read(sw); - if (ret) { - dev_err(&sw->dev, "reading DROM failed\n"); - return ret; - } + if (ret) + dev_warn(&sw->dev, "reading DROM failed: %d\n", ret); tb_sw_dbg(sw, "uid: %#llx\n", sw->uid); tb_check_quirks(sw); -- cgit From 51d4d64c7ce50a501db4688b36448819755ae74d Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 3 Mar 2022 07:13:27 -0600 Subject: thunderbolt: Clarify register definitions for `tb_cap_plug_events` The USB4 1.0 specification outlines the `cap_plug_events` structure as `VSC_CS_1`. This shows that 4 bits of `VSC_CS_1` are TBT3 compatible in USB4, but TBT3 controllers also support disabling XHCI. Update the names and comments to more closely match the specification. This should not change anything functionally. Signed-off-by: Mario Limonciello Signed-off-by: Mika Westerberg --- drivers/thunderbolt/tb_regs.h | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h index 70795a2aa9bb..db3005cba203 100644 --- a/drivers/thunderbolt/tb_regs.h +++ b/drivers/thunderbolt/tb_regs.h @@ -146,14 +146,14 @@ struct tb_eeprom_ctl { struct tb_cap_plug_events { struct tb_cap_extended_short cap_header; - u32 __unknown1:2; - u32 plug_events:5; - u32 __unknown2:25; - u32 __unknown3; - u32 __unknown4; + u32 __unknown1:2; /* VSC_CS_1 */ + u32 plug_events:5; /* VSC_CS_1 */ + u32 __unknown2:25; /* VSC_CS_1 */ + u32 vsc_cs_2; + u32 vsc_cs_3; struct tb_eeprom_ctl eeprom_ctl; - u32 __unknown5[7]; - u32 drom_offset; /* 32 bit register, but eeprom addresses are 16 bit */ + u32 __unknown5[7]; /* VSC_CS_5 -> VSC_CS_11 */ + u32 drom_offset; /* VSC_CS_12: 32 bit register, but eeprom addresses are 16 bit */ } __packed; /* device headers */ @@ -464,6 +464,10 @@ struct tb_regs_hop { /* Plug Events registers */ #define TB_PLUG_EVENTS_USB_DISABLE BIT(2) +#define TB_PLUG_EVENTS_CS_1_LANE_DISABLE BIT(3) +#define TB_PLUG_EVENTS_CS_1_DPOUT_DISABLE BIT(4) +#define TB_PLUG_EVENTS_CS_1_LOW_DPIN_DISABLE BIT(5) +#define TB_PLUG_EVENTS_CS_1_HIGH_DPIN_DISABLE BIT(6) #define TB_PLUG_EVENTS_PCIE_WR_DATA 0x1b #define TB_PLUG_EVENTS_PCIE_CMD 0x1c -- cgit From 144c4a77a3e1e520daba85eafd28999af22e1aa5 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 3 Mar 2022 07:13:28 -0600 Subject: thunderbolt: Rename EEPROM handling bits to match USB4 spec The structure `tb_eeprom_ctl` is used to show the bits accessed when reading/writing EEPROM. As this structure is specified in the USB4 spec as `VSC_CS_4` update the names and use of members to match the specification. This should not change anything functionally. Signed-off-by: Mario Limonciello Signed-off-by: Mika Westerberg --- drivers/thunderbolt/eeprom.c | 24 ++++++++++++------------ drivers/thunderbolt/tb_regs.h | 10 +++++----- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c index 10cdbcb55df9..c90d22f56d4e 100644 --- a/drivers/thunderbolt/eeprom.c +++ b/drivers/thunderbolt/eeprom.c @@ -17,7 +17,7 @@ */ static int tb_eeprom_ctl_write(struct tb_switch *sw, struct tb_eeprom_ctl *ctl) { - return tb_sw_write(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + 4, 1); + return tb_sw_write(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + ROUTER_CS_4, 1); } /* @@ -25,7 +25,7 @@ static int tb_eeprom_ctl_write(struct tb_switch *sw, struct tb_eeprom_ctl *ctl) */ static int tb_eeprom_ctl_read(struct tb_switch *sw, struct tb_eeprom_ctl *ctl) { - return tb_sw_read(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + 4, 1); + return tb_sw_read(sw, ctl, TB_CFG_SWITCH, sw->cap_plug_events + ROUTER_CS_4, 1); } enum tb_eeprom_transfer { @@ -46,18 +46,18 @@ static int tb_eeprom_active(struct tb_switch *sw, bool enable) if (res) return res; if (enable) { - ctl.access_high = 1; + ctl.bit_banging_enable = 1; res = tb_eeprom_ctl_write(sw, &ctl); if (res) return res; - ctl.access_low = 0; + ctl.fl_cs = 0; return tb_eeprom_ctl_write(sw, &ctl); } else { - ctl.access_low = 1; + ctl.fl_cs = 1; res = tb_eeprom_ctl_write(sw, &ctl); if (res) return res; - ctl.access_high = 0; + ctl.bit_banging_enable = 0; return tb_eeprom_ctl_write(sw, &ctl); } } @@ -65,8 +65,8 @@ static int tb_eeprom_active(struct tb_switch *sw, bool enable) /* * tb_eeprom_transfer - transfer one bit * - * If TB_EEPROM_IN is passed, then the bit can be retrieved from ctl->data_in. - * If TB_EEPROM_OUT is passed, then ctl->data_out will be written. + * If TB_EEPROM_IN is passed, then the bit can be retrieved from ctl->fl_do. + * If TB_EEPROM_OUT is passed, then ctl->fl_di will be written. */ static int tb_eeprom_transfer(struct tb_switch *sw, struct tb_eeprom_ctl *ctl, enum tb_eeprom_transfer direction) @@ -77,7 +77,7 @@ static int tb_eeprom_transfer(struct tb_switch *sw, struct tb_eeprom_ctl *ctl, if (res) return res; } - ctl->clock = 1; + ctl->fl_sk = 1; res = tb_eeprom_ctl_write(sw, ctl); if (res) return res; @@ -86,7 +86,7 @@ static int tb_eeprom_transfer(struct tb_switch *sw, struct tb_eeprom_ctl *ctl, if (res) return res; } - ctl->clock = 0; + ctl->fl_sk = 0; return tb_eeprom_ctl_write(sw, ctl); } @@ -101,7 +101,7 @@ static int tb_eeprom_out(struct tb_switch *sw, u8 val) if (res) return res; for (i = 0; i < 8; i++) { - ctl.data_out = val & 0x80; + ctl.fl_di = val & 0x80; res = tb_eeprom_transfer(sw, &ctl, TB_EEPROM_OUT); if (res) return res; @@ -126,7 +126,7 @@ static int tb_eeprom_in(struct tb_switch *sw, u8 *val) res = tb_eeprom_transfer(sw, &ctl, TB_EEPROM_IN); if (res) return res; - *val |= ctl.data_in; + *val |= ctl.fl_do; } return 0; } diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h index db3005cba203..b301eeb0c89b 100644 --- a/drivers/thunderbolt/tb_regs.h +++ b/drivers/thunderbolt/tb_regs.h @@ -133,11 +133,11 @@ struct tb_cap_phy { } __packed; struct tb_eeprom_ctl { - bool clock:1; /* send pulse to transfer one bit */ - bool access_low:1; /* set to 0 before access */ - bool data_out:1; /* to eeprom */ - bool data_in:1; /* from eeprom */ - bool access_high:1; /* set to 1 before access */ + bool fl_sk:1; /* send pulse to transfer one bit */ + bool fl_cs:1; /* set to 0 before access */ + bool fl_di:1; /* to eeprom */ + bool fl_do:1; /* from eeprom */ + bool bit_banging_enable:1; /* set to 1 before access */ bool not_present:1; /* should be 0 */ bool unknown1:1; bool present:1; /* should be 1 */ -- cgit