[coreboot] r991 - in coreboot-v3/southbridge/intel: . i82801gx

svn at coreboot.org svn at coreboot.org
Tue Nov 11 19:16:02 CET 2008


Author: rminnich
Date: 2008-11-11 19:16:02 +0100 (Tue, 11 Nov 2008)
New Revision: 991

Added:
   coreboot-v3/southbridge/intel/i82801gx/
   coreboot-v3/southbridge/intel/i82801gx/IOMAP
   coreboot-v3/southbridge/intel/i82801gx/Makefile
   coreboot-v3/southbridge/intel/i82801gx/ac97.c
   coreboot-v3/southbridge/intel/i82801gx/ac97audio.dts
   coreboot-v3/southbridge/intel/i82801gx/ac97modem.dts
   coreboot-v3/southbridge/intel/i82801gx/cmos_failover.c
   coreboot-v3/southbridge/intel/i82801gx/i82801gx.c
   coreboot-v3/southbridge/intel/i82801gx/i82801gx.h
   coreboot-v3/southbridge/intel/i82801gx/i82801gx_nvs.h
   coreboot-v3/southbridge/intel/i82801gx/i82801gx_reset.c
   coreboot-v3/southbridge/intel/i82801gx/i82801gx_smbus.h
   coreboot-v3/southbridge/intel/i82801gx/ich7_ich7r_ich7dh_lpc.dts
   coreboot-v3/southbridge/intel/i82801gx/ich7m_dh_lpc.dts
   coreboot-v3/southbridge/intel/i82801gx/ich7m_ich7u_lpc.dts
   coreboot-v3/southbridge/intel/i82801gx/ide.c
   coreboot-v3/southbridge/intel/i82801gx/ide.dts
   coreboot-v3/southbridge/intel/i82801gx/lpc.c
   coreboot-v3/southbridge/intel/i82801gx/mobilepci.dts
   coreboot-v3/southbridge/intel/i82801gx/nic.c
   coreboot-v3/southbridge/intel/i82801gx/nic.dts
   coreboot-v3/southbridge/intel/i82801gx/pci.c
   coreboot-v3/southbridge/intel/i82801gx/pci.dts
   coreboot-v3/southbridge/intel/i82801gx/pcie.c
   coreboot-v3/southbridge/intel/i82801gx/pcie2.dts
   coreboot-v3/southbridge/intel/i82801gx/pcie3.dts
   coreboot-v3/southbridge/intel/i82801gx/pcie4.dts
   coreboot-v3/southbridge/intel/i82801gx/pcie5.dts
   coreboot-v3/southbridge/intel/i82801gx/pcie6.dts
   coreboot-v3/southbridge/intel/i82801gx/sata.c
   coreboot-v3/southbridge/intel/i82801gx/sata.dts
   coreboot-v3/southbridge/intel/i82801gx/smbus.c
   coreboot-v3/southbridge/intel/i82801gx/smbus.dts
   coreboot-v3/southbridge/intel/i82801gx/smi.c
   coreboot-v3/southbridge/intel/i82801gx/smihandler.c
   coreboot-v3/southbridge/intel/i82801gx/smm.ld
   coreboot-v3/southbridge/intel/i82801gx/smmhandler.S
   coreboot-v3/southbridge/intel/i82801gx/smmrelocate.S
   coreboot-v3/southbridge/intel/i82801gx/stage1_smbus.c
   coreboot-v3/southbridge/intel/i82801gx/usb.c
   coreboot-v3/southbridge/intel/i82801gx/usb1.dts
   coreboot-v3/southbridge/intel/i82801gx/usb2.dts
   coreboot-v3/southbridge/intel/i82801gx/usb3.dts
   coreboot-v3/southbridge/intel/i82801gx/usb4.dts
   coreboot-v3/southbridge/intel/i82801gx/usb_ehci.c
   coreboot-v3/southbridge/intel/i82801gx/watchdog.c
Log:
initial commit of i82801gx for v3
This is from v2. Once again, the pattern:
- save the chip name for the common enable parts, hence i82801gx.c
- remove the leading i82801_ from most other bits, since we compile
in different directories now
- Every device of a type has a distinct .c file (e.g. pcie.c)
- Each device of a type may be realized in more than one bit of silicon, 
and have more than one set of operations, although code is common. 
These are placed into distinct operations structs (see pcie.c)
- for every distinct device, there is a .dts file. 

This set of rules makes for simple cross-part standardization of code. 

Signed-off-by: Ronald G. Minnich <rminnich at gmail.com>
Acked-by: Ronald G. Minnich <rminnich at gmail.com>



Added: coreboot-v3/southbridge/intel/i82801gx/IOMAP
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/IOMAP	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/IOMAP	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,35 @@
+Non-automatic IO-Addresses
+--------------------------
+
+The following dynamic IO BARs are used on the ICH7 for the Kontron Default BIOS:
+
+GPIOBASE	0x480 (64 bytes)
+PMBASE		0x800 (128 bytes)
+SMBASE		0x400 (32 bytes)
+HWMON		0xa00 (??)
+
+The following dynamic IO BARs are used on the ICH7 for the Getac Default BIOS:
+
+GPIOBASE	0x1180 (64 bytes)
+PMBASE		0x1000 (128 bytes)
+SMBASE		0x18e0 (32 bytes)
+
+The Getac also needs an IO Trapped area of 0x0C bytes (defaults to 0x800)
+
+coreboot:
+GPIOBASE	0x480 (64 bytes)
+PMBASE		0x500 (128 bytes)
+SMBASE		0x400 (32 bytes)
+HWMON		0xa00 (??)
+
+
+
+NOTE: Coreboot sets the SMBASE to 0xf00 in auto.c. But it gets relocated 
+in stage2 because its a "normal BAR" (to 0x2080 in one case here). 
+
+This is not unhealthy but at least confusing. We should provide a method to
+nail down certain resources for stage2. 
+
+For a list of static I/O space allocation look at 6.3.1 of the ICH7 Family
+Datasheet.
+

Added: coreboot-v3/southbridge/intel/i82801gx/Makefile
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/Makefile	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/Makefile	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,42 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007 coresystems GmbH
+## (Written by Stefan Reinauer <stepan at coresystems.de> for 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; 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
+##
+
+ifeq ($(CONFIG_SOUTHBRIDGE_AMD_SB600),y)
+
+STAGE2_CHIPSET_SRC += $(src)/southbridge/intel/i82801gx/i82801gx.c
+
+STAGE2_CHIPSET_SRC += \
+					$(src)/southbridge/intel/i82801gx/ac97.c \
+ 					$(src)/southbridge/intel/i82801gx/ide.c \
+ 					$(src)/southbridge/intel/i82801gx/lpc.c \
+ 					$(src)/southbridge/intel/i82801gx/nic.c \
+					$(src)/southbridge/intel/i82801gx/pci.c \
+					$(src)/southbridge/intel/i82801gx/pcie.c \
+					$(src)/southbridge/intel/i82801gx/sata.c \
+					$(src)/southbridge/intel/i82801gx/smbus.c \
+					$(src)/southbridge/intel/i82801gx/usb_ehci.c \
+  					$(src)/southbridge/intel/i82801gx/usb.c	\
+  					$(src)/southbridge/intel/i82801gx/watchdog.c
+					
+STAGE0_CHIPSET_SRC += \
+					$(src)/southbridge/intel/i82801gx/stage1_smbus.c
+
+endif

Added: coreboot-v3/southbridge/intel/i82801gx/ac97.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/ac97.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/ac97.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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 <types.h>
+#include <lib.h>
+#include <console.h>
+#include <device/pci.h>
+#include <msr.h>
+#include <legacy.h>
+#include <device/pci_ids.h>
+#include <statictree.h>
+#include <config.h>
+#include "i82801gx.h"
+
+static void ac97_audio_init(struct device *dev)
+{
+	// XXX init AC97 codecs.
+}
+
+static void ac97_modem_init(struct device *dev)
+{
+	// XXX init modem?
+}
+
+/* 82801GB/GR/GDH/GBM/GHM (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH) */
+/* Note: 82801GU (ICH7-U) doesn't have AC97 audio. */
+struct device_operations ac97audio = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27de}}},
+	.constructor		 = default_device_constructor,
+	.phase3_chip_setup_dev	= i82801gx_enable,
+	.phase3_scan		 = 0,
+	.phase4_read_resources	 = pci_dev_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_dev_enable_resources,
+	.phase6_init		 = ac97_audio_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};
+
+/* 82801GB/GR/GDH/GBM/GHM (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH) */
+/* Note: 82801GU (ICH7-U) doesn't have AC97 modem. */
+struct device_operations ac97modem = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27dd}}},
+	.constructor		 = default_device_constructor,
+	.phase3_chip_setup_dev	= i82801gx_enable,
+	.phase3_scan		 = 0,
+	.phase4_read_resources	 = pci_dev_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_dev_enable_resources,
+	.phase6_init		 = ac97_modem_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};
+

Added: coreboot-v3/southbridge/intel/i82801gx/ac97audio.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/ac97audio.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/ac97audio.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+{
+	device_operations = "ac97audio";
+	/* configuration variables go here */
+};

Added: coreboot-v3/southbridge/intel/i82801gx/ac97modem.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/ac97modem.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/ac97modem.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+{
+	device_operations = "ac97modem";
+	/* configuration variables go here */
+};

Added: coreboot-v3/southbridge/intel/i82801gx/cmos_failover.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/cmos_failover.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/cmos_failover.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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 "i82801gx.h"
+
+#define RTC_FAILED    (1 <<2)
+#define GEN_PMCON_3     0xa4
+
+static void check_cmos_failed(void)
+{
+	u8 byte;
+	byte = pci_read_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_3);
+	if (byte & RTC_FAILED) {
+		// clear bit 1 and bit 2
+		byte = cmos_read(RTC_BOOT_BYTE);
+		byte &= 0x0c;
+		byte |= MAX_REBOOT_CNT << 4;
+		cmos_write(byte, RTC_BOOT_BYTE);
+	}
+}

Added: coreboot-v3/southbridge/intel/i82801gx/i82801gx.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/i82801gx.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/i82801gx.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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 <device/device.h>
+
+void i82801gx_enable(struct device * dev)
+{
+}

Added: coreboot-v3/southbridge/intel/i82801gx/i82801gx.h
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/i82801gx.h	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/i82801gx.h	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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
+ */
+
+#ifndef SOUTHBRIDGE_INTEL_I82801GX_I82801GX_H
+#define SOUTHBRIDGE_INTEL_I82801GX_I82801GX_H
+
+#include "chip.h"
+extern void i82801gx_enable(device_t dev);
+
+#define PCI_DMA_CFG		0x90
+#define SERIRQ_CNTL		0x64
+#define GEN_CNTL		0xd0
+#define GEN_STS			0xd4
+#define RTC_CONF		0xd8
+#define GEN_PMCON_1		0xa0
+#define GEN_PMCON_2		0xa2
+#define GEN_PMCON_3		0xa4
+
+#define PMBASE			0x40
+#define ACPI_CNTL		0x44
+#define BIOS_CNTL		0x4E
+#define GPIO_BASE		0x48 /* LPC GPIO Base Address Register */
+#define GPIO_CNTL		0x4C /* LPC GPIO Control Register */
+
+#define PIRQA_ROUT		0x60
+#define PIRQB_ROUT		0x61
+#define PIRQC_ROUT		0x62
+#define PIRQD_ROUT		0x63
+#define PIRQE_ROUT		0x68
+#define PIRQF_ROUT		0x69
+#define PIRQG_ROUT		0x6A
+#define PIRQH_ROUT		0x6B
+
+#define FUNC_DIS		0xF2
+
+#define LPC_IO_DEC		0x80 /* IO Decode Ranges Register */
+#define LPC_EN			0x82 /* LPC IF Enables Register */
+
+#define SBUS_NUM		0x19
+#define SUB_BUS_NUM		0x1A
+#define SMLT			0x1B
+#define IOBASE			0x1C
+#define IOLIM			0x1D
+#define MEMBASE			0x20
+#define MEMLIM			0x22
+#define CNF			0x50
+#define MTT			0x70
+#define PCI_MAST_STS		0x82
+
+/* GEN_PMCON_3 bits */
+#define RTC_BATTERY_DEAD	(1 << 2)
+#define RTC_POWER_FAILED	(1 << 1)
+#define SLEEP_AFTER_POWER_FAIL	(1 << 0)
+
+/* PCI Configuration Space (D31:F1) */
+#define INTR_LN			0x3c
+#define IDE_TIM_PRI		0x40	/* IDE timings, primary */
+#define   IDE_DECODE_ENABLE	(1 << 15)
+#define   IDE_SITRE		(1 << 14)
+#define IDE_TIM_SEC		0x42	/* IDE timings, secondary */
+#define IDE_CONFIG		0x54	/* IDE I/O Configuration Register */
+#define   SIG_MODE_NORMAL	(0 << 16)
+#define   SIG_MODE_TRISTATE	(1 << 16)
+#define   SIG_MODE_DRIVELOW	(2 << 16)
+#define   FAST_PCB1		(1 << 13)
+#define   FAST_PCB0		(1 << 12)
+#define   PCB1			(1 <<  1)
+#define   PCB0			(1 <<  0)
+
+/* PCI Configuration Space (D31:F3) */
+#define SMB_BASE		0x20
+#define HOSTC			0x40
+
+/* HOSTC bits */
+#define I2C_EN			(1 << 2)
+#define SMB_SMI_EN		(1 << 1)
+#define HST_EN			(1 << 0)
+
+/* SMBus I/O bits.
+ * TODO: It does not matter where we put the SMBus IO base, as long as we keep
+ * consistent and don't interfere with other devices. Stage2 will relocate 
+ * this anyways. But it's a general problem we have not solved in the brightest
+ * possible way.
+ */
+/* #define SMBUS_IO_BASE 0x1000 */
+#define SMBUS_IO_BASE		0x0400
+
+#define SMBHSTSTAT		0x0
+#define SMBHSTCTL		0x2
+#define SMBHSTCMD		0x3
+#define SMBXMITADD		0x4
+#define SMBHSTDAT0		0x5
+#define SMBHSTDAT1		0x6
+#define SMBBLKDAT		0x7
+#define SMBTRNSADD		0x9
+#define SMBSLVDATA		0xa
+#define SMLINK_PIN_CTL		0xe
+#define SMBUS_PIN_CTL		0xf
+
+#define SMBUS_TIMEOUT		(10 * 1000 * 100)
+
+/* HPET, if present */
+#define HPET_ADDR		0xfed0000
+
+#endif				/* SOUTHBRIDGE_INTEL_I82801GX_I82801GX_H */

