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

Hello all,

This patch is a WIP patch to get working S3 on AM2 boards. Currently it works on
 M2V-MX SE. The resume code does only the ram init right. No code which
saves/restores mem is there. It is not yet usable.

I needed to implement DQS timming save restore. I use NVRAM in K8M890 for this.
The SB600 has also such NVRAM.

There is quite strange errata for mine CPU, so the exit self refresh code is
strange.

Rudolf

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

iEYEARECAAYFAkm0OO4ACgkQ3J9wPJqZRNX+6wCg1SMFCEW8IDccBBJWcRV9KtaL
jU4An2rIGM5/nU6j/0AErME5oVSdPtSO
=SoLP
-----END PGP SIGNATURE-----
Index: src/southbridge/via/vt8237r/vt8237r_early_smbus.c
===================================================================
--- src/southbridge/via/vt8237r/vt8237r_early_smbus.c.orig	2009-02-20 21:09:55.030559516 +0100
+++ src/southbridge/via/vt8237r/vt8237r_early_smbus.c	2009-02-20 21:10:50.111343851 +0100
@@ -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/k8t890/k8t890_host_ctrl.c
===================================================================
--- src/southbridge/via/k8t890/k8t890_host_ctrl.c.orig	2009-02-20 21:09:55.151903475 +0100
+++ src/southbridge/via/k8t890/k8t890_host_ctrl.c	2009-02-24 22:31:35.653316192 +0100
@@ -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.orig	2009-02-20 21:09:55.162558464 +0100
+++ src/southbridge/via/k8t890/k8t890.h	2009-02-24 22:36:42.280565095 +0100
@@ -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/mainboard/asus/m2v-mx_se/dsdt.asl
===================================================================
--- src/mainboard/asus/m2v-mx_se/dsdt.asl.orig	2009-02-20 21:09:55.162558464 +0100
+++ src/mainboard/asus/m2v-mx_se/dsdt.asl	2009-03-08 21:20:36.655758732 +0100
@@ -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/northbridge/amd/amdk8/raminit_f.c
===================================================================
--- src/northbridge/amd/amdk8/raminit_f.c.orig	2009-02-20 21:09:55.167310746 +0100
+++ src/northbridge/amd/amdk8/raminit_f.c	2009-02-24 23:32:42.261564904 +0100
@@ -3008,11 +3008,14 @@
 }
 #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];
