-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi all,

This is yet another WIP patch. This one actually works (suspend/resume works in
Linux), but it:

1) corrupts memory around 0x1000 (the real mode trampoline)
2) it corrupts memory randomly in first 64KB copy_secondary_start_to_1m_below

It puts Coreboot to last 1MB below 32MB (and reserves the memory there). So all
I need is to solve the secondary.S starter and the real mode jumper -> somehow
not to corrupt the lowmem or find some hole where it can be hidden.

Rudolf

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAknMDVgACgkQ3J9wPJqZRNXa1gCgsqEF5ixml987NqZpq62nBPTZ
2T8AnR0MdwkbqdvzAuvCqAAAoZNBj3WX
=pvTU
-----END PGP SIGNATURE-----
Index: src/southbridge/via/vt8237r/vt8237r_early_smbus.c
===================================================================
--- src/southbridge/via/vt8237r/vt8237r_early_smbus.c	(revision 4030)
+++ src/southbridge/via/vt8237r/vt8237r_early_smbus.c	(working copy)
@@ -294,6 +294,61 @@
 	pci_write_config8(dev, 0x41, 0x7f);
 }
 
+
+int acpi_is_wakeup_early(void) {
+	device_t dev;
+	u16 tmp;
+
+	print_debug("IN TEST WAKEUP\n");
+	/* Power management controller */
+	dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA,
+				       PCI_DEVICE_ID_VIA_VT8237S_LPC), 0);
+
+	if (dev == PCI_DEV_INVALID)
+		die("Power management controller not found\r\n");
+
+	/* Set ACPI base address to I/O VT8237R_ACPI_IO_BASE. */
+	pci_write_config16(dev, 0x88, VT8237R_ACPI_IO_BASE | 0x1);
+
+	/* Enable ACPI accessm RTC signal gated with PSON. */
+	pci_write_config8(dev, 0x81, 0x84);
+
+	tmp = inw(VT8237R_ACPI_IO_BASE + 0x04);
+
+	print_debug_hex8(tmp);
+	return ((tmp & (7 << 10)) >> 10) == 1 ? 3 : 0 ;
+}
+
+void  acpi_clear_sleep(void) {
+	device_t dev;
+	u16 tmp;
+
+	print_debug("IN clear acpi sleep\n");
+	/* Power management controller */
+	dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA,
+				       PCI_DEVICE_ID_VIA_VT8237S_LPC), 0);
+
+	if (dev == PCI_DEV_INVALID)
+		die("Power management controller not found\r\n");
+
+	/* Set ACPI base address to I/O VT8237R_ACPI_IO_BASE. */
+	pci_write_config16(dev, 0x88, VT8237R_ACPI_IO_BASE | 0x1);
+
+	/* Enable ACPI accessm RTC signal gated with PSON. */
+	pci_write_config8(dev, 0x81, 0x84);
+
+	tmp = inw(VT8237R_ACPI_IO_BASE + 0x04);
+
+	print_debug_hex8(tmp);
+//	return ((tmp & (7 << 10)) >> 10) == 1 ? 3 : 0 ;
+
+	tmp &= 0xe3ff; //clear sleep to normal ON
+	tmp |= 0x2000;
+	outb(tmp, VT8237R_ACPI_IO_BASE + 0x04);
+	print_debug_hex8(tmp);
+
+}
+
 #if defined(__GNUC__)
 void vt8237_early_spi_init(void)
 {
Index: src/southbridge/via/vt8237r/vt8237r_lpc.c
===================================================================
--- src/southbridge/via/vt8237r/vt8237r_lpc.c	(revision 4030)
+++ src/southbridge/via/vt8237r/vt8237r_lpc.c	(working copy)
@@ -149,8 +149,13 @@
  * Set up the power management capabilities directly into ACPI mode.
  * This avoids having to handle any System Management Interrupts (SMIs).
  */
+
+ u8 acpi_sleep_type;
+
+
 static void setup_pm(device_t dev)
 {
+	u16 tmp;
 	/* Debounce LID and PWRBTN# Inputs for 16ms. */
 	pci_write_config8(dev, 0x80, 0x20);
 
@@ -171,10 +176,10 @@
 
 	/*
 	 * 7 = SMBus clock from RTC 32.768KHz
-	 * 5 = Internal PLL reset from susp
-	 * 2 = GPO2 is GPIO
+	 * 5 = Internal PLL reset from susp disabled
+	 * 2 = GPO2 is SUSA#
 	 */
-	pci_write_config8(dev, 0x94, 0xa4);
+	pci_write_config8(dev, 0x94, 0xa0);
 
 	/*
 	 * 7 = stp to sust delay 1msec
@@ -219,7 +224,15 @@
 	outb(0x0, VT8237R_ACPI_IO_BASE + 0x42);
 
 	/* SCI is generated for RTC/pwrBtn/slpBtn. */
-	outw(0x001, VT8237R_ACPI_IO_BASE + 0x04);
+	tmp = inw(VT8237R_ACPI_IO_BASE + 0x04);
+	acpi_sleep_type = ((tmp & (7 << 10)) >> 10) == 1 ? 3 : 0 ;
+	printk_debug("SLEEP type was %x %x\n", tmp, acpi_sleep_type);
+	tmp |= 1;
+	outw(tmp, VT8237R_ACPI_IO_BASE + 0x04);
+
+
+
+
 }
 
 static void vt8237r_init(struct device *dev)
Index: src/southbridge/via/k8t890/k8t890_early_car.c
===================================================================
--- src/southbridge/via/k8t890/k8t890_early_car.c	(revision 4030)
+++ src/southbridge/via/k8t890/k8t890_early_car.c	(working copy)
@@ -23,7 +23,15 @@
  */
 
 #include <stdlib.h>
+//include "k8t890.h"
+#warning hack the right header here
 
+/* The 256 bytes of NVRAM for S3 storage, 256B aligned */
+#define K8T890_NVRAM_IO_BASE	0xf00
+#define K8T890_MULTIPLE_FN_EN	0x4f
+
+
+
 /* AMD K8 LDT0, LDT1, LDT2 Link Control Registers */
 static ldtreg[3] = {0x86, 0xa6, 0xc6};
 
@@ -33,10 +41,22 @@
 
 u8 k8t890_early_setup_ht(void)
 {
-	u8 awidth, afreq, cldtfreq; 
+	u8 awidth, afreq, cldtfreq, reg;
 	u8 cldtwidth_in, cldtwidth_out, vldtwidth_in, vldtwidth_out, ldtnr, width;
 	u16 vldtcaps;
 
+	/* hack, enable NVRAM in chipset */
+	pci_write_config8(PCI_DEV(0, 0x0, 0), K8T890_MULTIPLE_FN_EN, 0x01);
+
+	/*
+	 * NVRAM I/O base at K8T890_NVRAM_IO_BASE
+	 */
+
+	pci_write_config8(PCI_DEV(0, 0x0, 2), 0xa2, (K8T890_NVRAM_IO_BASE >> 8));
+	reg = pci_read_config8(PCI_DEV(0, 0x0, 2), 0xa1);
+	reg |= 0x1;
+	pci_write_config8(PCI_DEV(0, 0x0, 2), 0xa1, reg);
+
 	/* check if connected non coherent, initcomplete (find the SB on K8 side) */
 	if (0x7 == pci_read_config8(PCI_DEV(0, 0x18, 0), 0x98)) {
 		ldtnr = 0;
Index: src/southbridge/via/k8t890/k8t890_host_ctrl.c
===================================================================
--- src/southbridge/via/k8t890/k8t890_host_ctrl.c	(revision 4030)
+++ src/southbridge/via/k8t890/k8t890_host_ctrl.c	(working copy)
@@ -37,14 +37,14 @@
 	 */
 	pci_write_config8(dev, 0xa0, 0x13);
 
-	/* Disable NVRAM and enable non-posted PCI writes. */
-	pci_write_config8(dev, 0xa1, 0x8e);
-
 	/*
-	 * NVRAM I/O base 0xe00-0xeff, but it is disabled.
+	 * NVRAM I/O base at K8T890_NVRAM_IO_BASE
 	 * Some bits are set and reserved.
 	 */
-	pci_write_config8(dev, 0xa2, 0x0e);
+	pci_write_config8(dev, 0xa2, (K8T890_NVRAM_IO_BASE >> 8));
+
+	/* enable NB NVRAM and enable non-posted PCI writes. */
+	pci_write_config8(dev, 0xa1, 0x8f);
 	/* Arbitration control, some bits are reserved. */
 	pci_write_config8(dev, 0xa5, 0x3c);
 
@@ -95,14 +95,15 @@
 	 */
 	pci_write_config8(dev, 0xa0, 0x13);
 
-	/* Disable NVRAM and enable non-posted PCI writes. */
-	pci_write_config8(dev, 0xa1, 0x8e);
-
 	/*
-	 * NVRAM I/O base 0xe00-0xeff, but it is disabled.
+	 * NVRAM I/O base at K8T890_NVRAM_IO_BASE
 	 */
 
-	pci_write_config8(dev, 0xa2, 0x0e);
+	pci_write_config8(dev, 0xa2, (K8T890_NVRAM_IO_BASE >> 8));
+
+	/* Enable NVRAM and enable non-posted PCI writes. */
+	pci_write_config8(dev, 0xa1, 0x8f);
+
 	/* Arbitration control  */
 	pci_write_config8(dev, 0xa5, 0x3c);
 
Index: src/southbridge/via/k8t890/k8t890.h
===================================================================
--- src/southbridge/via/k8t890/k8t890.h	(revision 4030)
+++ src/southbridge/via/k8t890/k8t890.h	(working copy)
@@ -29,6 +29,9 @@
  */
 #define K8T890_APIC_BASE	0xfecc0000
 
+/* The 256 bytes of NVRAM for S3 storage, 256B aligned */
+#define K8T890_NVRAM_IO_BASE	0xf00
+
 #define K8T890_MMCONFIG_MBAR	0x61
 #define K8T890_MULTIPLE_FN_EN	0x4f
 
@@ -36,6 +39,7 @@
 #define K8M890_FBSIZEMB		64
 
 #include <device/device.h>
+
 extern void writeback(struct device *dev, u16 where, u8 what);
 extern void dump_south(device_t dev);
 
Index: src/superio/ite/it8712f/it8712f_early_serial.c
===================================================================
--- src/superio/ite/it8712f/it8712f_early_serial.c	(revision 4030)
+++ src/superio/ite/it8712f/it8712f_early_serial.c	(working copy)
@@ -32,6 +32,7 @@
 #define IT8712F_CONFIG_REG_CONFIGSEL 0x22 /* Configuration Select. */
 #define IT8712F_CONFIG_REG_CLOCKSEL  0x23 /* Clock Selection. */
 #define IT8712F_CONFIG_REG_SWSUSP    0x24 /* Software Suspend, Flash I/F. */
+#define IT8712F_CONFIG_REG_MFC       0x2a /* Multi-function control */
 #define IT8712F_CONFIG_REG_WATCHDOG  0x72 /* Watchdog control. */
 
 #define IT8712F_CONFIGURATION_PORT   0x2e /* Write-only. */
@@ -78,6 +79,21 @@
 
 }
 
+static void it8712f_enable_3vsbsw(void) {
+
+	/* We need to set enable 3VSBSW#, this was documented only in IT8712F_V0.9.2!
+	 LDN 7, reg 0x2a - needed for S3, or memory power will be cut off.
+	 Enable 3VSBSW#. (For System Suspend-to-RAM)
+	 0: 3VSBSW# will be always inactive.
+	 1: 3VSBSW# enabled. It will be (NOT SUSB#) NAND SUSC#.
+	*/
+
+	it8712f_enter_conf();
+	it8712f_sio_write(0x07, IT8712F_CONFIG_REG_MFC, 0x80);
+	it8712f_exit_conf();
+}
+
+
 static void it8712f_kill_watchdog(void)
 {
 	it8712f_enter_conf();
Index: src/cpu/amd/model_fxx/fidvid.c
===================================================================
--- src/cpu/amd/model_fxx/fidvid.c	(revision 4030)
+++ src/cpu/amd/model_fxx/fidvid.c	(working copy)
@@ -73,7 +73,8 @@
 //		dword = 0x00070000; /* enable FID/VID change */
 		pci_write_config32(PCI_DEV(0, 0x18+i, 3), 0x80, dword);
 
-		dword = 0x00132113;
+		//2113_2113h
+		dword = 0x21132113;
 		pci_write_config32(PCI_DEV(0, 0x18+i, 3), 0x84, dword);
 
 	}
Index: src/cpu/amd/car/copy_and_run.c
===================================================================
--- src/cpu/amd/car/copy_and_run.c	(revision 4030)
+++ src/cpu/amd/car/copy_and_run.c	(working copy)
@@ -21,9 +21,30 @@
 static void copy_and_run(void)
 {
 	uint8_t *src, *dst; 
+	int i;
+	u32 *p = 4*1024;
         unsigned long ilen, olen;
 
+#if 0
+	print_debug("RAM low poison.\r\n");
 
+	for (i=(4*1024);i<(640*1024);i+=4) {
+		*p = p;
+		p++;
+	}
+#endif
+	
+/*
+	p = 1*1024*1024;
+	print_debug("RAM high poison.\r\n");
+
+	for (i=1;i<(30*1024*1024);i+=4) {
+		*p = p;
+		p++;
+	}
+
+*/
+
 #if !CONFIG_COMPRESS 
 	print_debug("Copying coreboot to RAM.\r\n");
 	__asm__ volatile (
Index: src/cpu/amd/car/clear_init_ram.c
===================================================================
--- src/cpu/amd/car/clear_init_ram.c	(revision 4030)
+++ src/cpu/amd/car/clear_init_ram.c	(working copy)
@@ -6,8 +6,7 @@
 	// gcc 3.4.5 will inline the copy_and_run and clear_init_ram in post_cache_as_ram
 	// will reuse %edi as 0 from clear_memory for copy_and_run part, actually it is increased already
 	// so noline clear_init_ram
-        clear_memory(0,  ((CONFIG_LB_MEM_TOPK<<10) - DCACHE_RAM_SIZE));
-
+        clear_memory( _RAMBASE,  (CONFIG_LB_MEM_TOPK << 10) -  _RAMBASE - DCACHE_RAM_SIZE);
 }
 
 /* be warned, this file will be used by core other than core 0/node 0 or core0/node0 when cpu_reset*/
Index: src/mainboard/asus/m2v-mx_se/Options.lb
===================================================================
--- src/mainboard/asus/m2v-mx_se/Options.lb	(revision 4030)
+++ src/mainboard/asus/m2v-mx_se/Options.lb	(working copy)
@@ -159,9 +159,9 @@
 default STACK_SIZE = 8 * 1024
 default HEAP_SIZE = 256 * 1024
 # More 1M for pgtbl.
-default CONFIG_LB_MEM_TOPK = 2048
+default CONFIG_LB_MEM_TOPK = 32768
 # to 1MB
-default _RAMBASE = 0x100000
+default _RAMBASE = 0x1F00000
 # default USE_OPTION_TABLE = !USE_FALLBACK_IMAGE
 default CONFIG_ROM_PAYLOAD = 1
 default CC = "$(CROSS_COMPILE)gcc -m32"
Index: src/mainboard/asus/m2v-mx_se/dsdt.asl
===================================================================
--- src/mainboard/asus/m2v-mx_se/dsdt.asl	(revision 4030)
+++ src/mainboard/asus/m2v-mx_se/dsdt.asl	(working copy)
@@ -30,8 +30,24 @@
 	 * Any others would involve declaring the wake up methods.
 	 */
 	Name (\_S0, Package () { 0x00, 0x00, 0x00, 0x00 })
+	Name (\_S3, Package () { 0x01, 0x01, 0x00, 0x00 })
 	Name (\_S5, Package () { 0x02, 0x02, 0x00, 0x00 })
 
+
+	/* blink a LED when entering the sleep (any type) */
+	Method (_PTS, 1, NotSerialized)
+	{
+		Store (0x1, \_SB.PCI0.ISA.LEDR)
+	}
+
+	/* cancel a LED blinking when waking from sleep (any type) */
+	Method (_WAK, 1, NotSerialized)
+	{
+		Store (0x0, \_SB.PCI0.ISA.LEDR)
+		/* wake OK */
+		Return(Package(0x02){0x00, 0x00})
+	}
+
 	/* Root of the bus hierarchy */
 	Scope (\_SB)
 	{
@@ -160,7 +176,14 @@
 			}
 			Device (ISA) {
 				Name (_ADR, 0x00110000)
-
+				OperationRegion (PCIC, PCI_Config, 0x0, 0xff)
+				Field (PCIC, ByteAcc, NoLock, Preserve)
+				{
+					Offset (0x94),
+					/* two LSB bits are blink rate */
+					LEDR,   2,
+				}
+				
 				/* PS/2 keyboard (seems to be important for WinXP install) */
 				Device (KBD)
 				{
Index: src/mainboard/asus/m2v-mx_se/mainboard.c
===================================================================
--- src/mainboard/asus/m2v-mx_se/mainboard.c	(revision 4030)
+++ src/mainboard/asus/m2v-mx_se/mainboard.c	(working copy)
@@ -29,11 +29,25 @@
 
 int add_mainboard_resources(struct lb_memory *mem)
 {
+        extern char _secondary_start[];
+        extern char _secondary_start_end[];
+        unsigned long code_size;
+
 #if HAVE_HIGH_TABLES == 1
 	printk_debug("Adding high table area\n");
 	lb_add_memory_range(mem, LB_MEM_TABLE,
 		high_tables_base, high_tables_size);
 #endif
+	lb_add_memory_range(mem, LB_MEM_RESERVED,
+		_RAMBASE, ((CONFIG_LB_MEM_TOPK<<10) - _RAMBASE));
+	lb_add_memory_range(mem, LB_MEM_RESERVED,
+		DCACHE_RAM_BASE, DCACHE_RAM_SIZE);
+
+        code_size = (unsigned long)_secondary_start_end - (unsigned long)_secondary_start;
+
+	lb_add_memory_range(mem, LB_MEM_RESERVED,
+		_secondary_start, code_size);
+
 	return 0;
 }
 
Index: src/mainboard/asus/m2v-mx_se/cache_as_ram_auto.c
===================================================================
--- src/mainboard/asus/m2v-mx_se/cache_as_ram_auto.c	(revision 4030)
+++ src/mainboard/asus/m2v-mx_se/cache_as_ram_auto.c	(working copy)
@@ -242,10 +242,12 @@
 	struct sys_info *sysinfo =
 	    (DCACHE_RAM_BASE + DCACHE_RAM_SIZE - DCACHE_RAM_GLOBAL_VAR_SIZE);
 	char *p;
+	u8 reg;
 
 	sio_init();
 	it8712f_enable_serial(SERIAL_DEV, TTYS0_BASE);
 	it8712f_kill_watchdog();
+	it8712f_enable_3vsbsw();
 	uart_init();
 	console_init();
 	enable_rom_decode();
Index: src/boot/hardwaremain.c
===================================================================
--- src/boot/hardwaremain.c	(revision 4030)
+++ src/boot/hardwaremain.c	(working copy)
@@ -37,6 +37,293 @@
 #include <part/init_timer.h>
 #include <boot/elf.h>
 
+//reboot.c from linux
+
+#include <stdint.h>
+#include <string.h>
+#include <arch/io.h>
+#include <console/console.h>
+
+int acpi_is_wakeup_early(void);
+
+int enable_a20(void);
+
+/* The following code and data reboots the machine by switching to real
+   mode and jumping to the BIOS reset entry point, as if the CPU has
+   really been reset.  The previous version asked the keyboard
+   controller to pulse the CPU reset line, which is more thorough, but
+   doesn't work with at least one type of 486 motherboard.  It is easy
+   to stop this code working; hence the copious comments. */
+
+static unsigned long long
+real_mode_gdt_entries [3] =
+{
+	0x0000000000000000ULL,	/* Null descriptor */
+	0x00009a000000ffffULL,	/* 16-bit real-mode 64k code at 0x00000000 */
+	0x000092000100ffffULL	/* 16-bit real-mode 64k data at 0x00000100 */
+};
+
+struct Xgt_desc_struct {
+         unsigned short size;
+         unsigned long address __attribute__((packed));
+         unsigned short pad;
+ } __attribute__ ((packed));
+
+static struct Xgt_desc_struct
+real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries },
+real_mode_idt = { 0x3ff, 0 },
+no_idt = { 0, 0 };
+
+
+/* This is 16-bit protected mode code to disable paging and the cache,
+   switch to real mode and jump to the BIOS reset code.
+
+   The instruction that switches to real mode by writing to CR0 must be
+   followed immediately by a far jump instruction, which set CS to a
+   valid value for real mode, and flushes the prefetch queue to avoid
+   running instructions that have already been decoded in protected
+   mode.
+
+   Clears all the flags except ET, especially PG (paging), PE
+   (protected-mode enable) and TS (task switch for coprocessor state
+   save).  Flushes the TLB after paging has been disabled.  Sets CD and
+   NW, to disable the cache on a 486, and invalidates the cache.  This
+   is more like the state of a 486 after reset.  I don't know if
+   something else should be done for other chips.
+
+   More could be done here to set up the registers as if a CPU reset had
+   occurred; hopefully real BIOSs don't assume much. */
+
+
+//	0x66, 0x0d, 0x00, 0x00, 0x00, 0x60,	/*    orl   $0x60000000,%eax */
+
+static unsigned char real_mode_switch [] =
+{
+	0x66, 0x0f, 0x20, 0xc0,			/*    movl  %cr0,%eax        */
+	0x24, 0xfe,				/*    andb  $0xfe,al         */
+	0x66, 0x0f, 0x22, 0xc0			/*    movl  %eax,%cr0        */
+};
+static unsigned char jump_to_wakeup [] =
+{
+	0xea, 0x00, 0x00, 0x00, 0xe0		/*    ljmp  $0xffff,$0x0000  */
+};
+
+/*
+ * Switch to real mode and then execute the code
+ * specified by the code and length parameters.
+ * We assume that length will aways be less that 100!
+ */ 
+ 
+
+static void dump_mem(u32 start, u32 end)
+{
+
+	u32 i;
+	print_debug("dump_mem:");
+	for(i=start;i<end;i++) {
+		if((i & 0xf)==0) {
+			printk_debug("\n%08x:", i);
+		}
+		printk_debug(" %02x", (unsigned char)*((unsigned char *)i));
+	}
+	print_debug("\n");
+ }
+
+void acpi_jump_wake(u32 vector)
+{
+u8 tmp;
+	printk_debug("IN ACPI JUMP WAKE TO %x\n", vector);
+	if (enable_a20())
+		die("failed to enable A20\n");
+	printk_debug("IN ACPI JUMP WAKE TO 2 %x\n", vector);
+	
+	
+	* ((u32 *) (jump_to_wakeup+1)) = ((vector >> 4) << 16) | (vector & 0xf);
+	printk_debug("%x %x %x %x %x\n", jump_to_wakeup[0], jump_to_wakeup[1], jump_to_wakeup[2], jump_to_wakeup[3],jump_to_wakeup[4]);
+
+	memcpy ((void *) (0x1000 - sizeof (real_mode_switch) - 100),
+		real_mode_switch, sizeof (real_mode_switch));
+	memcpy ((void *) (0x1000 - 100), jump_to_wakeup, sizeof(jump_to_wakeup));
+
+	dump_mem(vector, ((u32) vector) + 4096);
+
+	/* Set up the IDT for real mode. */
+
+	asm volatile("lidt %0"::"m" (real_mode_idt));
+	
+	/* Set up a GDT from which we can load segment descriptors for real
+	   mode.  The GDT is not used in real mode; it is just needed here to
+	   prepare the descriptors. */
+
+	asm volatile("lgdt %0"::"m" (real_mode_gdt));
+
+	/* Load the data segment registers, and thus the descriptors ready for
+	   real mode.  The base address of each segment is 0x100, 16 times the
+	   selector value being loaded here.  This is so that the segment
+	   registers don't have to be reloaded after switching to real mode:
+	   the values are consistent for real mode operation already. */
+
+	__asm__ __volatile__ ("movl $0x0010,%%eax\n"
+				"\tmovl %%eax,%%ds\n"
+				"\tmovl %%eax,%%es\n"
+				"\tmovl %%eax,%%fs\n"
+				"\tmovl %%eax,%%gs\n"
+				"\tmovl %%eax,%%ss" : : : "eax");
+
+	/* Jump to the 16-bit code that we copied earlier.  It disables paging
+	   and the cache, switches to real mode, and jumps to the BIOS reset
+	   entry point. */
+
+	__asm__ __volatile__ ("ljmp $0x0008,%0"
+				:
+				: "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100)));
+}
+
+
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/a20.c
+ *
+ * Enable A20 gate (return -1 on failure)
+ */
+
+//#include "boot.h"
+
+#define MAX_8042_LOOPS	100000
+
+static int empty_8042(void)
+{
+	u8 status;
+	int loops = MAX_8042_LOOPS;
+
+	while (loops--) {
+		udelay(1);
+
+		status = inb(0x64);
+		if (status & 1) {
+			/* Read and discard input data */
+			udelay(1);
+			(void)inb(0x60);
+		} else if (!(status & 2)) {
+			/* Buffers empty, finished! */
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
+/* Returns nonzero if the A20 line is enabled.  The memory address
+   used as a test is the int $0x80 vector, which should be safe. */
+
+#define A20_TEST_ADDR	(4*0x80)
+#define A20_TEST_SHORT  32
+#define A20_TEST_LONG	2097152	/* 2^21 */
+
+static int a20_test(int loops)
+{
+	int ok = 0;
+	int saved, ctr;
+
+//	set_fs(0x0000);
+//	set_gs(0xffff);
+
+	saved = ctr =  *((u32*) A20_TEST_ADDR);
+
+	while (loops--) {
+		//wrfs32(++ctr, A20_TEST_ADDR);
+		
+		*((u32*) A20_TEST_ADDR) = ++ctr;
+		
+		udelay(1);	/* Serialize and make delay constant */
+		
+		ok = *((u32 *) A20_TEST_ADDR+0xffff0+0x10) ^ ctr;
+		if (ok)
+			break;
+	}
+
+	*((u32*) A20_TEST_ADDR) = saved;
+	return ok;
+}
+
+/* Quick test to see if A20 is already enabled */
+static int a20_test_short(void)
+{
+	return a20_test(A20_TEST_SHORT);
+}
+
+/* Longer test that actually waits for A20 to come on line; this
+   is useful when dealing with the KBC or other slow external circuitry. */
+static int a20_test_long(void)
+{
+	return a20_test(A20_TEST_LONG);
+}
+
+static void enable_a20_kbc(void)
+{
+	empty_8042();
+
+	outb(0xd1, 0x64);	/* Command write */
+	empty_8042();
+
+	outb(0xdf, 0x60);	/* A20 on */
+	empty_8042();
+}
+
+static void enable_a20_fast(void)
+{
+	u8 port_a;
+
+	port_a = inb(0x92);	/* Configuration port A */
+	port_a |=  0x02;	/* Enable A20 */
+	port_a &= ~0x01;	/* Do not reset machine */
+	outb(port_a, 0x92);
+}
+
+/*
+ * Actual routine to enable A20; return 0 on ok, -1 on failure
+ */
+
+#define A20_ENABLE_LOOPS 255	/* Number of times to try */
+
+int enable_a20(void)
+{
+	int loops = A20_ENABLE_LOOPS;
+
+	while (loops--) {
+		/* First, check to see if A20 is already enabled
+		   (legacy free, etc.) */
+		if (a20_test_short())
+			return 0;
+
+		/* Try enabling A20 through the keyboard controller */
+		empty_8042();
+//if (a20_test_short())
+//	return 0; /* BIOS worked, but with delayed reaction */
+
+		enable_a20_kbc();
+		if (a20_test_long())
+			return 0;
+
+		/* Finally, try enabling the "fast A20 gate" */
+		enable_a20_fast();
+		if (a20_test_long())
+			return 0;
+	}
+
+	return -1;
+}
+
+
 /**
  * @brief Main function of the DRAM part of coreboot.
  *
@@ -46,6 +333,12 @@
  * Device Enumeration:
  *	In the dev_enumerate() phase, 
  */
+ 
+
+ extern u32 wake_vec;
+
+void find_resume_vector(void);
+ 
 void hardwaremain(int boot_complete)
 {
 	struct lb_memory *lb_mem;
@@ -86,8 +379,32 @@
 	/* Now that we have collected all of our information
 	 * write our configuration tables.
 	 */
+
+#if 0
+
+{
+	u32 *p = 4*1024;
+	int i;
+
+	printk_debug("RAM check low poison.\r\n");
+
+	for (i=4*1024;i<640*1024;i+=4) {
+		if (p != (*p)) {
+			printk_debug("BAdness at %p data %x\n", p, *p);
+		}
+		p++;
+	}
+	
+
+}
+#endif
+
+	find_resume_vector();
+
+	if (wake_vec)
+		acpi_jump_wake(wake_vec);
+
 	lb_mem = write_tables();
-
 #if CONFIG_FS_PAYLOAD == 1
 	filo(lb_mem);
 #else
Index: src/northbridge/amd/amdk8/raminit.c
===================================================================
--- src/northbridge/amd/amdk8/raminit.c	(revision 4030)
+++ src/northbridge/amd/amdk8/raminit.c	(working copy)
@@ -2262,6 +2262,8 @@
 
 #endif
 
+#include "exit_from_self.c"
+
 #define TIMEOUT_LOOPS 300000
 #if RAMINIT_SYSINFO == 1
 static void sdram_enable(int controllers, const struct mem_controller *ctrl, struct sys_info *sysinfo)
Index: src/northbridge/amd/amdk8/raminit_f.c
===================================================================
--- src/northbridge/amd/amdk8/raminit_f.c	(revision 4030)
+++ src/northbridge/amd/amdk8/raminit_f.c	(working copy)
@@ -3008,12 +3008,15 @@
 }
 #endif
 
+#include "exit_from_self.c"
 
 static void sdram_enable(int controllers, const struct mem_controller *ctrl,
 			  struct sys_info *sysinfo)
 {
 	int i;
+	int s = acpi_is_wakeup_early();
 
+
 #if K8_REV_F_SUPPORT_F0_F1_WORKAROUND == 1
 	 unsigned cpu_f0_f1[8];
 	/* FIXME: How about 32 node machine later? */
@@ -3059,6 +3062,14 @@
 	printk_debug("\n");
 #endif
 
+	/* lets override the rest of the routine */
+	if (s) {
+		printk_debug("Wakeup!\n");
+		exit_from_self(controllers, ctrl, sysinfo);
+		printk_debug("Mem running !\n");
+		return;
+	}
+
 	for (i = 0; i < controllers; i++) {
 		uint32_t dcl, dch;
 		if (!sysinfo->ctrl_present[ i ])
@@ -3192,7 +3203,11 @@
    #if K8_REV_F_SUPPORT_F0_F1_WORKAROUND == 1
 	dqs_timing(controllers, ctrl, tsc0, sysinfo);
    #else
+	dump_pci_device_index_wait(ctrl->f2, 0x98);
+	
 	dqs_timing(controllers, ctrl, sysinfo);
+
+	dump_pci_device_index_wait(ctrl->f2, 0x98);
    #endif
 #else
 
@@ -3205,7 +3220,6 @@
 		/* Skip everything if I don't have any memory on this controller */
 		if (sysinfo->mem_trained[i]!=0x80)
 			continue;
-
 		dqs_timing(i, &ctrl[i], sysinfo, 1);
 
 #if MEM_TRAIN_SEQ == 1
@@ -3225,7 +3239,6 @@
 
 }
 
-
 static void fill_mem_ctrl(int controllers, struct mem_controller *ctrl_a,
 			   const uint16_t *spd_addr)
 {
Index: src/northbridge/amd/amdk8/raminit_f_dqs.c
===================================================================
--- src/northbridge/amd/amdk8/raminit_f_dqs.c	(revision 4030)
+++ src/northbridge/amd/amdk8/raminit_f_dqs.c	(working copy)
@@ -1824,7 +1824,131 @@
 
 #if MEM_TRAIN_SEQ == 0
 
+#define NVRAM_BASE 0xf00
 
+
+int save_nvram(u32 dword, int size, int  nvram_pos) {
+printk_debug("Writing %x of size %d to nvram pos: %d\n", dword, size, nvram_pos);
+switch (size) {
+	case 1:
+		outb((dword & 0xff), NVRAM_BASE+nvram_pos);
+		nvram_pos +=1;
+		break;
+	case 2:
+		outw((dword & 0xffff), NVRAM_BASE+nvram_pos);
+		nvram_pos +=2;
+		break;
+	default:
+		outl(dword, NVRAM_BASE+nvram_pos);
+		nvram_pos +=4;
+		break;
+}
+return nvram_pos;
+}
+
+int load_nvram(int size, u32 *old_dword, int nvram_pos) {
+
+switch (size) {
+	case 1:
+		*old_dword &= ~0xff;
+		*old_dword |= inb(NVRAM_BASE+nvram_pos);
+		nvram_pos +=1;
+		break;
+	case 2:
+		*old_dword &= ~0xffff;
+		*old_dword |= inw(NVRAM_BASE+nvram_pos);
+		nvram_pos +=2;
+		break;
+	default:
+		*old_dword = inl(NVRAM_BASE+nvram_pos);
+		nvram_pos +=4;
+		break;
+}
+printk_debug("Loading %x of size %d to nvram pos:%d\n", * old_dword, size, nvram_pos-size);
+
+return nvram_pos;
+}
+
+int save_index_to_pos(unsigned int dev, int size, int index, int nvram_pos) {
+	u32 dword = pci_read_config32_index_wait(dev, 0x98, index);
+
+	return save_nvram(dword, size, nvram_pos);
+}
+
+int load_index_to_pos(unsigned int dev, int size, int index, int nvram_pos) {
+
+	u32 old_dword = pci_read_config32_index_wait(dev, 0x98, index);
+	nvram_pos = load_nvram(size, &old_dword, nvram_pos);
+	pci_write_config32_index_wait(dev, 0x98, index, old_dword);
+	return nvram_pos;
+}
+
+int dqs_load_MC_NVRAM_ch(unsigned int dev, int ch, int pos) {
+	/* 30 bytes per channel */
+	ch *= 0x20;
+	pos = load_index_to_pos(dev, 4, 0x00 + ch, pos);
+	pos = load_index_to_pos(dev, 4, 0x01 + ch, pos);
+	pos = load_index_to_pos(dev, 4, 0x02 + ch, pos);
+	pos = load_index_to_pos(dev, 1, 0x03 + ch, pos);
+	pos = load_index_to_pos(dev, 4, 0x04 + ch, pos);
+	pos = load_index_to_pos(dev, 4, 0x05 + ch, pos);
+	pos = load_index_to_pos(dev, 4, 0x06 + ch, pos);
+	pos = load_index_to_pos(dev, 1, 0x07 + ch, pos);
+	pos = load_index_to_pos(dev, 1, 0x10 + ch, pos);
+	pos = load_index_to_pos(dev, 1, 0x13 + ch, pos);
+	pos = load_index_to_pos(dev, 1, 0x16 + ch, pos);
+	pos = load_index_to_pos(dev, 1, 0x19 + ch, pos);
+	return pos;
+}
+
+
+
+int dqs_save_MC_NVRAM_ch(unsigned int dev, int ch, int pos) {
+	/* 30 bytes per channel */
+	ch *= 0x20;
+	pos = save_index_to_pos(dev, 4, 0x00 + ch, pos);
+	pos = save_index_to_pos(dev, 4, 0x01 + ch, pos);
+	pos = save_index_to_pos(dev, 4, 0x02 + ch, pos);
+	pos = save_index_to_pos(dev, 1, 0x03 + ch, pos);
+	pos = save_index_to_pos(dev, 4, 0x04 + ch, pos);
+	pos = save_index_to_pos(dev, 4, 0x05 + ch, pos);
+	pos = save_index_to_pos(dev, 4, 0x06 + ch, pos);
+	pos = save_index_to_pos(dev, 1, 0x07 + ch, pos);
+	pos = save_index_to_pos(dev, 1, 0x10 + ch, pos);
+	pos = save_index_to_pos(dev, 1, 0x13 + ch, pos);
+	pos = save_index_to_pos(dev, 1, 0x16 + ch, pos);
+	pos = save_index_to_pos(dev, 1, 0x19 + ch, pos);
+	return pos;
+}
+
+void dqs_save_MC_NVRAM(unsigned int dev) {
+int pos = 0;
+u32 reg;
+printk_debug("DQS SAVE NVRAM: %x\n", dev);
+pos = dqs_save_MC_NVRAM_ch(dev, 0, pos);
+pos = dqs_save_MC_NVRAM_ch(dev, 1, pos);
+/* save the maxasync lat here */
+	reg = pci_read_config32(dev, DRAM_CONFIG_HIGH);
+	pos = save_nvram(reg, 4, pos);
+//	reg &= ~(DCH_MaxAsyncLat_MASK <<DCH_MaxAsyncLat_SHIFT);
+//	reg |= ((dly - DCH_MaxAsyncLat_BASE) << DCH_MaxAsyncLat_SHIFT);
+//	pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, reg);
+}
+
+void dqs_restore_MC_NVRAM(unsigned int dev) {
+	int pos = 0;
+	u32 reg;
+
+printk_debug("DQS RESTORE FROM NVRAM: %x\n", dev);
+	pos = dqs_load_MC_NVRAM_ch(dev, 0, pos);
+	pos = dqs_load_MC_NVRAM_ch(dev, 1, pos);
+	/* save the maxasync lat here */
+	pos = load_nvram(4, &reg, pos);
+	reg &= (DCH_MaxAsyncLat_MASK <<DCH_MaxAsyncLat_SHIFT);
+	reg |= pci_read_config32(dev, DRAM_CONFIG_HIGH);
+	pci_write_config32(dev, DRAM_CONFIG_HIGH, reg);
+}
+
 #if K8_REV_F_SUPPORT_F0_F1_WORKAROUND == 1
 static void dqs_timing(int controllers, const struct mem_controller *ctrl, tsc_t *tsc0, struct sys_info *sysinfo)
 #else
@@ -1832,7 +1956,6 @@
 #endif
 {
 	int  i;
-
 	tsc_t tsc[5];
 
 	//need to enable mtrr, so dqs training could access the test address
@@ -1891,13 +2014,13 @@
 		if(train_DqsRcvrEn(ctrl+i, 2, sysinfo)) goto out;
 		printk_debug(" done\r\n");
 		sysinfo->mem_trained[i]=1;
+		dqs_save_MC_NVRAM((ctrl+i)->f2);
 	}
 
 out:
 	tsc[4] = rdtsc();
 	clear_mtrr_dqs(sysinfo->tom2_k);
 
-
 	for(i=0;i<5;i++) {
 		print_debug_dqs_tsc_x("DQS Training:tsc", i,  tsc[i].hi, tsc[i].lo);
 	}
Index: src/arch/i386/boot/acpi.c
===================================================================
--- src/arch/i386/boot/acpi.c	(revision 4030)
+++ src/arch/i386/boot/acpi.c	(working copy)
@@ -324,14 +324,43 @@
 	header->checksum	= acpi_checksum((void *)hpet, sizeof(acpi_hpet_t));
 }
 
+
+
+u32 wake_vec;
+
+
+extern u8 acpi_sleep_type;
+
+int acpi_is_wakeup(void) {
+	return (acpi_sleep_type == 3);
+}
+
+/* FIXME */
+#warning HACK!
+acpi_facs_t *facs = 0x1BFF0080;
+void find_resume_vector()
+{
+	if (acpi_is_wakeup()) {
+       wake_vec = facs->firmware_waking_vector;
+		printk_debug("OS waking vector is %x\n", wake_vec);
+	} else {
+		wake_vec = 0;
+	}
+}
+
+
 void acpi_create_facs(acpi_facs_t *facs)
 {
+	
 	memset( (void *)facs,0, sizeof(acpi_facs_t));
 
 	memcpy(facs->signature,"FACS",4);
 	facs->length = sizeof(acpi_facs_t);
 	facs->hardware_signature = 0;
+	
 	facs->firmware_waking_vector = 0;
+	wake_vec = 0;
+	
 	facs->global_lock = 0;
 	facs->flags = 0;
 	facs->x_firmware_waking_vector_l = 0;
Index: targets/asus/m2v-mx_se/Config.lb
===================================================================
--- targets/asus/m2v-mx_se/Config.lb	(revision 4030)
+++ targets/asus/m2v-mx_se/Config.lb	(working copy)
@@ -21,7 +21,7 @@
 mainboard asus/m2v-mx_se
 
 romimage "normal"
-	option ROM_SIZE = 512 * 1024
+	option ROM_SIZE =  (512 * 1024) - 39424
 	option USE_FALLBACK_IMAGE = 0
 	option ROM_IMAGE_SIZE = 128 * 1024
 	option COREBOOT_EXTRA_VERSION=".0Normal"

Attachment: s3_stuff.patch.sig
Description: Binary data

-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to