Added: coreboot-v3/southbridge/intel/i82801gx/i82801gx_nvs.h
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/i82801gx_nvs.h	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/i82801gx_nvs.h	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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
+ */
+
+typedef struct {
+	u16	osys;
+	u8	smif;
+	u8	prm0;
+	u8	prm1;
+	u8	scif;
+	u8	prm2;
+	u8	prm3;
+	u8	lckf;
+	u8	prm4;
+	u8	prm5;
+	u32	p80d;
+	u8	lids;
+	u8	pwrs;
+	u8	dbgs;
+	u8	linxs;
+	u8	rsvd;
+	u8	actt;
+	u8	psvt;
+	u8	tc1v;
+	u8	tc2v;
+	u8	tspv;
+	u8	crtt;
+	u8	dtse;
+	u8	dts1;
+	u8	dts2;
+	u8	rsvd2;
+	u8	bnum;
+	u8	b0sc, b1sc, b2sc;
+	u8	b0ss, b1ss, b2ss;
+	u8	rsvd3[3];
+	u8	apic;
+	u8	mpen;
+	u8	bten;
+	u8	ppcm;
+	u8	pcp0;
+	u8	pcp1;
+	u8	rsvd4[4];
+	u8	natp;
+	u8	cmap;
+	u8	cmbp;
+	u8	lptp;
+	u8	fdcp;
+	u8	rfdv;
+	u8	hotk;
+	u8	rtcf;
+	u8	util;
+	u8	acin;
+	u8	igds;
+	u8	tlst;
+	u8	cadl;
+	u8	padl;
+	u16	cste;
+	u16	pste;
+	u16	nste;
+	u16	sste;
+	u8	ndid;
+	u32	did1;
+	u32	did2;
+	u32	did3;
+	u32	did4;
+	u32	did5;
+	u8	rsvd5[0xb];
+	u8	brtl;
+	u8	odds;
+	u8	alse;
+	u8	alaf;
+	u8	llow;
+	u8	lhih;
+	u8	rsvd6;
+	u8	emae;
+	u16	emap;
+	u16	emal;
+	u8	rsvd7;
+	u8	mefe;
+	u8	igps;
+	u8	rsvd8[2];
+	u8	tpmp;
+	u8	tpme;
+	u8	rsvd9[8];
+	u8	gtf0[7];
+	u8	gtf2[7];
+	u8	idem;
+	u8	idet;
+	u8	dock;
+} global_nvs_t;
+

Added: coreboot-v3/southbridge/intel/i82801gx/i82801gx_reset.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/i82801gx_reset.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/i82801gx_reset.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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/io.h>
+
+void hard_reset(void)
+{
+	/* Try rebooting through port 0xcf9. */
+	outb((1 << 2) | (1 << 1), 0xcf9);
+}

Added: coreboot-v3/southbridge/intel/i82801gx/i82801gx_smbus.h
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/i82801gx_smbus.h	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/i82801gx_smbus.h	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,187 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2005 Yinghai Lu <yinghailu at gmail.com>
+ *
+ * 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 <device/smbus_def.h>
+
+static void smbus_delay(void)
+{
+	inb(0x80);
+}
+
+static int smbus_wait_until_ready(void)
+{
+	unsigned loops = SMBUS_TIMEOUT;
+	unsigned char byte;
+	do {
+		smbus_delay();
+		if (--loops == 0)
+			break;
+		byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+	} while (byte & 1);
+	return loops ? 0 : -1;
+}
+
+static int smbus_wait_until_done(void)
+{
+	unsigned loops = SMBUS_TIMEOUT;
+	unsigned char byte;
+	do {
+		smbus_delay();
+		if (--loops == 0)
+			break;
+		byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+	} while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
+	return loops ? 0 : -1;
+}
+
+static int smbus_wait_until_blk_done(void)
+{
+	unsigned loops = SMBUS_TIMEOUT;
+	unsigned char byte;
+	do {
+		smbus_delay();
+		if (--loops == 0)
+			break;
+		byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+	} while ((byte & (1 << 7)) == 0);
+	return loops ? 0 : -1;
+}
+
+static int do_smbus_read_byte(unsigned device, unsigned address)
+{
+	unsigned char global_status_register;
+	unsigned char byte;
+
+	if (smbus_wait_until_ready() < 0) {
+		return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+	}
+	/* Setup transaction */
+	/* Disable interrupts */
+	outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
+	/* Set the device I'm talking to */
+	outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBXMITADD);
+	/* Set the command/address... */
+	outb(address & 0xff, SMBUS_IO_BASE + SMBHSTCMD);
+	/* Set up for a byte data read */
+	outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xe3) | (0x2 << 2),
+	     (SMBUS_IO_BASE + SMBHSTCTL));
+	/* Clear any lingering errors, so the transaction will run */
+	outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
+
+	/* Clear the data byte... */
+	outb(0, SMBUS_IO_BASE + SMBHSTDAT0);
+
+	/* Start the command */
+	outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40),
+	     SMBUS_IO_BASE + SMBHSTCTL);
+
+	/* Poll for transaction completion */
+	if (smbus_wait_until_done() < 0) {
+		return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
+	}
+
+	global_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+
+	/* Ignore the "In Use" status... */
+	global_status_register &= ~(3 << 5);
+
+	/* Read results of transaction */
+	byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
+	if (global_status_register != (1 << 1)) {
+		return SMBUS_ERROR;
+	}
+	return byte;
+}
+
+/* This function is neither used nor tested by me (Corey Osgood), the author 
+(Yinghai) probably tested/used it on i82801er */
+static int do_smbus_write_block(unsigned device, unsigned length, unsigned cmd,
+				unsigned data1, unsigned data2)
+{
+	unsigned char byte;
+	unsigned char stat;
+	int i;
+
+#if CONFIG_USE_PRINTK_IN_CAR
+	printk_err("Untested smbus_write_block called\r\n");
+#else
+	print_err("Untested smbus_write_block called\r\n");
+#endif
+
+	/* Clear the PM timeout flags, SECOND_TO_STS */
+	outw(inw(0x0400 + 0x66), 0x0400 + 0x66);
+
+	if (smbus_wait_until_ready() < 0) {
+		return -2;
+	}
+
+	/* Setup transaction */
+	/* Obtain ownership */
+	outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
+	for (stat = 0; (stat & 0x40) == 0;) {
+		stat = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+	}
+	/* Clear the done bit */
+	outb(0x80, SMBUS_IO_BASE + SMBHSTSTAT);
+	/* Disable interrupts */
+	outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
+
+	/* Set the device I'm talking too */
+	outb(((device & 0x7f) << 1), SMBUS_IO_BASE + SMBXMITADD);
+
+	/* Set the command address */
+	outb(cmd & 0xff, SMBUS_IO_BASE + SMBHSTCMD);
+
+	/* Set the block length */
+	outb(length & 0xff, SMBUS_IO_BASE + SMBHSTDAT0);
+
+	/* Try sending out the first byte of data here */
+	byte = (data1 >> (0)) & 0x0ff;
+	outb(byte, SMBUS_IO_BASE + SMBBLKDAT);
+	/* Issue a block write command */
+	outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xe3) | (0x5 << 2) | 0x40,
+	     SMBUS_IO_BASE + SMBHSTCTL);
+
+	for (i = 0; i < length; i++) {
+
+		/* Poll for transaction completion */
+		if (smbus_wait_until_blk_done() < 0) {
+			return -3;
+		}
+
+		/* Load the next byte */
+		if (i > 3)
+			byte = (data2 >> (i % 4)) & 0x0ff;
+		else
+			byte = (data1 >> (i)) & 0x0ff;
+		outb(byte, SMBUS_IO_BASE + SMBBLKDAT);
+
+		/* Clear the done bit */
+		outb(inb(SMBUS_IO_BASE + SMBHSTSTAT),
+		     SMBUS_IO_BASE + SMBHSTSTAT);
+	}
+
+#if CONFIG_USE_PRINTK_IN_CAR
+	printk_debug("SMBUS Block complete\r\n");
+#else
+	print_debug("SMBUS Block complete\r\n");
+#endif
+	return 0;
+}

Added: coreboot-v3/southbridge/intel/i82801gx/ich7_ich7r_ich7dh_lpc.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/ich7_ich7r_ich7dh_lpc.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/ich7_ich7r_ich7dh_lpc.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "ich7_ich7r_ich7dh_lpc";
+	ide0_enable = "0";
+	ide1_enable = "1";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/ich7m_dh_lpc.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/ich7m_dh_lpc.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/ich7m_dh_lpc.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "ich7m_dh_lpc";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/ich7m_ich7u_lpc.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/ich7m_ich7u_lpc.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/ich7m_ich7u_lpc.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "ich7m_ich7u_lpc";
+	ide0_enable = "0";
+	ide1_enable = "1";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/ide.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/ide.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/ide.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,104 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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 <types.h>
+#include <lib.h>
+#include <console.h>
+#include <device/pci.h>
+#include <msr.h>
+#include <legacy.h>
+#include <device/pci_ids.h>
+#include <statictree.h>
+#include <config.h>
+#include "i82801gx.h"
+
+typedef struct southbridge_intel_i82801gx_config config_t;
+
+static void ide_init(struct device *dev)
+{
+	u16 ideTimingConfig;
+	u32 reg32;
+
+	/* Get the chip configuration */
+	config_t *config = dev->device_configuration;
+
+	int enable_primary = config->ide_enable_primary;
+	int enable_secondary = config->ide_enable_secondary;
+
+	reg32 = pci_read_config32(dev, PCI_COMMAND);
+	pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_IO | PCI_COMMAND_MASTER);
+
+	/* Native Capable, but not enabled. */
+	pci_write_config8(dev, 0x09, 0x8a);
+
+	ideTimingConfig = pci_read_config16(dev, IDE_TIM_PRI);
+	ideTimingConfig &= ~IDE_DECODE_ENABLE;
+	ideTimingConfig |= IDE_SITRE;
+	if (enable_primary) {
+		/* Enable primary IDE interface. */
+		ideTimingConfig |= IDE_DECODE_ENABLE;
+		ideTimingConfig |= (2 << 12); // ISP = 3 clocks
+		ideTimingConfig |= (3 << 8); // RCT = 1 clock
+		ideTimingConfig |= (1 << 1); // IE0
+		ideTimingConfig |= (1 << 0); // TIME0
+		printk_debug("IDE0 ");
+	}
+	pci_write_config16(dev, IDE_TIM_PRI, ideTimingConfig);
+
+	ideTimingConfig = pci_read_config16(dev, IDE_TIM_SEC);
+	ideTimingConfig &= ~IDE_DECODE_ENABLE;
+	ideTimingConfig |= IDE_SITRE;
+	if (enable_secondary) {
+		/* Enable secondary IDE interface. */
+		ideTimingConfig |= IDE_DECODE_ENABLE;
+		ideTimingConfig |= (2 << 12); // ISP = 3 clocks
+		ideTimingConfig |= (3 << 8); // RCT = 1 clock
+		ideTimingConfig |= (1 << 1); // IE0
+		ideTimingConfig |= (1 << 0); // TIME0
+		printk_debug("IDE1 ");
+	}
+	pci_write_config16(dev, IDE_TIM_SEC, ideTimingConfig);
+
+	/* Set IDE I/O Configuration */
+	if (enable_secondary)
+		reg32 = SIG_MODE_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
+	else
+		reg32 = SIG_MODE_NORMAL | FAST_PCB1 | PCB1;
+	pci_write_config32(dev, IDE_CONFIG, reg32);
+
+	/* Set Interrupt Line */
+	/* Interrupt Pin is set by D31IP.PIP */
+	pci_write_config32(dev, INTR_LN, 0xff); /* Int 15 */
+}
+
+struct device_operations i82801gx_ide = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27df}}},
+	.constructor		 = default_device_constructor,
+	.reset_bus		= pci_bus_reset,
+	.phase3_chip_setup_dev	= i82801gx_enable,
+	.phase3_scan		 = pci_scan_bridge,
+	.phase4_read_resources	 = pci_dev_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_bus_enable_resources,
+	.phase6_init		 = ide_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};

