Skip to content

Commit

Permalink
pci: move pcie_retraining_link in boot_x86_fsp
Browse files Browse the repository at this point in the history
the function relies a non-general delay() function, so move the function in a
more target-specific file.
  • Loading branch information
rizlik committed Apr 29, 2024
1 parent 53d012f commit ee4747e
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 79 deletions.
2 changes: 0 additions & 2 deletions include/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@
#define PCIE_LINK_CONTROL_OFF (0x10)
#define PCIE_LINK_STATUS_TRAINING (1 << 11)
#define PCIE_LINK_CONTROL_RETRAINING (1 << 5)
#define PCIE_TRAINING_TIMEOUT_MS (100)
typedef struct {
int bus;
int device;
Expand Down Expand Up @@ -124,7 +123,6 @@ uint32_t pci_enum_bus(uint8_t bus, struct pci_enum_info *info);

int pci_enum_do(void);
int pci_pre_enum(void);
int pcie_retraining_link(uint8_t bus, uint8_t dev, uint8_t fun);
void pci_dump_config_space(void);

#ifdef __cplusplus
Expand Down
70 changes: 70 additions & 0 deletions src/boot_x86_fsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ const uint8_t __attribute__((section(".sig_wolfboot_raw")))
#define ENDLINE "\r\n"

#define PCI_DEVICE_CONTROLLER_TO_PEX 0x6
#define PCIE_TRAINING_TIMEOUT_MS (100)

typedef uint32_t (*memory_init_cb)(void *udp, struct efi_hob **HobList);
typedef uint32_t (*temp_ram_exit_cb)(void *udp);
Expand Down Expand Up @@ -400,6 +401,75 @@ static void print_fsp_image_revision(struct fsp_info_header *h)
wolfBoot_printf("%x.%x.%x build %x\r\n", maj, min, rev, build);
}

static int pci_get_capability(uint8_t bus, uint8_t dev, uint8_t fun,
uint8_t cap_id, uint8_t *cap_off)
{
uint8_t r8, id;
uint32_t r32;

r32 = pci_config_read16(bus, dev, fun, PCI_STATUS_OFFSET);
if (!(r32 & PCI_STATUS_CAP_LIST))
return -1;
r8 = pci_config_read8(bus, dev, fun, PCI_CAP_OFFSET);
while (r8 != 0) {
id = pci_config_read8(bus, dev, fun, r8);
if (id == cap_id) {
*cap_off = r8;
return 0;
}
r8 = pci_config_read8(bus, dev, fun, r8 + 1);
}
return -1;
}

int pcie_retraining_link(uint8_t bus, uint8_t dev, uint8_t fun)
{
uint16_t link_status, link_control, vid;
uint8_t pcie_cap_off;
int ret, tries;

vid = pci_config_read16(bus, dev, 0, PCI_VENDOR_ID_OFFSET);
if (vid == 0xffff) {
return -1;
}

ret = pci_get_capability(bus, dev, fun, PCI_PCIE_CAP_ID, &pcie_cap_off);
if (ret != 0) {
return -1;
}

link_status = pci_config_read16(bus, dev, fun,
pcie_cap_off + PCIE_LINK_STATUS_OFF);
if (link_status & PCIE_LINK_STATUS_TRAINING) {
delay(PCIE_TRAINING_TIMEOUT_MS);
link_status = pci_config_read16(bus, dev, fun,
pcie_cap_off + PCIE_LINK_STATUS_OFF);
if (link_status & PCIE_LINK_STATUS_TRAINING) {
return -1;
}
}

link_control = pci_config_read16(bus, dev, fun,
pcie_cap_off + PCIE_LINK_CONTROL_OFF);
link_control |= PCIE_LINK_CONTROL_RETRAINING;
pci_config_write16(bus, dev, fun, pcie_cap_off + PCIE_LINK_CONTROL_OFF,
link_control);
tries = PCIE_TRAINING_TIMEOUT_MS / 10;
do {
link_status = pci_config_read16(bus, dev, fun,
pcie_cap_off + PCIE_LINK_STATUS_OFF);
if (!(link_status & PCIE_LINK_STATUS_TRAINING))
break;
delay(10);
} while(tries--);

if ((link_status & PCIE_LINK_STATUS_TRAINING)) {
return -1;
}

return 0;
}

