nb/intel/sandybridge: Start PEG link training
Issue observed: The PCIe Root port shows up in GNU/Linux but no PCIe device is being detected. Test system: * Gigabyte GA-B75M-D3H (Intel Pentium CPU G2130) * Lenovo T530 (Intel Core i5-3320M CPU) Problem description: The PEG Root port link training on Ivy Bridge needs to be manually started. Problem solution: The bits are set in early_init to meet PCIe reset timeout of 100msec. The bits should be set in PCI device enable function, but this causes the PCI enumeration to not detect the card, as it's still booting. Adding a fixed delay of 100msec resolves this problem, but this would increase boot time. Read the PCI base revision mask to make sure it's any IvyBridge CPU. Don't run the code on MRC path as it has its own PEG initilization code. Tested with: * Nvidia NVS 5400M (PCIe2) * ATI Radeon HD4780 (PCIe2) * Nvidia GeForce 8600 GT (PCIe1) Untested: * PCIe3 devices Final test results: The PEG device shows up under GNU/Linux and can be used without issues. Change-Id: Id8cfc43e5c4630b0ac217d98bb857c3308e6015b Signed-off-by: Patrick Rudolph <siro@das-labor.org> Reviewed-on: https://review.coreboot.org/11917 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
parent
801471436e
commit
e4f9d5c70a
|
@ -148,6 +148,41 @@ static void sandybridge_setup_graphics(void)
|
||||||
MCHBAR32(0x5418) = reg32;
|
MCHBAR32(0x5418) = reg32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void start_peg_link_training(void)
|
||||||
|
{
|
||||||
|
u32 tmp;
|
||||||
|
u32 deven;
|
||||||
|
|
||||||
|
/* PEG on IvyBridge+ needs a special startup sequence.
|
||||||
|
* As the MRC has its own initialization code skip it. */
|
||||||
|
if (((pci_read_config16(PCI_DEV(0, 0, 0), PCI_DEVICE_ID) &
|
||||||
|
BASE_REV_MASK) != BASE_REV_IVB) ||
|
||||||
|
IS_ENABLED(CONFIG_HAVE_MRC))
|
||||||
|
return;
|
||||||
|
|
||||||
|
deven = pci_read_config32(PCI_DEV(0, 0, 0), DEVEN);
|
||||||
|
|
||||||
|
if (deven & DEVEN_PEG10) {
|
||||||
|
tmp = pci_read_config32(PCI_DEV(0, 1, 0), 0xC24) & ~(1 << 16);
|
||||||
|
pci_write_config32(PCI_DEV(0, 1, 0), 0xC24, tmp | (1 << 5));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deven & DEVEN_PEG11) {
|
||||||
|
tmp = pci_read_config32(PCI_DEV(0, 1, 1), 0xC24) & ~(1 << 16);
|
||||||
|
pci_write_config32(PCI_DEV(0, 1, 1), 0xC24, tmp | (1 << 5));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deven & DEVEN_PEG12) {
|
||||||
|
tmp = pci_read_config32(PCI_DEV(0, 1, 2), 0xC24) & ~(1 << 16);
|
||||||
|
pci_write_config32(PCI_DEV(0, 1, 2), 0xC24, tmp | (1 << 5));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deven & DEVEN_PEG60) {
|
||||||
|
tmp = pci_read_config32(PCI_DEV(0, 6, 0), 0xC24) & ~(1 << 16);
|
||||||
|
pci_write_config32(PCI_DEV(0, 6, 0), 0xC24, tmp | (1 << 5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sandybridge_early_initialization(int chipset_type)
|
void sandybridge_early_initialization(int chipset_type)
|
||||||
{
|
{
|
||||||
u32 capid0_a;
|
u32 capid0_a;
|
||||||
|
@ -177,6 +212,15 @@ void sandybridge_early_initialization(int chipset_type)
|
||||||
pci_write_config32(PCI_DEV(0, 0, 0), DEVEN, deven);
|
pci_write_config32(PCI_DEV(0, 0, 0), DEVEN, deven);
|
||||||
|
|
||||||
sandybridge_setup_graphics();
|
sandybridge_setup_graphics();
|
||||||
|
|
||||||
|
/* Write magic value to start PEG link training.
|
||||||
|
* This should be done in PCI device enumeration, but
|
||||||
|
* the PCIe specification requires to wait at least 100msec
|
||||||
|
* after reset for devices to come up.
|
||||||
|
* As we don't want to increase boot time, enable it early and
|
||||||
|
* assume the PEG is up as soon as PCI enumeration starts.
|
||||||
|
* TODO: use time stamps to ensure the timings are met */
|
||||||
|
start_peg_link_training();
|
||||||
}
|
}
|
||||||
|
|
||||||
void northbridge_romstage_finalize(int s3resume)
|
void northbridge_romstage_finalize(int s3resume)
|
||||||
|
|
Loading…
Reference in New Issue