Patchwork Initial bits to support Thinkpad X60

login
register
about
Submitter Sven Schnelle
Date 2011-01-10 12:44:34
Message ID <87hbdhkjwt.fsf@begreifnix.stackframe.org>
Download mbox | patch
Permalink /patch/2503/
State Superseded
Headers show

Comments

Sven Schnelle - 2011-01-10 12:44:34
Paul Menzel <paulepanter@users.sourceforge.net> writes:

>> I'm adding the current version as diff to this email, in case anybody
>> wants to play with the code. Not sure if "it boot's Linux' is enough to
>> go into the coreboot SVN.
>
> It at least needs your Signed-off-by line [1].

Sorry, missed that. Trying again.

> Maybe you could also publish your Git tree on your server.

You may clone the tree with:

git clone git://git.stackframe.org/coreboot. Development Tree is 'X60'.

gitweb lives at http://git.stackframe.org/?p=coreboot;a=summary

Regards,

Sven.

commit 7d3a1ebf3de5746d3dec8f47e74458c15018c694
Author: Sven Schnelle <svens@stackframe.org>
Date:   Mon Jan 10 13:23:59 2011 +0100

    Initial bits for X60 support
    
    Signed-off-by: Sven Schnelle <svens@stackframe.org>
Peter Stuge - 2011-01-10 20:34:13
Nice, a ThinkPad patch! :) Many have wanted that.

Sven Schnelle wrote:
> commit 7d3a1ebf3de5746d3dec8f47e74458c15018c694
> Author: Sven Schnelle <svens@stackframe.org>
> Date:   Mon Jan 10 13:23:59 2011 +0100
> 
>     Initial bits for X60 support
>     
>     Signed-off-by: Sven Schnelle <svens@stackframe.org>

Well the commit is quite a lot more than initial bits for support. :)

Could you split this up in a few more commits? E.g. one that adds the
CPU model to the socket, one for speedstep (maybe combine them if
appropriate) and then the one that adds the new board?

Also, in particular for the patch that adds the new board, it is
quite beneficial to use svn cp to copy files and *then* modify them
for the new boards - that way the history is kept and the patch is
much easier to look at. I am not sure how well git svn supports these
operations. Maybe it does, but I haven't tried it.


//Peter
Sven Schnelle - 2011-01-11 13:13:50
Hi Peter,

Peter Stuge <peter@stuge.se> writes:

> Nice, a ThinkPad patch! :) Many have wanted that.
>
> Sven Schnelle wrote:
>> commit 7d3a1ebf3de5746d3dec8f47e74458c15018c694
>> Author: Sven Schnelle <svens@stackframe.org>
>> Date:   Mon Jan 10 13:23:59 2011 +0100
>> 
>>     Initial bits for X60 support
>>     
>>     Signed-off-by: Sven Schnelle <svens@stackframe.org>
>
> Well the commit is quite a lot more than initial bits for support. :)
>
> Could you split this up in a few more commits? E.g. one that adds the
> CPU model to the socket, one for speedstep (maybe combine them if
> appropriate) and then the one that adds the new board?

Hmm, i would first really appreciate comments from People who know the
CAR code if the modification is correct. I don't know the code well
enough to tell for sure.

But it should be not that big problem to split up the patches.

> Also, in particular for the patch that adds the new board, it is
> quite beneficial to use svn cp to copy files and *then* modify them
> for the new boards - that way the history is kept and the patch is
> much easier to look at. I am not sure how well git svn supports these
> operations. Maybe it does, but I haven't tried it.

Hmm, so i should 'svn cp' files like romstage.c, mainboard.c, etc?
Is the history really helpful if the target is different?

Regards,

Sven.
Stefan Reinauer - 2011-01-12 02:05:09
* Peter Stuge <peter@stuge.se> [110110 21:34]:
> Nice, a ThinkPad patch! :) Many have wanted that.
> 
> Sven Schnelle wrote:
> > commit 7d3a1ebf3de5746d3dec8f47e74458c15018c694
> > Author: Sven Schnelle <svens@stackframe.org>
> > Date:   Mon Jan 10 13:23:59 2011 +0100
> > 
> >     Initial bits for X60 support
> >     
> >     Signed-off-by: Sven Schnelle <svens@stackframe.org>
> 
> Well the commit is quite a lot more than initial bits for support. :)
> 
> Could you split this up in a few more commits? E.g. one that adds the
> CPU model to the socket, one for speedstep (maybe combine them if
> appropriate) and then the one that adds the new board?

Not sure we want to use that socket as it is the container for all the
old CPUs. Sure it isn't a mFCPGA478 'cause that's what Merom/Yonah
usually use.

Stefan
Sven Schnelle - 2011-01-12 08:14:46
Hi Stefan,

Stefan Reinauer <stepan@coreboot.org> writes:
>
> Not sure we want to use that socket as it is the container for all the
> old CPUs. Sure it isn't a mFCPGA478 'cause that's what Merom/Yonah
> usually use.

