Index: src/southbridge/intel/i82801dx/i82801dx_lpc.c
===================================================================
--- src/southbridge/intel/i82801dx/i82801dx_lpc.c	(revision 5220)
+++ src/southbridge/intel/i82801dx/i82801dx_lpc.c	(working copy)
@@ -4,6 +4,7 @@
  * Copyright (C) 2003 Linux Networx
  * Copyright (C) 2004 SuSE Linux AG
  * Copyright (C) 2004 Tyan Computer
+ * Copyright (C) 2010 Joseph Smith <joe@settoplinux.org>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -30,169 +31,207 @@
 #include <arch/io.h>
 #include "i82801dx.h"
 
+#define GPIO_BASE_ADDR	0x00000500 /* GPIO Base Address Register */
+
 #define NMI_OFF 0
 
-void i82801dx_enable_ioapic(struct device *dev)
+typedef struct southbridge_intel_i82801dx_config config_t;
+
+void i82801dx_enable_apic(struct device *dev)
 {
-	u32 dword;
-	volatile u32 *ioapic_sba = (volatile u32 *)0xfec00000;
-	volatile u32 *ioapic_sbd = (volatile u32 *)0xfec00010;
+	uint32_t reg32;
+	volatile uint32_t *ioapic_index = (volatile uint32_t *)0xfec00000;
+	volatile uint32_t *ioapic_data = (volatile uint32_t *)0xfec00010;
 
-	dword = pci_read_config32(dev, GEN_CNTL);
-	dword |= (3 << 7);	/* enable ioapic */
-	dword |= (1 << 13);	/* coprocessor error enable */
-	dword |= (1 << 1);	/* delay transaction enable */
-	dword |= (1 << 2);	/* DMA collection buf enable */
-	pci_write_config32(dev, GEN_CNTL, dword);
-	printk_debug("ioapic southbridge enabled %x\n", dword);
-	*ioapic_sba = 0;
-	*ioapic_sbd = (2 << 24);
-	//lyh *ioapic_sba=3;
-	//lyh *ioapic_sbd=1;    
-	*ioapic_sba = 0;
-	dword = *ioapic_sbd;
-	printk_debug("Southbridge apic id = %x\n", dword);
-	if (dword != (2 << 24))
-		die("");
-	//lyh *ioapic_sba=3;
-	//lyh dword=*ioapic_sbd;
-	//lyh printk_debug("Southbridge apic DT = %x\n",dword);
-	//lyh if(dword!=1)
-	//lyh   die("");
+	/* Set ACPI base address (I/O space). */
+	pci_write_config32(dev, PMBASE, (PMBASE_ADDR | 1));
 
+	/* Enable ACPI I/O and power management. */
+	pci_write_config8(dev, ACPI_CNTL, 0x10);
+
+	reg32 = pci_read_config32(dev, GEN_CNTL);
+	reg32 |= (3 << 7);	/* Enable IOAPIC */
+	reg32 |= (1 << 13);	/* Coprocessor error enable */
+	reg32 |= (1 << 1);	/* Delayed transaction enable */
+	reg32 |= (1 << 2);	/* DMA collection buffer enable */
+	pci_write_config32(dev, GEN_CNTL, reg32);
+	printk_debug("IOAPIC Southbridge enabled %x\n", reg32);
+
+	*ioapic_index = 0;
+	*ioapic_data = (1 << 25);
+
+	*ioapic_index = 0;
+	reg32 = *ioapic_data;
+	printk_debug("Southbridge APIC ID = %x\n", reg32);
+	if (reg32 != (1 << 25))
+		die("APIC Error\n");
+
+	/* TODO: From i82801ca, needed/useful on other ICH? */
+	*ioapic_index = 3; /* Select Boot Configuration register. */
+	*ioapic_data = 1; /* Use Processor System Bus to deliver interrupts. */
 }
 
 void i82801dx_enable_serial_irqs(struct device *dev)
 {
+	/* Set packet length and toggle silent mode bit. */
 	pci_write_config8(dev, SERIRQ_CNTL,
 			  (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0));
+	pci_write_config8(dev, SERIRQ_CNTL,
+			  (1 << 7) | (0 << 6) | ((21 - 17) << 2) | (0 << 0));
 }
 