Added: coreboot-v3/southbridge/intel/i82801gx/ide.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/ide.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/ide.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gx_ide";
+	ide_legacy_combined = "0";
+	ide_enable_primary = "0";
+	ide_enable_secondary = "0";
+	sata_ahci = "0";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/lpc.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/lpc.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/lpc.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,381 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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 <types.h>
+#include <lib.h>
+#include <console.h>
+#include <device/pci.h>
+#include <msr.h>
+#include <legacy.h>
+#include <device/pci_ids.h>
+#include <statictree.h>
+#include <config.h>
+#include "i82801gx.h"
+
+#include "../../../northbridge/intel/i945/ich7.h"
+
+#define MAINBOARD_POWER_OFF 0
+#define MAINBOARD_POWER_ON  1
+
+#ifndef MAINBOARD_POWER_ON_AFTER_FAIL
+#define MAINBOARD_POWER_ON_AFTER_FAIL MAINBOARD_POWER_ON
+#endif
+
+#define NMI_OFF 0
+
+/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
+ * 0x00 - 0000 = Reserved
+ * 0x01 - 0001 = Reserved
+ * 0x02 - 0010 = Reserved
+ * 0x03 - 0011 = IRQ3
+ * 0x04 - 0100 = IRQ4
+ * 0x05 - 0101 = IRQ5
+ * 0x06 - 0110 = IRQ6
+ * 0x07 - 0111 = IRQ7
+ * 0x08 - 1000 = Reserved
+ * 0x09 - 1001 = IRQ9
+ * 0x0A - 1010 = IRQ10
+ * 0x0B - 1011 = IRQ11
+ * 0x0C - 1100 = IRQ12
+ * 0x0D - 1101 = Reserved
+ * 0x0E - 1110 = IRQ14
+ * 0x0F - 1111 = IRQ15
+ * PIRQ[n]_ROUT[7] - PIRQ Routing Control
+ * 0x80 - The PIRQ is not routed.
+ */
+
+#define PIRQA 0x03
+#define PIRQB 0x05
+#define PIRQC 0x06
+#define PIRQD 0x07
+#define PIRQE 0x09
+#define PIRQF 0x0A
+#define PIRQG 0x0B
+#define PIRQH 0x0C
+
+static void i82801gx_enable_apic(struct device *dev)
+{
+	int i;
+	u32 reg32;
+	volatile u32 *ioapic_index = (volatile u32 *)0xfec00000;
+	volatile u32 *ioapic_data = (volatile u32 *)0xfec00010;
+
+	/* Enable ACPI I/O and power management. */
+	pci_write_config8(dev, ACPI_CNTL, 0x80);
+
+	*ioapic_index = 0;
+	*ioapic_data = (1 << 25);
+
+	*ioapic_index = 0;
+	reg32 = *ioapic_data;
+	printk(BIOS_DEBUG, "Southbridge APIC ID = %x\n", (reg32 >> 24) & 0x0f);
+	if (reg32 != (1 << 25))
+		die("APIC Error\n");
+
+	printk(BIOS_SPEW, "Dumping IOAPIC registers\n");
+	for (i=0; i<3; i++) {
+		*ioapic_index = i;
+		printk(BIOS_SPEW, "  reg 0x%04x:", i);
+		reg32 = *ioapic_data;
+		printk(BIOS_SPEW, " 0x%08x\n", reg32);
+	}
+
+	*ioapic_index = 3; /* Select Boot Configuration register. */
+	*ioapic_data = 1; /* Use Processor System Bus to deliver interrupts. */
+}
+
+static void i82801gx_enable_serial_irqs(struct device *dev)
+{
+	/* Set packet length and toggle silent mode bit for one frame. */
+	pci_write_config8(dev, SERIRQ_CNTL,
+			  (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
+}
+
+static void i82801gx_pirq_init(struct device * dev)
+{
+	pci_write_config8(dev, PIRQA_ROUT, 0x85);
+	pci_write_config8(dev, PIRQB_ROUT, 0x87);
+	pci_write_config8(dev, PIRQC_ROUT, 0x86);
+	pci_write_config8(dev, PIRQD_ROUT, 0x87);
+
+	pci_write_config8(dev, PIRQE_ROUT, 0x80);
+	pci_write_config8(dev, PIRQF_ROUT, 0x80);
+	pci_write_config8(dev, PIRQG_ROUT, 0x80);
+	pci_write_config8(dev, PIRQH_ROUT, 0x85);
+}
+
+static void i82801gx_power_options(struct device * dev)
+{
+	u8 reg8;
+	u16 reg16;
+
+	int pwr_on=MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
+	int nmi_option;
+
+	/* Which state do we want to goto after g3 (power restored)?
+	 * 0 == S0 Full On
+	 * 1 == S5 Soft Off
+	 */
+        get_option(&pwr_on, "power_on_after_fail");
+	reg8 = pci_read_config8(dev, GEN_PMCON_3);
+	reg8 &= 0xfe;
+	if (pwr_on) {
+		reg8 &= ~1;
+	} else {
+		reg8 |= 1;
+	}
+	reg8 |= (3 << 4);	/* avoid #S4 assertions */
+
+	pci_write_config8(dev, GEN_PMCON_3, reg8);
+	printk_info("Set power %s after power failure.\n", pwr_on ? "on" : "off");
+
+	/* Set up NMI on errors. */
+	reg8 = inb(0x61);
+	reg8 &= 0x0f;		/* Higher Nibble must be 0 */
+	reg8 &= ~(1 << 3);	/* IOCHK# NMI Enable */
+	// reg8 &= ~(1 << 2);	/* PCI SERR# Enable */
+	reg8 |= (1 << 2); /* PCI SERR# Disable for now */
+	outb(reg8, 0x61);
+
+	reg8 = inb(0x70);
+	nmi_option = NMI_OFF;
+	get_option(&nmi_option, "nmi");
+	if (nmi_option) {
+		printk_info ("NMI sources enabled.\n");
+		reg8 &= ~(1 << 7);	/* Set NMI. */
+	} else {
+		printk_info ("NMI sources disabled.\n");
+		reg8 |= ( 1 << 7);	/* Can't mask NMI from PCI-E and NMI_NOW */
+	}
+	outb(reg8, 0x70);
+
+	// Enable CPU_SLP# and Intel Speedstep, set SMI# rate down
+	reg16 = pci_read_config16(dev, GEN_PMCON_1);
+	reg16 &= ~3;
+	reg16 |= (1 << 3) | (1 << 5) | (1 << 10);
+	pci_write_config16(dev, GEN_PMCON_1, reg16);
+
+	// Set GPIO13 to SCI (?)
+	// This might be board specific
+	pci_write_config32(dev, 0xb8, 0x08000000);
+}
+
+void i82801gx_rtc_init(struct device *dev)
+{
+	u8 reg8;
+	u32 reg32;
+	int rtc_failed;
+
+	reg8 = pci_read_config8(dev, GEN_PMCON_3);
+	rtc_failed = reg8 & RTC_BATTERY_DEAD;
+	if (rtc_failed) {
+		reg8 &= ~RTC_BATTERY_DEAD;
+		pci_write_config8(dev, GEN_PMCON_3, reg8);
+	}
+	printk(BIOS_DEBUG, "rtc_failed = 0x%x\n", rtc_failed);
+
+	rtc_init(rtc_failed);
+}
+
+static void enable_hpet(struct device *dev)
+{
+	u32 reg32;
+	u32 code = (0 & 0x3);
+
+	reg32 = pci_read_config32(dev, GEN_CNTL);
+	reg32 |= (1 << 17);	/* Enable HPET. */
+	/*
+	 * Bits [16:15]	Memory Address Range
+	 * 00		FED0_0000h - FED0_03FFh
+	 * 01		FED0_1000h - FED0_13FFh
+	 * 10		FED0_2000h - FED0_23FFh
+	 * 11		FED0_3000h - FED0_33FFh
+	 */
+	reg32 &= ~(3 << 15);	/* Clear it */
+	reg32 |= (code << 15);
+	/* TODO: reg32 is never written to anywhere? */
+	printk(BIOS_DEBUG, "Enabling HPET @0x%x\n", HPET_ADDR | (code << 12));
+}
+
+static void i82801gx_lock_smm(struct device *dev)
+{
+	void smm_lock(void);
+	u8 reg8;
+
+#if ENABLE_ACPI_MODE_IN_COREBOOT
+	printk(BIOS_DEBUG, "Enabling ACPI via APMC:\n");
+	outb(0xe1, 0xb2); // Enable ACPI mode
+	printk(BIOS_DEBUG, "done.\n");
+#else
+	printk(BIOS_DEBUG, "Disabling ACPI via APMC:\n");
+	outb(0x1e, 0xb2); // Disable ACPI mode
+	printk(BIOS_DEBUG, "done.\n");
+#endif
+	/* Don't allow evil boot loaders, kernels, or 
+	 * userspace applications to deceive us:
+	 */
+	smm_lock();
+
+#if TEST_SMM_FLASH_LOCKDOWN
+	/* Now try this: */
+	printk(BIOS_DEBUG, "Locking BIOS to RO... ");
+	reg8 = pci_read_config8(dev, 0xdc);	/* BIOS_CNTL */
+	printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
+			(reg8&1)?"rw":"ro");
+	reg8 &= ~(1 << 0);			/* clear BIOSWE */
+	pci_write_config8(dev, 0xdc, reg8);
+	reg8 |= (1 << 1);			/* set BLE */
+	pci_write_config8(dev, 0xdc, reg8);
+	printk(BIOS_DEBUG, "ok.\n");
+	reg8 = pci_read_config8(dev, 0xdc);	/* BIOS_CNTL */
+	printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
+			(reg8&1)?"rw":"ro");
+
+	printk(BIOS_DEBUG, "Writing:\n");
+	*(volatile u8 *)0xfff00000 = 0x00;
+	printk(BIOS_DEBUG, "Testing:\n");
+	reg8 |= (1 << 0);			/* set BIOSWE */
+	pci_write_config8(dev, 0xdc, reg8);
+
+	reg8 = pci_read_config8(dev, 0xdc);	/* BIOS_CNTL */
+	printk(BIOS_DEBUG, " BLE: %s; BWE: %s\n", (reg8&2)?"on":"off",
+			(reg8&1)?"rw":"ro");
+	printk(BIOS_DEBUG, "Done.\n");
+#endif
+}
+
+static void lpc_init(struct device *dev)
+{
+	printk(BIOS_DEBUG, "i82801gx: lpc_init\n");
+
+	/* Set the value for PCI command register. */
+	pci_write_config16(dev, PCI_COMMAND, 0x000f);
+
+	/* IO APIC initialization. */
+	i82801gx_enable_apic(dev);
+
+	i82801gx_enable_serial_irqs(dev);
+
+	/* Setup the PIRQ. */
+	i82801gx_pirq_init(dev);
+
+	/* Setup power options. */
+	i82801gx_power_options(dev);
+
+	/* Set the state of the GPIO lines. */
+	//gpio_init(dev);
+
+	/* Initialize the real time clock. */
+	i82801gx_rtc_init(dev);
+
+	/* Initialize ISA DMA. */
+	isa_dma_init();
+
+	/* Initialize the High Precision Event Timers, if present. */
+	enable_hpet(dev);
+
+	setup_i8259();
+
+	i82801gx_lock_smm(dev);
+}
+
+static void i82801gx_lpc_read_resources(struct device * dev)
+{
+	struct resource *res;
+
+	/* Get the normal PCI resources of this device. */
+	pci_dev_read_resources(dev);
+
+	/* Add an extra subtractive resource for both memory and I/O. */
+	res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
+	res->flags =
+	    IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+
+	res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
+	res->flags =
+	    IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+}
+
+static void i82801gx_lpc_enable_resources(struct device * dev)
+{
+	pci_dev_enable_resources(dev);
+	enable_childrens_resources(dev);
+}
+
+static void set_subsystem(struct device * dev, unsigned vendor, unsigned device)
+{
+	printk(BIOS_DEBUG, "Setting LPC bridge subsystem ID\n");
+	pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+			pci_read_config32(dev, 0));
+}
+
+static struct pci_operations pci_ops = {
+	.set_subsystem = set_subsystem,
+};
+
+/* 82801GB/GR/GDH (ICH7/ICH7R/ICH7DH) */
+struct device_operations ich7_ich7r_ich7dh_lpc = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27b8}}},
+	.constructor		 = default_device_constructor,
+	.reset_bus		= pci_bus_reset,
+	.phase3_chip_setup_dev	= i82801gx_enable,
+	.phase3_scan		 = scan_static_bus,
+	.phase4_read_resources	 = i82801gx_lpc_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = i82801gx_lpc_enable_resources,
+	.phase6_init		 = lpc_init,
+	.ops_pci		 = &pci_ops,
+};
+
+
+/* 82801GBM/GU (ICH7-M/ICH7-U) */
+struct device_operations ich7m_ich7u_lpc = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27b9}}},
+	.constructor		 = default_device_constructor,
+	.reset_bus		= pci_bus_reset,
+	.phase3_chip_setup_dev	= i82801gx_enable,
+	.phase3_scan		 = scan_static_bus,
+	.phase4_read_resources	 = i82801gx_lpc_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = i82801gx_lpc_enable_resources,
+	.phase6_init		 = lpc_init,
+	.ops_pci		 = &pci_ops,
+};
+
+/* 82801GHM (ICH7-M DH) */
+struct device_operations ich7m_dh_lpc = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27bd}}},
+	.constructor		 = default_device_constructor,
+	.reset_bus		= pci_bus_reset,
+	.phase3_chip_setup_dev	= i82801gx_enable,
+	.phase3_scan		 = scan_static_bus,
+	.phase4_read_resources	 = i82801gx_lpc_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = i82801gx_lpc_enable_resources,
+	.phase6_init		 = lpc_init,
+	.ops_pci		 = &pci_ops,
+};
+

Added: coreboot-v3/southbridge/intel/i82801gx/mobilepci.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/mobilepci.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/mobilepci.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gmu_pci";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/nic.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/nic.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/nic.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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
+ */
+
+/* This code should work for all ICH* southbridges with a NIC. */
+
+#include <types.h>
+#include <lib.h>
+#include <console.h>
+#include <device/pci.h>
+#include <msr.h>
+#include <legacy.h>
+#include <device/pci_ids.h>
+#include <statictree.h>
+#include <config.h>
+
+static void nic_init(struct device *dev)
+{
+	/* Nothing yet */
+}
+
+/* 82801GB/GR/GDH/GBM/GHM (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH) */
+/* Note: 82801GU (ICH7-U) doesn't have a NIC. */
+/* PCI ID loaded from EEPROM. If EEPROM is 0, 0x27dc is used. */
+struct device_operations  = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27dc}}},
+	.constructor		 = default_device_constructor,
+	.phase4_read_resources	 = pci_dev_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_dev_enable_resources,
+	.phase6_init		 = nic_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};

