Arthur Heymans (arthur@aheymans.xyz) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17659
-gerrit
commit 0e25c1064809021d57db41fdfccdc659d3f9f879 Author: Arthur Heymans arthur@aheymans.xyz Date: Wed Nov 30 18:40:38 2016 +0100
nb/intel/x4x: Fix raminit unconditionally resetting
The raminit only succeeds when it starts from a cold boot. To achieve this it unconditionally did a cold reset. Now it detects whether it underwent a hot reset (bit 8 of MCHBAR32(0xf14)) before issuing a cold reset to make raminit work.
It also adds a 2s delay before reset because some disk drives expect a warm reboot when the OS wants to reboot and therefore are not shut down properly / in time. If the drive is unexpectedly powered off which happens during a cold reset, it can cause data loss. Giving the drive 2 extra seconds can work around this issue. A proper fix would be to fix the raminit such that it works on a hot reset.
Change-Id: I6063dd6aed908558155d2523f35d7241ff1f4fde Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- src/northbridge/intel/x4x/raminit_ddr2.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c index b3ee34a..de62517 100644 --- a/src/northbridge/intel/x4x/raminit_ddr2.c +++ b/src/northbridge/intel/x4x/raminit_ddr2.c @@ -258,10 +258,20 @@ static void checkreset_ddr2(struct sysinfo *s) { u8 pmcon2; u8 reset = 0; + u32 pmir;
+ pmir = pci_read_config32(PCI_DEV(0, 0x1f, 0), 0xac); pmcon2 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2); - if (!(pmcon2 & 0x80)) { - pmcon2 |= 0x80; + + if ((MCHBAR32(0xf14) & (1 << 8))) { + printk(BIOS_DEBUG, + "Waiting two seconds for disks to timeout...\n"); + mdelay(2000); + reset = 1; + } + + if (pmcon2 & 0x80) { + pmcon2 &= ~0x80; pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2); reset = 1;
@@ -273,10 +283,16 @@ static void checkreset_ddr2(struct sysinfo *s) } if (reset) { printk(BIOS_DEBUG, "Reset...\n"); + /* Do a global reset. only useful on ICH10 */ + pmir |= (1 << 20); + pci_write_config32(PCI_DEV(0, 0x1f, 0), 0xac, pmir); outb(0xe, 0xcf9); asm ("hlt"); } - pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2 | 0x80); + pmir &= ~(1 << 20); + pmcon2 |= 0x80; + pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, pmcon2); + pci_write_config32(PCI_DEV(0, 0x1f, 0), 0xac, pmir); }
static void setioclk_ddr2(struct sysinfo *s)