Intel Spec Finder (http://ark.intel.com/Product.aspx?id=27228) says it's
'PBGA479' which is soldered directly to the Board, so mPGA479M looked
like the best fit. But the mFCPGA478 works without modifications, so we
may use that.

I have no problem changing the code to 478, i'm just not sure what the
right Socket is.

Regards,

Sven

Patch

diff --git a/src/cpu/intel/socket_mPGA479M/Makefile.inc b/src/cpu/intel/socket_mPGA479M/Makefile.inc
index 260d1c8..83e6049 100644
--- a/src/cpu/intel/socket_mPGA479M/Makefile.inc
+++ b/src/cpu/intel/socket_mPGA479M/Makefile.inc
@@ -1,6 +1,7 @@ 
 ramstage-y += socket_mPGA479M.c
 subdirs-y += ../model_69x
 subdirs-y += ../model_6dx
+subdirs-y += ../model_6ex
 subdirs-y += ../model_f2x
 subdirs-y += ../../x86/tsc
 subdirs-y += ../../x86/mtrr
@@ -9,5 +10,5 @@  subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/smm
 subdirs-y += ../microcode
 subdirs-y += ../hyperthreading
+subdirs-y += ../speedstep
 
-cpu_incs += $(src)/cpu/intel/car/cache_as_ram.inc
diff --git a/src/mainboard/Kconfig b/src/mainboard/Kconfig
index cbee0a0..e86c310 100644
--- a/src/mainboard/Kconfig
+++ b/src/mainboard/Kconfig
@@ -54,6 +54,8 @@  config VENDOR_IBASE
 	bool "iBase"
 config VENDOR_IBM
 	bool "IBM"
+config VENDOR_LENOVO
+	bool "Lenovo"
 config VENDOR_IEI
 	bool "IEI"
 config VENDOR_INTEL
@@ -147,6 +149,7 @@  source "src/mainboard/iwill/Kconfig"
 source "src/mainboard/jetway/Kconfig"
 source "src/mainboard/kontron/Kconfig"
 source "src/mainboard/lanner/Kconfig"
+source "src/mainboard/lenovo/Kconfig"
 source "src/mainboard/lippert/Kconfig"
 source "src/mainboard/mitac/Kconfig"
 source "src/mainboard/msi/Kconfig"
diff --git a/src/mainboard/lenovo/Kconfig b/src/mainboard/lenovo/Kconfig
new file mode 100644
index 0000000..580c4a8
--- /dev/null
+++ b/src/mainboard/lenovo/Kconfig
@@ -0,0 +1,17 @@ 
+if VENDOR_LENOVO
+
+choice
+	prompt "Mainboard model"
+
+config BOARD_LENOVO_X60
+	bool "Thinkpad X60"
+
+endchoice
+
+source "src/mainboard/lenovo/x60/Kconfig"
+
+config MAINBOARD_VENDOR
+	string
+	default "Lenovo"
+
+endif # VENDOR_LENOVO
diff --git a/src/mainboard/lenovo/x60/Kconfig b/src/mainboard/lenovo/x60/Kconfig
new file mode 100644
index 0000000..c71f8a5
--- /dev/null
+++ b/src/mainboard/lenovo/x60/Kconfig
@@ -0,0 +1,53 @@ 
+if BOARD_LENOVO_X60
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+	def_bool y
+	select ARCH_X86
+	select CPU_INTEL_CORE
+	select CPU_INTEL_SOCKET_MPGA479M
+	select NORTHBRIDGE_INTEL_I945GM
+	select SOUTHBRIDGE_INTEL_I82801GX
+	select BOARD_HAS_FADT
+	select HAVE_OPTION_TABLE
+	select HAVE_PIRQ_TABLE
+	select HAVE_MP_TABLE
+	select MMCONF_SUPPORT
+	select HAVE_SMI_HANDLER
+	select HAVE_ACPI_TABLES
+#	select HAVE_ACPI_RESUME
+	select BOARD_ROMSIZE_KB_1024
+	select CHANNEL_XOR_RANDOMIZATION
+
+config MAINBOARD_DIR
+	string
+	default lenovo/x60
+
+config DCACHE_RAM_BASE
+	hex
+	default 0xffdf8000
+
+config DCACHE_RAM_SIZE
+	hex
+	default 0x8000
+
+config MAINBOARD_PART_NUMBER
+	string
+	default "X60"
+
+config MMCONF_BASE_ADDRESS
+	hex
+	default 0xf0000000
+
+config IRQ_SLOT_COUNT
+	int
+	default 18
+
+config MAX_CPUS
+	int
+	default 2
+
+config MAX_PHYSICAL_CPUS
+	int
+	default 1
+
+endif
diff --git a/src/mainboard/lenovo/x60/Makefile.inc b/src/mainboard/lenovo/x60/Makefile.inc
new file mode 100644
index 0000000..10f00a0
--- /dev/null
+++ b/src/mainboard/lenovo/x60/Makefile.inc
@@ -0,0 +1,20 @@ 
+##
+## This file is part of the coreboot project.
+##
+## Copyright (c) 2011 Sven Schnelle <svens@stackframe.org>
+##
+## 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
+##
+
+smm-$(CONFIG_HAVE_SMI_HANDLER) += mainboard_smi.c
diff --git a/src/mainboard/lenovo/x60/acpi_tables.c b/src/mainboard/lenovo/x60/acpi_tables.c
new file mode 100644
index 0000000..0a34673
--- /dev/null
+++ b/src/mainboard/lenovo/x60/acpi_tables.c
@@ -0,0 +1,364 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * 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 <string.h>
+#include <console/console.h>
+#include <arch/io.h>
+#include <arch/ioapic.h>
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
+#include <arch/smp/mpspec.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include "dmi.h"
+
+extern const unsigned char AmlCode[];
+#if CONFIG_HAVE_ACPI_SLIC
+unsigned long acpi_create_slic(unsigned long current);
+#endif
+
+#define OLD_ACPI 0
+#if OLD_ACPI
+static void acpi_create_gnvs(global_nvs_t *gnvs)
+{
+	memset (gnvs, 0, sizeof(global_nvs_t));
+
+	gnvs->LIDS = 1;
+	gnvs->PWRS = 1;
+
+	gnvs->ACTT = 0x37;
+	gnvs->PSVT = 0x4f;
+
+	gnvs->TC1V = 0x00;
+	gnvs->TC2V = 0x0a;
+	gnvs->TSPV = 0x02;
+
+	gnvs->CRTT = 0x77;
+
+	gnvs->B0SC = 0x54;
+	gnvs->APIC = 0x01;
+	gnvs->MPEN = 0x01;
+
+	gnvs->PPCM = 0x02;
+	gnvs->PCP0 = 0xbf;
+	gnvs->PCP1 = 0xbf;
+
+	gnvs->CMAP = 0x01;
+	gnvs->CMBP = 0x01;
+	gnvs->LT0  = 0x01;
+	gnvs->FDCP = 0x01;
+	gnvs->CMCP = 0x01;
+	gnvs->CMDP = 0x01;
+	gnvs->P2M  = 0x02;
+
+	gnvs->IGDS = 0x01;
+
+	gnvs->CADL = 0x09;
+	gnvs->PADL = 0x09;
+
+	gnvs->NDID = 3;
+	gnvs->DID1 = 0x80000100;
+	gnvs->DID2 = 0x80000240;
+	gnvs->DID3 = 0x80000410;
+	gnvs->DID4 = 0x80000410;
+	gnvs->DID5 = 0x00000005;
+
+	gnvs->ALAF = 0x64;
+	gnvs->LLOW = 0x2c;
+	gnvs->LHIH = 0x01;
+
+        // tolud = pci_read_config32(dev_find_slot(0, PCI_DEVFN(2, 0)), 0x5c);
+	// oemb->topm = tolud;
+}
+#endif
+
+#include "southbridge/intel/i82801gx/nvs.h"
+static void acpi_create_gnvs(global_nvs_t *gnvs)
+{
+	memset((void *)gnvs, 0, sizeof(*gnvs));
+	gnvs->apic = 1;
+	gnvs->mpen = 1; /* Enable Multi Processing */
+
+	/* Enable both COM ports */
+	gnvs->cmap = 0x01;
+	gnvs->cmbp = 0x01;
+
+	/* IGD Displays */
+	gnvs->ndid = 3;
+	gnvs->did[0] = 0x80000100;
+	gnvs->did[1] = 0x80000240;
+	gnvs->did[2] = 0x80000410;
+	gnvs->did[3] = 0x80000410;
+	gnvs->did[4] = 0x00000005;
+}
+
+static void acpi_create_intel_hpet(acpi_hpet_t * hpet)
+{
+#define HPET_ADDR  0xfed00000ULL
+	acpi_header_t *header = &(hpet->header);
+	acpi_addr_t *addr = &(hpet->addr);
+
+	memset((void *) hpet, 0, sizeof(acpi_hpet_t));
+
+	/* fill out header fields */
+	memcpy(header->signature, "HPET", 4);
+	memcpy(header->oem_id, OEM_ID, 6);
+	memcpy(header->oem_table_id, "COREBOOT", 8);
+	memcpy(header->asl_compiler_id, ASLC, 4);
+
+	header->length = sizeof(acpi_hpet_t);
+	header->revision = 1;
+
+	/* fill out HPET address */
+	addr->space_id = 0;	/* Memory */
+	addr->bit_width = 64;
+	addr->bit_offset = 0;
+	addr->addrl = HPET_ADDR & 0xffffffff;
+	addr->addrh = HPET_ADDR >> 32;
+
+	hpet->id = 0x8086a201;	/* Intel */
+	hpet->number = 0x00;
+	hpet->min_tick = 0x0080;
+
+	header->checksum =
+	    acpi_checksum((void *) hpet, sizeof(acpi_hpet_t));
+}
+
+unsigned long acpi_fill_madt(unsigned long current)
+{
+	/* Local APICs */
+	current = acpi_create_madt_lapics(current);
+
+	/* IOAPIC */
+	current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
+				2, IO_APIC_ADDR, 0);
+
+	/* LAPIC_NMI */
+	current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
+				current, 0,
+				MP_IRQ_POLARITY_HIGH |
+				MP_IRQ_TRIGGER_EDGE, 0x01);
+	current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)
+				current, 1, MP_IRQ_POLARITY_HIGH |
+				MP_IRQ_TRIGGER_EDGE, 0x01);
+
+	/* INT_SRC_OVR */
+	current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
+		 current, 0, 0, 2, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_EDGE);
+	current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
+		 current, 0, 9, 9, MP_IRQ_POLARITY_HIGH | MP_IRQ_TRIGGER_LEVEL);
+
+
+	return current;
+}
+
+unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id)
+{
+	generate_cpu_entries();
+	return (unsigned long) (acpigen_get_current());
+}
+
+unsigned long acpi_fill_slit(unsigned long current)
+{
+	// Not implemented
+	return current;
+}
+
+unsigned long acpi_fill_srat(unsigned long current)
+{
+	/* No NUMA, no SRAT */
+	return current;
+}
+
+void smm_setup_structures(void *gnvs, void *tcg, void *smi1);
+
+#define ALIGN_CURRENT current = ((current + 0x0f) & -0x10)
+unsigned long write_acpi_tables(unsigned long start)
+{
+	unsigned long current;
+	int i;
+	acpi_rsdp_t *rsdp;
+	acpi_rsdt_t *rsdt;
+	acpi_xsdt_t *xsdt;
+	acpi_hpet_t *hpet;
+	acpi_madt_t *madt;
+	acpi_mcfg_t *mcfg;
+	acpi_fadt_t *fadt;
+	acpi_facs_t *facs;
+#if CONFIG_HAVE_ACPI_SLIC
+	acpi_header_t *slic;
+#endif
+	acpi_header_t *ssdt;
+	acpi_header_t *dsdt;
+	void *gnvs;
+
+	current = start;
+
+	/* Align ACPI tables to 16byte */
+	ALIGN_CURRENT;
+
+	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);
+	ALIGN_CURRENT;
+	rsdt = (acpi_rsdt_t *) current;
+	current += sizeof(acpi_rsdt_t);
+	ALIGN_CURRENT;
+	xsdt = (acpi_xsdt_t *) current;
+	current += sizeof(acpi_xsdt_t);
+	ALIGN_CURRENT;
+
+	/* clear all table memory */
+	memset((void *) start, 0, current - start);
+
+	acpi_write_rsdp(rsdp, rsdt, xsdt);
+	acpi_write_rsdt(rsdt);
+	acpi_write_xsdt(xsdt);
+
+	/*
+	 * We explicitly add these tables later on:
+	 */
+	printk(BIOS_DEBUG, "ACPI:    * HPET\n");
+
+	hpet = (acpi_hpet_t *) current;
+	current += sizeof(acpi_hpet_t);
+	ALIGN_CURRENT;
+	acpi_create_intel_hpet(hpet);
+	acpi_add_table(rsdp, hpet);
+
+	/* If we want to use HPET Timers Linux wants an MADT */
+	printk(BIOS_DEBUG, "ACPI:    * MADT\n");
+
+	madt = (acpi_madt_t *) current;
+	acpi_create_madt(madt);
+	current += madt->header.length;
+	ALIGN_CURRENT;
+	acpi_add_table(rsdp, madt);
+
+	printk(BIOS_DEBUG, "ACPI:    * MCFG\n");
+	mcfg = (acpi_mcfg_t *) current;
+	acpi_create_mcfg(mcfg);
+	current += mcfg->header.length;
+	ALIGN_CURRENT;
+	acpi_add_table(rsdp, mcfg);
+
+	printk(BIOS_DEBUG, "ACPI:     * FACS\n");
+	facs = (acpi_facs_t *) current;
+	current += sizeof(acpi_facs_t);
+	ALIGN_CURRENT;
+	acpi_create_facs(facs);
+
+	dsdt = (acpi_header_t *) current;
+	memcpy(dsdt, &AmlCode, sizeof(acpi_header_t));
+	current += dsdt->length;
+	memcpy(dsdt, &AmlCode, dsdt->length);
+
+	/* Fix up global NVS region for SMI handler. The GNVS region lives
+	 * in the (high) table area. The low memory map looks like this:
+	 *
+	 * 0x00000000 - 0x000003ff	Real Mode IVT
+	 * 0x00000020 - 0x0000019c	Low MP Table (XXX conflict?)
+	 * 0x00000400 - 0x000004ff	BDA (somewhat unused)
+	 * 0x00000500 - 0x0000052f	Moved GDT
+	 * 0x00000530 - 0x00000b64	coreboot table
+	 * 0x0007c000 - 0x0007dfff	OS boot sector (unused?)
+	 * 0x0007e000 - 0x0007ffff	free to use (so no good for acpi+smi)
+	 * 0x00080000 - 0x0009fbff	usable ram
+	 * 0x0009fc00 - 0x0009ffff	EBDA (unused?)
+	 * 0x000a0000 - 0x000bffff	VGA memory
+	 * 0x000c0000 - 0x000cffff	VGA option rom
+	 * 0x000d0000 - 0x000dffff	free for other option roms?
+	 * 0x000e0000 - 0x000fffff	SeaBIOS? (conflict with low tables:)
+	 * 0x000f0000 - 0x000f03ff	PIRQ table
+	 * 0x000f0400 - 0x000f66??	ACPI tables
+	 * 0x000f66?? - 0x000f????	DMI tables
+	 */
+
+	ALIGN_CURRENT;
+
+	/* Pack GNVS into the ACPI table area */
+	for (i=0; i < dsdt->length; i++) {
+		if (*(u32*)(((u32)dsdt) + i) == 0xC0DEBABE) {
+			printk(BIOS_DEBUG, "ACPI: Patching up global NVS in DSDT at offset 0x%04x -> 0x%08x\n", i, (u32)current);
+			*(u32*)(((u32)dsdt) + i) = current; // 0x92 bytes
+			break;
+		}
+	}
+
+	/* And fill it */
+	acpi_create_gnvs((global_nvs_t *)current);
+
+	/* Keep pointer around */
+	gnvs = (void *)current;
+
+	current += 0x100;
+	ALIGN_CURRENT;
+
+	/* And tell SMI about it */
+	smm_setup_structures(gnvs, NULL, NULL);
+
+	/* We patched up the DSDT, so we need to recalculate the checksum */
+	dsdt->checksum = 0;
+	dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length);
+
+	printk(BIOS_DEBUG, "ACPI:     * DSDT @ %p Length %x\n", dsdt,
+		     dsdt->length);
+
+#if CONFIG_HAVE_ACPI_SLIC
+	printk(BIOS_DEBUG, "ACPI:     * SLIC\n");
+	slic = (acpi_header_t *)current;
+	current += acpi_create_slic(current);
+	ALIGN_CURRENT;
+	acpi_add_table(rsdp, slic);
+#endif
+
+	printk(BIOS_DEBUG, "ACPI:     * FADT\n");
+	fadt = (acpi_fadt_t *) current;
+	current += sizeof(acpi_fadt_t);
+	ALIGN_CURRENT;
+
+	acpi_create_fadt(fadt, facs, dsdt);
+	acpi_add_table(rsdp, fadt);
+
+	printk(BIOS_DEBUG, "ACPI:     * SSDT\n");
+	ssdt = (acpi_header_t *)current;
+	acpi_create_ssdt_generator(ssdt, "COREBOOT");
+	current += ssdt->length;
+	acpi_add_table(rsdp, ssdt);
+	ALIGN_CURRENT;
+
+	printk(BIOS_DEBUG, "current = %lx\n", current);
+
+	printk(BIOS_DEBUG, "ACPI:     * DMI (Linux workaround)\n");
+	memcpy((void *)0xfff80, dmi_table, DMI_TABLE_SIZE);
+#if CONFIG_WRITE_HIGH_TABLES == 1
+	memcpy((void *)current, dmi_table, DMI_TABLE_SIZE);
+	current += DMI_TABLE_SIZE;
+	ALIGN_CURRENT;
+#endif
+
+	printk(BIOS_INFO, "ACPI: done.\n");
+
+	return current;
+}
diff --git a/src/mainboard/lenovo/x60/chip.h b/src/mainboard/lenovo/x60/chip.h
new file mode 100644
index 0000000..70f9bb4
--- /dev/null
+++ b/src/mainboard/lenovo/x60/chip.h
@@ -0,0 +1,21 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2011 Sven Schnelle <svens@stackframe.org>
+ *
+ * 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
+ */
+
+extern struct chip_operations mainboard_ops;
+struct mainboard_config {};
diff --git a/src/mainboard/lenovo/x60/cmos.layout b/src/mainboard/lenovo/x60/cmos.layout
new file mode 100644
index 0000000..4dc9112
--- /dev/null
+++ b/src/mainboard/lenovo/x60/cmos.layout
@@ -0,0 +1,145 @@ 
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2007-2008 coresystems GmbH
+#
+# 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
+#
+
+# -----------------------------------------------------------------
+entries
+
+#start-bit length  config config-ID    name
+#0            8       r       0        seconds
+#8            8       r       0        alarm_seconds
+#16           8       r       0        minutes
+#24           8       r       0        alarm_minutes
+#32           8       r       0        hours
+#40           8       r       0        alarm_hours
+#48           8       r       0        day_of_week
+#56           8       r       0        day_of_month
+#64           8       r       0        month
+#72           8       r       0        year
+# -----------------------------------------------------------------
+# Status Register A
+#80           4       r       0        rate_select
+#84           3       r       0        REF_Clock
+#87           1       r       0        UIP
+# -----------------------------------------------------------------
+# Status Register B
+#88           1       r       0        auto_switch_DST
+#89           1       r       0        24_hour_mode
+#90           1       r       0        binary_values_enable
+#91           1       r       0        square-wave_out_enable
+#92           1       r       0        update_finished_enable
+#93           1       r       0        alarm_interrupt_enable
+#94           1       r       0        periodic_interrupt_enable
+#95           1       r       0        disable_clock_updates
+# -----------------------------------------------------------------
+# Status Register C
+#96           4       r       0        status_c_rsvd
+#100          1       r       0        uf_flag
+#101          1       r       0        af_flag
+#102          1       r       0        pf_flag
+#103          1       r       0        irqf_flag
+# -----------------------------------------------------------------
+# Status Register D
+#104          7       r       0        status_d_rsvd
+#111          1       r       0        valid_cmos_ram
+# -----------------------------------------------------------------
+# Diagnostic Status Register
+#112          8       r       0        diag_rsvd1
+
+# -----------------------------------------------------------------
+0          120       r       0        reserved_memory
+#120        264       r       0        unused
+
+# -----------------------------------------------------------------
+# RTC_BOOT_BYTE (coreboot hardcoded)
+384          1       e       4        boot_option
+385          1       e       4        last_boot
+388          4       r       0        reboot_bits
+#390          2       r       0        unused?
+
+# -----------------------------------------------------------------
+# coreboot config options: console
+392          3       e       5        baud_rate
+395          4       e       6        debug_level
+#399          1       r       0        unused
+
+# coreboot config options: cpu
+400          1       e       2        hyper_threading
+#401          7       r       0        unused
+
+# coreboot config options: southbridge
+408          1       e       1        nmi
+#409          2       e       7        power_on_after_fail
+#411          5       r       0        unused
+
+# coreboot config options: bootloader
+416        512       s       0        boot_devices
+928          8       h       0        boot_default
+#936         48       r       0        unused
+
+# coreboot config options: check sums
+984         16       h       0        check_sum
+#1000        24       r       0        amd_reserved
+
+# ram initialization internal data
+1024         8       r       0        C0WL0REOST
+1032         8       r       0        C1WL0REOST
+1040         8       r       0        RCVENMT
+1048         4       r       0        C0DRT1
+1052         4       r       0        C1DRT1
+
+# -----------------------------------------------------------------
+
+enumerations
+
+#ID value   text
+1     0     Disable
+1     1     Enable
+2     0     Enable
+2     1     Disable
+4     0     Fallback
+4     1     Normal
+5     0     115200
+5     1     57600
+5     2     38400
+5     3     19200
+5     4     9600
+5     5     4800
+5     6     2400
+5     7     1200
+6     1     Emergency
+6     2     Alert
+6     3     Critical
+6     4     Error
+6     5     Warning
+6     6     Notice
+6     7     Info
+6     8     Debug
+6     9     Spew
+7     0     Disable
+7     1     Enable
+7     2     Keep
+
+# -----------------------------------------------------------------
+checksums
+
+checksum 392 983 984
+
+
diff --git a/src/mainboard/lenovo/x60/devicetree.cb b/src/mainboard/lenovo/x60/devicetree.cb
new file mode 100644
index 0000000..fdd1a88
--- /dev/null
+++ b/src/mainboard/lenovo/x60/devicetree.cb
@@ -0,0 +1,79 @@ 
+##
+## This file is part of the coreboot project.
+##
+## Copyright (c) 2011 Sven Schnelle <svens@stackframe.org>
+##
+## 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
+##
+
+chip northbridge/intel/i945
+
+        device lapic_cluster 0 on
+                chip cpu/intel/socket_MPGA479M
+                        device lapic 0 on end
+                end
+        end
+
+        device pci_domain 0 on
+                device pci 00.0 on end # host bridge
+		device pci 02.0 on end # vga controller
+		device pci 02.1 on end # display controller
+                chip southbridge/intel/i82801gx
+			register "pirqa_routing" = "0x8b"
+			register "pirqb_routing" = "0x8b"
+			register "pirqc_routing" = "0x8b"
+			register "pirqd_routing" = "0x8b"
+			register "pirqe_routing" = "0x8b"
+			register "pirqf_routing" = "0x8b"
+			register "pirqg_routing" = "0x8b"
+			register "pirqh_routing" = "0x8b"
+
+                        register "sata_ahci" = "0x0"
+
+                        register "gpi13_routing" = "2"
+                        register "gpi12_routing" = "2"
+                        register "gpi8_routing" = "2"
+
+			device pci 1b.0 on end # Audio Controller
+			device pci 1c.0 on end # Ethernet
+			device pci 1c.1 on end # Atheros WLAN
+			device pci 1d.0 on end # USB UHCI
+			device pci 1d.1 on end # USB UHCI
+			device pci 1d.2 on end # USB UHCI
+			device pci 1d.3 on end # USB UHCI
+			device pci 1d.7 on end # USB2 EHCI
+			device pci 1f.0 on # PCI-LPC bridge
+			       chip superio/lenovo/x60_ec
+#					device pnp 2e.5 on # Keyboard+Mouse
+#						 io 0x60 = 0x60
+#						 io 0x62 = 0x64
+#						irq 0x70 = 1
+#						irq 0x72 = 12
+#					end
+#                                end
+#				chip superio/lenovo/pmh7
+#					device pnp ff.1 on # dummy address
+#					end
+				end
+                        end
+			device pci 1f.1 off end # IDE
+                        device pci 1f.2 on end  # SATA
+                        device pci 1f.3 on end  # SMBus
+		end
+		chip southbridge/ricoh/rl5c476
+		end
+	end
+end
diff --git a/src/mainboard/lenovo/x60/dmi.h b/src/mainboard/lenovo/x60/dmi.h
new file mode 100644
index 0000000..96b5873
--- /dev/null
+++ b/src/mainboard/lenovo/x60/dmi.h
@@ -0,0 +1,29 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * 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
+ */
+
+#define DMI_TABLE_SIZE 0x55
+
+static u8 dmi_table[DMI_TABLE_SIZE] = {
+	0x5f, 0x53, 0x4d, 0x5f, 0x29, 0x1f, 0x02, 0x03, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x5f, 0x44, 0x4d, 0x49, 0x5f, 0x61, 0x35, 0x00, 0xa0, 0xff, 0x0f, 0x00, 0x01, 0x00, 0x23, 0x00,
+	0x00, 0x14, 0x00, 0x00, 0x01, 0x02, 0x00, 0xe0, 0x03, 0x07, 0x90, 0xde, 0xcb, 0x7f, 0x00, 0x00,
+	0x00, 0x00, 0x37, 0x01, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+	0x47, 0x6d, 0x62, 0x48, 0x00, 0x32, 0x2e, 0x30, 0x00, 0x30, 0x33, 0x2f, 0x31, 0x33, 0x2f, 0x32,
+	0x30, 0x30, 0x38, 0x00, 0x00
+};
diff --git a/src/mainboard/lenovo/x60/dsdt.asl b/src/mainboard/lenovo/x60/dsdt.asl
new file mode 100644
index 0000000..e69de29
diff --git a/src/mainboard/lenovo/x60/fadt.c b/src/mainboard/lenovo/x60/fadt.c
new file mode 100644
index 0000000..e45db8a
--- /dev/null
+++ b/src/mainboard/lenovo/x60/fadt.c
@@ -0,0 +1,164 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2008 coresystems GmbH
+ *
+ * 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 <string.h>
+#include <device/pci.h>
+#include <arch/acpi.h>
+
+/* FIXME: This needs to go into a separate .h file
+ * to be included by the ich7 smi handler, ich7 smi init
+ * code and the mainboard fadt.
+ */
+#define APM_CNT		0xb2
+#define   CST_CONTROL	0x85
+#define   PST_CONTROL	0x80
+#define   ACPI_DISABLE	0x1e
+#define   ACPI_ENABLE	0xe1
+#define   GNVS_UPDATE   0xea
+
+void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt)
+{
+	acpi_header_t *header = &(fadt->header);
+	u16 pmbase = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x1f,0)), 0x40) & 0xfffe;
+
+	memset((void *) fadt, 0, sizeof(acpi_fadt_t));
+	memcpy(header->signature, "FACP", 4);
+	header->length = sizeof(acpi_fadt_t);
+	header->revision = 3;
+	memcpy(header->oem_id, "CORE  ", 6);
+	memcpy(header->oem_table_id, "COREBOOT", 8);
+	memcpy(header->asl_compiler_id, "CORE", 4);
+	header->asl_compiler_revision = 0;
+
+	fadt->firmware_ctrl = (unsigned long) facs;
+	fadt->dsdt = (unsigned long) dsdt;
+	fadt->model = 0x00;
+	fadt->preferred_pm_profile = PM_MOBILE;
+	fadt->sci_int = 0x9;
+	fadt->smi_cmd = APM_CNT;
+	fadt->acpi_enable = ACPI_ENABLE;
+	fadt->acpi_disable = ACPI_DISABLE;
+	fadt->s4bios_req = 0x0;
+	fadt->pstate_cnt = PST_CONTROL;
+
+	fadt->pm1a_evt_blk = pmbase;
+	fadt->pm1b_evt_blk = 0x0;
+	fadt->pm1a_cnt_blk = pmbase + 0x4;
+	fadt->pm1b_cnt_blk = 0x0;
+	fadt->pm2_cnt_blk = pmbase + 0x20;
+	fadt->pm_tmr_blk = pmbase + 0x8;
+	fadt->gpe0_blk = pmbase + 0x28;
+	fadt->gpe1_blk = 0;
+
+	fadt->pm1_evt_len = 4;
+	fadt->pm1_cnt_len = 2;
+	fadt->pm2_cnt_len = 1;
+	fadt->pm_tmr_len = 4;
+	fadt->gpe0_blk_len = 8;
+	fadt->gpe1_blk_len = 0;
+	fadt->gpe1_base = 0;
+	fadt->cst_cnt = CST_CONTROL;
+	fadt->p_lvl2_lat = 1;
+	fadt->p_lvl3_lat = 0x23;
+	fadt->flush_size = 0;
+	fadt->flush_stride = 0;
+	fadt->duty_offset = 1;
+	fadt->duty_width = 3;
+	fadt->day_alrm = 0xd;
+	fadt->mon_alrm = 0x00;
+	fadt->century = 0x32;
+	fadt->iapc_boot_arch = 0x00;
+	fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
+			ACPI_FADT_SLEEP_BUTTON | ACPI_FADT_S4_RTC_WAKE |
+			ACPI_FADT_DOCKING_SUPPORTED;
+
+	fadt->reset_reg.space_id = 0;
+	fadt->reset_reg.bit_width = 0;
+	fadt->reset_reg.bit_offset = 0;
+	fadt->reset_reg.resv = 0;
+	fadt->reset_reg.addrl = 0x0;
+	fadt->reset_reg.addrh = 0x0;
+
+	fadt->reset_value = 0;
+	fadt->x_firmware_ctl_l = (unsigned long)facs;
+	fadt->x_firmware_ctl_h = 0;
+	fadt->x_dsdt_l = (unsigned long)dsdt;
+	fadt->x_dsdt_h = 0;
+
+	fadt->x_pm1a_evt_blk.space_id = 1;
+	fadt->x_pm1a_evt_blk.bit_width = 32;
+	fadt->x_pm1a_evt_blk.bit_offset = 0;
+	fadt->x_pm1a_evt_blk.resv = 0;
+	fadt->x_pm1a_evt_blk.addrl = pmbase;
+	fadt->x_pm1a_evt_blk.addrh = 0x0;
+
+	fadt->x_pm1b_evt_blk.space_id = 0;
+	fadt->x_pm1b_evt_blk.bit_width = 0;
+	fadt->x_pm1b_evt_blk.bit_offset = 0;
+	fadt->x_pm1b_evt_blk.resv = 0;
+	fadt->x_pm1b_evt_blk.addrl = 0x0;
+	fadt->x_pm1b_evt_blk.addrh = 0x0;
+
+	fadt->x_pm1a_cnt_blk.space_id = 1;
+	fadt->x_pm1a_cnt_blk.bit_width = 16;
+	fadt->x_pm1a_cnt_blk.bit_offset = 0;
+	fadt->x_pm1a_cnt_blk.resv = 0;
+	fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
+	fadt->x_pm1a_cnt_blk.addrh = 0x0;
+
+	fadt->x_pm1b_cnt_blk.space_id = 0;
+	fadt->x_pm1b_cnt_blk.bit_width = 0;
+	fadt->x_pm1b_cnt_blk.bit_offset = 0;
+	fadt->x_pm1b_cnt_blk.resv = 0;
+	fadt->x_pm1b_cnt_blk.addrl = 0x0;
+	fadt->x_pm1b_cnt_blk.addrh = 0x0;
+
+	fadt->x_pm2_cnt_blk.space_id = 1;
+	fadt->x_pm2_cnt_blk.bit_width = 8;
+	fadt->x_pm2_cnt_blk.bit_offset = 0;
+	fadt->x_pm2_cnt_blk.resv = 0;
+	fadt->x_pm2_cnt_blk.addrl = pmbase + 0x20;
+	fadt->x_pm2_cnt_blk.addrh = 0x0;
+
+	fadt->x_pm_tmr_blk.space_id = 1;
+	fadt->x_pm_tmr_blk.bit_width = 32;
+	fadt->x_pm_tmr_blk.bit_offset = 0;
+	fadt->x_pm_tmr_blk.resv = 0;
+	fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
+	fadt->x_pm_tmr_blk.addrh = 0x0;
+
+	fadt->x_gpe0_blk.space_id = 1;
+	fadt->x_gpe0_blk.bit_width = 64;
+	fadt->x_gpe0_blk.bit_offset = 0;
+	fadt->x_gpe0_blk.resv = 0;
+	fadt->x_gpe0_blk.addrl = pmbase + 0x28;
+	fadt->x_gpe0_blk.addrh = 0x0;
+
+	fadt->x_gpe1_blk.space_id = 0;
+	fadt->x_gpe1_blk.bit_width = 0;
+	fadt->x_gpe1_blk.bit_offset = 0;
+	fadt->x_gpe1_blk.resv = 0;
+	fadt->x_gpe1_blk.addrl = 0x0;
+	fadt->x_gpe1_blk.addrh = 0x0;
+
+	header->checksum =
+	    acpi_checksum((void *) fadt, header->length);
+}
diff --git a/src/mainboard/lenovo/x60/irq_tables.c b/src/mainboard/lenovo/x60/irq_tables.c
new file mode 100644
index 0000000..ce0bc4f
--- /dev/null
+++ b/src/mainboard/lenovo/x60/irq_tables.c
@@ -0,0 +1,61 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 Sven Schnelle <svens@stackframe.org>
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 <arch/pirq_routing.h>
+
+const struct irq_routing_table intel_irq_routing_table = {
+	PIRQ_SIGNATURE,		/* u32 signature */
+	PIRQ_VERSION,		/* u16 version */
+	32 + 16 * 15,		/* Max. number of devices on the bus */
+	0x00,			/* Interrupt router bus */
+	(0x1f << 3) | 0x0,	/* Interrupt router dev */
+	0,			/* IRQs devoted exclusively to PCI usage */
+	0x8086,			/* Vendor */
+	0x122e,			/* Device */
+	0,			/* Miniport */
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
+	0xf5,			/* Checksum (has to be set to some value that
+				 * would give 0 after the sum of all bytes
+				 * for this structure (including checksum).
+                                 */
+	{
+		/* bus,        dev | fn,   {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */
+		{0x00, (0x1b << 3) | 0x0, {{0x00, 0xdef8}, {0x61, 0x1cf8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0x0},
+		{0x00, (0x1c << 3) | 0x0, {{0x68, 0x1cf8}, {0x69, 0x1cf8}, {0x6a, 0x1cf8}, {0x6b, 0x1cf8}}, 0x0, 0x0},
+		{0x00, (0x1d << 3) | 0x0, {{0x60, 0x1cf8}, {0x61, 0x1cf8}, {0x62, 0x1cf8}, {0x63, 0x1cf8}}, 0x0, 0x0},
+		{0x00, (0x1f << 3) | 0x0, {{0x6b, 0x1cf8}, {0x60, 0x1cf8}, {0x60, 0x1cf8}, {0x00, 0xdef8}}, 0x0, 0x0},
+		{0x02, (0x00 << 3) | 0x0, {{0x68, 0x1cf8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0x0},
+		{0x03, (0x00 << 3) | 0x0, {{0x69, 0x1cf8}, {0x6a, 0x1cf8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x1, 0x0},
+		{0x03, (0x1f << 3) | 0x0, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0x0},
+		{0x04, (0x00 << 3) | 0x0, {{0x6a, 0x1cf8}, {0x6b, 0x1cf8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x2, 0x0},
+		{0x04, (0x1f << 3) | 0x0, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0x0},
+		{0x0c, (0x00 << 3) | 0x0, {{0x6b, 0x1cf8}, {0x68, 0x1cf8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x3, 0x0},
+		{0x0c, (0x1f << 3) | 0x0, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0x0},
+		{0x15, (0x00 << 3) | 0x0, {{0x60, 0x1cf8}, {0x61, 0x1cf8}, {0x62, 0x1cf8}, {0x00, 0xdef8}}, 0x0, 0x0},
+		{0x00, (0x00 << 3) | 0x0, {{0x60, 0x1cf8}, {0x61, 0x1cf8}, {0x62, 0x1cf8}, {0x63, 0x1cf8}}, 0x0, 0x0},
+		{0x00, (0x02 << 3) | 0x0, {{0x60, 0x1cf8}, {0x00, 0x1cf8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0x0},
+		{0x00, (0x01 << 3) | 0x0, {{0x60, 0x1cf8}, {0x61, 0x1cf8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x0, 0x0},
+	}
+};
+
+unsigned long write_pirq_routing_table(unsigned long addr)
+{
+	return copy_pirq_routing_table(addr);
+}
diff --git a/src/mainboard/lenovo/x60/mainboard.c b/src/mainboard/lenovo/x60/mainboard.c
new file mode 100644
index 0000000..73cd8fa
--- /dev/null
+++ b/src/mainboard/lenovo/x60/mainboard.c
@@ -0,0 +1,92 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2011 Sven Schnelle <svens@stackframe.org>
+ *
+ * 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 <console/console.h>
+#include <device/device.h>
+#include <arch/io.h>
+#include <boot/tables.h>
+#include <delay.h>
+#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
+#include <x86emu/x86emu.h>
+#endif
+#include <arch/coreboot_tables.h>
+#include "chip.h"
+#include <device/pci_def.h>
+#include <device/pci_ops.h>
+#include <arch/io.h>
+
+static void pmh7_register_set_bit(int reg, int bit)
+{
+	char val;
+
+	outb(reg, 0x15ec);
+	val = inb(0x15ee);
+	outb(reg, 0x15ec);
+	outb(val | (1 << bit), 0x15ee);
+}
+
+static void backlight_enable(void)
+{
+	pmh7_register_set_bit(0x50, 5);
+}
+
+#if CONFIG_PCI_OPTION_ROM_RUN_YABEL
+static int int15_handler(void)
+{
+	u8 display_id;
+
+	printk(BIOS_DEBUG, "%s: AX=%04x BX=%04x CX=%04x DX=%04x\n",
+			  __func__, M.x86.R_AX, M.x86.R_BX, M.x86.R_CX, M.x86.R_DX);
+
+	switch (M.x86.R_AX) {
+	default:
+		/* Interrupt was not handled */
+		return 0;
+	}
+
+	/* Interrupt handled */
+	return 1;
+}
+
+static void int15_install(void)
+{
+	typedef int (* yabel_handleIntFunc)(void);
+	extern yabel_handleIntFunc yabel_intFuncArray[256];
+	yabel_intFuncArray[0x15] = int15_handler;
+}
+#endif
+
+
+static void mainboard_enable(device_t dev)
+{
+	backlight_enable();
+
+#if CONFIG_PCI_OPTION_ROM_RUN_YABEL
+	/* Install custom int15 handler for VGA OPROM */
+	int15_install();
+#endif
+}
+
+struct chip_operations mainboard_ops = {
+	CHIP_NAME("Lenovo Thinkpad X60")
+	.enable_dev = mainboard_enable,
+};
+
diff --git a/src/mainboard/lenovo/x60/mainboard_smi.c b/src/mainboard/lenovo/x60/mainboard_smi.c
new file mode 100644
index 0000000..6736ace
--- /dev/null
+++ b/src/mainboard/lenovo/x60/mainboard_smi.c
@@ -0,0 +1,53 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * 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 <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <cpu/x86/smm.h>
+#include "southbridge/intel/i82801gx/nvs.h"
+
+/* The southbridge SMI handler checks whether gnvs has a
+ * valid pointer before calling the trap handler
+ */
+extern global_nvs_t *gnvs;
+
+int mainboard_io_trap_handler(int smif)
+{
+	switch (smif) {
+	case 0x99:
+		printk(BIOS_DEBUG, "Sample\n");
+		//gnvs->smif = 0;
+		break;
+	default:
+		return 0;
+	}
+
+	/* On success, the IO Trap Handler returns 0
+	 * On failure, the IO Trap Handler returns a value != 0
+	 *
+	 * For now, we force the return value to 0 and log all traps to
+	 * see what's going on.
+	 */
+	//gnvs->smif = 0;
+	return 1;
+}
+
diff --git a/src/mainboard/lenovo/x60/mptable.c b/src/mainboard/lenovo/x60/mptable.c
new file mode 100644
index 0000000..8cf4a09
--- /dev/null
+++ b/src/mainboard/lenovo/x60/mptable.c
@@ -0,0 +1,84 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2011 Sven Schnelle <svens@stackframe.org>
+ *
+ * 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
+ */
+
+/* generated by MPTable, version 2.0.15*/
+/* as modified by RGM for coreboot */
+#include <console/console.h>
+#include <arch/smp/mpspec.h>
+#include <arch/ioapic.h>
+#include <device/pci.h>
+#include <string.h>
+#include <stdint.h>
+
+static void *smp_write_config_table(void *v)
+{
+        struct mp_config_table *mc;
+
+        mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
+
+        mptable_init(mc, LAPIC_ADDR);
+
+        smp_write_processors(mc);
+
+
+/*Bus:		Bus ID	Type*/
+/*	smp_write_bus(mc, 0, "PCI   ");
+	smp_write_bus(mc, 2, "PCI   ");
+	smp_write_bus(mc, 3, "PCI   ");
+	smp_write_bus(mc, 21, "PCI   ");
+	smp_write_bus(mc, 22, "ISA   ");*/
+/*I/O APICs:	APIC ID	Version	State		Address*/
+	smp_write_ioapic(mc, 2, 0x20, IO_APIC_ADDR);
+	/* TODO: If you have multiple IOAPICs, add them here. */
+/*I/O Ints:	Type	Polarity    Trigger	Bus ID	 IRQ	APIC ID	PIN#
+*/	smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0x0, 0x2, 0x0);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0x1, 0x2, 0x1);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0x0, 0x2, 0x2);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0x3, 0x2, 0x3);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0x4, 0x2, 0x4);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0x5, 0x2, 0x5);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0x6, 0x2, 0x6);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0x7, 0x2, 0x7);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0x8, 0x2, 0x8);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0x9, 0x2, 0x9);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0xa, 0x2, 0xa);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0xb, 0x2, 0xb);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0xc, 0x2, 0xc);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0xd, 0x2, 0xd);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0xe, 0x2, 0xe);
+	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0xf, 0x2, 0xf);
+/*Local Ints:	Type	Polarity    Trigger	Bus ID	 IRQ	APIC ID	PIN#*/
+	smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0x0, MP_APIC_ALL, 0x0);
+	smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x16, 0x0, MP_APIC_ALL, 0x1);
+
+	mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);
+	mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
+	printk(BIOS_DEBUG, "Wrote the mp table end at: %p - %p\n",
+		mc, smp_next_mpe_entry(mc));
+	return smp_next_mpe_entry(mc);
+}
+
+unsigned long write_smp_table(unsigned long addr)
+{
+	void *v;
+	v = smp_write_floating_table(addr);
+	return (unsigned long)smp_write_config_table(v);
+}
diff --git a/src/mainboard/lenovo/x60/romstage.c b/src/mainboard/lenovo/x60/romstage.c
new file mode 100644
index 0000000..cb58881
--- /dev/null
+++ b/src/mainboard/lenovo/x60/romstage.c
@@ -0,0 +1,386 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2011 Sven Schnelle <svens@stackframe.org>
+ *
+ * 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 <stdint.h>
+#include <string.h>
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <device/pci_def.h>
+#include <device/pnp_def.h>
+#include <cpu/x86/lapic.h>
+#include <lib.h>
+#include <pc80/mc146818rtc.h>
+#include <console/console.h>
+#include <usbdebug.h>
+#include <cpu/x86/bist.h>
+#include "northbridge/intel/i945/i945.h"
+#include "northbridge/intel/i945/raminit.h"
+#include "southbridge/intel/i82801gx/i82801gx.h"
+
+void setup_ich7_gpios(void)
+{
+	printk(BIOS_DEBUG, " GPIOS...");
+
+	outl(0x1f40f7c2, DEFAULT_GPIOBASE + 0x00);	/* GPIO_USE_SEL */
+	outl(0xe0e8ffc3, DEFAULT_GPIOBASE + 0x04);	/* GP_IO_SEL */
+	outl(0xfbf6ddfd, DEFAULT_GPIOBASE + 0x0c);	/* GP_LVL */
+	/* Output Control Registers */
+	outl(0x00040000, DEFAULT_GPIOBASE + 0x18);	/* GPO_BLINK */
+	/* Input Control Registers */
+	outl(0x000039ff, DEFAULT_GPIOBASE + 0x2c);	/* GPI_INV */
+	outl(0x000100f2, DEFAULT_GPIOBASE + 0x30);	/* GPIO_USE_SEL2 */
+	outl(0x000000f0, DEFAULT_GPIOBASE + 0x34);	/* GP_IO_SEL2 */
+	outl(0x00030043, DEFAULT_GPIOBASE + 0x38);	/* GP_LVL */
+
+}
+
+static void ich7_enable_lpc(void)
+{
+	// Enable Serial IRQ
+	pci_write_config8(PCI_DEV(0, 0x1f, 0), 0x64, 0xd0);
+	// decode range
+	pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x80, 0x0210);
+	// decode range
+	pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x82, 0x1f0d);
+
+	/* range 0x1600 - 0x167f */
+	pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x84, 0x1601);
+	pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x86, 0x007c);
+
+	/* range 0x15e0 - 0x10ef */
+	pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x88, 0x15e1);
+	pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x8a, 0x000c);
+
+	/* range 0x1680 - 0x169f */
+	pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x8c, 0x1681);
+	pci_write_config16(PCI_DEV(0, 0x1f, 0), 0x8e, 0x001c);
+
+}
+
+static void pnp_write_register(device_t dev, int reg, int val)
+{
+	unsigned int port = dev >> 8;
+	outb(reg, port);
+	outb(val, port+1);
+}
+
+static void dock_write_register(int reg, int value)
+{
+	outb(reg, 0x164e);
+	outb(value, 0x164f);
+	/* original software reads the chip id after every
+	   I/O operation. Not sure if they are doing it for
+	   some code switching depending on hardware or just
+	   to have a delay after every operation.
+
+	   Do it the same way for now, we may remove it later
+	   if it isn't needed
+	*/
+	outb(0x20, 0x164e);
+	inb(0x164f);
+}
+
+static void dock_dlpc_init(void)
+{
+	/* Select DLPC module */
+	dock_write_register(0x07, 0x19);
+	/* DLPC Base Address 0x164c */
+	dock_write_register(0x60, 0x16);
+	dock_write_register(0x61, 0x4c);
+	/* Activate DLPC */
+	dock_write_register(0x30, 0x01);
+	outb(0x07, 0x164c);
+
+	while(!(inb(0x164c) & 8))
+		udelay(100 * 100);
+}
+
+static void dock_gpio_set_mode(int port, int mode)
+{
+	dock_write_register(0xf0, port);
+	dock_write_register(0xf1, mode);
+
+}
+
+static void dock_gpio_init(void)
+{
+	/* Select GPIO module */
+	dock_write_register(0x07, 0x07);
+	/* GPIO Base Address 0x1680 */
+	dock_write_register(0x60, 0x16);
+	dock_write_register(0x61, 0x80);
+
+	/* Activate GPIO */
+	dock_write_register(0x30, 0x01);
+
+	dock_gpio_set_mode(0x00, 3);
+	dock_gpio_set_mode(0x01, 3);
+	dock_gpio_set_mode(0x02, 0);
+	dock_gpio_set_mode(0x03, 3);
+	dock_gpio_set_mode(0x04, 4);
+	dock_gpio_set_mode(0x20, 4);
+	dock_gpio_set_mode(0x21, 4);
+	dock_gpio_set_mode(0x23, 4);
+}
+
+static void connect_dock(void)
+{
+	/* Enable 14.318MHz CLK on CLKIN */
+	dock_write_register(0x29, 0x00);
+	dock_write_register(0x29, 0xa0);
+	dock_gpio_init();
+	/* Assert D_PLTRST# */
+	outb(0xfe, 0x1680);
+	dock_dlpc_init();
+	/* Deassert D_PLTRST# */
+	outb(0xff, 0x1680);
+}
+
+static void early_superio_config(void)
+{
+	device_t dev;
+
+	dev=PNP_DEV(0x2e, 0x00);
+	pnp_write_register(dev, 0x29, 0x06);
+
+	/* Enable COM1 */
+	pnp_write_register(dev, 0x07, 0x03);
+	pnp_write_register(dev, 0x60, 0x03);
+	pnp_write_register(dev, 0x61, 0xf8);
+	pnp_write_register(dev, 0x30, 0x01);
+}
+
+static void rcba_config(void)
+{
+	/* Set up virtual channel 0 */
+	RCBA32(0x0014) = 0x80000001;
+	RCBA32(0x001c) = 0x03128010;
+
+	/* Device 1f interrupt pin register */
+	RCBA32(0x3100) = 0x00001230;
+	RCBA32(0x3108) = 0x40004321;
+
+	/* PCIe Interrupts */
+	RCBA32(0x310c) = 0x00004321;
+	/* HD Audio Interrupt */
+	RCBA32(0x3110) = 0x00000002;
+
+	/* dev irq route register */
+	RCBA16(0x3140) = 0x1007;
+	RCBA16(0x3142) = 0x0076;
+	RCBA16(0x3144) = 0x3210;
+	RCBA16(0x3146) = 0x7654;
+	RCBA16(0x3148) = 0x0010;
+
+	/* Enable IOAPIC */
+	RCBA8(0x31ff) = 0x03;
+
+	/* Enable upper 128bytes of CMOS */
+//	RCBA32(0x3400) = (1 << 2);
+
+	/* Disable unused devices */
+	RCBA32(0x3418) = FD_PCIE6 | FD_PCIE5 | FD_INTLAN | FD_ACMOD | FD_ACAUD;
+	RCBA32(0x3418) |= (1 << 0); // Required.
+}
+
+static void early_ich7_init(void)
+{
+	uint8_t reg8;
+	uint32_t reg32;
+
+	// program secondary mlt XXX byte?
+	pci_write_config8(PCI_DEV(0, 0x1e, 0), 0x1b, 0x20);
+
+	// reset rtc power status
+	reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa4);
+	reg8 &= ~(1 << 2);
+	pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa4, reg8);
+
+	// usb transient disconnect
+	reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xad);
+	reg8 |= (3 << 0);
+	pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xad, reg8);
+
+	reg32 = pci_read_config32(PCI_DEV(0, 0x1d, 7), 0xfc);
+	reg32 |= (1 << 29) | (1 << 17);
+	pci_write_config32(PCI_DEV(0, 0x1d, 7), 0xfc, reg32);
+
+	reg32 = pci_read_config32(PCI_DEV(0, 0x1d, 7), 0xdc);
+	reg32 |= (1 << 31) | (1 << 27);
+	pci_write_config32(PCI_DEV(0, 0x1d, 7), 0xdc, reg32);
+
+	RCBA32(0x0088) = 0x0011d000;
+	RCBA16(0x01fc) = 0x060f;
+	RCBA32(0x01f4) = 0x86000040;
+	RCBA32(0x0214) = 0x10030549;
+	RCBA32(0x0218) = 0x00020504;
+	RCBA8(0x0220) = 0xc5;
+	reg32 = RCBA32(0x3410);
+	reg32 |= (1 << 6);
+	RCBA32(0x3410) = reg32;
+	reg32 = RCBA32(0x3430);
+	reg32 &= ~(3 << 0);
+	reg32 |= (1 << 0);
+	RCBA32(0x3430) = reg32;
+	RCBA32(0x3418) |= (1 << 0);
+	RCBA16(0x0200) = 0x2008;
+	RCBA8(0x2027) = 0x0d;
+	RCBA16(0x3e08) |= (1 << 7);
+	RCBA16(0x3e48) |= (1 << 7);
+	RCBA32(0x3e0e) |= (1 << 7);
+	RCBA32(0x3e4e) |= (1 << 7);
+
+	// next step only on ich7m b0 and later:
+	reg32 = RCBA32(0x2034);
+	reg32 &= ~(0x0f << 16);
+	reg32 |= (5 << 16);
+	RCBA32(0x2034) = reg32;
+}
+
+#include <cbmem.h>
+
+void main(unsigned long bist)
+{
+	u32 reg32;
+	int boot_mode = 0;
+
+	if (bist == 0)
+		enable_lapic();
+
+	/* Force PCIRST# */
+	pci_write_config16(PCI_DEV(0, 0x1e, 0), BCTRL, SBR);
+	udelay(200 * 1000);
+	pci_write_config16(PCI_DEV(0, 0x1e, 0), BCTRL, 0);
+
+	ich7_enable_lpc();
+
+	connect_dock();
+
+	early_superio_config();
+	/* Set up the console */
+	uart_init();
+
+
+#if CONFIG_USBDEBUG
+	i82801gx_enable_usbdebug(1);
+	early_usbdebug_init();
+#endif
+
+	console_init();
+
+	/* Halt if there was a built in self test failure */
+	report_bist_failure(bist);
+
+	if (MCHBAR16(SSKPD) == 0xCAFE) {
+		printk(BIOS_DEBUG, "soft reset detected, rebooting properly\n");
+		outb(0x6, 0xcf9);
+		while (1) asm("hlt");
+	}
+
+	/* Perform some early chipset initialization required
+	 * before RAM initialization can work
+	 */
+	i945_early_initialization();
+
+	/* Read PM1_CNT */
+	reg32 = inl(DEFAULT_PMBASE + 0x04);
+	printk(BIOS_DEBUG, "PM1_CNT: %08x\n", reg32);
+	if (((reg32 >> 10) & 7) == 5) {
+#if CONFIG_HAVE_ACPI_RESUME
+		printk(BIOS_DEBUG, "Resume from S3 detected.\n");
+		boot_mode = 2;
+		/* Clear SLP_TYPE. This will break stage2 but
+		 * we care for that when we get there.
+		 */
+		outl(reg32 & ~(7 << 10), DEFAULT_PMBASE + 0x04);
+
+#else
+		printk(BIOS_DEBUG, "Resume from S3 detected, but disabled.\n");
+#endif
+	}
+
+	/* Enable SPD ROMs and DDR-II DRAM */
+	enable_smbus();
+
+#if CONFIG_DEFAULT_CONSOLE_LOGLEVEL > 8
+	dump_spd_registers();
+#endif
+
+	sdram_initialize(boot_mode);
+
+	/* Perform some initialization that must run before stage2 */
+	early_ich7_init();
+
+	/* This should probably go away. Until now it is required
+	 * and mainboard specific
+	 */
+	rcba_config();
+
+	/* Chipset Errata! */
+	fixup_i945_errata();
+
+	/* Initialize the internal PCIe links before we go into stage2 */
+	i945_late_initialization();
+
+#if !CONFIG_HAVE_ACPI_RESUME
+#if CONFIG_DEFAULT_CONSOLE_LOGLEVEL > 8
+#if CONFIG_DEBUG_RAM_SETUP
+	sdram_dump_mchbar_registers();
+
+	{
+		/* This will not work if TSEG is in place! */
+		u32 tom = pci_read_config32(PCI_DEV(0,2,0), 0x5c);
+
+		printk(BIOS_DEBUG, "TOM: 0x%08x\n", tom);
+		ram_check(0x00000000, 0x000a0000);
+		ram_check(0x00100000, tom);
+	}
+#endif
+#endif
+#endif
+
+	MCHBAR16(SSKPD) = 0xCAFE;
+
+#if CONFIG_HAVE_ACPI_RESUME
+	/* Start address of high memory tables */
+	unsigned long high_ram_base = get_top_of_ram() - HIGH_MEMORY_SIZE;
+
+	/* If there is no high memory area, we didn't boot before, so
+	 * this is not a resume. In that case we just create the cbmem toc.
+	 */
+	if ((boot_mode == 2) && cbmem_reinit((u64)high_ram_base)) {
+		void *resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
+
+		/* copy 1MB - 64K to high tables ram_base to prevent memory corruption
+		 * through stage 2. We could keep stuff like stack and heap in high tables
+		 * memory completely, but that's a wonderful clean up task for another
+		 * day.
+		 */
+		if (resume_backup_memory)
+			memcpy(resume_backup_memory, (void *)CONFIG_RAMBASE, HIGH_MEMORY_SAVE);
+
+		/* Magic for S3 resume */
+		pci_write_config32(PCI_DEV(0, 0x00, 0), SKPAD, 0xcafed00d);
+	}
+#endif
+	/* Set legacy Brightness control to full brightness */
+	pci_write_config8(PCI_DEV(0, 2, 1), 0xf4, 0xff);
+}