Added: coreboot-v3/southbridge/intel/i82801gx/nic.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/nic.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/nic.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gx_nic";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/pci.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/pci.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/pci.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,154 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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 <types.h>
+#include <lib.h>
+#include <console.h>
+#include <device/pci.h>
+#include <msr.h>
+#include <legacy.h>
+#include <device/pci_ids.h>
+#include <statictree.h>
+#include <config.h>
+
+static void pci_init(struct device *dev)
+{
+	u16 reg16;
+
+#if 0
+	/* Commented out for now because it will break on some machines. */
+	/* Set latency timer to 32. */
+	pci_write_config16(dev, 0x1b, 0x20);
+#endif
+
+	/* disable parity error response */
+	reg16 = pci_read_config16(dev, 0x3e);
+	reg16 &= ~(1 << 0);
+	pci_write_config16(dev, 0x3e, reg16);
+
+	/* Clear errors in status registers */
+	reg16 = pci_read_config16(dev, 0x06);
+	reg16 |= 0xf900;
+	pci_write_config16(dev, 0x06, reg16);
+
+	reg16 = pci_read_config16(dev, 0x1e);
+	reg16 |= 0xf900;
+	pci_write_config16(dev, 0x1e, reg16);
+}
+
+static void ich_pci_dev_enable_resources(struct device *dev)
+{
+	const struct pci_operations *ops;
+	u16 command;
+
+	/* Set the subsystem vendor and device id for mainboard devices */
+	ops = ops_pci(dev);
+	if (dev->on_mainboard && ops && ops->set_subsystem) {
+		printk_debug("%s subsystem <- %02x/%02x\n",
+			dev_path(dev), 
+			MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID,
+			MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID);
+		ops->set_subsystem(dev, 
+			MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID,
+			MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID);
+	}
+
+#if 0
+	/* If we write to PCI_COMMAND, on some systems 
+	 * this will cause the ROM and APICs not being visible
+	 * anymore.
+	 */
+	command = pci_read_config16(dev, PCI_COMMAND);
+	command |= dev->command;
+	printk_debug("%s cmd <- %02x\n", dev_path(dev), command);
+	pci_write_config16(dev, PCI_COMMAND, command);
+#endif
+}
+
+static void ich_pci_bus_enable_resources(struct device *dev)
+{
+	u16 ctrl;
+	/* enable IO in command register if there is VGA card
+	 * connected with (even it does not claim IO resource)
+	 */
+	if (dev->link[0].bridge_ctrl & PCI_BRIDGE_CTL_VGA)
+		dev->command |= PCI_COMMAND_IO;
+	ctrl = pci_read_config16(dev, PCI_BRIDGE_CONTROL);
+	ctrl |= dev->link[0].bridge_ctrl;
+	ctrl |= (PCI_BRIDGE_CTL_PARITY + PCI_BRIDGE_CTL_SERR); /* error check */
+	printk_debug("%s bridge ctrl <- %04x\n", dev_path(dev), ctrl);
+	pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl);
+
+	/* This is the reason we need our own pci_bus_enable_resources */
+	ich_pci_dev_enable_resources(dev);
+
+	enable_childrens_resources(dev);
+}
+
+static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+#if 0
+	/* Currently disabled because it causes a "BAR 9" memory resource
+	 * conflict:
+	 */
+	u32 pci_id;
+
+	printk_debug("Setting PCI bridge subsystem ID\n");
+	pci_id = pci_read_config32(dev, 0);
+	pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID, pci_id );
+#endif
+}
+
+static struct pci_operations pci_ops = {
+	.set_subsystem = set_subsystem,
+};
+
+
+/* Desktop */
+/* 82801BA/CA/DB/EB/ER/FB/FR/FW/FRW/GB/GR/GDH/HB/IB/6300ESB/i3100 */
+struct device_operations i82801g_pci = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x244e}}},
+	.constructor		 = default_device_constructor,
+	.reset_bus		= pci_bus_reset,
+	.phase3_scan		 = pci_scan_bridge,
+	.phase4_read_resources	 = pci_bus_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = ich_pci_bus_enable_resources,
+	.phase6_init		 = pci_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};
+
+/* Mobile / Ultra Mobile */
+/* 82801BAM/CAM/DBL/DBM/FBM/GBM/GHM/GU/HBM/HEM */
+struct device_operations i82801gmu_pci = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x2448}}},
+	.constructor		 = default_device_constructor,
+	.reset_bus		= pci_bus_reset,
+	.phase3_scan		 = pci_scan_bridge,
+	.phase4_read_resources	 = pci_bus_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = ich_pci_bus_enable_resources,
+	.phase6_init		 = pci_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};

Added: coreboot-v3/southbridge/intel/i82801gx/pci.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/pci.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/pci.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801g_pci";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/pcie.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/pcie.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/pcie.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,172 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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 <types.h>
+#include <lib.h>
+#include <console.h>
+#include <device/pci.h>
+#include <msr.h>
+#include <legacy.h>
+#include <device/pci_ids.h>
+#include <statictree.h>
+#include <config.h>
+
+static void pci_init(struct device *dev)
+{
+	u16 reg16;
+	u32 reg32;
+
+	printk(BIOS_DEBUG, "Initializing ICH7 PCIe bridge.\n");
+#if 0
+	// When the latency of the PCIe(!) bridge is set to 0x20
+	// all devices on the secondary bus of the PCI(!) bridge
+	// suddenly vanish. If you know why, please explain here.
+
+	/* Set latency timer to 32. */
+	pci_write_config16(dev, 0x1b, 0x20);
+#endif
+
+	/* disable parity error response */
+	reg16 = pci_read_config16(dev, 0x3e);
+	reg16 &= ~(1 << 0);
+	pci_write_config16(dev, 0x3e, reg16);
+
+	/* Clear errors in status registers */
+	reg16 = pci_read_config16(dev, 0x06);
+	reg16 |= 0xf900;
+	pci_write_config16(dev, 0x06, reg16);
+
+	reg16 = pci_read_config16(dev, 0x1e);
+	reg16 |= 0xf900;
+	pci_write_config16(dev, 0x1e, reg16);
+
+	reg32 = pci_read_config32(dev, 0x20);
+	printk(BIOS_DEBUG, "    MBL    = 0x%08x\n", reg32);
+	reg32 = pci_read_config32(dev, 0x24);
+	printk(BIOS_DEBUG, "    PMBL   = 0x%08x\n", reg32);
+	reg32 = pci_read_config32(dev, 0x28);
+	printk(BIOS_DEBUG, "    PMBU32 = 0x%08x\n", reg32);
+	reg32 = pci_read_config32(dev, 0x2c);
+	printk(BIOS_DEBUG, "    PMLU32 = 0x%08x\n", reg32);
+}
+
+static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+	u32 pci_id;
+
+	printk(BIOS_DEBUG, "Setting PCIe bridge subsystem ID.\n");
+	pci_id = pci_read_config32(dev, 0);
+	pci_write_config32(dev, 0x94, pci_id );
+}
+
+static struct pci_operations pci_ops = {
+	.set_subsystem = set_subsystem,
+};
+
+/* 82801GB/GR/GDH/GBM/GHM (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH) */
+struct device_operations i82801gx_pcie_port1 = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27d0}}},
+	.constructor		 = default_device_constructor,
+	.reset_bus		= pci_bus_reset,
+	.phase3_scan		 = pci_scan_bridge,
+	.phase4_read_resources	 = pci_bus_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_bus_enable_resources,
+	.phase6_init		 = pci_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};
+
+/* 82801GB/GR/GDH/GBM/GHM (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH) */
+struct device_operations i82801gx_pcie_port2 = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27d2}}},
+	.constructor		 = default_device_constructor,
+	.reset_bus		= pci_bus_reset,
+	.phase3_scan		 = pci_scan_bridge,
+	.phase4_read_resources	 = pci_bus_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_bus_enable_resources,
+	.phase6_init		 = pci_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};
+
+/* 82801GB/GR/GDH/GBM/GHM (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH) */
+struct device_operations i82801gx_pcie_port3 = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27d4}}},
+	.constructor		 = default_device_constructor,
+	.reset_bus		= pci_bus_reset,
+	.phase3_scan		 = pci_scan_bridge,
+	.phase4_read_resources	 = pci_bus_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_bus_enable_resources,
+	.phase6_init		 = pci_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};
+
+/* 82801GB/GR/GDH/GBM/GHM (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH) */
+struct device_operations i82801gx_pcie_port4 = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27d6}}},
+	.constructor		 = default_device_constructor,
+	.reset_bus		= pci_bus_reset,
+	.phase3_scan		 = pci_scan_bridge,
+	.phase4_read_resources	 = pci_bus_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_bus_enable_resources,
+	.phase6_init		 = pci_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};
+
+/* 82801GR/GDH/GHM (ICH7R/ICH7DH/ICH7-M DH) */
+struct device_operations i82801gx_pcie_port5 = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27e0}}},
+	.constructor		 = default_device_constructor,
+	.reset_bus		= pci_bus_reset,
+	.phase3_scan		 = pci_scan_bridge,
+	.phase4_read_resources	 = pci_bus_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_bus_enable_resources,
+	.phase6_init		 = pci_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};
+
+/* 82801GR/GDH/GHM (ICH7R/ICH7DH/ICH7-M DH) */
+struct device_operations i82801gx_pcie_port6 = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27e2}}},
+	.constructor		 = default_device_constructor,
+	.reset_bus		= pci_bus_reset,
+	.phase3_scan		 = pci_scan_bridge,
+	.phase4_read_resources	 = pci_bus_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_bus_enable_resources,
+	.phase6_init		 = pci_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};
+

Added: coreboot-v3/southbridge/intel/i82801gx/pcie2.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/pcie2.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/pcie2.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gx_pcie_port2";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/pcie3.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/pcie3.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/pcie3.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gx_pcie_port3";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/pcie4.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/pcie4.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/pcie4.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gx_pcie_port4";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/pcie5.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/pcie5.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/pcie5.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gx_pcie_port5";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/pcie6.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/pcie6.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/pcie6.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gx_pcie_port6";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/sata.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/sata.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/sata.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,210 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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 <types.h>
+#include <lib.h>
+#include <console.h>
+#include <device/pci.h>
+#include <msr.h>
+#include <legacy.h>
+#include <device/pci_ids.h>
+#include <statictree.h>
+#include <config.h>
+#include "i82801gx.h"
+
+typedef struct southbridge_intel_i82801gx_config config_t;
+
+static void sata_init(struct device *dev)
+{
+	u32 reg32;
+	/* Get the chip configuration */
+	config_t *config = dev->device_configuration;
+
+	printk(BIOS_DEBUG, "i82801gx_sata: initializing...\n");
+	/* SATA configuration */
+
+	/* Enable BARs */
+	pci_write_config16(dev, 0x04, 0x0007);
+
+	if (config->ide_legacy_combined) {
+		pci_write_config8(dev, 0x09, 0x80);
+
+		/* Set timings */
+		pci_write_config16(dev, IDE_TIM_PRI, 0x8000);
+		pci_write_config16(dev, IDE_TIM_SEC, 0xa307);
+
+		/* Sync DMA */
+		pci_write_config16(dev, 0x48, 0x0004);
+		pci_write_config16(dev, 0x4a, 0x0200);
+
+		/* Combine IDE - SATA configuration */
+		pci_write_config8(dev, 0x90, 0x02);
+
+		/* Port 0 & 1 enable */
+		pci_write_config8(dev, 0x92, 0x0f);
+
+		/* SATA Initialization register */
+		pci_write_config32(dev, 0x94, 0x40000180);
+	} else if(config->sata_ahci) {
+		/* Allow both Legacy and Native mode */
+		pci_write_config8(dev, 0x09, 0x8f);
+
+		/* Set Interrupt Line */
+		/* Interrupt Pin is set by D31IP.PIP */
+		pci_write_config8(dev, INTR_LN, 0x0a);
+
+		/* Set timings */
+		pci_write_config16(dev, IDE_TIM_PRI, 0xa307);
+		pci_write_config16(dev, IDE_TIM_SEC, 0x8000);
+
+		/* Sync DMA */
+		pci_write_config16(dev, 0x48, 0x0001);
+		pci_write_config16(dev, 0x4a, 0x0001);
+
+		/* Set IDE I/O Configuration */
+		reg32 = SIG_MODE_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
+		pci_write_config32(dev, IDE_CONFIG, reg32);
+
+		/* Set Sata Controller Mode. */
+		pci_write_config8(dev, 0x90, 0xc0); // WTF - Reserved?
+
+		/* Port 0 & 1 enable */
+		pci_write_config8(dev, 0x92, 0x0f);
+
+		/* SATA Initialization register */
+		pci_write_config32(dev, 0x94, 0x1a000180);
+	} else {
+		/* Native mode capable on both primary and secondary (0xa)
+		 * or'ed with enabled (0x50) = 0xf
+		 */
+		pci_write_config8(dev, 0x09, 0x8f);
+
+		/* Set Interrupt Line */
+		/* Interrupt Pin is set by D31IP.PIP */
+		pci_write_config8(dev, INTR_LN, 0xff);
+	
+		/* Set timings */
+		pci_write_config16(dev, IDE_TIM_PRI, 0xa307);
+		pci_write_config16(dev, IDE_TIM_SEC, 0xe303);
+	
+		/* Sync DMA */
+		pci_write_config16(dev, 0x48, 0x0005);
+		pci_write_config16(dev, 0x4a, 0x0201);
+	
+		/* Set IDE I/O Configuration */
+		reg32 = SIG_MODE_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0;
+		pci_write_config32(dev, IDE_CONFIG, reg32);
+	
+		/* Set Sata Controller Mode. */
+		pci_write_config8(dev, 0x90, 0x02);
+	
+		/* Port 0 & 1 enable XXX */
+		pci_write_config8(dev, 0x92, 0x15);
+	
+		/* SATA Initialization register */
+		pci_write_config32(dev, 0x94, 0x1a000180);
+	}
+
+	/* All configurations need this SATA initialization sequence */
+	pci_write_config8(dev, 0xa0, 0x40);
+	pci_write_config8(dev, 0xa6, 0x22);
+	pci_write_config8(dev, 0xa0, 0x78);
+	pci_write_config8(dev, 0xa6, 0x22);
+	pci_write_config8(dev, 0xa0, 0x88);
+	reg32 = pci_read_config32(dev, 0xa4);
+	reg32 &= 0xc0c0c0c0;
+	reg32 |= 0x1b1b1212;
+	pci_write_config32(dev, 0xa4, reg32);
+	pci_write_config8(dev, 0xa0, 0x8c);
+	reg32 = pci_read_config32(dev, 0xa4);
+	reg32 &= 0xc0c0ff00;
+	reg32 |= 0x121200aa;
+	pci_write_config32(dev, 0xa4, reg32);
+	pci_write_config8(dev, 0xa0, 0x00);
+}
+
+static struct device_operations sata_ops = {
+	.read_resources		= pci_dev_read_resources,
+	.set_resources		= pci_dev_set_resources,
+	.enable_resources	= ,
+	.init			= ,
+	.scan_bus		= 0,
+	.enable			= i82801gx_enable,
+};
+
+/* Desktop Non-AHCI and Non-RAID Mode */
+/* 82801GB/GR/GDH (ICH7/ICH7R/ICH7DH) */
+struct device_operations i82801gx_sata_normal_driver = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27c0}}},
+	.constructor		 = default_device_constructor,
+	.reset_bus		= pci_bus_reset,
+	.phase3_chip_setup_dev	= i82801gx_enable,
+	.phase4_read_resources	 = pci_dev_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_dev_enable_resources,
+	.phase6_init		 = sata_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};
+
+#if 0
+/* NOTE: Any of the below are not properly supported yet. */
+
+/* Desktop AHCI Mode */
+/* 82801GB/GR/GDH (ICH7/ICH7R/ICH7DH) */
+static const struct pci_driver i82801gx_sata_ahci_driver __pci_driver = {
+	.ops	= &sata_ops,
+	.vendor	= PCI_VENDOR_ID_INTEL,
+	.device	= 0x27c1,
+};
+
+/* Desktop RAID mode */
+/* 82801GB/GR/GDH (ICH7/ICH7R/ICH7DH) */
+static const struct pci_driver i82801gx_sata_raid_driver __pci_driver = {
+	.ops	= &sata_ops,
+	.vendor	= PCI_VENDOR_ID_INTEL,
+	.device	= 0x27c3,
+};
+
+/* Mobile Non-AHCI and Non-RAID Mode */
+/* 82801GBM/GHM (ICH7-M/ICH7-M DH) */
+static const struct pci_driver i82801gx_sata_mobile_normal_driver __pci_driver = {
+	.ops	= &sata_ops,
+	.vendor	= PCI_VENDOR_ID_INTEL,
+	.device	= 0x27c4,
+};
+
+/* Mobile AHCI Mode */
+/* 82801GBM/GHM (ICH7-M/ICH7-M DH) */
+static const struct pci_driver i82801gx_sata_mobile_ahci_driver __pci_driver = {
+	.ops	= &sata_ops,
+	.vendor	= PCI_VENDOR_ID_INTEL,
+	.device	= 0x27c5,
+};
+
+/* ICH7M DH Raid Mode */
+/* 82801GHM (ICH7-M DH) */
+static const struct pci_driver i82801gx_sata_ich7dh_raid_driver __pci_driver = {
+	.ops	= &sata_ops,
+	.vendor	= PCI_VENDOR_ID_INTEL,
+	.device	= 0x27c6,
+};
+#endif
\ No newline at end of file

