1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <acpi/acpigen.h>
5 #include <acpi/acpigen_pci.h>
6 #include <console/console.h>
7 #include <device/pci.h>
8 #include <device/pci_ids.h>
9 #include <device/xhci.h>
12 #define PCI_XHCI_CLASSCODE 0x0c0330 /* USB3.0 xHCI controller */
14 static unsigned int controller_count
;
15 static const struct device_operations xhci_pci_ops
;
18 unsigned int high_speed
;
19 unsigned int super_speed
;
22 __weak
enum cb_err
pci_xhci_get_wake_gpe(const struct device
*dev
, int *gpe
)
28 static void xhci_count_ports(void *context
, const struct xhci_supported_protocol
*data
)
30 struct port_counts
*counts
= context
;
32 switch (data
->major_rev
) {
34 counts
->super_speed
+= data
->port_count
;
37 counts
->high_speed
+= data
->port_count
;
40 printk(BIOS_INFO
, "%s: Unknown USB Version: %#x\n", __func__
, data
->major_rev
);
45 static bool xhci_port_exists(const struct device
*dev
, const struct usb_path
*path
)
47 /* Cache the counts so we don't have to iterate on each invocation. */
49 const struct device
*dev
;
50 struct port_counts counts
;
53 if (cache
.dev
!= dev
) {
54 cache
.counts
.high_speed
= 0;
55 cache
.counts
.super_speed
= 0;
58 xhci_for_each_supported_usb_cap(dev
, &cache
.counts
, xhci_count_ports
);
61 /* port_ids are 0 based */
62 switch (path
->port_type
) {
64 return path
->port_id
< cache
.counts
.super_speed
;
66 return path
->port_id
< cache
.counts
.high_speed
;
68 printk(BIOS_INFO
, "%s: Unknown USB Version: %#x\n", __func__
, path
->port_type
);
73 static const struct device
*get_xhci_dev(const struct device
*dev
)
75 while (dev
&& dev
->ops
!= &xhci_pci_ops
) {
76 if (dev
->path
.type
== DEVICE_PATH_ROOT
)
85 static const char *xhci_acpi_name(const struct device
*dev
)
90 const struct device
*xhci_dev
;
92 /* Generate ACPI names for the usb_acpi driver */
93 if (dev
->path
.type
== DEVICE_PATH_USB
) {
94 /* Ports index start at 1 */
95 port_id
= dev
->path
.usb
.port_id
+ 1;
97 switch (dev
->path
.usb
.port_type
) {
107 printk(BIOS_INFO
, "%s: Unknown USB Version: %#x\n", __func__
,
108 dev
->path
.usb
.port_type
);
112 xhci_dev
= get_xhci_dev(dev
);
114 die("%s: xHCI controller not found for %s\n", __func__
, dev_path(dev
));
117 * We only want to return an ACPI name for a USB port if the controller
118 * physically has the port. This has the desired side effect of making the
119 * usb_acpi driver skip generating an ACPI node for a device which has
120 * no port. This prevents writing an invalid SSDT table which the OS then
123 if (!xhci_port_exists(xhci_dev
, &dev
->path
.usb
)) {
124 printk(BIOS_WARNING
, "%s: %s does not exist on xHC ", __func__
,
126 /* dev_path uses a static buffer :( */
127 printk(BIOS_WARNING
, "%s\n", dev_path(xhci_dev
));
132 name
= malloc(ACPI_NAME_BUFFER_SIZE
);
133 snprintf(name
, ACPI_NAME_BUFFER_SIZE
, pattern
, port_id
);
137 } else if (dev
->ops
== &xhci_pci_ops
) {
141 printk(BIOS_ERR
, "%s: Unknown device %s\n", __func__
, dev_path(dev
));
146 static void xhci_generate_port_acpi(void *context
, const struct xhci_supported_protocol
*data
)
150 struct port_counts
*counts
= context
;
151 unsigned int *dev_num
;
153 xhci_print_supported_protocol(data
);
155 if (data
->major_rev
== 3) {
157 dev_num
= &counts
->super_speed
;
158 } else if (data
->major_rev
== 2) {
160 dev_num
= &counts
->high_speed
;
162 printk(BIOS_INFO
, "%s: Unknown USB Version: %#x\n", __func__
, data
->major_rev
);
166 for (unsigned int i
= 0; i
< data
->port_count
; ++i
) {
167 snprintf(buf
, sizeof(buf
), format
, ++(*dev_num
));
168 acpigen_write_device(buf
);
169 acpigen_write_name_byte("_ADR", data
->port_offset
+ i
);
174 static void xhci_add_devices(const struct device
*dev
)
176 /* Used by the callback to track how many ports have been seen. */
177 struct port_counts counts
= {0, 0};
179 acpigen_write_device("RHUB");
180 acpigen_write_name_integer("_ADR", 0x00000000);
182 xhci_for_each_supported_usb_cap(dev
, &counts
, xhci_generate_port_acpi
);
187 static void xhci_fill_ssdt(const struct device
*dev
)
190 const char *scope
= acpi_device_scope(dev
);
191 const char *name
= acpi_device_name(dev
);
196 printk(BIOS_DEBUG
, "xHCI SSDT generation\n");
198 acpigen_write_scope(scope
);
199 acpigen_write_device(name
);
201 acpigen_write_ADR_pci_device(dev
);
202 acpigen_write_name_string("_DDN", "xHC - Extensible Host Controller");
203 acpigen_write_STA(acpi_device_status(dev
));
205 if (pci_xhci_get_wake_gpe(dev
, &gpe
) == CB_SUCCESS
) {
206 printk(BIOS_DEBUG
, "%s: Got GPE %d for %s\n", __func__
, gpe
, dev_path(dev
));
208 printk(BIOS_ERR
, "%s: Error getting GPE for : %s\n", __func__
, dev_path(dev
));
213 acpigen_write_PRW(gpe
, SLP_TYP_S3
);
214 acpigen_write_name_integer("_S0W", ACPI_DEVICE_SLEEP_D0
);
215 acpigen_write_name_integer("_S3W", ACPI_DEVICE_SLEEP_D3_COLD
);
216 acpigen_write_name_integer("_S4W", ACPI_DEVICE_SLEEP_D3_COLD
);
219 xhci_add_devices(dev
);
225 static void xhci_enable(struct device
*dev
)
228 uint32_t class = pci_read_config32(dev
, PCI_CLASS_REVISION
);
229 /* Class code, the upper 3 bytes of PCI_CLASS_REVISION. */
232 if (class != PCI_XHCI_CLASSCODE
) {
233 printk(BIOS_ERR
, "Incorrect xHCI class code: %#x\n", class);
238 name
= malloc(ACPI_NAME_BUFFER_SIZE
);
239 snprintf(name
, ACPI_NAME_BUFFER_SIZE
, "XHC%d", controller_count
++);
243 static const struct device_operations xhci_pci_ops
= {
244 .read_resources
= pci_dev_read_resources
,
245 .set_resources
= pci_dev_set_resources
,
246 .enable_resources
= pci_dev_enable_resources
,
247 .init
= pci_dev_init
,
248 .scan_bus
= scan_static_bus
,
249 .enable
= xhci_enable
,
250 .ops_pci
= &pci_dev_ops_pci
,
251 .acpi_fill_ssdt
= xhci_fill_ssdt
,
252 .acpi_name
= xhci_acpi_name
,
255 static const unsigned short amd_pci_device_ids
[] = {
256 PCI_DID_AMD_FAM17H_MODEL18H_XHCI0
,
257 PCI_DID_AMD_FAM17H_MODEL18H_XHCI1
,
258 PCI_DID_AMD_FAM17H_MODEL20H_XHCI0
,
259 PCI_DID_AMD_FAM17H_MODEL60H_XHCI
,
260 PCI_DID_AMD_FAM17H_MODELA0H_XHCI0
,
261 PCI_DID_AMD_FAM17H_MODELA0H_XHCI1
,
262 PCI_DID_AMD_FAM17H_MODELA0H_XHCI2
,
266 static const struct pci_driver xhci_pci_driver __pci_driver
= {
267 .ops
= &xhci_pci_ops
,
268 .vendor
= PCI_VID_AMD
,
269 .devices
= amd_pci_device_ids
,