diff --git a/src/northbridge/intel/haswell/haswell.h b/src/northbridge/intel/haswell/haswell.h index 4bcaaa7728..b160f83876 100644 --- a/src/northbridge/intel/haswell/haswell.h +++ b/src/northbridge/intel/haswell/haswell.h @@ -20,6 +20,14 @@ #include "registers/host_bridge.h" +/* Device 0:1.0 PCI configuration space (PCIe Graphics) */ + +#define PEG_DCAP2 0xc4 /* 32bit */ + +#define PEG_ESD 0x144 /* 32bit */ +#define PEG_LE1D 0x150 /* 32bit */ +#define PEG_LE1A 0x158 /* 64bit */ + /* Device 0:2.0 PCI configuration space (Graphics Device) */ #define MSAC 0x62 /* Multi Size Aperture Control */ @@ -59,6 +67,7 @@ #define EPBAR8(x) *((volatile u8 *)(DEFAULT_EPBAR + (x))) #define EPBAR16(x) *((volatile u16 *)(DEFAULT_EPBAR + (x))) #define EPBAR32(x) *((volatile u32 *)(DEFAULT_EPBAR + (x))) +#define EPBAR64(x) *((volatile u64 *)(DEFAULT_EPBAR + (x))) #include "registers/epbar.h" @@ -69,6 +78,7 @@ #define DMIBAR8(x) *((volatile u8 *)(DEFAULT_DMIBAR + (x))) #define DMIBAR16(x) *((volatile u16 *)(DEFAULT_DMIBAR + (x))) #define DMIBAR32(x) *((volatile u32 *)(DEFAULT_DMIBAR + (x))) +#define DMIBAR64(x) *((volatile u64 *)(DEFAULT_DMIBAR + (x))) #include "registers/dmibar.h" diff --git a/src/northbridge/intel/haswell/northbridge.c b/src/northbridge/intel/haswell/northbridge.c index 5619d95728..9cf564f474 100644 --- a/src/northbridge/intel/haswell/northbridge.c +++ b/src/northbridge/intel/haswell/northbridge.c @@ -498,12 +498,77 @@ static void northbridge_dmi_init(void) } } +static void northbridge_topology_init(void) +{ + const u32 eple_a[3] = { EPLE2A, EPLE3A, EPLE4A }; + const u32 eple_d[3] = { EPLE2D, EPLE3D, EPLE4D }; + + u32 reg32; + + /* Set the CID1 Egress Port 0 Root Topology */ + reg32 = EPBAR32(EPESD); + reg32 &= ~(0xff << 16); + reg32 |= 1 << 16; + EPBAR32(EPESD) = reg32; + + reg32 = EPBAR32(EPLE1D); + reg32 &= ~(0xff << 16); + reg32 |= 1 | (1 << 16); + EPBAR32(EPLE1D) = reg32; + EPBAR64(EPLE1A) = (uintptr_t)DEFAULT_DMIBAR; + + for (unsigned int i = 0; i <= 2; i++) { + const struct device *const dev = pcidev_on_root(1, i); + + if (!dev || !dev->enabled) + continue; + + EPBAR64(eple_a[i]) = (u64)PCI_DEV(0, 1, i); + + reg32 = EPBAR32(eple_d[i]); + reg32 &= ~(0xff << 16); + reg32 |= 1 | (1 << 16); + EPBAR32(eple_d[i]) = reg32; + + pci_update_config32(dev, PEG_ESD, ~(0xff << 16), (1 << 16)); + pci_write_config32(dev, PEG_LE1A, (uintptr_t)DEFAULT_EPBAR); + pci_write_config32(dev, PEG_LE1A + 4, 0); + pci_update_config32(dev, PEG_LE1D, ~(0xff << 16), (1 << 16) | 1); + + /* Read and write to lock register */ + pci_or_config32(dev, PEG_DCAP2, 0); + } + + /* Set the CID1 DMI Port Root Topology */ + reg32 = DMIBAR32(DMIESD); + reg32 &= ~(0xff << 16); + reg32 |= 1 << 16; + DMIBAR32(DMIESD) = reg32; + + reg32 = DMIBAR32(DMILE1D); + reg32 &= ~(0xffff << 16); + reg32 |= 1 | (2 << 16); + DMIBAR32(DMILE1D) = reg32; + DMIBAR64(DMILE1A) = (uintptr_t)DEFAULT_RCBA; + + DMIBAR64(DMILE2A) = (uintptr_t)DEFAULT_EPBAR; + reg32 = DMIBAR32(DMILE2D); + reg32 &= ~(0xff << 16); + reg32 |= 1 | (1 << 16); + DMIBAR32(DMILE2D) = reg32; + + /* Program RO and Write-Once Registers */ + DMIBAR32(DMIPVCCAP1) = DMIBAR32(DMIPVCCAP1); + DMIBAR32(DMILCAP) = DMIBAR32(DMILCAP); +} + static void northbridge_init(struct device *dev) { u8 bios_reset_cpl, pair; init_egress(); northbridge_dmi_init(); + northbridge_topology_init(); /* Enable Power Aware Interrupt Routing. */ pair = MCHBAR8(INTRDIRCTL); diff --git a/src/northbridge/intel/haswell/registers/epbar.h b/src/northbridge/intel/haswell/registers/epbar.h index 963ceaddf4..699a2ba578 100644 --- a/src/northbridge/intel/haswell/registers/epbar.h +++ b/src/northbridge/intel/haswell/registers/epbar.h @@ -20,5 +20,9 @@ #define EPLE1A 0x058 /* 64bit */ #define EPLE2D 0x060 /* 32bit */ #define EPLE2A 0x068 /* 64bit */ +#define EPLE3D 0x070 /* 32bit */ +#define EPLE3A 0x078 /* 64bit */ +#define EPLE4D 0x080 /* 32bit */ +#define EPLE4A 0x088 /* 64bit */ #endif /* __HASWELL_REGISTERS_EPBAR_H__ */