Added: coreboot-v3/southbridge/intel/i82801gx/sata.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/sata.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/sata.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gx_sata_normal_driver";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/smbus.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/smbus.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/smbus.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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 <types.h>
+#include <lib.h>
+#include <console.h>
+#include <device/pci.h>
+#include <msr.h>
+#include <legacy.h>
+#include <device/pci_ids.h>
+#include <statictree.h>
+#include <config.h>
+#include "i82801gx.h"
+#include "i82801_smbus.h"
+
+int smbus_read_byte(struct bus *bus, device_t dev, u8 address)
+{
+	u16 device;
+	struct resource *res;
+
+	device = dev->path.u.i2c.device;
+	res = find_resource(bus->dev, 0x20);
+
+	return do_smbus_read_byte(res->base, device, address);
+}
+
+static struct smbus_bus_operations lops_smbus_bus = {
+	.read_byte	= smbus_read_byte,
+};
+
+/* 82801GB/GR/GDH/GBM/GHM/GU (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH/ICH7-U) */
+struct device_operations i82801gx_smbus = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27da}}},
+	.constructor		 = default_device_constructor,
+	.phase3_chip_setup_dev	= i82801gx_enable,
+	.phase3_scan			= scan_static_bus,
+	.phase4_read_resources	 = pci_dev_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_dev_enable_resources,
+	.ops_pci		 = &pci_dev_ops_pci,
+	.ops_smbus_bus		= &lops_smbus_bus,
+};
+

Added: coreboot-v3/southbridge/intel/i82801gx/smbus.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/smbus.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/smbus.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gx_smbus";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/smi.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/smi.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/smi.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,335 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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 <device/device.h>
+#include <device/pci.h>
+#include <console/console.h>
+#include <arch/io.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include <string.h>
+#include "chip.h"
+
+// Future TODO: Move to i82801gx directory
+#include "../../../northbridge/intel/i945/ich7.h"
+
+extern unsigned char smm[];
+extern unsigned int smm_len;
+
+/* I945 */
+#define SMRAM		0x9d
+#define   D_OPEN	(1 << 6)
+#define   D_CLS		(1 << 5)
+#define   D_LCK		(1 << 4)
+#define   G_SMRAME	(1 << 3)
+#define   C_BASE_SEG	((0 << 2) | (1 << 1) | (0 << 0))
+
+/* ICH7 */
+#define PM1_STS		0x00
+#define PM1_EN		0x02
+#define PM1_CNT		0x04
+#define PM1_TMR		0x08
+#define PROC_CNT	0x10
+#define LV2		0x14
+#define LV3		0x15
+#define LV4		0x16
+#define PM2_CNT		0x20 // mobile only
+#define GPE0_STS	0x28
+#define GPE0_EN		0x2c
+#define SMI_EN		0x30
+#define   EL_SMI_EN	 (1 << 25) // Intel Quick Resume Technology
+#define   INTEL_USB2_EN	 (1 << 18) // Intel-Specific USB2 SMI logic
+#define   LEGACY_USB2_EN (1 << 17) // Legacy USB2 SMI logic
+#define   PERIODIC_EN	 (1 << 14) // SMI on PERIODIC_STS in SMI_STS
+#define   TCO_EN	 (1 << 13) // Enable TCO Logic (BIOSWE et al)
+#define   MCSMI_EN	 (1 << 11) // Trap microcontroller range access
+#define   BIOS_RLS	 (1 <<  7) // asserts SCI on bit set
+#define   SWSMI_TMR_EN	 (1 <<  6) // start software smi timer on bit set
+#define   APMC_EN	 (1 <<  5) // Writes to APM_CNT cause SMI#
+#define   SLP_SMI_EN	 (1 <<  4) // Write to SLP_EN in PM1_CNT asserts SMI#
+#define   LEGACY_USB_EN  (1 <<  3) // Legacy USB circuit SMI logic
+#define   BIOS_EN	 (1 <<  2) // Assert SMI# on setting GBL_RLS bit
+#define   EOS		 (1 <<  1) // End of SMI (deassert SMI#)
+#define   GBL_SMI_EN	 (1 <<  0) // SMI# generation at all?
+#define SMI_STS		0x34
+#define ALT_GP_SMI_EN	0x38
+#define ALT_GP_SMI_STS	0x3a
+#define GPE_CNTL	0x42
+#define DEVACT_STS	0x44
+#define SS_CNT		0x50
+#define C3_RES		0x54
+
+/* While we read PMBASE dynamically in case it changed, let's
+ * initialize it with a sane value
+ */
+static u16 pmbase = DEFAULT_PMBASE;
+
+/**
+ * @brief read and clear PM1_STS 
+ * @return PM1_STS register
+ */
+static u16 reset_pm1_status(void)
+{
+	u16 reg16;
+	
+	reg16 = inw(pmbase + PM1_STS);
+	/* set status bits are cleared by writing 1 to them */
+	outw(reg16, pmbase + PM1_STS);
+	
+	return reg16;
+}
+
+static void dump_pm1_status(u16 pm1_sts)
+{
+	printk_debug("PM1_STS: ");
+	if (pm1_sts & (1 << 15)) printk_debug("WAK ");
+	if (pm1_sts & (1 << 14)) printk_debug("PCIEXPWAK ");
+	if (pm1_sts & (1 << 11)) printk_debug("PRBTNOR ");
+	if (pm1_sts & (1 << 10)) printk_debug("RTC ");
+	if (pm1_sts & (1 <<  8)) printk_debug("PWRBTN ");
+	if (pm1_sts & (1 <<  5)) printk_debug("GBL ");
+	if (pm1_sts & (1 <<  4)) printk_debug("BM ");
+	if (pm1_sts & (1 <<  0)) printk_debug("TMROF ");
+	printk_debug("\n");
+}
+
+/**
+ * @brief read and clear SMI_STS 
+ * @return SMI_STS register
+ */
+static u32 reset_smi_status(void)
+{
+	u32 reg32;
+	
+	reg32 = inl(pmbase + SMI_STS);
+	/* set status bits are cleared by writing 1 to them */
+	outl(reg32, pmbase + SMI_STS);
+	
+	return reg32;
+}
+
+static void dump_smi_status(u32 smi_sts)
+{
+	printk_debug("SMI_STS: ");
+	if (smi_sts & (1 << 26)) printk_debug("SPI ");
+	if (smi_sts & (1 << 25)) printk_debug("EL_SMI ");
+	if (smi_sts & (1 << 21)) printk_debug("MONITOR ");
+	if (smi_sts & (1 << 20)) printk_debug("PCI_EXP_SMI ");
+	if (smi_sts & (1 << 18)) printk_debug("INTEL_USB2 ");
+	if (smi_sts & (1 << 17)) printk_debug("LEGACY_USB2 ");
+	if (smi_sts & (1 << 16)) printk_debug("SMBUS_SMI ");
+	if (smi_sts & (1 << 15)) printk_debug("SERIRQ_SMI ");
+	if (smi_sts & (1 << 14)) printk_debug("PERIODIC ");
+	if (smi_sts & (1 << 13)) printk_debug("TCO ");
+	if (smi_sts & (1 << 12)) printk_debug("DEVMON ");
+	if (smi_sts & (1 << 11)) printk_debug("MCSMI ");
+	if (smi_sts & (1 << 10)) printk_debug("GPI ");
+	if (smi_sts & (1 <<  9)) printk_debug("GPE0 ");
+	if (smi_sts & (1 <<  8)) printk_debug("PM1 ");
+	if (smi_sts & (1 <<  6)) printk_debug("SWSMI_TMR ");
+	if (smi_sts & (1 <<  5)) printk_debug("APM ");
+	if (smi_sts & (1 <<  4)) printk_debug("SLP_SMI ");
+	if (smi_sts & (1 <<  3)) printk_debug("LEGACY_USB ");
+	if (smi_sts & (1 <<  2)) printk_debug("BIOS ");
+	printk_debug("\n");
+}
+
+
+/**
+ * @brief read and clear GPE0_STS
+ * @return GPE0_STS register
+ */
+static u32 reset_gpe0_status(void)
+{
+	u32 reg32;
+	
+	reg32 = inl(pmbase + GPE0_STS);
+	/* set status bits are cleared by writing 1 to them */
+	outl(reg32, pmbase + GPE0_STS);
+	
+	return reg32;
+}
+
+static void dump_gpe0_status(u32 gpe0_sts)
+{
+	int i;
+	printk_debug("GPE0_STS: ");
+	for (i=31; i<= 16; i--) {
+		if (gpe0_sts & (1 << i)) printk_debug("GPIO%d ", (i-16));
+	}
+	if (gpe0_sts & (1 << 14)) printk_debug("USB4 ");
+	if (gpe0_sts & (1 << 13)) printk_debug("PME_B0 ");
+	if (gpe0_sts & (1 << 12)) printk_debug("USB3 ");
+	if (gpe0_sts & (1 << 11)) printk_debug("PME ");
+	if (gpe0_sts & (1 << 10)) printk_debug("EL_SCI/BATLOW ");
+	if (gpe0_sts & (1 <<  9)) printk_debug("PCI_EXP ");
+	if (gpe0_sts & (1 <<  8)) printk_debug("RI ");
+	if (gpe0_sts & (1 <<  7)) printk_debug("SMB_WAK ");
+	if (gpe0_sts & (1 <<  6)) printk_debug("TCO_SCI ");
+	if (gpe0_sts & (1 <<  5)) printk_debug("AC97 ");
+	if (gpe0_sts & (1 <<  4)) printk_debug("USB2 ");
+	if (gpe0_sts & (1 <<  3)) printk_debug("USB1 ");
+	if (gpe0_sts & (1 <<  2)) printk_debug("HOT_PLUG ");
+	if (gpe0_sts & (1 <<  0)) printk_debug("THRM ");
+	printk_debug("\n");
+}
+
+/**
+ * @brief read and clear TCOx_STS 
+ * @return TCOx_STS registers
+ */
+static u32 reset_tco_status(void)
+{
+	u32 tcobase = pmbase + 0x60;
+	u32 reg32;
+	
+	reg32 = inl(tcobase + 0x04);
+	/* set status bits are cleared by writing 1 to them */
+	outl(reg32 & ~(1<<18), tcobase + 0x04); //  Don't clear BOOT_STS before SECOND_TO_STS
+	if (reg32 & (1 << 18))
+		outl(reg32 & (1<<18), tcobase + 0x04); // clear BOOT_STS
+	
+	return reg32;
+}
+
+
+static void dump_tco_status(u32 tco_sts)
+{
+	printk_debug("TCO_STS: ");
+	if (tco_sts & (1 << 20)) printk_debug("SMLINK_SLV ");
+	if (tco_sts & (1 << 18)) printk_debug("BOOT ");
+	if (tco_sts & (1 << 17)) printk_debug("SECOND_TO ");
+	if (tco_sts & (1 << 16)) printk_debug("INTRD_DET ");
+	if (tco_sts & (1 << 12)) printk_debug("DMISERR ");
+	if (tco_sts & (1 << 10)) printk_debug("DMISMI ");
+	if (tco_sts & (1 <<  9)) printk_debug("DMISCI ");
+	if (tco_sts & (1 <<  8)) printk_debug("BIOSWR ");
+	if (tco_sts & (1 <<  7)) printk_debug("NEWCENTURY ");
+	if (tco_sts & (1 <<  3)) printk_debug("TIMEOUT ");
+	if (tco_sts & (1 <<  2)) printk_debug("TCO_INT ");
+	if (tco_sts & (1 <<  1)) printk_debug("SW_TCO ");
+	if (tco_sts & (1 <<  0)) printk_debug("NMI2SMI ");
+	printk_debug("\n");
+}
+
+
+
+/**
+ * @brief Set the EOS bit
+ */
+static void smi_set_eos(void)
+{
+	u8 reg8;
+	
+	reg8 = inb(pmbase + SMI_EN);
+	reg8 |= EOS;
+	outb(reg8, pmbase + SMI_EN);
+}
+
+extern uint8_t smm_relocation_start, smm_relocation_end;
+
+void smm_relocate(void)
+{
+	u32 smi_en;
+
+	printk_debug("Initializing SMM handler...");
+
+	pmbase = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x1f, 0)), 0x40) & 0xfffc;
+	printk_spew(" ... pmbase = 0x%04x\n", pmbase);
+
+	smi_en = inl(pmbase + SMI_EN);
+	if (smi_en & APMC_EN) {
+		printk_info("SMI# handler already enabled?\n");
+		return;
+	}
+
+	/* copy the SMM relocation code */
+	memcpy((void *)0x38000, &smm_relocation_start,
+			&smm_relocation_end - &smm_relocation_start);
+
+	printk_debug("\n");
+	dump_smi_status(reset_smi_status());
+	dump_pm1_status(reset_pm1_status());
+	dump_gpe0_status(reset_gpe0_status());
+	dump_tco_status(reset_tco_status());
+
+	/* Enable SMI generation:
+	 *  - on TCO events
+	 *  - on APMC writes (io 0xb2)
+	 *  - on writes to SLP_EN (sleep states)
+	 *  - on writes to GBL_RLS (bios commands)
+	 * No SMIs:
+	 *  - on microcontroller writes (io 0x62/0x66)
+	 */
+	outl(smi_en | (TCO_EN | APMC_EN | SLP_SMI_EN | BIOS_EN |
+				EOS | GBL_SMI_EN), pmbase + SMI_EN);
+
+	/**
+	 * There are several methods of raising a controlled SMI# via
+	 * software, among them:
+	 *  - Writes to io 0xb2 (APMC)
+	 *  - Writes to the Local Apic ICR with Delivery mode SMI.
+	 *
+	 * Using the local apic is a bit more tricky. According to 
+	 * AMD Family 11 Processor BKDG no destination shorthand must be 
+	 * used.
+	 * The whole SMM initialization is quite a bit hardware specific, so
+	 * I'm not too worried about the better of the methods at the moment
+	 */
+
+	/* raise an SMI interrupt */
+	printk_spew("  ... raise SMI#\n");
+	outb(0x00, 0xb2);
+}
+
+void smm_install(void)
+{
+	/* enable the SMM memory window */
+	pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
+				D_OPEN | G_SMRAME | C_BASE_SEG);
+
+	/* copy the real SMM handler */
+	memcpy((void *)0xa0000, smm, smm_len);
+	wbinvd();
+
+	/* close the SMM memory window and enable normal SMM */
+	pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
+			G_SMRAME | C_BASE_SEG);
+}
+
+void smm_init(void)
+{
+	smm_relocate();
+	smm_install();
+}
+
+void smm_lock(void)
+{
+	/* LOCK the SMM memory window and enable normal SMM.
+	 * After running this function, only a full reset can
+	 * make the SMM registers writable again.
+	 */
+	printk_debug("Locking SMM.\n");
+	pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
+			D_LCK | G_SMRAME | C_BASE_SEG);
+}
+

