This adds a cbmem_toc_ptr_t structure, which is written just below the FADT,
so we can find it using the FADP information.  The actual writing is only
implemented for the Intel 82371EB southbridge.

Also adds code to acpi.c resume codepath to use this pointer when the chipset
has not overridden the weak get_cbmem_toc() function.

Effectively the latter part affects all boards that already implement ACPI S2
or S3 resume, but shouldn't change behaviour since none of them generate the
structure:

asus/m2v
asus/m4a785-m
asus/m2v-mx_se
gigabyte/ma78gm
gigabyte/ma785gmt
jetway/pa78vm5
iwill/dk8_htx
asrock/939a785gmh
amd/dbm690t
amd/mahogany
amd/tilapia_fam10
amd/pistachio
amd/serengeti_cheetah_fam10
amd/serengeti_cheetah
amd/mahogany_fam10
kontron/kt690
iei/kino-780am2-fam10
technexion/tim5690
technexion/tim8690

BTW, via/epia-m700 defines HAVE_ACPI_TABLES, but does not supply a dsdt.asl
(only a get_dsdt script)

Signed-off-by: Tobias Diedrich <ranma+coreboot@tdiedrich.de>

---

Index: src/arch/i386/boot/acpi.c
===================================================================
--- src/arch/i386/boot/acpi.c.orig	2010-12-01 19:11:35.000000000 +0100
+++ src/arch/i386/boot/acpi.c	2010-12-01 19:11:36.000000000 +0100
@@ -517,6 +517,7 @@
 	acpi_rsdt_t *rsdt;
 	acpi_facs_t *facs;
 	acpi_fadt_t *fadt;
+	cbmem_toc_ptr_t *cbmem_tocp;
 	void *wake_vec;
 	int i;
 
@@ -537,11 +538,22 @@
 		return NULL;
 
 	printk(BIOS_DEBUG, "RSDP found at %p\n", rsdp);
+	cbmem_tocp = (cbmem_toc_ptr_t *)(rsdp->rsdt_address - sizeof(cbmem_toc_ptr_t));
 	rsdt = (acpi_rsdt_t *) rsdp->rsdt_address;
 
 	end = (char *)rsdt + rsdt->header.length;
 	printk(BIOS_DEBUG, "RSDT found at %p ends at %p\n", rsdt, end);
 
+	if (get_cbmem_toc() == 0) { /* Only use cbmem_tocp if there is no chipset override */
+		if (cbmem_tocp->sig != CBMEM_TOC_PTR_SIG) {
+			printk(BIOS_DEBUG, "cbmem toc pointer not found at %p (sig %08x sz %d)\n", cbmem_tocp, cbmem_tocp->sig, sizeof(cbmem_toc_ptr_t));
+			return NULL;
+		}
+		set_cbmem_toc(cbmem_tocp->ptr);
+	} else {
+		printk(BIOS_DEBUG, "cbmem toc is at %p\n", get_cbmem_toc());
+	}
+
 	for (i = 0; ((char *)&rsdt->entry[i]) < end; i++) {
 		fadt = (acpi_fadt_t *)rsdt->entry[i];
 		if (strncmp((char *)fadt, "FACP", 4) == 0)
Index: src/southbridge/intel/i82371eb/acpi_tables.c
===================================================================
--- src/southbridge/intel/i82371eb/acpi_tables.c.orig	2010-12-01 19:11:35.000000000 +0100
+++ src/southbridge/intel/i82371eb/acpi_tables.c	2010-12-01 19:11:36.000000000 +0100
@@ -26,6 +26,7 @@
 #include <arch/smp/mpspec.h>
 #include <device/device.h>
 #include <device/pci_ids.h>
+#include <cbmem.h>
 #include "i82371eb.h"
 
 extern const unsigned char AmlCode[];
@@ -104,6 +105,7 @@
 unsigned long __attribute__((weak)) write_acpi_tables(unsigned long start)
 {
 	unsigned long current;
+	cbmem_toc_ptr_t *cbmem_tocp;
 	acpi_rsdp_t *rsdp;
 	acpi_rsdt_t *rsdt;
 	acpi_fadt_t *fadt;
@@ -113,20 +115,28 @@
 	acpi_header_t *dsdt;
 
 	/* Align ACPI tables to 16 byte. */
-	start = (start + 0x0f) & -0x10;
-	current = start;
+	current = ALIGN(start, 16);
 
 	printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx...\n", start);
 
 	/* We need at least an RSDP and an RSDT table. */
 	rsdp = (acpi_rsdp_t *) current;
 	current += sizeof(acpi_rsdp_t);
+
+	/* put cbmem toc ptr structure directly below rsdt */
+	printk(BIOS_INFO, "ACPI: Writing cbmem_toc pointer at %lx...\n", current);
+	cbmem_tocp = (cbmem_toc_ptr_t *) current;
+	current += sizeof(cbmem_toc_ptr_t);
+
 	rsdt = (acpi_rsdt_t *) current;
 	current += sizeof(acpi_rsdt_t);
 
 	/* Clear all table memory. */
 	memset((void *) start, 0, current - start);
 
+	cbmem_tocp->sig = CBMEM_TOC_PTR_SIG;
+	cbmem_tocp->ptr = get_cbmem_toc();
+
 	acpi_write_rsdp(rsdp, rsdt, NULL);
 	acpi_write_rsdt(rsdt);
 
Index: src/include/cbmem.h
===================================================================
--- src/include/cbmem.h.orig	2010-12-01 19:11:35.000000000 +0100
+++ src/include/cbmem.h	2010-12-01 19:11:36.000000000 +0100
@@ -39,6 +39,13 @@
 #define CBMEM_ID_RESUME		0x5245534d
 #define CBMEM_ID_NONE		0x00000000
 
+#define CBMEM_TOC_PTR_SIG	0x43425443
+
+typedef struct cbmem_toc_ptr {
+	u32 sig;
+	void *ptr;
+} __attribute__((packed)) cbmem_toc_ptr_t;
+
 void cbmem_initialize(void);
 
 void cbmem_init(u64 baseaddr, u64 size);
Index: src/lib/cbmem.c
===================================================================
--- src/lib/cbmem.c.orig	2010-12-01 19:11:35.000000000 +0100
+++ src/lib/cbmem.c	2010-12-01 19:11:36.000000000 +0100
@@ -52,6 +52,9 @@
 
 static struct cbmem_entry *bss_cbmem_toc;
 
+/* chipset can override get/set_cbmem_toc to store the cbmem_toc address
+ * in nvram if available */
+
 struct cbmem_entry *__attribute__((weak)) get_cbmem_toc(void)
 {
 	return bss_cbmem_toc;
@@ -59,7 +62,7 @@
 
 void __attribute__((weak)) set_cbmem_toc(struct cbmem_entry * x)
 {
-	/* do nothing, this should be called by chipset to save TOC in NVRAM */
+	bss_cbmem_toc = x;
 }
 
 #endif



