aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/fw/pciinit.c1
-rw-r--r--src/hw/pci.c64
-rw-r--r--src/hw/pci.h1
3 files changed, 54 insertions, 12 deletions
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index d5e87f00..d25931bb 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -480,6 +480,7 @@ static void mch_mmconfig_setup(u16 bdf)
pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, 0);
pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper);
pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower);
+ pci_enable_mmconfig(Q35_HOST_BRIDGE_PCIEXBAR_ADDR, "q35");
}
static void mch_mem_addr_setup(struct pci_device *dev, void *arg)
diff --git a/src/hw/pci.c b/src/hw/pci.c
index 7aca1e6b..d9dbf313 100644
--- a/src/hw/pci.c
+++ b/src/hw/pci.c
@@ -14,6 +14,13 @@
#define PORT_PCI_CMD 0x0cf8
#define PORT_PCI_DATA 0x0cfc
+static u32 mmconfig;
+
+static void *mmconfig_addr(u16 bdf, u32 addr)
+{
+ return (void*)(mmconfig + ((u32)bdf << 12) + addr);
+}
+
static u32 ioconfig_cmd(u16 bdf, u32 addr)
{
return 0x80000000 | (bdf << 8) | (addr & 0xfc);
@@ -21,38 +28,62 @@ static u32 ioconfig_cmd(u16 bdf, u32 addr)
void pci_config_writel(u16 bdf, u32 addr, u32 val)
{
- outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
- outl(val, PORT_PCI_DATA);
+ if (MODESEGMENT && mmconfig) {
+ writel(mmconfig_addr(bdf, addr), val);
+ } else {
+ outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
+ outl(val, PORT_PCI_DATA);
+ }
}
void pci_config_writew(u16 bdf, u32 addr, u16 val)
{
- outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
- outw(val, PORT_PCI_DATA + (addr & 2));
+ if (MODESEGMENT && mmconfig) {
+ writew(mmconfig_addr(bdf, addr), val);
+ } else {
+ outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
+ outw(val, PORT_PCI_DATA + (addr & 2));
+ }
}
void pci_config_writeb(u16 bdf, u32 addr, u8 val)
{
- outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
- outb(val, PORT_PCI_DATA + (addr & 3));
+ if (MODESEGMENT && mmconfig) {
+ writeb(mmconfig_addr(bdf, addr), val);
+ } else {
+ outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
+ outb(val, PORT_PCI_DATA + (addr & 3));
+ }
}
u32 pci_config_readl(u16 bdf, u32 addr)
{
- outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
- return inl(PORT_PCI_DATA);
+ if (MODESEGMENT && mmconfig) {
+ return readl(mmconfig_addr(bdf, addr));
+ } else {
+ outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
+ return inl(PORT_PCI_DATA);
+ }
}
u16 pci_config_readw(u16 bdf, u32 addr)
{
- outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
- return inw(PORT_PCI_DATA + (addr & 2));
+ if (MODESEGMENT && mmconfig) {
+ return readw(mmconfig_addr(bdf, addr));
+ } else {
+ outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
+ return inw(PORT_PCI_DATA + (addr & 2));
+ }
}
u8 pci_config_readb(u16 bdf, u32 addr)
{
- outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
- return inb(PORT_PCI_DATA + (addr & 3));
+ if (MODESEGMENT && mmconfig) {
+ return readb(mmconfig_addr(bdf, addr));
+ } else {
+ outl(ioconfig_cmd(bdf, addr), PORT_PCI_CMD);
+ return inb(PORT_PCI_DATA + (addr & 3));
+ }
}
void
@@ -63,6 +94,15 @@ pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
pci_config_writew(bdf, addr, val);
}
+void
+pci_enable_mmconfig(u64 addr, const char *name)
+{
+ if (addr >= 0x100000000ll)
+ return;
+ dprintf(1, "PCIe: using %s mmconfig at 0x%llx\n", name, addr);
+ mmconfig = addr;
+}
+
u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap)
{
int i;
diff --git a/src/hw/pci.h b/src/hw/pci.h
index 2e30e289..01c51f70 100644
--- a/src/hw/pci.h
+++ b/src/hw/pci.h
@@ -39,6 +39,7 @@ u32 pci_config_readl(u16 bdf, u32 addr);
u16 pci_config_readw(u16 bdf, u32 addr);
u8 pci_config_readb(u16 bdf, u32 addr);
void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
+void pci_enable_mmconfig(u64 addr, const char *name);
u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap);
int pci_next(int bdf, int bus);
int pci_probe_host(void);