-void i82801dx_lpc_route_dma(struct device *dev, u8 mask)
+static void i82801dx_pirq_init(device_t dev)
 {
-	u16 word;
-	int i;
-	word = pci_read_config16(dev, PCI_DMA_CFG);
-	word &= ((1 << 10) - (1 << 8));
-	for (i = 0; i < 8; i++) {
-		if (i == 4)
-			continue;
-		word |= ((mask & (1 << i)) ? 3 : 1) << (i * 2);
+	/* Get the chip configuration */
+	config_t *config = dev->chip_info;
+
+	pci_write_config8(dev, PIRQA_ROUT, config->pirqa_routing);
+	pci_write_config8(dev, PIRQB_ROUT, config->pirqb_routing);
+	pci_write_config8(dev, PIRQC_ROUT, config->pirqc_routing);
+	pci_write_config8(dev, PIRQD_ROUT, config->pirqd_routing);
+	pci_write_config8(dev, PIRQE_ROUT, config->pirqe_routing);
+	pci_write_config8(dev, PIRQF_ROUT, config->pirqf_routing);
+	pci_write_config8(dev, PIRQG_ROUT, config->pirqg_routing);
+	pci_write_config8(dev, PIRQH_ROUT, config->pirqh_routing);
+
+}
+
+static void i82801dx_power_options(device_t dev)
+{
+	uint8_t byte;
+	int pwr_on = -1;
+	int nmi_option;
+
+	/* power after power fail */
+	/* FIXME this doesn't work! */
+	/* Which state do we want to goto after g3 (power restored)?
+	 * 0 == S0 Full On
+	 * 1 == S5 Soft Off
+	 */
+	pci_write_config8(dev, GEN_PMCON_3, pwr_on ? 0 : 1);
+	printk_info("Set power %s if power fails\n", pwr_on ? "on" : "off");
+
+	/* Set up NMI on errors. */
+	byte = inb(0x61);
+	byte &= ~(1 << 3);	/* IOCHK# NMI Enable */
+	byte &= ~(1 << 2);	/* PCI SERR# Enable */
+	outb(byte, 0x61);
+	byte = inb(0x70);
+
+	nmi_option = NMI_OFF;
+	get_option(&nmi_option, "nmi");
+	if (nmi_option) {
+		byte &= ~(1 << 7);	/* Set NMI. */
+		outb(byte, 0x70);
 	}
-	pci_write_config16(dev, PCI_DMA_CFG, word);
 }
 
+static void gpio_init(device_t dev)
+{
+	pci_write_config32(dev, GPIO_BASE, (GPIO_BASE_ADDR | 1));
+	pci_write_config8(dev, GPIO_CNTL, 0x10);
+}
+
 void i82801dx_rtc_init(struct device *dev)
 {
-	u8 byte;
-	u32 dword;
+	uint8_t reg8;
+	uint32_t reg32;
 	int rtc_failed;
-	byte = pci_read_config8(dev, GEN_PMCON_3);
-	rtc_failed = byte & RTC_FAILED;
+
+	reg8 = pci_read_config8(dev, GEN_PMCON_3);
+	rtc_failed = reg8 & RTC_BATTERY_DEAD;
 	if (rtc_failed) {
-		byte &= ~(1 << 1);	/* preserve the power fail state */
-		pci_write_config8(dev, GEN_PMCON_3, byte);
+		reg8 &= ~(1 << 1);	/* Preserve the power fail state. */
+		pci_write_config8(dev, GEN_PMCON_3, reg8);
 	}
-	dword = pci_read_config32(dev, GEN_STS);
-	rtc_failed |= dword & (1 << 2);
+	reg32 = pci_read_config32(dev, GEN_STS);
+	rtc_failed |= reg32 & (1 << 2);
 	rtc_init(rtc_failed);
-}
 
-void i82801dx_1f0_misc(struct device *dev)
-{
-	pci_write_config16(dev, PCICMD, 0x014f);
-	pci_write_config32(dev, PMBASE, 0x00001001);
-	pci_write_config8(dev, ACPI_CNTL, 0x10);
-	pci_write_config32(dev, GPIO_BASE, 0x00001181);
-	pci_write_config8(dev, GPIO_CNTL, 0x10);
-	pci_write_config32(dev, PIRQA_ROUT, 0x0A05030B);
-	pci_write_config8(dev, PIRQE_ROUT, 0x07);
+	/* Enable access to the upper 128 byte bank of CMOS RAM. */
 	pci_write_config8(dev, RTC_CONF, 0x04);
-	pci_write_config8(dev, COM_DEC, 0x10);	//lyh E0->
-	pci_write_config16(dev, LPC_EN, 0x000F);	//LYH 000D->
 }
 
-static void enable_hpet(struct device *dev)
+void i82801dx_lpc_route_dma(struct device *dev, uint8_t mask)
 {
-	const unsigned long hpet_address = 0xfed0000;
+	uint16_t reg16;
+	int i;
 
-	u32 dword;
-	u32 code = (0 & 0x3);
+	reg16 = pci_read_config16(dev, PCI_DMA_CFG);
+	reg16 &= 0x300;
+	for (i = 0; i < 8; i++) {
+		if (i == 4)
+			continue;
+		reg16 |= ((mask & (1 << i)) ? 3 : 1) << (i * 2);
+	}
+	pci_write_config16(dev, PCI_DMA_CFG, reg16);
+}
 
-	dword = pci_read_config32(dev, GEN_CNTL);
-	dword |= (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 */
+static void i82801dx_lpc_decode_en(device_t dev)
+{
+	/* Decode 0x3F8-0x3FF (COM1) for COMA port, 0x2F8-0x2FF (COM2) for COMB.
+	 * LPT decode defaults to 0x378-0x37F and 0x778-0x77F.
+	 * Floppy decode defaults to 0x3F0-0x3F5, 0x3F7.
+	 * We also need to set the value for LPC I/F Enables Register.
+	 */
+	pci_write_config8(dev, COM_DEC, 0x10);
+	pci_write_config16(dev, LPC_EN, 0x300F);
+}
 
-	dword &= ~(3 << 15);	/* clear it */
-	dword |= (code << 15);
+static void enable_hpet(struct device *dev)
+{
+#ifdef HPET_PRESENT
+	uint32_t reg32;
+	uint32_t code = (0 & 0x3);
 
-	printk_debug("enabling HPET @0x%x\n", hpet_address | (code << 12));
+	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_debug("Enabling HPET @0x%x\n", HPET_ADDR | (code << 12));
+#endif
 }
 
 static void lpc_init(struct device *dev)
 {
-	u8 byte;
-	int pwr_on = -1;
-	int nmi_option;
+	/* Set the value for PCI command register. */
+	pci_write_config16(dev, PCI_COMMAND, 0x000f);
 
-	/* IO APIC initialization */
-	i82801dx_enable_ioapic(dev);
+	/* IO APIC initialization. */
+	i82801dx_enable_apic(dev);
 
 	i82801dx_enable_serial_irqs(dev);
 
-#ifdef SUSPICIOUS_LOOKING_CODE
-	// The ICH-4 datasheet does not mention this configuration register. 
-	// This code may have been inherited (incorrectly) from code for the AMD 766 southbridge,
-	// which *does* support this functionality.
+	/* Setup the PIRQ. */
+	i82801dx_pirq_init(dev);
 
-	/* posted memory write enable */
-	byte = pci_read_config8(dev, 0x46);
-	pci_write_config8(dev, 0x46, byte | (1 << 0));
-#endif
+	/* Setup power options. */
+	i82801dx_power_options(dev);
 
-	/* power after power fail */
-	/* FIXME this doesn't work! */
-	/* Which state do we want to goto after g3 (power restored)?
-	 * 0 == S0 Full On
-	 * 1 == S5 Soft Off
-	 */
-	pci_write_config8(dev, GEN_PMCON_3, pwr_on ? 0 : 1);
-	printk_info("set power %s after power fail\n", pwr_on ? "on" : "off");
-#if 0
-	/* Enable Error reporting */
-	/* Set up sync flood detected */
-	byte = pci_read_config8(dev, 0x47);
-	byte |= (1 << 1);
-	pci_write_config8(dev, 0x47, byte);
-#endif
+	/* Set the state of the GPIO lines. */
+	gpio_init(dev);
 
-	/* Set up NMI on errors */
-	byte = inb(0x61);
-	byte &= ~(1 << 3);	/* IOCHK# NMI Enable */
-	byte &= ~(1 << 2);	/* PCI SERR# Enable */
-	outb(byte, 0x61);
-	byte = inb(0x70);
-	nmi_option = NMI_OFF;
-	get_option(&nmi_option, "nmi");
-	if (nmi_option) {
-		byte &= ~(1 << 7);	/* set NMI */
-		outb(byte, 0x70);
-	}
-
-	/* Initialize the real time clock */
+	/* Initialize the real time clock. */
 	i82801dx_rtc_init(dev);
 
+	/* Route DMA. */
 	i82801dx_lpc_route_dma(dev, 0xff);
 
-	/* Initialize isa dma */
+	/* Initialize ISA DMA. */
 	isa_dma_init();
 
-	i82801dx_1f0_misc(dev);
-	/* Initialize the High Precision Event Timers */
+	/* Setup decode ports and LPC I/F enables. */
+	i82801dx_lpc_decode_en(dev);
+
+	/* Initialize the High Precision Event Timers, if present. */
 	enable_hpet(dev);
 }
 
@@ -208,15 +247,15 @@
 	res->base = 0;
 	res->size = 0x1000;
 	res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
-	    IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+		     IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
 
 	res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
 	res->base = 0xff800000;
-	res->size = 0x00800000;	/* 8 MB for flash */
+	res->size = 0x00800000; /* 8 MB for flash */
 	res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
-	    IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+		     IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
 
-	res = new_resource(dev, 3);	/* IOAPIC */
+	res = new_resource(dev, 3); /* IOAPIC */
 	res->base = 0xfec00000;
 	res->size = 0x00001000;
 	res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
@@ -229,12 +268,12 @@
 }
 
 static struct device_operations lpc_ops = {
-	.read_resources = i82801dx_lpc_read_resources,
-	.set_resources = pci_dev_set_resources,
-	.enable_resources = i82801dx_lpc_enable_resources,
-	.init = lpc_init,
-	.scan_bus = scan_static_bus,
-	.enable = i82801dx_enable,
+	.read_resources		= i82801dx_lpc_read_resources,
+	.set_resources		= pci_dev_set_resources,
+	.enable_resources	= i82801dx_lpc_enable_resources,
+	.init			= lpc_init,
+	.scan_bus		= scan_static_bus,
+	.enable			= i82801dx_enable,
 };
 
 /* 82801DB/DBL */
Index: src/southbridge/intel/i82801dx/i82801dx.h
===================================================================
--- src/southbridge/intel/i82801dx/i82801dx.h	(revision 5220)
+++ src/southbridge/intel/i82801dx/i82801dx.h	(working copy)
@@ -77,8 +77,14 @@
 #define BIOS_CNTL       0x4E
 #define GPIO_BASE       0x58
 #define GPIO_CNTL       0x5C
-#define PIRQA_ROUT      0x60
-#define PIRQE_ROUT      0x68
+#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 COM_DEC         0xE0
 #define LPC_EN          0xE6
 #define FUNC_DIS        0xF2
@@ -190,4 +196,9 @@
 #define TCOBASE		0x60 /* TCO Base Address Register */
 #define TCO1_CNT	0x08 /* TCO1 Control Register */
 
+/* GEN_PMCON_3 bits */
+#define RTC_BATTERY_DEAD	(1 << 2)
+#define RTC_POWER_FAILED	(1 << 1)
+#define SLEEP_AFTER_POWER_FAIL	(1 << 0)
+
 #endif /* I82801DX_H */
