diff options
| author | Michael Brown | 2022-08-08 17:39:40 +0200 |
|---|---|---|
| committer | Michael Brown | 2022-08-08 17:39:40 +0200 |
| commit | 0965cec53c9e421f900bb050b1c83196a0a5687b (patch) | |
| tree | 4fa44fd1259f17fb9e40e299b51aadba09980f07 /src/drivers/bus | |
| parent | [intelxl] Update list of PCI IDs (diff) | |
| download | ipxe-0965cec53c9e421f900bb050b1c83196a0a5687b.tar.gz ipxe-0965cec53c9e421f900bb050b1c83196a0a5687b.tar.xz ipxe-0965cec53c9e421f900bb050b1c83196a0a5687b.zip | |
[pci] Generalise function-level reset mechanism
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/bus')
| -rw-r--r-- | src/drivers/bus/pciextra.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/src/drivers/bus/pciextra.c b/src/drivers/bus/pciextra.c index 3082d8a3d..23617bc9a 100644 --- a/src/drivers/bus/pciextra.c +++ b/src/drivers/bus/pciextra.c @@ -1,6 +1,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <stdint.h> +#include <ipxe/timer.h> #include <ipxe/pci.h> static int pci_find_capability_common ( struct pci_device *pci, @@ -112,3 +113,24 @@ unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ) { size = size & ~( size - 1 ); return size; } + +/** + * Perform PCI Express function-level reset (FLR) + * + * @v pci PCI device + * @v exp PCI Express Capability address + */ +void pci_reset ( struct pci_device *pci, unsigned int exp ) { + uint16_t control; + + /* Perform a PCIe function-level reset */ + pci_read_config_word ( pci, ( exp + PCI_EXP_DEVCTL ), &control ); + control |= PCI_EXP_DEVCTL_FLR; + pci_write_config_word ( pci, ( exp + PCI_EXP_DEVCTL ), control ); + + /* Allow time for reset to complete */ + mdelay ( PCI_EXP_FLR_DELAY_MS ); + + /* Re-enable device */ + adjust_pci_device ( pci ); +} |
