[coreboot] Patch set updated for coreboot: ff18431 S3 code in coreboot public folder.
Zheng Bao (zheng.bao@amd.com)
gerrit at coreboot.org
Wed Feb 15 03:32:36 CET 2012
Zheng Bao (zheng.bao at amd.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/623
-gerrit
commit ff18431547606654d8530d4c9bd0b0514a1125b8
Author: zbao <fishbaozi at gmail.com>
Date: Tue Feb 14 18:51:46 2012 +0800
S3 code in coreboot public folder.
1. Move the Stack to hig memory.
2. Restore the MTRR before cb jump to the wakeup vector.
Change-Id: I9872e02fcd7eed98e7f630aa29ece810ac32d55a
Signed-off-by: Zheng Bao <zheng.bao at amd.com>
Signed-off-by: zbao <fishbaozi at gmail.com>
---
src/arch/x86/Makefile.inc | 10 +
src/arch/x86/boot/acpi.c | 2 +
src/arch/x86/boot/tables.c | 3 +-
src/boot/hardwaremain.c | 5 +-
src/cpu/amd/agesa/Makefile.inc | 2 +
src/cpu/amd/agesa/cache_as_ram.inc | 7 +
src/cpu/amd/agesa/family14/Kconfig | 8 +
src/cpu/amd/agesa/family14/model_14_init.c | 165 ++++++-----
src/cpu/amd/agesa/s3_resume.c | 348 ++++++++++++++++++++++
src/cpu/amd/agesa/s3_resume.h | 42 +++
src/cpu/amd/car/post_cache_as_ram.c | 18 +-
src/devices/pci_device.c | 10 +
src/include/cbmem.h | 11 +-
src/include/string.h | 1 +
src/lib/cbmem.c | 2 +
src/lib/memcpy.c | 15 +
src/northbridge/amd/agesa/family14/northbridge.c | 104 +++++--
17 files changed, 622 insertions(+), 131 deletions(-)
diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc
index c9cbb01..31de1e3 100755
--- a/src/arch/x86/Makefile.inc
+++ b/src/arch/x86/Makefile.inc
@@ -107,6 +107,16 @@ ifeq ($(CONFIG_INCLUDE_CONFIG_FILE),y)
sed -e '/^#/d' -e '/^ *$$/d' $(DOTCONFIG) >> $(obj)/config.tmp ; \
$(CBFSTOOL) $@.tmp add $(obj)/config.tmp config raw; rm -f $(obj)/config.tmp ; fi
endif
+ifeq ($(CONFIG_HAVE_ACPI_RESUME),y)
+# This S3 storage area in flash is a bit tricky. The location is set and used
+# by the southbridge ROM access functions. This should probably be
+# connected with the #define somehow...
+ @printf " S3 NVRAM 0xffff0000 (S3 storage area)\n"
+ rm -f $(obj)/s3.rom
+ dd if=/dev/zero of=$(obj)/fill.rom bs=20k count=1 2> /dev/null
+ $(CBFSTOOL) $@.tmp add $(obj)/fill.rom "s3nv" raw 0xffff0000
+ rm -f $(obj)/s3.rom
+endif
mv $@.tmp $@
@printf " CBFSPRINT $(subst $(obj)/,,$(@))\n\n"
$(CBFSTOOL) $@ print
diff --git a/src/arch/x86/boot/acpi.c b/src/arch/x86/boot/acpi.c
index f1be034..077f47c 100644
--- a/src/arch/x86/boot/acpi.c
+++ b/src/arch/x86/boot/acpi.c
@@ -474,6 +474,8 @@ void suspend_resume(void)
wake_vec = acpi_find_wakeup_vector();
if (wake_vec)
acpi_jump_to_wakeup(wake_vec);
+ else
+ die("Error: No Wake Vector Found!\n Reset for normal boot path.");
}
/* This is to be filled by SB code - startup value what was found. */
diff --git a/src/arch/x86/boot/tables.c b/src/arch/x86/boot/tables.c
index 29d2ec0..ba5cdf3 100644
--- a/src/arch/x86/boot/tables.c
+++ b/src/arch/x86/boot/tables.c
@@ -230,13 +230,12 @@ struct lb_memory *write_tables(void)
}
post_code(0x9e);
-
#if CONFIG_HAVE_ACPI_RESUME
/* Let's prepare the ACPI S3 Resume area now already, so we can rely on
* it begin there during reboot time. We don't need the pointer, nor
* the result right now. If it fails, ACPI resume will be disabled.
*/
- cbmem_add(CBMEM_ID_RESUME, HIGH_MEMORY_SAVE);
+ cbmem_add(CBMEM_ID_RESUME, HIGH_MEMORY_SAVE + HIGH_SCRATCH_MEMORY_SIZE);
#endif
#if CONFIG_MULTIBOOT
diff --git a/src/boot/hardwaremain.c b/src/boot/hardwaremain.c
index 3d15b55..56a5f0c 100644
--- a/src/boot/hardwaremain.c
+++ b/src/boot/hardwaremain.c
@@ -35,7 +35,7 @@ it with the version available from LANL.
#include <boot/tables.h>
#include <boot/elf.h>
#include <cbfs.h>
-#if CONFIG_HAVE_ACPI_RESUME
+#if CONFIG_HAVE_ACPI_RESUME == 1
#include <arch/acpi.h>
#endif
#if CONFIG_WRITE_HIGH_TABLES
@@ -94,7 +94,8 @@ void hardwaremain(int boot_complete)
cbmem_initialize();
#endif
#if CONFIG_HAVE_ACPI_RESUME == 1
- suspend_resume();
+ if (acpi_slp_type == 3)
+ suspend_resume();
post_code(0x8a);
#endif
diff --git a/src/cpu/amd/agesa/Makefile.inc b/src/cpu/amd/agesa/Makefile.inc
index 4331435..cfe6a43 100644
--- a/src/cpu/amd/agesa/Makefile.inc
+++ b/src/cpu/amd/agesa/Makefile.inc
@@ -20,5 +20,7 @@ subdirs-$(CONFIG_CPU_AMD_AGESA_FAMILY10) += family10
subdirs-$(CONFIG_CPU_AMD_AGESA_FAMILY12) += family12
subdirs-$(CONFIG_CPU_AMD_AGESA_FAMILY14) += family14
+romstage-$(CONFIG_HAVE_ACPI_RESUME) += s3_resume.c
+ramstage-$(CONFIG_HAVE_ACPI_RESUME) += s3_resume.c
ramstage-y += apic_timer.c
cpu_incs += $(src)/cpu/amd/agesa/cache_as_ram.inc
diff --git a/src/cpu/amd/agesa/cache_as_ram.inc b/src/cpu/amd/agesa/cache_as_ram.inc
index f328db4..2124bf3 100755
--- a/src/cpu/amd/agesa/cache_as_ram.inc
+++ b/src/cpu/amd/agesa/cache_as_ram.inc
@@ -86,6 +86,13 @@ disable_cache_as_ram:
/* Save return stack */
movd %esp, %xmm0
+ /* Disable cache */
+ movl %cr0, %eax
+ orl $(1 << 30), %eax
+ movl %eax, %cr0
+
+ invd
+
AMD_DISABLE_STACK
/* Restore the return stack */
diff --git a/src/cpu/amd/agesa/family14/Kconfig b/src/cpu/amd/agesa/family14/Kconfig
index 702270c..d1140f3 100644
--- a/src/cpu/amd/agesa/family14/Kconfig
+++ b/src/cpu/amd/agesa/family14/Kconfig
@@ -67,3 +67,11 @@ config HAVE_INIT_TIMER
default y
depends on CPU_AMD_AGESA_FAMILY14
+config RESUME_SCRATCH_MEMORY_SIZE
+# This is derived from AGESA gccar.inc
+# BSP_STACK_SIZE + CORE0_STACK_SIZE * 8 + CORE1_STACK_SIZE * 64 + HEAP_SIZE
+# For 2 core Fam14: BSP_STACK_SIZE + CORE1_STACK_SIZE + HEAP_SIZE
+# 0x10000 + 0x1000 + 20000
+ hex
+ default 0x31000
+ depends on CPU_AMD_AGESA_FAMILY14
diff --git a/src/cpu/amd/agesa/family14/model_14_init.c b/src/cpu/amd/agesa/family14/model_14_init.c
index 6f697cf..d90695a 100644
--- a/src/cpu/amd/agesa/family14/model_14_init.c
+++ b/src/cpu/amd/agesa/family14/model_14_init.c
@@ -32,109 +32,126 @@
#include <cpu/x86/cache.h>
#include <cpu/x86/mtrr.h>
#include <cpu/amd/amdfam14.h>
+#include <arch/acpi.h>
+#include <cpu/amd/agesa/s3_resume.h>
#define MCI_STATUS 0x401
msr_t rdmsr_amd(u32 index)
{
- msr_t result;
- __asm__ __volatile__(
- "rdmsr"
- :"=a"(result.lo), "=d"(result.hi)
- :"c"(index), "D"(0x9c5a203a)
- );
- return result;
+ msr_t result;
+ __asm__ __volatile__(
+ "rdmsr"
+ :"=a"(result.lo), "=d"(result.hi)
+ :"c"(index), "D"(0x9c5a203a)
+ );
+ return result;
}
void wrmsr_amd(u32 index, msr_t msr)
{
- __asm__ __volatile__(
- "wrmsr"
- : /* No outputs */
- :"c"(index), "a"(msr.lo), "d"(msr.hi), "D"(0x9c5a203a)
- );
+ __asm__ __volatile__(
+ "wrmsr"
+ : /* No outputs */
+ :"c"(index), "a"(msr.lo), "d"(msr.hi), "D"(0x9c5a203a)
+ );
}
static void model_14_init(device_t dev)
{
- printk(BIOS_DEBUG, "Model 14 Init.\n");
-
- u8 i;
- msr_t msr;
- int msrno;
+ u32 i;
+ msr_t msr;
#if CONFIG_LOGICAL_CPUS == 1
- u32 siblings;
+ u32 siblings;
+#endif
+ printk(BIOS_DEBUG, "Model 14 Init.\n");
+
+ disable_cache ();
+ /*
+ * AGESA sets the MTRRs main MTRRs. The shadow area needs to be set
+ * by coreboot. The amd_setup_mtrrs should work, but needs debug on fam14.
+ * TODO:
+ * amd_setup_mtrrs();
+ */
+
+ /* Enable access to AMD RdDram and WrDram extension bits */
+ msr = rdmsr(SYSCFG_MSR);
+ msr.lo |= SYSCFG_MSR_MtrrFixDramModEn;
+ msr.lo &= ~SYSCFG_MSR_MtrrFixDramEn;
+ wrmsr(SYSCFG_MSR, msr);
+
+ /* Set shadow WB, RdMEM, WrMEM */
+ msr.lo = msr.hi = 0;
+ wrmsr (0x259, msr);
+ msr.hi = msr.lo = 0x1e1e1e1e;
+ wrmsr(0x250, msr);
+ wrmsr(0x258, msr);
+ for (i = 0x268; i <= 0x26f; i++)
+ wrmsr(i, msr);
+
+ msr = rdmsr(SYSCFG_MSR);
+ msr.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
+ msr.lo |= SYSCFG_MSR_MtrrFixDramEn;
+ wrmsr(SYSCFG_MSR, msr);
+
+#if CONFIG_HAVE_ACPI_RESUME == 1
+ if (acpi_slp_type == 3)
+ restore_mtrr();
#endif
- disable_cache ();
- /* Enable access to AMD RdDram and WrDram extension bits */
- msr = rdmsr(SYSCFG_MSR);
- msr.lo |= SYSCFG_MSR_MtrrFixDramModEn;
- wrmsr(SYSCFG_MSR, msr);
-
- // BSP: make a0000-bffff UC, c0000-fffff WB, same as OntarioApMtrrSettingsList for APs
- msr.lo = msr.hi = 0;
- wrmsr (0x259, msr);
- msr.lo = msr.hi = 0x1e1e1e1e;
- for (msrno = 0x268; msrno <= 0x26f; msrno++)
- wrmsr (msrno, msr);
-
- /* disable access to AMD RdDram and WrDram extension bits */
- msr = rdmsr(SYSCFG_MSR);
- msr.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
- wrmsr(SYSCFG_MSR, msr);
- enable_cache ();
-
- /* zero the machine check error status registers */
- msr.lo = 0;
- msr.hi = 0;
- for (i = 0; i < 6; i++) {
- wrmsr(MCI_STATUS + (i * 4), msr);
- }
-
- /* Enable the local cpu apics */
- setup_lapic();
+ x86_mtrr_check();
+ x86_enable_cache();
+
+ /* zero the machine check error status registers */
+ msr.lo = 0;
+ msr.hi = 0;
+ for (i = 0; i < 6; i++) {
+ wrmsr(MCI_STATUS + (i * 4), msr);
+ }
+
+ /* Enable the local cpu apics */
+ setup_lapic();
#if CONFIG_LOGICAL_CPUS == 1
- siblings = cpuid_ecx(0x80000008) & 0xff;
-
- if (siblings > 0) {
- msr = rdmsr_amd(CPU_ID_FEATURES_MSR);
- msr.lo |= 1 << 28;
- wrmsr_amd(CPU_ID_FEATURES_MSR, msr);
-
- msr = rdmsr_amd(CPU_ID_EXT_FEATURES_MSR);
- msr.hi |= 1 << (33 - 32);
- wrmsr_amd(CPU_ID_EXT_FEATURES_MSR, msr);
- }
- printk(BIOS_DEBUG, "siblings = %02d, ", siblings);
+ siblings = cpuid_ecx(0x80000008) & 0xff;
+
+ if (siblings > 0) {
+ msr = rdmsr_amd(CPU_ID_FEATURES_MSR);
+ msr.lo |= 1 << 28;
+ wrmsr_amd(CPU_ID_FEATURES_MSR, msr);
+
+ msr = rdmsr_amd(CPU_ID_EXT_FEATURES_MSR);
+ msr.hi |= 1 << (33 - 32);
+ wrmsr_amd(CPU_ID_EXT_FEATURES_MSR, msr);
+ }
#endif
- /* DisableCf8ExtCfg */
- msr = rdmsr(NB_CFG_MSR);
- msr.hi &= ~(1 << (46 - 32));
- wrmsr(NB_CFG_MSR, msr);
+ /* DisableCf8ExtCfg */
+ msr = rdmsr(NB_CFG_MSR);
+ msr.hi &= ~(1 << (46 - 32));
+ wrmsr(NB_CFG_MSR, msr);
+ /* Write protect SMM space with SMMLOCK. */
+ msr = rdmsr(HWCR_MSR);
+ msr.lo |= (1 << 0);
+ wrmsr(HWCR_MSR, msr);
- /* Write protect SMM space with SMMLOCK. */
- msr = rdmsr(HWCR_MSR);
- msr.lo |= (1 << 0);
- wrmsr(HWCR_MSR, msr);
+ printk(BIOS_SPEW, "%s done.\n", __func__);
}
static struct device_operations cpu_dev_ops = {
- .init = model_14_init,
+ .init = model_14_init,
};
static struct cpu_device_id cpu_table[] = {
- { X86_VENDOR_AMD, 0x500f00 }, /* ON-A0 */
- { X86_VENDOR_AMD, 0x500f01 }, /* ON-A1 */
- { X86_VENDOR_AMD, 0x500f10 }, /* ON-B0 */
- { X86_VENDOR_AMD, 0x500f20 }, /* ON-C0 */
- { 0, 0 },
+ { X86_VENDOR_AMD, 0x500f00 }, /* ON-A0 */
+ { X86_VENDOR_AMD, 0x500f01 }, /* ON-A1 */
+ { X86_VENDOR_AMD, 0x500f10 }, /* ON-B0 */
+ { X86_VENDOR_AMD, 0x500f20 }, /* ON-C0 */
+ { 0, 0 },
};
static const struct cpu_driver model_14 __cpu_driver = {
- .ops = &cpu_dev_ops,
- .id_table = cpu_table,
+ .ops = &cpu_dev_ops,
+ .id_table = cpu_table,
};
diff --git a/src/cpu/amd/agesa/s3_resume.c b/src/cpu/amd/agesa/s3_resume.c
new file mode 100644
index 0000000..d67bf80
--- /dev/null
+++ b/src/cpu/amd/agesa/s3_resume.c
@@ -0,0 +1,348 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/amd/mtrr.h>
+#include <cpu/x86/cache.h>
+#if CONFIG_WRITE_HIGH_TABLES
+#include <cbmem.h>
+#endif
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ops.h>
+#include <arch/io.h>
+#include <arch/acpi.h>
+#include <string.h>
+#include "Porting.h"
+#include "BiosCallOuts.h"
+#include "s3_resume.h"
+#include "agesawrapper.h"
+
+#ifndef __PRE_RAM__
+#include "spi.h"
+#endif
+
+void restore_mtrr(void)
+{
+ u32 msr;
+ volatile UINT32 *msrPtr = (volatile UINT32 *)S3_DATA_MTRR_POS;
+ msr_t msr_data;
+
+ printk(BIOS_SPEW, "%s\n", __func__);
+
+ disable_cache();
+
+ /* Enable access to AMD RdDram and WrDram extension bits */
+ msr_data = rdmsr(SYS_CFG);
+ msr_data.lo |= SYSCFG_MSR_MtrrFixDramModEn;
+ wrmsr(SYS_CFG, msr_data);
+
+ /* Now restore the Fixed MTRRs */
+ msr_data.lo = *msrPtr;
+ msrPtr ++;
+ msr_data.hi = *msrPtr;
+ msrPtr ++;
+ wrmsr(0x250, msr_data);
+
+ msr_data.lo = *msrPtr;
+ msrPtr ++;
+ msr_data.hi = *msrPtr;
+ msrPtr ++;
+ wrmsr(0x258, msr_data);
+
+ msr_data.lo = *msrPtr;
+ msrPtr ++;
+ msr_data.hi = *msrPtr;
+ msrPtr ++;
+ wrmsr(0x259, msr_data);
+
+ for (msr = 0x268; msr <= 0x26F; msr++) {
+ msr_data.lo = *msrPtr;
+ msrPtr ++;
+ msr_data.hi = *msrPtr;
+ msrPtr ++;
+ wrmsr(msr, msr_data);
+ }
+
+ /* Disable access to AMD RdDram and WrDram extension bits */
+ msr_data = rdmsr(SYS_CFG);
+ msr_data.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
+ wrmsr(SYS_CFG, msr_data);
+
+ /* Restore the Variable MTRRs */
+ for (msr = 0x200; msr <= 0x20F; msr++) {
+ msr_data.lo = *msrPtr;
+ msrPtr ++;
+ msr_data.hi = *msrPtr;
+ msrPtr ++;
+ wrmsr(msr, msr_data);
+ }
+
+ /* Restore SYSCFG MTRR */
+ msr_data.lo = *msrPtr;
+ msrPtr ++;
+ msr_data.hi = *msrPtr;
+ msrPtr ++;
+ wrmsr(SYS_CFG, msr_data);
+}
+
+inline void *backup_resume(void)
+{
+ unsigned long high_ram_base;
+ void *resume_backup_memory;
+
+ /* Start address of high memory tables */
+ high_ram_base = (u32) get_cbmem_toc();
+
+ /*
+ * printk(BIOS_DEBUG, "CBMEM TOC is at: %x\n", (u32_t)high_ram_base);
+ * printk(BIOS_DEBUG, "CBMEM TOC 0-size:%x\n ",(u32_t)(high_ram_base + HIGH_MEMORY_SIZE + 4096));
+ */
+
+ cbmem_reinit((u64) high_ram_base);
+
+ resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
+ if (((u32) resume_backup_memory == 0)
+ || ((u32) resume_backup_memory == -1)) {
+ printk(BIOS_ERR, "Error: resume_backup_memory: %x\n",
+ (u32) resume_backup_memory);
+ for (;;) ;
+ }
+
+ return resume_backup_memory;
+}
+
+void move_stack_high_mem(void *resume_backup_memory)
+{
+#if 0
+ u32 *sp, index;
+ __asm__ volatile ("mov %%esp, %0":"=r" (sp)
+ ::);
+ printk(BIOS_DEBUG, "%x:", (u32) sp);
+ printk(BIOS_DEBUG, "[%08x,%08x,%08x,%08x]\n", sp[0], sp[1], sp[2], sp[3]);
+ printk(BIOS_DEBUG, "%x:", (u32) (sp + 4));
+ printk(BIOS_DEBUG, "[%08x,%08x,%08x,%08x]\n", sp[4], sp[5], sp[6], sp[7]);
+ printk(BIOS_DEBUG, "%x:", (u32) (sp + 8));
+ printk(BIOS_DEBUG, "[%08x,%08x,%08x,%08x]\n", sp[8], sp[9], sp[10], sp[11]);
+#endif
+
+ memcopy_fast(resume_backup_memory, (void *)BSP_STACK_BASE_ADDR,
+ (HIGH_SCRATCH_MEMORY_SIZE - BIOS_HEAP_SIZE));
+
+ __asm__
+ volatile ("add %0, %%esp; add %0, %%ebp; invd"::"g"
+ (resume_backup_memory - BSP_STACK_BASE_ADDR)
+ :);
+
+#if 0
+ __asm__ volatile ("mov %%esp, %0":"=r" (sp)
+ ::);
+ printk(BIOS_DEBUG, "%x:", (u32) sp);
+ printk(BIOS_DEBUG, "[%08x,%08x,%08x,%08x]\n", sp[0], sp[1], sp[2], sp[3]);
+ printk(BIOS_DEBUG, "%x:", (u32) (sp + 4));
+ printk(BIOS_DEBUG, "[%08x,%08x,%08x,%08x]\n", sp[4], sp[5], sp[6],sp[7]);
+ printk(BIOS_DEBUG, "%x:", (u32) (sp + 8));
+ printk(BIOS_DEBUG, "[%08x,%08x,%08x,%08x]\n", sp[8], sp[9], sp[10], sp[11]);
+#endif
+}
+
+void OemAgesaSaveMtrr(void)
+{
+#ifndef __PRE_RAM__
+ u32 spi_address;
+ msr_t msr_data;
+ device_t dev;
+ u32 nvram_pos = S3_DATA_MTRR_POS;
+ u32 i;
+
+ dev = dev_find_slot(0, PCI_DEVFN(0x14, 3));
+ spi_address = pci_read_config32(dev, 0xA0) & ~0x1F;
+
+ /* Enable access to AMD RdDram and WrDram extension bits */
+ msr_data = rdmsr(SYS_CFG);
+ msr_data.lo |= SYSCFG_MSR_MtrrFixDramModEn;
+ wrmsr(SYS_CFG, msr_data);
+
+ /* Fixed MTRRs */
+ msr_data = rdmsr(0x250);
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+ nvram_pos += 4;
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+ nvram_pos += 4;
+
+ msr_data = rdmsr(0x258);
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+ nvram_pos += 4;
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+ nvram_pos += 4;
+
+ msr_data = rdmsr(0x259);
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+ nvram_pos += 4;
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+ nvram_pos += 4;
+
+ for (i = 0x268; i < 0x270; i++) {
+ msr_data = rdmsr(i);
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+ nvram_pos += 4;
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+ nvram_pos += 4;
+ }
+
+ /* Disable access to AMD RdDram and WrDram extension bits */
+ msr_data = rdmsr(SYS_CFG);
+ msr_data.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
+ wrmsr(SYS_CFG, msr_data);
+
+ /* Variable MTRRs */
+ for (i = 0x200; i < 0x210; i++) {
+ msr_data = rdmsr(i);
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+ nvram_pos += 4;
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+ nvram_pos += 4;
+ }
+
+ /* SYS_CFG */
+ msr_data = rdmsr(0xC0010010);
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+ nvram_pos += 4;
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+ nvram_pos += 4;
+
+ /* TOM */
+ msr_data = rdmsr(0xC001001A);
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+ nvram_pos += 4;
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+ nvram_pos += 4;
+
+ /* TOM2 */
+ msr_data = rdmsr(0xC001001D);
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+ nvram_pos += 4;
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+ nvram_pos += 4;
+
+#endif
+}
+
+void OemAgesaGetS3Info(S3_DATA_TYPE S3DataType, u32 *DataSize, void **Data)
+{
+ AMD_CONFIG_PARAMS StdHeader;
+ if (S3DataType == S3DataTypeNonVolatile) {
+ *Data = (void *)S3_DATA_NONVOLATILE_POS;
+ *DataSize = *(UINTN *) (*Data);
+ *Data += 4;
+ } else {
+ *DataSize = *(UINTN *) S3_DATA_VOLATILE_POS;
+ *Data = (void *) GetHeapBase(&StdHeader);
+ memcopy_fast((void *)(*Data), (void *)(S3_DATA_VOLATILE_POS + 4), *DataSize);
+ }
+}
+
+u32 OemAgesaSaveS3Info(S3_DATA_TYPE S3DataType, u32 DataSize, void *Data)
+{
+
+ u32 pos = S3_DATA_VOLATILE_POS;
+#ifndef __PRE_RAM__
+ u32 spi_address, data;
+ u32 nvram_pos;
+ device_t dev;
+#endif
+
+ if (S3DataType == S3DataTypeNonVolatile) {
+ pos = S3_DATA_NONVOLATILE_POS;
+ } else { /* S3DataTypeVolatile */
+ pos = S3_DATA_VOLATILE_POS;
+ }
+
+#ifndef __PRE_RAM__
+ dev = dev_find_slot(0, PCI_DEVFN(0x14, 3));
+ spi_address = pci_read_config32(dev, 0xA0) & ~0x1F;
+
+ /* printk(BIOS_DEBUG, "spi_address=%x\n", spi_address); */
+ readSPIID((u8 *) spi_address);
+ writeSPIStatus((u8 *)spi_address, 0);
+ if (S3DataType == S3DataTypeNonVolatile) {
+ sectorEraseSPI((u8 *) spi_address, S3_DATA_NONVOLATILE_POS);
+ } else {
+ sectorEraseSPI((u8 *) spi_address, S3_DATA_VOLATILE_POS);
+ sectorEraseSPI((u8 *) spi_address,
+ S3_DATA_VOLATILE_POS + 0x1000);
+ sectorEraseSPI((u8 *) spi_address,
+ S3_DATA_VOLATILE_POS + 0x2000);
+ sectorEraseSPI((u8 *) spi_address,
+ S3_DATA_VOLATILE_POS + 0x3000);
+ }
+
+ nvram_pos = 0;
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos + pos, DataSize);
+
+ for (nvram_pos = 0; nvram_pos < DataSize; nvram_pos += 4) {
+ data = *(u32 *) (Data + nvram_pos);
+ dwordnoneAAIProgram((u8 *) spi_address, nvram_pos + pos + 4,
+ *(u32 *) (Data + nvram_pos));
+ }
+#endif
+
+ return AGESA_SUCCESS;
+}
+
+void set_resume_cache(void)
+{
+ msr_t msr;
+
+ /* disable fixed mtrr for now, it will be enabled by mtrr restore */
+ msr = rdmsr(SYSCFG_MSR);
+ msr.lo &= ~(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrFixDramModEn);
+ wrmsr(SYSCFG_MSR, msr);
+
+ /* Enable caching for 0 - coreboot ram using variable mtrr */
+ msr.lo = 0 | MTRR_TYPE_WRBACK;
+ msr.hi = 0;
+ wrmsr(MTRRphysBase_MSR(0), msr);
+ msr.lo = ~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid;
+ msr.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1;
+ wrmsr(MTRRphysMask_MSR(0), msr);
+
+ /* Set the default memory type and disable fixed and enable variable MTRRs */
+ msr.hi = 0;
+ msr.lo = (1 << 11);
+ wrmsr(MTRRdefType_MSR, msr);
+
+ enable_cache();
+}
+
+void s3_resume(void)
+{
+ int status;
+
+ printk(BIOS_DEBUG, "agesawrapper_amds3laterestore ");
+ status = agesawrapper_amds3laterestore();
+ if (status)
+ printk(BIOS_DEBUG, "error level: %x \n", (u32) status);
+ else
+ printk(BIOS_DEBUG, "passed.\n");
+}
diff --git a/src/cpu/amd/agesa/s3_resume.h b/src/cpu/amd/agesa/s3_resume.h
new file mode 100644
index 0000000..a62f90e
--- /dev/null
+++ b/src/cpu/amd/agesa/s3_resume.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef S3_RESUME_H
+#define S3_RESUME_H
+
+#define S3_DATA_NONVOLATILE_POS 0xFFFF4000
+#define S3_DATA_VOLATILE_POS 0xFFFF0000
+#define S3_DATA_MTRR_POS 0xFFFF3100
+
+typedef enum {
+ S3DataTypeNonVolatile=0, ///< NonVolatile Data Type
+ S3DataTypeVolatile ///< Volatile Data Type
+} S3_DATA_TYPE;
+
+void restore_mtrr(void);
+void s3_resume(void);
+inline void *backup_resume(void);
+void set_resume_cache(void);
+void move_stack_high_mem(void *resume_backup_memory);
+
+u32 OemAgesaSaveS3Info (S3_DATA_TYPE S3DataType, u32 DataSize, void *Data);
+void OemAgesaGetS3Info (S3_DATA_TYPE S3DataType, u32 *DataSize, void **Data);
+void OemAgesaSaveMtrr (void);
+
+#endif
diff --git a/src/cpu/amd/car/post_cache_as_ram.c b/src/cpu/amd/car/post_cache_as_ram.c
index 270c542..74423f2 100644
--- a/src/cpu/amd/car/post_cache_as_ram.c
+++ b/src/cpu/amd/car/post_cache_as_ram.c
@@ -13,22 +13,6 @@ static inline void print_debug_pcar(const char *strval, uint32_t val)
printk(BIOS_DEBUG, "%s%08x\n", strval, val);
}
-/* from linux kernel 2.6.32 asm/string_32.h */
-
-static void inline __attribute__((always_inline)) memcopy(void *dest, const void *src, unsigned long bytes)
-{
- int d0, d1, d2;
- asm volatile("cld ; rep ; movsl\n\t"
- "movl %4,%%ecx\n\t"
- "andl $3,%%ecx\n\t"
- "jz 1f\n\t"
- "rep ; movsb\n\t"
- "1:"
- : "=&c" (d0), "=&D" (d1), "=&S" (d2)
- : "0" (bytes / 4), "g" (bytes), "1" ((long)dest), "2" ((long)src)
- : "memory", "cc");
-}
-
#if CONFIG_HAVE_ACPI_RESUME == 1
static inline void *backup_resume(void) {
@@ -58,7 +42,7 @@ static inline void *backup_resume(void) {
if (resume_backup_memory) {
print_debug_pcar("Will copy coreboot region to: ", (uint32_t) resume_backup_memory);
/* copy only backup only memory used for CAR */
- memcopy(resume_backup_memory+HIGH_MEMORY_SAVE-CONFIG_DCACHE_RAM_SIZE,
+ memcopy_fast(resume_backup_memory+HIGH_MEMORY_SAVE-CONFIG_DCACHE_RAM_SIZE,
(void *)((CONFIG_RAMTOP)-CONFIG_DCACHE_RAM_SIZE),
CONFIG_DCACHE_RAM_SIZE); //inline
}
diff --git a/src/devices/pci_device.c b/src/devices/pci_device.c
index 2ccb38a..59ccff6 100644
--- a/src/devices/pci_device.c
+++ b/src/devices/pci_device.c
@@ -650,6 +650,10 @@ void pci_dev_set_subsystem(struct device *dev, unsigned vendor, unsigned device)
((device & 0xffff) << 16) | (vendor & 0xffff));
}
+#if CONFIG_HAVE_ACPI_RESUME == 1
+extern u8 acpi_slp_type;
+#endif
+
/** Default handler: only runs the relevant PCI BIOS. */
void pci_dev_init(struct device *dev)
{
@@ -664,6 +668,12 @@ void pci_dev_init(struct device *dev)
((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA))
return;
+#if CONFIG_HAVE_ACPI_RESUME == 1
+ /* Don't re-run roms on s3 resume. */
+ if (acpi_slp_type == 3)
+ return;
+#endif
+
rom = pci_rom_probe(dev);
if (rom == NULL)
return;
diff --git a/src/include/cbmem.h b/src/include/cbmem.h
index 7c5ec07..b7207b9 100644
--- a/src/include/cbmem.h
+++ b/src/include/cbmem.h
@@ -25,11 +25,16 @@
extern uint64_t high_tables_base, high_tables_size;
#if CONFIG_HAVE_ACPI_RESUME
-#define HIGH_MEMORY_SIZE ((CONFIG_RAMTOP - CONFIG_RAMBASE) + HIGH_MEMORY_DEF_SIZE)
-#define HIGH_MEMORY_SAVE ( HIGH_MEMORY_SIZE - HIGH_MEMORY_DEF_SIZE )
+#ifdef CONFIG_RESUME_SCRATCH_MEMORY_SIZE
+#define HIGH_SCRATCH_MEMORY_SIZE CONFIG_RESUME_SCRATCH_MEMORY_SIZE
#else
-#define HIGH_MEMORY_SIZE HIGH_MEMORY_DEF_SIZE
+#define HIGH_SCRATCH_MEMORY_SIZE 0
#endif
+#define HIGH_MEMORY_SAVE (CONFIG_RAMTOP - CONFIG_RAMBASE)
+#define HIGH_MEMORY_SIZE (HIGH_MEMORY_SAVE + HIGH_SCRATCH_MEMORY_SIZE + HIGH_MEMORY_DEF_SIZE)
+#else /* CONFIG_HAVE_ACPI_RESUME */
+#define HIGH_MEMORY_SIZE HIGH_MEMORY_DEF_SIZE
+#endif /* CONFIG_HAVE_ACPI_RESUME */
#define CBMEM_ID_FREESPACE 0x46524545
#define CBMEM_ID_GDT 0x4c474454
diff --git a/src/include/string.h b/src/include/string.h
index 2168947..234f848 100644
--- a/src/include/string.h
+++ b/src/include/string.h
@@ -8,6 +8,7 @@ void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);
void *memset(void *s, int c, size_t n);
int memcmp(const void *s1, const void *s2, size_t n);
+void inline __attribute__((always_inline)) memcopy_fast(void *dest, const void *src, unsigned long bytes);
#if !defined(__PRE_RAM__)
int sprintf(char * buf, const char *fmt, ...);
#endif
diff --git a/src/lib/cbmem.c b/src/lib/cbmem.c
index 202f521..18f05b5 100644
--- a/src/lib/cbmem.c
+++ b/src/lib/cbmem.c
@@ -176,6 +176,8 @@ void *cbmem_find(u32 id)
return NULL;
for (i = 0; i < MAX_CBMEM_ENTRIES; i++) {
+ printk(BIOS_SPEW, "CBMEM TOC ID %d is: %x base: %x%x\n", i,
+ (u32) cbmem_toc[i].id, (u32) (cbmem_toc[i].base >> 32), (u32) cbmem_toc[i].base);
if (cbmem_toc[i].id == id)
return (void *)(unsigned long)cbmem_toc[i].base;
}
diff --git a/src/lib/memcpy.c b/src/lib/memcpy.c
index 1053a53..217f73b 100644
--- a/src/lib/memcpy.c
+++ b/src/lib/memcpy.c
@@ -10,3 +10,18 @@ void *memcpy(void *vdest, const void *vsrc, size_t bytes)
return vdest;
}
+
+/* from linux kernel 2.6.32 asm/string_32.h */
+void inline __attribute__((always_inline)) memcopy_fast(void *dest, const void *src, unsigned long bytes)
+{
+ int d0, d1, d2;
+ asm volatile("cld ; rep ; movsl\n\t"
+ "movl %4,%%ecx\n\t"
+ "andl $3,%%ecx\n\t"
+ "jz 1f\n\t"
+ "rep ; movsb\n\t"
+ "1:"
+ : "=&c" (d0), "=&D" (d1), "=&S" (d2)
+ : "0" (bytes / 4), "g" (bytes), "1" ((long)dest), "2" ((long)src)
+ : "memory", "cc");
+}
diff --git a/src/northbridge/amd/agesa/family14/northbridge.c b/src/northbridge/amd/agesa/family14/northbridge.c
index b2ca256..759f0c2 100644
--- a/src/northbridge/amd/agesa/family14/northbridge.c
+++ b/src/northbridge/amd/agesa/family14/northbridge.c
@@ -28,6 +28,7 @@
#include <string.h>
#include <bitops.h>
#include <cpu/cpu.h>
+#include <cbmem.h>
#include <cpu/x86/lapic.h>
@@ -332,11 +333,6 @@ static struct hw_mem_hole_info get_hw_mem_hole_info(void)
}
#endif
-#if CONFIG_WRITE_HIGH_TABLES==1
-#define HIGH_TABLES_SIZE 64 // maximum size of high tables in KB
-extern uint64_t high_tables_base, high_tables_size;
-#endif
-
#if CONFIG_GFXUMA == 1
extern uint64_t uma_memory_base, uma_memory_size;
@@ -691,12 +687,12 @@ printk(BIOS_DEBUG, "adsr: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n", mmi
if (high_tables_base==0) {
/* Leave some space for ACPI, PIRQ and MP tables */
#if CONFIG_GFXUMA == 1
- high_tables_base = uma_memory_base - (HIGH_TABLES_SIZE * 1024);
+ high_tables_base = uma_memory_base - HIGH_MEMORY_SIZE;
#else
- high_tables_base = (mmio_basek - HIGH_TABLES_SIZE) * 1024;
+ high_tables_base = (mmio_basek * 1024) - HIGH_MEMORY_SIZE;
#endif
- high_tables_size = HIGH_TABLES_SIZE * 1024;
- printk(BIOS_DEBUG, " split: %dK table at =%08llx\n", HIGH_TABLES_SIZE,
+ high_tables_size = HIGH_MEMORY_SIZE;
+ printk(BIOS_DEBUG, " split: %dK table at =%08llx\n", (u32)high_tables_size,
high_tables_base);
}
#endif
@@ -721,17 +717,18 @@ printk(BIOS_DEBUG, "adsr: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n", mmi
if (high_tables_base==0) {
/* Leave some space for ACPI, PIRQ and MP tables */
#if CONFIG_GFXUMA == 1
- high_tables_base = uma_memory_base - (HIGH_TABLES_SIZE * 1024);
- printk(BIOS_DEBUG, " adsr - uma_memory_base = %llx.\n",uma_memory_base);
+ high_tables_base = uma_memory_base - HIGH_MEMORY_SIZE;
+ printk(BIOS_DEBUG, " adsr - uma_memory_base = %llx, ",uma_memory_base);
#else
- high_tables_base = (limitk - HIGH_TABLES_SIZE) * 1024;
+ high_tables_base = (limitk * 1024)- HIGH_MEMORY_SIZE;
#endif
- high_tables_size = HIGH_TABLES_SIZE * 1024;
- }
+ high_tables_size = HIGH_MEMORY_SIZE;
+ }
#endif
}
printk(BIOS_DEBUG, " adsr - mmio_basek = %lx.\n",mmio_basek);
printk(BIOS_DEBUG, " adsr - high_tables_size = %llx.\n",high_tables_size);
+printk(BIOS_DEBUG, " adsr - high_tables_base=%x%x\n", (u32) (high_tables_base >> 32), (u32) high_tables_base);
#if CONFIG_GFXUMA == 1
printk(BIOS_DEBUG, "adsr - adding uma resource.\n");
@@ -746,22 +743,46 @@ printk(BIOS_DEBUG, " adsr - high_tables_size = %llx.\n",high_tables_size);
printk(BIOS_DEBUG, " adsr - leaving this lovely routine.\n");
}
+extern u8 acpi_slp_type;
static void domain_enable_resources(device_t dev)
{
u32 val;
#if CONFIG_AMD_SB_CIMX
+ #if CONFIG_HAVE_ACPI_RESUME == 1
+ if (acpi_slp_type != 3) {
+ sb_After_Pci_Init();
+ sb_Mid_Post_Init();
+ } else {
+ sb_After_Pci_Restore_Init();
+ }
+ #else
sb_After_Pci_Init();
sb_Mid_Post_Init();
+ #endif
#endif
/* Must be called after PCI enumeration and resource allocation */
printk(BIOS_DEBUG, "\nFam14h - domain_enable_resources: AmdInitMid.\n");
- val = agesawrapper_amdinitmid ();
- if(val) {
- printk(BIOS_DEBUG, "agesawrapper_amdinitmid failed: %x \n", val);
+
+#if CONFIG_HAVE_ACPI_RESUME == 1
+ if (acpi_slp_type != 3) {
+ printk(BIOS_DEBUG, "agesawrapper_amdinitmid ");
+ val = agesawrapper_amdinitmid ();
+ if (val)
+ printk(BIOS_DEBUG, "error level: %x \n", val);
+ else
+ printk(BIOS_DEBUG, "passed.\n");
}
+#else
+ printk(BIOS_DEBUG, "agesawrapper_amdinitmid ");
+ val = agesawrapper_amdinitmid ();
+ if (val)
+ printk(BIOS_DEBUG, "error level: %x \n", val);
+ else
+ printk(BIOS_DEBUG, "passed.\n");
+#endif
printk(BIOS_DEBUG, " ader - leaving domain_enable_resources.\n");
}
@@ -795,24 +816,41 @@ static void cpu_bus_set_resources(device_t dev)
pci_dev_set_resources(dev);
}
-static void cpu_bus_init(device_t dev)
+static u32 cpu_bus_scan(device_t dev, u32 max)
{
- struct device_path cpu_path;
device_t cpu;
- int apic_id;
-
- initialize_cpus(dev->link_list);
+ struct device_path cpu_path;
+ int apic_id, cores_found;
+
+ /* There is only one node for fam14, but there may be multiple cores. */
+ cpu = dev_find_slot(0, PCI_DEVFN(0x18, 0));
+ if (!cpu)
+ printk(BIOS_ERR, "ERROR: %02x:%02x.0 not found", 0, 0x18);
+
+ cores_found = (pci_read_config32(dev_find_slot(0,PCI_DEVFN(0x18,0x3)), 0xe8) >> 12) & 3;
+ printk(BIOS_DEBUG, " AP siblings=%d\n", cores_found);
+
+
+ for (apic_id = 0; apic_id <= cores_found; apic_id++) {
+ cpu_path.type = DEVICE_PATH_APIC;
+ cpu_path.apic.apic_id = apic_id;
+ cpu = alloc_find_dev(dev->link_list, &cpu_path);
+ if (cpu) {
+ cpu->enabled = 1;
+ cpu->path.apic.node_id = 0;
+ cpu->path.apic.core_id = apic_id;
+ printk(BIOS_DEBUG, "CPU: %s %s\n",
+ dev_path(cpu), cpu->enabled?"enabled":"disabled");
+ } else {
+ cpu->enabled = 0;
+ }
+ }
+ return max;
+}
- /* Build the AP cpu device path(s) */
- for (apic_id = 1; apic_id < CONFIG_MAX_CPUS; apic_id++) {
- cpu_path.type = DEVICE_PATH_APIC;
- cpu_path.apic.apic_id = apic_id;
- cpu = alloc_dev(dev->link_list, &cpu_path);
- if (!cpu) return;
- cpu->enabled = 1;
- cpu->path.apic.node_id = 0;
- cpu->path.apic.core_id = apic_id;
- }
+static void cpu_bus_init(device_t dev)
+{
+ initialize_cpus(dev->link_list);
}
@@ -858,7 +896,7 @@ static struct device_operations cpu_bus_ops = {
.set_resources = cpu_bus_set_resources,
.enable_resources = NULL,
.init = cpu_bus_init,
- .scan_bus = NULL,
+ .scan_bus = cpu_bus_scan,
};
More information about the coreboot
mailing list