/*!
* \brief Staging of FSP_S after verification
*
Expand Down
77 changes: 0 additions & 77 deletions src/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -775,83 +775,6 @@ uint32_t pci_enum_bus(uint8_t bus, struct pci_enum_info *info)
return 0;
}

static int pci_get_capability(uint8_t bus, uint8_t dev, uint8_t fun,
uint8_t cap_id, uint8_t *cap_off)
{
uint8_t r8, id;
uint32_t r32;

r32 = pci_config_read16(bus, dev, fun, PCI_STATUS_OFFSET);
if (!(r32 & PCI_STATUS_CAP_LIST))
return -1;
r8 = pci_config_read8(bus, dev, fun, PCI_CAP_OFFSET);
while (r8 != 0) {
id = pci_config_read8(bus, dev, fun, r8);
if (id == cap_id) {
*cap_off = r8;
return 0;
}
r8 = pci_config_read8(bus, dev, fun, r8 + 1);
}
return -1;
}

int pcie_retraining_link(uint8_t bus, uint8_t dev, uint8_t fun)
{
uint16_t link_status, link_control, vid;
uint8_t pcie_cap_off;
int ret, tries;

PCI_DEBUG_PRINTF("retraining link: %x:%x.%x\r\n", bus, dev, fun);
vid = pci_config_read16(bus, dev, 0, PCI_VENDOR_ID_OFFSET);
if (vid == 0xffff) {
PCI_DEBUG_PRINTF("can't find dev: %x:%x.%d\r\n", bus, dev, fun);
return -1;
}

ret = pci_get_capability(bus, dev, fun, PCI_PCIE_CAP_ID, &pcie_cap_off);
if (ret != 0) {
PCI_DEBUG_PRINTF("can't find PCIE cap pointer\r\n");
return -1;
}

PCI_DEBUG_PRINTF("pcie cap off: 0x%x\r\n", pcie_cap_off);
link_status = pci_config_read16(bus, dev, fun,
pcie_cap_off + PCIE_LINK_STATUS_OFF);
if (link_status & PCIE_LINK_STATUS_TRAINING) {
PCI_DEBUG_PRINTF("link already training, waiting...\r\n");
delay(PCIE_TRAINING_TIMEOUT_MS);
link_status = pci_config_read16(bus, dev, fun,
pcie_cap_off + PCIE_LINK_STATUS_OFF);
if (link_status & PCIE_LINK_STATUS_TRAINING) {
PCI_DEBUG_PRINTF("link training error: timeout\r\n");
return -1;
}
}

link_control = pci_config_read16(bus, dev, fun,
pcie_cap_off + PCIE_LINK_CONTROL_OFF);
link_control |= PCIE_LINK_CONTROL_RETRAINING;
pci_config_write16(bus, dev, fun, pcie_cap_off + PCIE_LINK_CONTROL_OFF,
link_control);
tries = PCIE_TRAINING_TIMEOUT_MS / 10;
do {
link_status = pci_config_read16(bus, dev, fun,
pcie_cap_off + PCIE_LINK_STATUS_OFF);
if (!(link_status & PCIE_LINK_STATUS_TRAINING))
break;
delay(10);
} while(tries--);

if ((link_status & PCIE_LINK_STATUS_TRAINING)) {
PCI_DEBUG_PRINTF("Timeout reached during retraining\r\n");
return -1;
}

PCI_DEBUG_PRINTF("retraining complete\r\n");
return 0;
}

int pci_pre_enum(void)
{
uint32_t reg;
Expand Down

0 comments on commit ee4747e

Please sign in to comment.