Added: coreboot-v3/southbridge/intel/i82801gx/smihandler.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/smihandler.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/smihandler.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,551 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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 <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include "chip.h"
+
+// Future TODO: Move to i82801gx directory
+#include "../../../northbridge/intel/i945/ich7.h"
+
+#define DEBUG_SMI
+
+#define ACPI_DISABLE	0x1e
+#define ACPI_ENABLE	0xe1
+
+/* I945 */
+#define SMRAM		0x9d
+#define   D_OPEN	(1 << 6)
+#define   D_CLS		(1 << 5)
+#define   D_LCK		(1 << 4)
+#define   G_SMRANE	(1 << 3)
+#define   C_BASE_SEG	((0 << 2) | (1 << 1) | (0 << 0))
+
+/* ICH7 */
+#define PM1_STS		0x00
+#define PM1_EN		0x02
+#define PM1_CNT		0x04
+#define PM1_TMR		0x08
+#define PROC_CNT	0x10
+#define LV2		0x14
+#define LV3		0x15
+#define LV4		0x16
+#define PM2_CNT		0x20 // mobile only
+#define GPE0_STS	0x28
+#define GPE0_EN		0x2c
+#define SMI_EN		0x30
+#define   EL_SMI_EN	 (1 << 25) // Intel Quick Resume Technology
+#define   INTEL_USB2_EN	 (1 << 18) // Intel-Specific USB2 SMI logic
+#define   LEGACY_USB2_EN (1 << 17) // Legacy USB2 SMI logic
+#define   PERIODIC_EN	 (1 << 14) // SMI on PERIODIC_STS in SMI_STS
+#define   TCO_EN	 (1 << 13) // Enable TCO Logic (BIOSWE et al)
+#define   MCSMI_EN	 (1 << 11) // Trap microcontroller range access
+#define   BIOS_RLS	 (1 <<  7) // asserts SCI on bit set
+#define   SWSMI_TMR_EN	 (1 <<  6) // start software smi timer on bit set
+#define   APMC_EN	 (1 <<  5) // Writes to APM_CNT cause SMI#
+#define   SLP_SMI_EN	 (1 <<  4) // Write to SLP_EN in PM1_CNT asserts SMI#
+#define   LEGACY_USB_EN  (1 <<  3) // Legacy USB circuit SMI logic
+#define   BIOS_EN	 (1 <<  2) // Assert SMI# on setting GBL_RLS bit
+#define   EOS		 (1 <<  1) // End of SMI (deassert SMI#)
+#define   GBL_SMI_EN	 (1 <<  0) // SMI# generation at all?
+#define SMI_STS		0x34
+#define ALT_GP_SMI_EN	0x38
+#define ALT_GP_SMI_STS	0x3a
+#define GPE_CNTL	0x42
+#define DEVACT_STS	0x44
+#define SS_CNT		0x50
+#define C3_RES		0x54
+
+#include "i82801gx_nvs.h"
+
+/* While we read PMBASE dynamically in case it changed, let's
+ * initialize it with a sane value
+ */
+static u16 pmbase = DEFAULT_PMBASE;
+
+typedef enum { SMI_LOCKED, SMI_UNLOCKED } smi_semaphore;
+
+/* SMI multiprocessing semaphore */
+static volatile smi_semaphore smi_handler_status = SMI_UNLOCKED;
+
+static int smi_obtain_lock(void)
+{
+	u8 ret = SMI_LOCKED;
+
+	asm volatile (
+		"movb %2, %%al\n"
+		"xchgb %%al, %1\n"
+		"movb %%al, %0\n"
+		: "=g" (ret), "=m" (smi_handler_status)
+		: "g" (SMI_LOCKED)
+		: "eax"
+	);
+
+	return (ret == SMI_UNLOCKED);
+}
+
+static void smi_release_lock(void)
+{
+	asm volatile (
+		"movb %1, %%al\n"
+		"xchgb %%al, %0\n"
+		: "=m" (smi_handler_status)
+		: "g" (SMI_UNLOCKED)
+		: "eax"
+	);
+}
+
+#define LAPIC_ID 0xfee00020
+static inline __attribute__((always_inline)) unsigned long nodeid(void)
+{
+	return (*((volatile unsigned long *)(LAPIC_ID)) >> 24);
+}
+
+
+/**
+ * @brief read and clear PM1_STS 
+ * @return PM1_STS register
+ */
+static u16 reset_pm1_status(void)
+{
+	u16 reg16;
+	
+	reg16 = inw(pmbase + PM1_STS);
+	/* set status bits are cleared by writing 1 to them */
+	outw(reg16, pmbase + PM1_STS);
+	
+	return reg16;
+}
+
+static void dump_pm1_status(u16 pm1_sts)
+{
+	printk_debug("PM1_STS: ");
+	if (pm1_sts & (1 << 15)) printk_debug("WAK ");
+	if (pm1_sts & (1 << 14)) printk_debug("PCIEXPWAK ");
+	if (pm1_sts & (1 << 11)) printk_debug("PRBTNOR ");
+	if (pm1_sts & (1 << 10)) printk_debug("RTC ");
+	if (pm1_sts & (1 <<  8)) printk_debug("PWRBTN ");
+	if (pm1_sts & (1 <<  5)) printk_debug("GBL ");
+	if (pm1_sts & (1 <<  4)) printk_debug("BM ");
+	if (pm1_sts & (1 <<  0)) printk_debug("TMROF ");
+	printk_debug("\n");
+}
+
+/**
+ * @brief read and clear SMI_STS 
+ * @return SMI_STS register
+ */
+static u32 reset_smi_status(void)
+{
+	u32 reg32;
+	
+	reg32 = inl(pmbase + SMI_STS);
+	/* set status bits are cleared by writing 1 to them */
+	outl(reg32, pmbase + SMI_STS);
+	
+	return reg32;
+}
+
+static void dump_smi_status(u32 smi_sts)
+{
+	printk_debug("SMI_STS: ");
+	if (smi_sts & (1 << 26)) printk_debug("SPI ");
+	if (smi_sts & (1 << 25)) printk_debug("EL_SMI ");
+	if (smi_sts & (1 << 21)) printk_debug("MONITOR ");
+	if (smi_sts & (1 << 20)) printk_debug("PCI_EXP_SMI ");
+	if (smi_sts & (1 << 18)) printk_debug("INTEL_USB2 ");
+	if (smi_sts & (1 << 17)) printk_debug("LEGACY_USB2 ");
+	if (smi_sts & (1 << 16)) printk_debug("SMBUS_SMI ");
+	if (smi_sts & (1 << 15)) printk_debug("SERIRQ_SMI ");
+	if (smi_sts & (1 << 14)) printk_debug("PERIODIC ");
+	if (smi_sts & (1 << 13)) printk_debug("TCO ");
+	if (smi_sts & (1 << 12)) printk_debug("DEVMON ");
+	if (smi_sts & (1 << 11)) printk_debug("MCSMI ");
+	if (smi_sts & (1 << 10)) printk_debug("GPI ");
+	if (smi_sts & (1 <<  9)) printk_debug("GPE0 ");
+	if (smi_sts & (1 <<  8)) printk_debug("PM1 ");
+	if (smi_sts & (1 <<  6)) printk_debug("SWSMI_TMR ");
+	if (smi_sts & (1 <<  5)) printk_debug("APM ");
+	if (smi_sts & (1 <<  4)) printk_debug("SLP_SMI ");
+	if (smi_sts & (1 <<  3)) printk_debug("LEGACY_USB ");
+	if (smi_sts & (1 <<  2)) printk_debug("BIOS ");
+	printk_debug("\n");
+}
+
+
+/**
+ * @brief read and clear GPE0_STS
+ * @return GPE0_STS register
+ */
+static u32 reset_gpe0_status(void)
+{
+	u32 reg32;
+	
+	reg32 = inl(pmbase + GPE0_STS);
+	/* set status bits are cleared by writing 1 to them */
+	outl(reg32, pmbase + GPE0_STS);
+	
+	return reg32;
+}
+
+static void dump_gpe0_status(u32 gpe0_sts)
+{
+	int i;
+	printk_debug("GPE0_STS: ");
+	for (i=31; i<= 16; i--) {
+		if (gpe0_sts & (1 << i)) printk_debug("GPIO%d ", (i-16));
+	}
+	if (gpe0_sts & (1 << 14)) printk_debug("USB4 ");
+	if (gpe0_sts & (1 << 13)) printk_debug("PME_B0 ");
+	if (gpe0_sts & (1 << 12)) printk_debug("USB3 ");
+	if (gpe0_sts & (1 << 11)) printk_debug("PME ");
+	if (gpe0_sts & (1 << 10)) printk_debug("EL_SCI/BATLOW ");
+	if (gpe0_sts & (1 <<  9)) printk_debug("PCI_EXP ");
+	if (gpe0_sts & (1 <<  8)) printk_debug("RI ");
+	if (gpe0_sts & (1 <<  7)) printk_debug("SMB_WAK ");
+	if (gpe0_sts & (1 <<  6)) printk_debug("TCO_SCI ");
+	if (gpe0_sts & (1 <<  5)) printk_debug("AC97 ");
+	if (gpe0_sts & (1 <<  4)) printk_debug("USB2 ");
+	if (gpe0_sts & (1 <<  3)) printk_debug("USB1 ");
+	if (gpe0_sts & (1 <<  2)) printk_debug("HOT_PLUG ");
+	if (gpe0_sts & (1 <<  0)) printk_debug("THRM ");
+	printk_debug("\n");
+}
+
+
+/**
+ * @brief read and clear TCOx_STS 
+ * @return TCOx_STS registers
+ */
+static u32 reset_tco_status(void)
+{
+	u32 tcobase = pmbase + 0x60;
+	u32 reg32;
+	
+	reg32 = inl(tcobase + 0x04);
+	/* set status bits are cleared by writing 1 to them */
+	outl(reg32 & ~(1<<18), tcobase + 0x04); //  Don't clear BOOT_STS before SECOND_TO_STS
+	if (reg32 & (1 << 18))
+		outl(reg32 & (1<<18), tcobase + 0x04); // clear BOOT_STS
+	
+	return reg32;
+}
+
+
+static void dump_tco_status(u32 tco_sts)
+{
+	printk_debug("TCO_STS: ");
+	if (tco_sts & (1 << 20)) printk_debug("SMLINK_SLV ");
+	if (tco_sts & (1 << 18)) printk_debug("BOOT ");
+	if (tco_sts & (1 << 17)) printk_debug("SECOND_TO ");
+	if (tco_sts & (1 << 16)) printk_debug("INTRD_DET ");
+	if (tco_sts & (1 << 12)) printk_debug("DMISERR ");
+	if (tco_sts & (1 << 10)) printk_debug("DMISMI ");
+	if (tco_sts & (1 <<  9)) printk_debug("DMISCI ");
+	if (tco_sts & (1 <<  8)) printk_debug("BIOSWR ");
+	if (tco_sts & (1 <<  7)) printk_debug("NEWCENTURY ");
+	if (tco_sts & (1 <<  3)) printk_debug("TIMEOUT ");
+	if (tco_sts & (1 <<  2)) printk_debug("TCO_INT ");
+	if (tco_sts & (1 <<  1)) printk_debug("SW_TCO ");
+	if (tco_sts & (1 <<  0)) printk_debug("NMI2SMI ");
+	printk_debug("\n");
+}
+
+
+/* ********************* smi_util ************************* */
+
+/* Data */
+#define UART_RBR 0x00
+#define UART_TBR 0x00
+
+/* Control */
+#define UART_IER 0x01
+#define UART_IIR 0x02
+#define UART_FCR 0x02
+#define UART_LCR 0x03
+#define UART_MCR 0x04
+#define UART_DLL 0x00
+#define UART_DLM 0x01
+
+/* Status */
+#define UART_LSR 0x05
+#define UART_MSR 0x06
+#define UART_SCR 0x07
+
+static int uart_can_tx_byte(void)
+{
+	return inb(TTYS0_BASE + UART_LSR) & 0x20;
+}
+
+static void uart_wait_to_tx_byte(void)
+{
+	while(!uart_can_tx_byte()) 
+	;
+}
+
+static void uart_wait_until_sent(void)
+{
+	while(!(inb(TTYS0_BASE + UART_LSR) & 0x40))
+	; 
+}
+
+static void uart_tx_byte(unsigned char data)
+{
+	uart_wait_to_tx_byte();
+	outb(data, TTYS0_BASE + UART_TBR);
+	/* Make certain the data clears the fifos */
+	uart_wait_until_sent();
+}
+
+void console_tx_flush(void)
+{
+	uart_wait_to_tx_byte();
+}
+
+void console_tx_byte(unsigned char byte)
+{
+	if (byte == '\n')
+		uart_tx_byte('\r');
+	uart_tx_byte(byte);
+}
+
+/* We are using PCIe accesses for now
+ *  1. the chipset can do it
+ *  2. we don't need to worry about how we leave 0xcf8/0xcfc behind
+ */
+#include "../../../northbridge/intel/i945/pcie_config.c"
+
+/* ********************* smi_util ************************* */
+
+
+void io_trap_handler(int smif)
+{
+	u8 reg8;
+	global_nvs_t *gnvs = (global_nvs_t *)0xc00;
+
+	printk_debug("SMI function trap 0x%x: ", smif);
+
+
+	switch (smif) {
+	case 0x32:
+		printk_debug("OS Init\n");
+		break;
+	case 0xd6:
+		printk_debug("Get Brightness\n");
+		outb(0x17, 0x66);
+		reg8 = inb(0x62);
+		gnvs->brtl = reg8;
+		break;
+	default:
+		printk_debug("Unknown function\n");
+		break;
+	}
+
+	/* 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;
+}
+
+/**
+ * @brief Set the EOS bit
+ */
+static void smi_set_eos(void)
+{
+	u8 reg8;
+	
+	reg8 = inb(pmbase + SMI_EN);
+	reg8 |= EOS;
+	outb(reg8, pmbase + SMI_EN);
+}
+
+/**
+ * @brief Interrupt handler for SMI#
+ *
+ * @param smm_revision revision of the smm state save map
+ */
+
+void smi_handler(u32 smm_revision)
+{
+	u8 reg8;
+	u16 pmctrl;
+	u16 pm1_sts;
+	u32 smi_sts, gpe0_sts, tco_sts;
+	unsigned int node;
+	smm_state_save_area_t state_save;
+
+	/* Are we ok to execute the handler? */
+	if (!smi_obtain_lock())
+		return;
+
+	node=nodeid();
+
+#ifdef DEBUG_SMI
+	console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
+#else
+	console_loglevel = 1;
+#endif
+
+	printk_debug("\nSMI# #%d\n", node);
+
+	switch (smm_revision) {
+	case 0x00030007:
+		state_save.type = LEGACY;
+		state_save.legacy_state_save = (legacy_smm_state_save_area_t *)
+			(0xa8000 + 0x7e00 - (node * 0x400));
+		break;
+	case 0x00030100:
+		state_save.type = EM64T;
+		state_save.em64t_state_save = (em64t_smm_state_save_area_t *)
+			(0xa8000 + 0x7d00 - (node * 0x400));
+		break;
+	default:
+		printk_debug("smm_revision: 0x%08x\n", smm_revision);
+		printk_debug("SMI# not supported on your CPU\n");
+		/* Don't release lock, so no further SMI will happen,
+		 * if we don't handle it anyways.
+		 */
+		return;
+	}
+
+	pmbase = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
+	printk_spew("SMI#: pmbase = 0x%04x\n", pmbase);
+	
+	/* We need to clear the SMI status registers, or we won't see what's
+	 * happening in the following calls.
+	 */
+	smi_sts = reset_smi_status();
+	dump_smi_status(smi_sts);
+
+	if (smi_sts & (1 << 21)) { // MONITOR
+		global_nvs_t *gnvs = (global_nvs_t *)0xc00;
+		int i;
+		u32 reg32;
+
+		reg32 = RCBA32(0x1e00); // TRSR - Trap Status Register
+#if 0
+		/* Comment in for some useful debug */
+		for (i=0; i<4; i++) {
+			if (reg32 & (1 << i)) {
+				printk_debug("  io trap #%d\n", i);
+			}
+		}
+#endif
+		RCBA32(0x1e00) = reg32; // TRSR
+
+		reg32 = RCBA32(0x1e10);
+
+		if ((reg32 & 0xfffc) != 0x808) {
+			printk_debug("  trapped io address = 0x%x\n", reg32 & 0xfffc);
+			printk_debug("  AHBE = %x\n", (reg32 >> 16) & 0xf);
+			printk_debug("  read/write: %s\n", (reg32 & (1 << 24)) ? "read" :
+				"write");
+		}
+
+		if (!(reg32 & (1 << 24))) {
+			/* Write Cycle */
+			reg32 = RCBA32(0x1e18);
+			printk_debug("  iotrap written data = 0x%08x\n", reg32);
+
+		}
+
+		if (gnvs->smif)
+			io_trap_handler(gnvs->smif); // call function smif
+	}
+
+	if (smi_sts & (1 << 13)) { // TCO
+		tco_sts = reset_tco_status();
+		dump_tco_status(tco_sts);
+
+		if (tco_sts & (1 << 8)) { // BIOSWR
+			u8 bios_cntl;
+
+			bios_cntl = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0xdc);
+
+			if (bios_cntl & 1) {
+				/* BWE is RW, so the SMI was caused by a
+				 * write to BWE, not by a write to the BIOS
+				 */
+
+				/* This is the place where we notice someone
+				 * is trying to tinker with the BIOS. We are
+				 * trying to be nice and just ignore it. A more
+				 * resolute answer would be to power down the
+				 * box.
+				 */
+				printk_debug("Switching back to RO\n");
+				pcie_write_config32(PCI_DEV(0, 0x1f, 0), 0xdc, (bios_cntl & ~1));
+			} /* No else for now? */
+		}
+	}
+
+	if (smi_sts & (1 << 8)) { // PM1
+		pm1_sts = reset_pm1_status();
+		dump_pm1_status(pm1_sts);
+	}
+
+	if (smi_sts & (1 << 9)) { // GPE0
+		gpe0_sts = reset_gpe0_status();
+		dump_gpe0_status(gpe0_sts);
+	}
+
+	if (smi_sts & (1 << 5)) { // APM
+		/* Emulate B2 register as the FADT / Linux expects it */
+
+		reg8 = inb(0xb2);
+		switch (reg8) {
+		case ACPI_DISABLE:
+			pmctrl = inw(pmbase + 0x04);
+			pmctrl |= (1 << 0);
+			outw(pmctrl, pmbase + 0x04);
+			printk_debug("SMI#: ACPI disabled.\n");
+			break;
+		case ACPI_ENABLE:
+			pmctrl = inw(pmbase + 0x04);
+			pmctrl &= ~(1 << 0);
+			outw(pmctrl, pmbase + 0x04);
+			printk_debug("SMI#: ACPI enabled.\n");
+			break;
+		}
+	}
+
+	if (smi_sts & (1 << 4)) { // SLP_SMI
+		u32 reg32;
+		reg32 = inl(pmbase + 0x04);
+		printk_debug("SMI#: SLP = 0x%08x\n");
+		printk_debug("SMI#: Powering off.\n");
+		outl((6 << 10), pmbase + 0x04);
+		outl((1 << 13) | (6 << 10), pmbase + 0x04);
+		printk_debug("....\n");
+	}
+
+
+	smi_release_lock();
+
+	/* De-assert SMI# signal to allow another SMI */
+	smi_set_eos();
+}

