Commit | Line | Data |
---|---|---|
1cb36293 ML |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * Thunderbolt driver - quirks | |
4 | * | |
5 | * Copyright (c) 2020 Mario Limonciello <mario.limonciello@dell.com> | |
6 | */ | |
7 | ||
8 | #include "tb.h" | |
9 | ||
10 | static void quirk_force_power_link(struct tb_switch *sw) | |
11 | { | |
12 | sw->quirks |= QUIRK_FORCE_POWER_LINK_CONTROLLER; | |
13 | } | |
14 | ||
7c37bb30 MW |
15 | static void quirk_dp_credit_allocation(struct tb_switch *sw) |
16 | { | |
17 | if (sw->credit_allocation && sw->min_dp_main_credits == 56) { | |
18 | sw->min_dp_main_credits = 18; | |
19 | tb_sw_dbg(sw, "quirked DP main: %u\n", sw->min_dp_main_credits); | |
20 | } | |
21 | } | |
22 | ||
7af9da8c SM |
23 | static void quirk_clx_disable(struct tb_switch *sw) |
24 | { | |
25 | sw->quirks |= QUIRK_NO_CLX; | |
26 | tb_sw_dbg(sw, "disabling CL states\n"); | |
27 | } | |
28 | ||
f0a57dd3 GF |
29 | static void quirk_usb3_maximum_bandwidth(struct tb_switch *sw) |
30 | { | |
31 | struct tb_port *port; | |
32 | ||
33 | tb_switch_for_each_port(sw, port) { | |
34 | if (!tb_port_is_usb3_down(port)) | |
35 | continue; | |
36 | port->max_bw = 16376; | |
37 | tb_port_dbg(port, "USB3 maximum bandwidth limited to %u Mb/s\n", | |
38 | port->max_bw); | |
39 | } | |
40 | } | |
41 | ||
1cb36293 | 42 | struct tb_quirk { |
7c37bb30 MW |
43 | u16 hw_vendor_id; |
44 | u16 hw_device_id; | |
1cb36293 ML |
45 | u16 vendor; |
46 | u16 device; | |
47 | void (*hook)(struct tb_switch *sw); | |
48 | }; | |
49 | ||
ef7e1207 | 50 | static const struct tb_quirk tb_quirks[] = { |
1cb36293 | 51 | /* Dell WD19TB supports self-authentication on unplug */ |
7c37bb30 MW |
52 | { 0x0000, 0x0000, 0x00d4, 0xb070, quirk_force_power_link }, |
53 | { 0x0000, 0x0000, 0x00d4, 0xb071, quirk_force_power_link }, | |
54 | /* | |
55 | * Intel Goshen Ridge NVM 27 and before report wrong number of | |
56 | * DP buffers. | |
57 | */ | |
58 | { 0x8087, 0x0b26, 0x0000, 0x0000, quirk_dp_credit_allocation }, | |
f0a57dd3 GF |
59 | /* |
60 | * Limit the maximum USB3 bandwidth for the following Intel USB4 | |
61 | * host routers due to a hardware issue. | |
62 | */ | |
63 | { 0x8087, PCI_DEVICE_ID_INTEL_ADL_NHI0, 0x0000, 0x0000, | |
64 | quirk_usb3_maximum_bandwidth }, | |
65 | { 0x8087, PCI_DEVICE_ID_INTEL_ADL_NHI1, 0x0000, 0x0000, | |
66 | quirk_usb3_maximum_bandwidth }, | |
67 | { 0x8087, PCI_DEVICE_ID_INTEL_RPL_NHI0, 0x0000, 0x0000, | |
68 | quirk_usb3_maximum_bandwidth }, | |
69 | { 0x8087, PCI_DEVICE_ID_INTEL_RPL_NHI1, 0x0000, 0x0000, | |
70 | quirk_usb3_maximum_bandwidth }, | |
71 | { 0x8087, PCI_DEVICE_ID_INTEL_MTL_M_NHI0, 0x0000, 0x0000, | |
72 | quirk_usb3_maximum_bandwidth }, | |
73 | { 0x8087, PCI_DEVICE_ID_INTEL_MTL_P_NHI0, 0x0000, 0x0000, | |
74 | quirk_usb3_maximum_bandwidth }, | |
75 | { 0x8087, PCI_DEVICE_ID_INTEL_MTL_P_NHI1, 0x0000, 0x0000, | |
76 | quirk_usb3_maximum_bandwidth }, | |
7af9da8c SM |
77 | /* |
78 | * CLx is not supported on AMD USB4 Yellow Carp and Pink Sardine platforms. | |
79 | */ | |
80 | { 0x0438, 0x0208, 0x0000, 0x0000, quirk_clx_disable }, | |
81 | { 0x0438, 0x0209, 0x0000, 0x0000, quirk_clx_disable }, | |
82 | { 0x0438, 0x020a, 0x0000, 0x0000, quirk_clx_disable }, | |
83 | { 0x0438, 0x020b, 0x0000, 0x0000, quirk_clx_disable }, | |
1cb36293 ML |
84 | }; |
85 | ||
86 | /** | |
87 | * tb_check_quirks() - Check for quirks to apply | |
88 | * @sw: Thunderbolt switch | |
89 | * | |
9c8cac6a | 90 | * Apply any quirks for the Thunderbolt controller. |
1cb36293 ML |
91 | */ |
92 | void tb_check_quirks(struct tb_switch *sw) | |
93 | { | |
94 | int i; | |
95 | ||
96 | for (i = 0; i < ARRAY_SIZE(tb_quirks); i++) { | |
97 | const struct tb_quirk *q = &tb_quirks[i]; | |
98 | ||
7c37bb30 MW |
99 | if (q->hw_vendor_id && q->hw_vendor_id != sw->config.vendor_id) |
100 | continue; | |
101 | if (q->hw_device_id && q->hw_device_id != sw->config.device_id) | |
102 | continue; | |
103 | if (q->vendor && q->vendor != sw->vendor) | |
104 | continue; | |
105 | if (q->device && q->device != sw->device) | |
106 | continue; | |
107 | ||
108 | q->hook(sw); | |
1cb36293 ML |
109 | } |
110 | } |