@@ -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/exit_from_self.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/northbridge/amd/amdk8/exit_from_self.c	2009-03-08 22:14:27.180728554 +0100
@@ -0,0 +1,154 @@
+
+void exit_from_self(int controllers, const struct mem_controller *ctrl,
+			  struct sys_info *sysinfo) {
+	int i;
+	u32 dcl, dch;
+	u32 pcidev;
+	u8 bitmask;
+
+	for (i = 0; i < controllers; i++) {
+		if (!sysinfo->ctrl_present[ i ])
+			continue;
+		/* Skip everything if I don't have any memory on this controller */
+		dch = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_HIGH);
+		if (!(dch & DCH_MemClkFreqVal)) {
+			continue;
+		}
+
+		/* ChipKill */
+		dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
+		if (dcl & DCL_DimmEccEn) {
+			uint32_t mnc;
+			printk_spew("ECC enabled\n");
+			mnc = pci_read_config32(ctrl[i].f3, MCA_NB_CONFIG);
+			mnc |= MNC_ECC_EN;
+			if (dcl & DCL_Width128) {
+				mnc |= MNC_CHIPKILL_EN;
+			}
+			pci_write_config32(ctrl[i].f3, MCA_NB_CONFIG, mnc);
+		}
+
+	printk_debug("before exit errata\n");
+		/* 
+		1. Restore memory controller registers as normal.
+2. Set the DisAutoRefresh bit (Dev:2x8C[18]).
+3. Set the EnDramInit bit (Dev:2x7C[31]), clear all other bits in the same register).
+4. Wait at least 750 us.
+5. Clear the EnDramInit bit.
+6. Clear the DisAutoRefresh bit.
+7. Read the value of Dev:2x80 and write that value back to Dev:2x80.
+8. Set the exit from the self refresh bit (Dev:2x90[1]).
+9. Clear the exit from self refresh bit immediately.
+Note: Steps 8 and 9 must be executed in a single 64-byte aligned uninterrupted instruction stream.
+*/
+
+		enable_lapic();
+	printk_debug("before exit errata - lapic enabled\n");
+
+		init_timer();
+
+	printk_debug("before exit errata - timer enabled\n");
+
+		dcl = pci_read_config32(ctrl[i].f2, DRAM_TIMING_HIGH);
+		dcl |= (1 << 18);
+		pci_write_config32(ctrl[i].f2, DRAM_TIMING_HIGH, dcl);
+
+		dcl = DI_EnDramInit;
+		pci_write_config32(ctrl[i].f2, DRAM_INIT, dcl);
+
+		delay(1);
+
+	printk_debug("before exit errata - after mdelay\n");
+
+		dcl = pci_read_config32(ctrl[i].f2, DRAM_INIT);
+		dcl &= ~DI_EnDramInit;
+		pci_write_config32(ctrl[i].f2, DRAM_INIT, dcl);
+
+		dcl = pci_read_config32(ctrl[i].f2, DRAM_TIMING_HIGH);
+		dcl &= ~(1 << 18);
+		pci_write_config32(ctrl[i].f2, DRAM_TIMING_HIGH, dcl);
+
+		dcl = pci_read_config32(ctrl[i].f2, DRAM_BANK_ADDR_MAP);
+		pci_write_config32(ctrl[i].f2, DRAM_BANK_ADDR_MAP, dcl);
+
+
+		pcidev = 0x80000000 | (((0x18 << 3) | 0x2 ) << 8) | 0x90;
+		bitmask = 2;
+		__asm__ __volatile__(
+		"pushl %0\n\t"
+		"movw $0xcf8, %%dx\n\t"
+		"out %%eax, (%%dx)\n\t"
+		"movw $0xcfc, %%dx\n\t"
+		"inb %%dx, %%al\n\t"
+		"orb %1, %%al\n\t"
+		"not %1\n\t"
+		".align 64\n\t"
+		"out  %%al, (%%dx) \n\t"
+		"andb %1, %%al\n\t"
+		"out %%al, (%%dx)\n\t"
+		"popl %0\n\t"
+		: : "a" (pcidev) , "q" (bitmask) : "edx");
+	}
+
+	printk_debug("after exit errata\n");
+
+
+	for (i = 0; i < controllers; i++) {
+		uint32_t dcm;
+		if (!sysinfo->ctrl_present[ i ])
+			continue;
+		/* Skip everything if I don't have any memory on this controller */
+		if (sysinfo->meminfo[i].dimm_mask==0x00) continue;
+
+		printk_debug("Exiting memory from self refresh: ");
+		int loops = 0;
+		do {
+			loops++;
+			if ((loops & 1023) == 0) {
+				printk_debug(".");
+			}
+			dcm = pci_read_config32(ctrl[i].f2, DRAM_CTRL_MISC);
+		} while(((dcm & DCM_MemClrStatus) == 0) /* || ((dcm & DCM_DramEnabled) == 0)*/ );
+
+		if (loops >= TIMEOUT_LOOPS) {
+			printk_debug(" failed\n");
+			continue;
+		}
+
+		printk_debug(" done\n");
+	}
+
+#if HW_MEM_HOLE_SIZEK != 0
+	/* init hw mem hole here */
+	/* DramHoleValid bit only can be set after MemClrStatus is set by Hardware */
+	set_hw_mem_hole(controllers, ctrl);
+#endif
+
+	/* store tom to sysinfo, and it will be used by dqs_timing */
+	{
+		msr_t msr;
+		//[1M, TOM)
+		msr = rdmsr(TOP_MEM);
+		sysinfo->tom_k = ((msr.hi<<24) | (msr.lo>>8))>>2;
+
+		//[4G, TOM2)
+		msr = rdmsr(TOP_MEM2);
+		sysinfo->tom2_k = ((msr.hi<<24)| (msr.lo>>8))>>2;
+	}
+
+	for (i = 0; i < controllers; i++) {
+
+		dqs_restore_MC_NVRAM((ctrl+i)->f2);
+
+		sysinfo->mem_trained[i] = 1; // mem was trained
+
+		if (!sysinfo->ctrl_present[ i ])
+			continue;
+
+		/* Skip everything if I don't have any memory on this controller */
+		if (sysinfo->meminfo[i].dimm_mask==0x00)
+			continue;
+
+	}
+}
+
Index: src/northbridge/amd/amdk8/raminit_f_dqs.c
===================================================================
--- src/northbridge/amd/amdk8/raminit_f_dqs.c.orig	2009-02-24 23:49:24.488565053 +0100
+++ src/northbridge/amd/amdk8/raminit_f_dqs.c	2009-02-24 23:37:22.000000000 +0100
@@ -1824,6 +1824,130 @@
 
 #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)
@@ -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/cpu/amd/model_fxx/fidvid.c
===================================================================
--- src/cpu/amd/model_fxx/fidvid.c.orig	2009-03-01 18:27:08.690239405 +0100
+++ src/cpu/amd/model_fxx/fidvid.c	2009-03-01 18:29:31.874238495 +0100
@@ -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/mainboard/asus/m2v-mx_se/cache_as_ram_auto.c
===================================================================
--- src/mainboard/asus/m2v-mx_se/cache_as_ram_auto.c.orig	2009-03-08 20:19:04.499726000 +0100
+++ src/mainboard/asus/m2v-mx_se/cache_as_ram_auto.c	2009-03-08 21:23:32.607726343 +0100
@@ -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/southbridge/via/vt8237r/vt8237r_lpc.c
===================================================================
--- src/southbridge/via/vt8237r/vt8237r_lpc.c.orig	2009-03-08 21:02:44.324726369 +0100
+++ src/southbridge/via/vt8237r/vt8237r_lpc.c	2009-03-08 21:08:14.004727530 +0100
@@ -27,6 +27,7 @@
 #include <pc80/mc146818rtc.h>
 #include <cpu/x86/lapic.h>
 #include <pc80/keyboard.h>
+#include <pc80/i8259.h>
 #include <stdlib.h>
 #include "vt8237r.h"
 #include "chip.h"
@@ -47,7 +48,6 @@
 #define INT		(1 << 8)
 
 extern void dump_south(device_t dev);
-extern void setup_i8259(void);
 
 static struct ioapicreg {
 	u32 reg;
@@ -171,10 +171,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
Index: src/superio/ite/it8712f/it8712f_early_serial.c
===================================================================
--- src/superio/ite/it8712f/it8712f_early_serial.c.orig	2009-03-08 21:24:00.671727808 +0100
+++ src/superio/ite/it8712f/it8712f_early_serial.c	2009-03-08 21:33:55.472384905 +0100
@@ -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();

Attachment: ram_resume.patch.sig
Description: Binary data

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

Reply via email to