1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <amdblocks/xhci.h>
4 #include <console/console.h>
5 #include <cpu/x86/smm.h>
6 #include <device/pci_def.h>
7 #include <device/pci_ids.h>
8 #include <device/pci_ops.h>
9 #include <device/pci_type.h>
10 #include <device/xhci.h>
15 #define PORTSC_OFFSET 0x400
16 #define PORTSC_STRIDE 0x10
17 #define XHCI_PROG_ID 0x30
19 static void xhci_port_wake_check(uintptr_t base
, uint8_t controller
, uint8_t num
, uint8_t event
)
21 for (uint8_t i
= 0; i
< num
; i
++) {
22 uint32_t portsc
= read32p(base
+ i
* PORTSC_STRIDE
);
24 /* Encode the controller number and port number. */
25 uint32_t payload
= controller
<< 8 | i
;
27 /* Ensure that we've read a valid value. */
28 if (portsc
== 0xffffffff)
31 /* Check for connect/disconnect wake. */
32 if (xhci_portsc_csc(portsc
) && xhci_portsc_wake_capable(portsc
)) {
33 elog_add_event_wake(event
, payload
);
37 if (xhci_portsc_plc(portsc
) && xhci_portsc_resume(portsc
))
38 elog_add_event_wake(event
, payload
);
47 static void xhci_cap_callback(void *data
, const struct xhci_supported_protocol
*protocol
)
49 const struct xhci_context
*context
= (const struct xhci_context
*)data
;
50 uint8_t count
= protocol
->port_count
;
51 const struct xhci_capability_regs
*cap_regs
=
52 (const struct xhci_capability_regs
*)context
->bar
;
53 uint8_t controller
= context
->controller
;
54 /* PORTSC registers start at operational base + 0x400 + 0x10 * (n - 1). */
55 uintptr_t op_base
= context
->bar
+ cap_regs
->caplength
;
56 uintptr_t addr
= op_base
+ PORTSC_OFFSET
+ PORTSC_STRIDE
* (protocol
->port_offset
- 1);
58 switch (protocol
->major_rev
) {
60 xhci_port_wake_check(addr
, controller
, count
, ELOG_WAKE_SOURCE_PME_XHCI_USB_2
);
64 xhci_port_wake_check(addr
, controller
, count
, ELOG_WAKE_SOURCE_PME_XHCI_USB_3
);
68 printk(BIOS_WARNING
, "Skipping logging XHCI events for controller %u, unsupported protocol",
74 void soc_xhci_log_wake_events(void)
76 const volatile struct smm_pci_resource_info
*res_store
;
80 smm_pci_get_stored_resources(&res_store
, &res_count
);
81 for (size_t i_slot
= 0; i_slot
< res_count
; i_slot
++) {
82 /* Skip any non-XHCI controller devices. */
83 if (res_store
[i_slot
].class_device
!= PCI_CLASS_SERIAL_USB
||
84 res_store
[i_slot
].class_prog
!= XHCI_PROG_ID
) {
88 /* Validate our BAR. */
89 uintptr_t stored_bar
= res_store
[i_slot
].resources
[0].base
;
90 uintptr_t bar
= pci_s_read_config32(res_store
[i_slot
].pci_addr
,
92 bar
&= ~PCI_BASE_ADDRESS_MEM_ATTR_MASK
;
94 if (!stored_bar
|| !bar
|| bar
!= stored_bar
) {
95 printk(BIOS_WARNING
, "Skipping logging XHCI events for controller %u, resource error, stored %" PRIxPTR
", found %" PRIxPTR
"\n",
96 i_xhci
, stored_bar
, bar
);
101 struct xhci_context context
= {
103 .controller
= i_xhci
,
106 const struct resource
*res
= (const struct resource
*)(&res_store
[i_slot
].resources
[0]);
108 = xhci_resource_for_each_supported_usb_cap(res
, &context
,
111 printk(BIOS_ERR
, "Failed to iterate over capabilities for XHCI controller %u (%d)\n",