1
1
/* SPDX-License-Identifier: GPL-2.0-only */
2
2
3
- #include "chip.h"
4
3
#include <acpi/acpigen.h>
5
4
#include <console/console.h>
6
5
#include <delay.h>
9
8
#include <device/pciexp.h>
10
9
#include <device/pci_ids.h>
11
10
#include <timer.h>
11
+ #include "chip.h"
12
+ #include "dtbt.h"
13
+
12
14
13
- #define PCIE2TBT 0x54C
14
- #define PCIE2TBT_VALID BIT(0)
15
- #define PCIE2TBT_GO2SX 2
16
- #define PCIE2TBT_GO2SX_NO_WAKE 3
17
- #define PCIE2TBT_SX_EXIT_TBT_CONNECTED 4
18
- #define PCIE2TBT_OS_UP 6
19
- #define PCIE2TBT_SET_SECURITY_LEVEL 8
20
- #define PCIE2TBT_GET_SECURITY_LEVEL 9
21
- #define PCIE2TBT_BOOT_ON 24
22
- #define PCIE2TBT_USB_ON 25
23
- #define PCIE2TBT_GET_ENUMERATION_METHOD 26
24
- #define PCIE2TBT_SET_ENUMERATION_METHOD 27
25
- #define PCIE2TBT_POWER_CYCLE 28
26
- #define PCIE2TBT_SX_START 29
27
- #define PCIE2TBT_ACL_BOOT 30
28
- #define PCIE2TBT_CONNECT_TOPOLOGY 31
29
-
30
- #define TBT2PCIE 0x548
31
- #define TBT2PCIE_DONE BIT(0)
32
-
33
- // Default timeout for mailbox commands unless otherwise specified.
34
- #define TIMEOUT_MS 1000
35
- // Default timeout for controller to ack GO2SX/GO2SX_NO_WAKE mailbox command.
36
- #define GO2SX_TIMEOUT_MS 600
15
+ /*
16
+ * We only want to enable the first/primary bridge device,
17
+ * as sending mailbox commands to secondary ones will fail,
18
+ * and we only want to create a single ACPI device in the SSDT.
19
+ */
20
+ static bool enable_done = false;
21
+ static bool ssdt_done = false;
37
22
38
23
static void dtbt_cmd (struct device * dev , u32 command , u32 data , u32 timeout )
39
24
{
40
25
u32 reg = (data << 8 ) | (command << 1 ) | PCIE2TBT_VALID ;
41
26
u32 status ;
42
27
43
- printk (BIOS_DEBUG , "dTBT send command %08x\n" , command );
28
+ printk (BIOS_SPEW , "dTBT send command 0x%x\n" , command );
29
+ /* Send command */
44
30
pci_write_config32 (dev , PCIE2TBT , reg );
45
-
46
- if (!wait_ms (timeout , (status = pci_read_config32 (dev , TBT2PCIE )) & TBT2PCIE_DONE )) {
47
- printk (BIOS_ERR , "dTBT command %08x send timeout %08x\n" , command , status );
48
- }
49
-
31
+ /* Wait for done bit to be cleared */
32
+ if (!wait_ms (timeout , (status = pci_read_config32 (dev , TBT2PCIE )) & TBT2PCIE_DONE ))
33
+ printk (BIOS_ERR , "dTBT command 0x%x send timeout, status 0x%x\n" , command , status );
34
+ /* Clear valid bit */
50
35
pci_write_config32 (dev , PCIE2TBT , 0 );
51
- if (! wait_ms ( timeout , !( pci_read_config32 ( dev , TBT2PCIE ) & TBT2PCIE_DONE ))) {
52
- printk ( BIOS_ERR , "dTBT command %08x clear timeout\n" , command );
53
- }
36
+ /* Wait for done bit to be cleared */
37
+ if (! wait_ms ( timeout , ( status = pci_read_config32 ( dev , TBT2PCIE )) & TBT2PCIE_DONE ))
38
+ printk ( BIOS_ERR , "dTBT command 0x%x clear valid bit timeout, status 0x%x\n" , command , status );
54
39
}
55
40
56
41
static void dtbt_write_dsd (void )
@@ -86,6 +71,9 @@ static void dtbt_fill_ssdt(const struct device *dev)
86
71
const char * parent_scope ;
87
72
const char * dev_name = acpi_device_name (dev );
88
73
74
+ if (ssdt_done )
75
+ return ;
76
+
89
77
bus = dev -> upstream ;
90
78
if (!bus ) {
91
79
printk (BIOS_ERR , "dTBT bus invalid\n" );
@@ -113,7 +101,7 @@ static void dtbt_fill_ssdt(const struct device *dev)
113
101
acpigen_write_name_integer ("_ADR" , 0 );
114
102
dtbt_write_opregion (bus );
115
103
116
- /* Method */
104
+ /* PTS Method */
117
105
acpigen_write_method_serialized ("PTS" , 0 );
118
106
119
107
acpigen_write_debug_string ("dTBT prepare to sleep" );
@@ -129,26 +117,49 @@ static void dtbt_fill_ssdt(const struct device *dev)
129
117
acpigen_write_device_end ();
130
118
acpigen_write_scope_end ();
131
119
132
- printk (BIOS_DEBUG , "dTBT fill SSDT\n" );
133
- printk (BIOS_DEBUG , " Dev %s\n" , dev_path (dev ));
134
- //printk(BIOS_DEBUG, " Bus %s\n", bus_path(bus));
135
- printk (BIOS_DEBUG , " Parent %s\n" , dev_path (parent ));
136
- printk (BIOS_DEBUG , " Scope %s\n" , parent_scope );
137
- printk (BIOS_DEBUG , " Device %s\n" , dev_name );
138
-
139
120
// \.TBTS Method
140
121
acpigen_write_scope ("\\" );
141
122
acpigen_write_method ("TBTS" , 0 );
142
123
acpigen_emit_namestring (acpi_device_path_join (dev , "PTS" ));
143
124
acpigen_write_method_end ();
144
125
acpigen_write_scope_end ();
126
+
127
+ printk (BIOS_INFO , "%s.%s %s\n" , parent_scope , dev_name , dev_path (dev ));
128
+ ssdt_done = true;
145
129
}
146
130
147
131
static const char * dtbt_acpi_name (const struct device * dev )
148
132
{
149
133
return "DTBT" ;
150
134
}
151
135
136
+ static void dtbt_enable (struct device * dev )
137
+ {
138
+ if (!is_dev_enabled (dev ) || enable_done )
139
+ return ;
140
+
141
+ printk (BIOS_INFO , "dTBT controller found at %s\n" , dev_path (dev ));
142
+
143
+ // XXX: Recommendation is to set SL1 ("User Authorization")
144
+ printk (BIOS_DEBUG , "dTBT set security level SL0\n" );
145
+ /* Set security level */
146
+ dtbt_cmd (dev , PCIE2TBT_SET_SECURITY_LEVEL , SEC_LEVEL_NONE , MBOX_TIMEOUT_MS );
147
+
148
+ if (acpi_is_wakeup_s3 ()) {
149
+ printk (BIOS_DEBUG , "dTBT SX exit\n" );
150
+ dtbt_cmd (dev , PCIE2TBT_SX_EXIT_TBT_CONNECTED , 0 , MBOX_TIMEOUT_MS );
151
+ /* Read TBT2PCIE register, verify not invalid */
152
+ if (pci_read_config32 (dev , TBT2PCIE ) == 0xffffffff )
153
+ printk (BIOS_ERR , "dTBT S3 resume failure.\n" );
154
+ } else {
155
+ printk (BIOS_DEBUG , "dTBT set boot on\n" );
156
+ dtbt_cmd (dev , PCIE2TBT_BOOT_ON , 0 , MBOX_TIMEOUT_MS );
157
+ printk (BIOS_DEBUG , "dTBT set USB on\n" );
158
+ dtbt_cmd (dev , PCIE2TBT_USB_ON , 0 , MBOX_TIMEOUT_MS );
159
+ }
160
+ enable_done = true;
161
+ }
162
+
152
163
static struct pci_operations dtbt_device_ops_pci = {
153
164
.set_subsystem = 0 ,
154
165
};
@@ -162,38 +173,30 @@ static struct device_operations dtbt_device_ops = {
162
173
.scan_bus = pciexp_scan_bridge ,
163
174
.reset_bus = pci_bus_reset ,
164
175
.ops_pci = & dtbt_device_ops_pci ,
176
+ .enable = dtbt_enable
165
177
};
166
178
167
- static void dtbt_enable (struct device * dev )
168
- {
169
- if (!is_dev_enabled (dev ) || dev -> path .type != DEVICE_PATH_PCI )
170
- return ;
171
-
172
- if (pci_read_config16 (dev , PCI_VENDOR_ID ) != PCI_VID_INTEL )
173
- return ;
174
-
175
- // TODO: check device ID
176
-
177
- dev -> ops = & dtbt_device_ops ;
178
-
179
- printk (BIOS_INFO , "dTBT controller found at %s\n" , dev_path (dev ));
180
-
181
- // XXX: Recommendation is to set SL1 ("User Authorization")
182
- printk (BIOS_DEBUG , "dTBT set security level SL0\n" );
183
- dtbt_cmd (dev , PCIE2TBT_SET_SECURITY_LEVEL , 0 , TIMEOUT_MS );
184
- // XXX: Must verify change or rollback all controllers
179
+ /* We only want to match the (first) bridge device */
180
+ static const unsigned short pci_device_ids [] = {
181
+ AR_2C_BRG ,
182
+ AR_4C_BRG ,
183
+ AR_LP_BRG ,
184
+ AR_4C_C0_BRG ,
185
+ AR_2C_C0_BRG ,
186
+ TR_2C_BRG ,
187
+ TR_4C_BRG ,
188
+ TR_4C_BRG ,
189
+ MR_2C_BRG ,
190
+ MR_4C_BRG ,
191
+ 0
192
+ };
185
193
186
- if (acpi_is_wakeup_s3 ()) {
187
- printk (BIOS_DEBUG , "dTBT SX exit\n" );
188
- dtbt_cmd (dev , PCIE2TBT_SX_EXIT_TBT_CONNECTED , 0 , TIMEOUT_MS );
189
- // TODO: "wait for fast link bring-up" loop (timeout: 5s)
190
- } else {
191
- printk (BIOS_DEBUG , "dTBT boot on\n" );
192
- dtbt_cmd (dev , PCIE2TBT_BOOT_ON , 0 , TIMEOUT_MS );
193
- }
194
- }
194
+ static const struct pci_driver intel_dtbt_driver __pci_driver = {
195
+ .ops = & dtbt_device_ops ,
196
+ .vendor = PCI_VID_INTEL ,
197
+ .devices = pci_device_ids ,
198
+ };
195
199
196
200
struct chip_operations drivers_intel_dtbt_ops = {
197
201
.name = "Intel Discrete Thunderbolt" ,
198
- .enable_dev = dtbt_enable ,
199
202
};
0 commit comments