Added: coreboot-v3/southbridge/intel/i82801gx/smm.ld
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/smm.ld	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/smm.ld	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,53 @@
+
+/* Maximum number of CPUs/cores */
+CPUS = 4;
+
+SECTIONS
+{
+	/* This is the actual SMM handler. 
+	 *
+	 * We just put code, rodata, data and bss all in a row.
+	 */
+	. = 0xa0000;
+	.handler (.): {
+		/* Assembler stub */
+		*(.handler)
+
+		/* C code of the SMM handler */
+		*(.text);
+		*(.text.*);
+
+		/* C read-only data of the SMM handler */
+		. = ALIGN(16);
+		*(.rodata)
+		*(.rodata.*)
+
+		/* C read-write data of the SMM handler */
+		 . = ALIGN(4);
+		*(.data)
+
+		/* C uninitialized data of the SMM handler */
+		 . = ALIGN(4);
+		*(.bss)
+		*(.sbss)
+
+		/* What is this? */
+		*(COMMON)
+		 . = ALIGN(4);
+	}
+
+	/* We are using the ASEG interleaved to stuff the SMM handlers
+	 * for all CPU cores in there. The jump table redirects the execution
+	 * to the actual SMM handler
+	 */
+	. = 0xa8000 - (( CPUS - 1) * 0x400);
+	.jumptable : {
+		*(.jumptable)
+	}	
+
+	/DISCARD/ : {
+		*(.comment)
+		*(.note)
+		*(.note.*)
+	}
+}

Added: coreboot-v3/southbridge/intel/i82801gx/smmhandler.S
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/smmhandler.S	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/smmhandler.S	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,201 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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
+ */
+
+/* NOTE: This handler assumes the SMM window goes from 0xa0000
+ * to 0xaffff. In fact, at least on Intel Core CPUs (i945 chipset)
+ * the SMM window is 128K big, covering 0xa0000 to 0xbffff.
+ * So there is a lot of potential for growth in here. Let's stick
+ * to 64k if we can though.
+ */
+
+/*
+ * +--------------------------------+ 0xaffff
+ * |  Save State Map Node 0         |
+ * |  Save State Map Node 1         |
+ * |  Save State Map Node 2         |
+ * |  Save State Map Node 3         |
+ * |  ...                           |
+ * +--------------------------------+ 0xaf000
+ * |                                |
+ * |                                |
+ * |                                |
+ * +--------------------------------+ 0xa8400
+ * | SMM Entry Node 0 (+ stack)     | 
+ * +--------------------------------+ 0xa8000
+ * | SMM Entry Node 1 (+ stack)     | 
+ * | SMM Entry Node 2 (+ stack)     | 
+ * | SMM Entry Node 3 (+ stack)     | 
+ * | ...                            |
+ * +--------------------------------+ 0xa7400
+ * |                                |
+ * | SMM Handler                    |
+ * |                                |
+ * +--------------------------------+ 0xa0000
+ *
+ */
+
+#include <arch/asm.h>
+
+#define LAPIC_ID 0xfee00020
+
+/* SMM_HANDLER_OFFSET is the 16bit offset within the ASEG
+ * at which smm_handler_start lives. At the moment the handler
+ * lives right at 0xa0000, so the offset is 0. 
+ */
+
+#define SMM_HANDLER_OFFSET 0x0000
+
+/* initially SMM is some sort of real mode. Let gcc know
+ * how to treat the SMM handler stub
+ */
+
+.section ".handler", "a", @progbits
+
+.code16
+
+/**
+ * SMM code to enable protected mode and jump to the
+ * C-written function void smi_handler(u32 smm_revision)
+ *
+ * All the bad magic is not all that bad after all.
+ */
+smm_handler_start:
+	movw    $(smm_gdtptr16 - smm_handler_start + SMM_HANDLER_OFFSET), %bx
+	data32  lgdt %cs:(%bx)
+
+	movl    %cr0, %eax
+	andl    $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
+	orl     $0x60000001, %eax /* CD, NW, PE = 1 */
+	movl    %eax, %cr0
+
+	/* Enable protected mode */
+	data32  ljmp    $0x08, $1f
+
+.code32
+1:
+	/* Use flat data segment */
+	movw    $0x10, %ax
+	movw    %ax, %ds
+	movw    %ax, %es
+	movw    %ax, %ss
+	movw    %ax, %fs
+	movw    %ax, %gs
+
+	/* Get this CPU's LAPIC ID */
+	movl $LAPIC_ID, %esi
+	movl (%esi), %ecx
+	shr  $24, %ecx
+	
+	/* calculate stack offset by multiplying the APIC ID
+	 * by 1024 (0x400), and save that offset in ebp.
+	 */
+	shl $10, %ecx
+	movl %ecx, %ebp
+
+	/* We put the stack for each core right above 
+	 * its SMM entry point. Core 0 starts at 0xa8000, 
+	 * we spare 0x10 bytes for the jump to be sure.
+	 */
+	movl $0xa8010, %eax
+	subl %ecx, %eax		/* subtract offset, see above */
+	movl %eax, %ebx		/* Save bottom of stack in ebx */
+
+#define SMM_STACK_SIZE	(0x400 - 0x10)
+	/* clear stack */
+	cld
+	movl	%eax, %edi
+	movl	$(SMM_STACK_SIZE >> 2), %ecx
+	xorl	%eax, %eax
+	rep	stosl
+
+	/* set new stack */
+	addl	$SMM_STACK_SIZE, %ebx
+	movl	%ebx, %esp
+
+	/* Get SMM revision */
+	movl $0xa8000 + 0x7efc, %ebx	/* core 0 address */
+	subl %ebp, %ebx			/* subtract core X offset */
+	movl (%ebx), %eax
+	pushl %eax
+
+	/* Call 32bit C handler */
+	call smi_handler
+
+	/* To return, just do rsm. It will "clean up" protected mode */
+	rsm
+
+.code16
+
+.align	4, 0xff
+
+smm_gdtptr16:
+	.word	smm_gdt_end - smm_gdt - 1
+	.long	smm_gdt - smm_handler_start + 0xa0000 + SMM_HANDLER_OFFSET
+
+.code32
+
+smm_gdt:
+	/* The first GDT entry can not be used. Keep it zero */
+	.long	0x00000000, 0x00000000
+
+	/* gdt selector 0x08, flat code segment */
+	.word	0xffff, 0x0000		
+	.byte	0x00, 0x9b, 0xcf, 0x00 /* G=1 and 0x0f, 4GB limit */	
+
+	/* gdt selector 0x10, flat data segment */
+	.word	0xffff, 0x0000		
+	.byte	0x00, 0x93, 0xcf, 0x00
+
+smm_gdt_end:
+
+
+.section ".jumptable", "a", @progbits
+
+/* This is the SMM jump table. All cores use the same SMM handler
+ * for simplicity. But SMM Entry needs to be different due to the 
+ * save state area. The jump table makes sure all CPUs jump into the
+ * real handler on SMM entry.
+ */
+
+/* This code currently supports up to 4 CPU cores. If more than 4 CPU cores
+ * shall be used, below table has to be updated, as well as smm.ld
+ */
+
+/* GNU AS/LD will always generate code that assumes CS is 0xa000. In reality
+ * CS will be set to SMM_BASE[19:4] though. Knowing that the smm handler is the
+ * first thing in the ASEG, we do a far jump here, to set CS to 0xa000.
+ */
+
+.code16
+jumptable:
+	/* core 3 */
+	ljmp $0xa000, $SMM_HANDLER_OFFSET 
+.align 1024, 0x00
+	/* core 2 */
+	ljmp $0xa000, $SMM_HANDLER_OFFSET 
+.align 1024, 0x00
+	/* core 1 */
+	ljmp $0xa000, $SMM_HANDLER_OFFSET 
+.align 1024, 0x00
+	/* core 0 */
+	ljmp $0xa000, $SMM_HANDLER_OFFSET
+.align 1024, 0x00
+

Added: coreboot-v3/southbridge/intel/i82801gx/smmrelocate.S
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/smmrelocate.S	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/smmrelocate.S	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,168 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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 <arch/asm.h>
+#include "../../../../src/northbridge/intel/i945/ich7.h"
+
+#undef DEBUG_SMM_RELOCATION
+//#define DEBUG_SMM_RELOCATION
+
+#define LAPIC_ID 0xfee00020
+
+.global smm_relocation_start
+.global smm_relocation_end
+
+/* initially SMM is some sort of real mode. */
+.code16
+
+/**
+ * This trampoline code relocates SMBASE to 0xa0000 - ( lapicid * 0x400 )
+ *
+ * Why 0x400? It is a safe value to cover the save state area per CPU. On
+ * current AMD CPUs this area is _documented_ to be 0x200 bytes. On Intel
+ * Core 2 CPUs the _documented_ parts of the save state area is 48 bytes
+ * bigger, effectively sizing our data structures 0x300 bytes.
+ *
+ * LAPICID	SMBASE		SMM Entry 	SAVE STATE
+ *    0		0xa0000		0xa8000		0xafd00
+ *    1		0x9fc00		0xa7c00		0xaf900
+ *    2		0x9f800		0xa7800		0xaf500
+ *    3		0x9f400		0xa7400		0xaf100
+ *    4		0x9f000		0xa7000		0xaed00
+ *    5		0x9ec00		0xa6c00		0xae900
+ *    6		0x9e800		0xa6800		0xae500
+ *    7		0x9e400		0xa6400		0xae100
+ *    8		0x9e000		0xa6000		0xadd00
+ *    9		0x9dc00		0xa5c00		0xad900
+ *   10		0x9d800		0xa5800		0xad500
+ *   11		0x9d400		0xa5400		0xad100
+ *   12		0x9d000		0xa5000		0xacd00
+ *   13		0x9cc00		0xa4c00		0xac900
+ *   14		0x9c800		0xa4800		0xac500
+ *   15		0x9c400		0xa4400		0xac100
+ *    .		   .		   .		   .
+ *    .		   .		   .		   .
+ *    .		   .		   .		   .
+ *   31		0x98400		0xa0400		0xa8100
+ *
+ * With 32 cores, the SMM handler would need to fit between
+ * 0xa0000-0xa0400 and the stub plus stack would need to go
+ * at 0xa8000-0xa8100 (example for core 0). That is not enough.
+ *
+ * This means we're basically limited to 16 cpu cores before 
+ * we need to use the TSEG/HSEG for the actual SMM handler plus stack.
+ * When we exceed 32 cores, we also need to put SMBASE to TSEG/HSEG.
+ *
+ * If we figure out the documented values above are safe to use,
+ * we could pack the structure above even more, so we could use the
+ * scheme to pack save state areas for 63 AMD CPUs or 58 Intel CPUs
+ * in the ASEG.
+ *
+ * Note: Some versions of Pentium M need their SMBASE aligned to 32k.
+ * On those the above only works for up to 2 cores. But for now we only
+ * care fore Core (2) Duo/Solo
+ *
+ */
+
+smm_relocation_start:
+	/* Check revision to see if AMD64 style SMM_BASE
+	 *   Intel Core Solo/Duo:  0x30007
+	 *   Intel Core2 Solo/Duo: 0x30100
+	 *   AMD64:                0x3XX64
+	 * This check does not make much sense, unless someone ports
+	 * SMI handling to AMD64 CPUs.
+	 */
+
+	mov $0x38000 + 0x7efc, %ebx
+	addr32 mov (%ebx), %al
+	cmp $0x64, %al
+	je 1f
+ 
+	mov $0x38000 + 0x7ef8, %ebx
+	jmp smm_relocate
+1:
+	mov $0x38000 + 0x7f00, %ebx
+
+smm_relocate:
+	/* Get this CPU's LAPIC ID */
+	movl $LAPIC_ID, %esi
+	addr32 movl (%esi), %ecx
+	shr  $24, %ecx
+	
+	/* calculate offset by multiplying the 
+	 * apic ID by 1024 (0x400)
+	 */
+	movl %ecx, %edx
+	shl $10, %edx
+
+	movl $0xa0000, %eax
+	subl %edx, %eax	/* subtract offset, see above */
+
+	addr32 movl %eax, (%ebx)
+
+
+	/* The next section of code is hardware specific */
+
+	/* Clear SMI status */
+	movw $(DEFAULT_PMBASE + 0x34), %dx
+	inw %dx, %ax
+	outw %ax, %dx
+
+	/* Clear PM1 status */
+	movw $(DEFAULT_PMBASE + 0x00), %dx
+	inw %dx, %ax
+	outw %ax, %dx
+
+	/* Set EOS bit so other SMIs can occur */
+	movw $(DEFAULT_PMBASE + 0x30), %dx
+	inl %dx, %eax
+	orl $(1 << 1), %eax
+	outl %eax, %dx
+
+	/* End of hardware specific section. */
+#ifdef DEBUG_SMM_RELOCATION
+	/* print [SMM-x] so we can determine if CPUx went to SMM */
+	movw $TTYS0_BASE, %dx
+	mov $'[', %al
+	outb %al, %dx
+	mov $'S', %al
+	outb %al, %dx
+	mov $'M', %al
+	outb %al, %dx
+	outb %al, %dx
+	movb $'-', %al
+	outb %al, %dx
+	/* calculate ascii of cpu number. More than 9 cores? -> FIXME */
+	movb %cl, %al
+	addb $'0', %al 
+	outb %al, %dx
+	mov $']', %al
+	outb %al, %dx
+	mov $'\r', %al
+	outb %al, %dx
+	mov $'\n', %al
+	outb %al, %dx
+#endif
+
+	/* That's it. return */
+	rsm
+smm_relocation_end:
+

Added: coreboot-v3/southbridge/intel/i82801gx/stage1_smbus.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/stage1_smbus.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/stage1_smbus.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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 <types.h>
+#include <lib.h>
+#include <console.h>
+#include <device/pci.h>
+#include <msr.h>
+#include <legacy.h>
+#include <device/pci.h>
+#include <statictree.h>
+#include <config.h>
+#include <io.h>
+#include "i82801gx.h"
+#include "i82801gx_smbus.h"
+
+static void enable_smbus(void)
+{
+	u32 dev;
+
+	/* Set the SMBus device statically. */
+	dev = PCI_BDF(0x0, 0x1f, 0x3);
+
+	/* Check to make sure we've got the right device. */
+	if (pci_conf1_read_config16(dev, 0x2) != 0x27da) {
+		die("SMBus controller not found!");
+	}
+
+	/* Set SMBus I/O base. */
+	pci_conf1_write_config32(dev, SMB_BASE,
+			   SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO);
+
+	/* Set SMBus enable. */
+	pci_conf1_write_config8(dev, HOSTC, HST_EN);
+
+	/* Set SMBus I/O space enable. */
+	pci_conf1_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO);
+
+	/* Disable interrupt generation. */
+	outb(0, SMBUS_IO_BASE + SMBHSTCTL);
+
+	/* Clear any lingering errors, so transactions can run. */
+	outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
+	print_debug("SMBus controller enabled.\r\n");
+}
+
+int smbus_read_byte(u16 device, u16 address)
+{
+	return do_smbus_read_byte(device, address);
+}
+

Added: coreboot-v3/southbridge/intel/i82801gx/usb.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/usb.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/usb.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,104 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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 <types.h>
+#include <lib.h>
+#include <console.h>
+#include <device/pci.h>
+#include <msr.h>
+#include <legacy.h>
+#include <device/pci_ids.h>
+#include <statictree.h>
+#include <config.h>
+#include "i82801gx.h"
+
+static void usb_init(struct device *dev)
+{
+	u32 reg32;
+	u8 reg8;
+
+	/* USB Specification says the device must be Bus Master */
+	printk(BIOS_DEBUG, "UHCI: Setting up controller.. ");
+
+	reg32 = pci_read_config32(dev, PCI_COMMAND);
+	pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER);
+
+	reg8 = pci_read_config8(dev, 0xca);
+	reg8 |= (1 << 0);
+	pci_write_config8(dev, 0xca, reg8);
+
+	printk(BIOS_DEBUG, "done.\n");
+}
+
+/* 82801GB/GR/GDH/GBM/GHM/GU (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH/ICH7-U) */
+struct device_operations i82801gb_usb1 = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27c8}}},
+	.constructor		 = default_device_constructor,
+	.phase3_chip_setup_dev	= i82801gx_enable,
+	.phase4_read_resources	 = pci_dev_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_dev_enable_resources,
+	.phase6_init		 = usb_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};
+
+/* 82801GB/GR/GDH/GBM/GHM/GU (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH/ICH7-U) */
+struct device_operations i82801gb_usb2 = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27c9}}},
+	.constructor		 = default_device_constructor,
+	.phase3_chip_setup_dev	= i82801gx_enable,
+	.phase4_read_resources	 = pci_dev_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_dev_enable_resources,
+	.phase6_init		 = usb_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};
+
+/* 82801GB/GR/GDH/GBM/GHM/GU (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH/ICH7-U) */
+struct device_operations i82801gb_usb3 = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27ca}}},
+	.constructor		 = default_device_constructor,
+	.phase3_chip_setup_dev	= i82801gx_enable,
+	.phase4_read_resources	 = pci_dev_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_dev_enable_resources,
+	.phase6_init		 = usb_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};
+
+/* 82801GB/GR/GDH/GBM/GHM/GU (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH/ICH7-U) */
+struct device_operations i82801gb_usb4 = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27cb}}},
+	.constructor		 = default_device_constructor,
+	.phase3_chip_setup_dev	= i82801gx_enable,
+	.phase4_read_resources	 = pci_dev_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_dev_enable_resources,
+	.phase6_init		 = usb_init,
+	.ops_pci		 = &pci_dev_ops_pci,
+};

Added: coreboot-v3/southbridge/intel/i82801gx/usb1.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/usb1.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/usb1.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gb_usb1";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/usb2.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/usb2.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/usb2.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gb_usb2";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/usb3.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/usb3.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/usb3.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gb_usb3";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/usb4.dts
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/usb4.dts	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/usb4.dts	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Ronald G. Minnich <rminnich at gmail.com>
+ *
+ * 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
+ */
+
+{
+	device_operations = "i82801gb_usb4";
+};

Added: coreboot-v3/southbridge/intel/i82801gx/usb_ehci.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/usb_ehci.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/usb_ehci.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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 <types.h>
+#include <lib.h>
+#include <console.h>
+#include <device/pci.h>
+#include <msr.h>
+#include <legacy.h>
+#include <device/pci_ids.h>
+#include <statictree.h>
+#include <config.h>
+#include "i82801gx.h"
+
+static void usb_ehci_init(struct device *dev)
+{
+	u32 reg32;
+
+	printk(BIOS_DEBUG, "EHCI: Setting up controller.. ");
+	reg32 = pci_read_config32(dev, PCI_COMMAND);
+	pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER);
+
+	reg32 = pci_read_config32(dev, 0xdc);
+	reg32 |= (1 << 31) | (1 << 27);
+	pci_write_config32(dev, 0xdc, reg32);
+
+	reg32 = pci_read_config32(dev, 0xfc);
+	reg32 &= ~(3 << 2);
+	reg32 |= (2 << 2) | (1 << 29) | (1 << 17);
+	pci_write_config32(dev, 0xfc, reg32);
+
+	printk(BIOS_DEBUG, "done.\n");
+}
+
+static void usb_ehci_set_subsystem(struct device * dev, unsigned vendor,
+				   unsigned device)
+{
+	u8 access_cntl;
+
+	access_cntl = pci_read_config8(dev, 0x80);
+
+	/* Enable writes to protected registers. */
+	pci_write_config8(dev, 0x80, access_cntl | 1);
+
+	/* Write the subsystem vendor and device ID. */
+	pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+			   ((device & 0xffff) << 16) | (vendor & 0xffff));
+
+	/* Restore protection. */
+	pci_write_config8(dev, 0x80, access_cntl);
+}
+
+static struct pci_operations lops_pci = {
+	.set_subsystem	= &usb_ehci_set_subsystem,
+};
+
+/* 82801GB/GR/GDH/GBM/GHM/GU (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH/ICH7-U) */
+struct device_operations i82801gx_usb_ehci = {
+	.id = {.type = DEVICE_ID_PCI,
+		{.pci = {.vendor = PCI_VENDOR_ID_INTEL,
+			      .device = 0x27cc}}},
+	.constructor		 = default_device_constructor,
+	.phase3_chip_setup_dev	= i82801gx_enable,
+	.phase4_read_resources	 = pci_dev_read_resources,
+	.phase4_set_resources	 = pci_dev_set_resources,
+	.phase5_enable_resources = pci_bus_enable_resources,
+	.phase6_init		 = usb_ehci_init,
+	.ops_pci		 = &lops_pci,
+};
+

Added: coreboot-v3/southbridge/intel/i82801gx/watchdog.c
===================================================================
--- coreboot-v3/southbridge/intel/i82801gx/watchdog.c	                        (rev 0)
+++ coreboot-v3/southbridge/intel/i82801gx/watchdog.c	2008-11-11 18:16:02 UTC (rev 991)
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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; 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 <types.h>
+#include <lib.h>
+#include <console.h>
+#include <device/pci.h>
+#include <msr.h>
+#include <legacy.h>
+#include <device/pci_ids.h>
+#include <statictree.h>
+#include <config.h>
+
+void watchdog_off(void)
+{
+	struct device * dev;
+	unsigned long value, base;
+
+	/* Turn off the ICH7 watchdog. */
+	dev = dev_find_slot(0, PCI_DEVFN(0x1f, 0));
+
+	/* Enable I/O space. */
+	value = pci_read_config16(dev, 0x04);
+	value |= (1 << 10);
+	pci_write_config16(dev, 0x04, value);
+
+	/* Get TCO base. */
+	base = (pci_read_config32(dev, 0x40) & 0x0fffe) + 0x60;
+
+	/* Disable the watchdog timer. */
+	value = inw(base + 0x08);
+	value |= 1 << 11;
+	outw(value, base + 0x08);
+
+	/* Clear TCO timeout status. */
+	outw(0x0008, base + 0x04);
+	outw(0x0002, base + 0x06);
+
+	printk(BIOS_DEBUG, "ICH7 watchdog disabled\r\n");
+}





More information about the coreboot mailing list