This does the following:
cd coreboot/src/southbridge
svn mv i82801ca i82801cx
svn mv i82801dbm i82801dx
svn mv i82801er i82801ex
svn copy i82801xx i82801bx
svn mv i82801xx i82801ax
Plus, fixing up the filenames in these directories and the romstage.c and
Kconfig files of the mainboards using those drivers.
Plus, switching the thomson ip1000 and rca rm4100 to the i82801dx driver.
There's a lot more to be done, like
- adding device IDs for the ICH3 and newer drivers that have been kept in
i82801xx so far
- drop the additional parts support from the ax and bx drivers.
Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Uwe Hermann <uwe@hermann-uwe.de>
Acked-by: Joseph Smith <joe@settoplinux.org>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5167 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
diff --git a/src/southbridge/intel/i82801dx/Kconfig b/src/southbridge/intel/i82801dx/Kconfig
new file mode 100644
index 0000000..6a35691
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/Kconfig
@@ -0,0 +1,2 @@
+config SOUTHBRIDGE_INTEL_I82801DX
+ bool
diff --git a/src/southbridge/intel/i82801dx/Makefile.inc b/src/southbridge/intel/i82801dx/Makefile.inc
new file mode 100644
index 0000000..7167e1d
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/Makefile.inc
@@ -0,0 +1,9 @@
+driver-y += i82801dx.o
+driver-y += i82801dx_usb.o
+driver-y += i82801dx_lpc.o
+driver-y += i82801dx_ide.o
+driver-y += i82801dx_usb2.o
+driver-y += i82801dx_ac97.o
+#driver-y += i82801dx_nic.o
+#driver-y += i82801dx_pci.o
+obj-y += i82801dx_reset.o
diff --git a/src/southbridge/intel/i82801dx/chip.h b/src/southbridge/intel/i82801dx/chip.h
new file mode 100644
index 0000000..fdbb7d2
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/chip.h
@@ -0,0 +1,27 @@
+#ifndef I82801DX_CHIP_H
+#define I82801DX_CHIP_H
+
+struct southbridge_intel_i82801dx_config
+{
+ int enable_usb;
+ int enable_native_ide;
+ /**
+ * Interrupt Routing configuration
+ * If bit7 is 1, the interrupt is disabled.
+ */
+ uint8_t pirqa_routing;
+ uint8_t pirqb_routing;
+ uint8_t pirqc_routing;
+ uint8_t pirqd_routing;
+ uint8_t pirqe_routing;
+ uint8_t pirqf_routing;
+ uint8_t pirqg_routing;
+ uint8_t pirqh_routing;
+
+ uint8_t ide0_enable;
+ uint8_t ide1_enable;
+};
+
+extern struct chip_operations southbridge_intel_i82801dx_ops;
+
+#endif /* I82801DBM_CHIP_H */
diff --git a/src/southbridge/intel/i82801dx/cmos_failover.c b/src/southbridge/intel/i82801dx/cmos_failover.c
new file mode 100644
index 0000000..4821fad
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/cmos_failover.c
@@ -0,0 +1,16 @@
+//kind of cmos_err for ich5
+#define RTC_FAILED (1 <<2)
+#define GEN_PMCON_3 0xa4
+static void check_cmos_failed(void)
+{
+
+ uint8_t 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 |= CONFIG_MAX_REBOOT_CNT << 4;
+ cmos_write(byte, RTC_BOOT_BYTE);
+ }
+}
diff --git a/src/southbridge/intel/i82801dx/i82801dx.c b/src/southbridge/intel/i82801dx/i82801dx.c
new file mode 100644
index 0000000..abfd8c2
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/i82801dx.c
@@ -0,0 +1,65 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include "i82801dx.h"
+
+void i82801dx_enable(device_t dev)
+{
+ unsigned int index = 0;
+ uint8_t bHasDisableBit = 0;
+ uint16_t cur_disable_mask, new_disable_mask;
+
+// all 82801dbm devices are in bus 0
+ unsigned int devfn = PCI_DEVFN(0x1f, 0); // lpc
+ device_t lpc_dev = dev_find_slot(0, devfn); // 0
+ if (!lpc_dev)
+ return;
+
+ // Calculate disable bit position for specified device:function
+ // NOTE: For ICH-4, only the following devices can be disabled:
+ // D31: F0, F1, F3, F5, F6,
+ // D29: F0, F1, F2, F7
+
+ if (PCI_SLOT(dev->path.pci.devfn) == 31) {
+ index = PCI_FUNC(dev->path.pci.devfn);
+
+ switch (index) {
+ case 0:
+ case 1:
+ case 3:
+ case 5:
+ case 6:
+ bHasDisableBit = 1;
+ break;
+
+ default:
+ break;
+ };
+
+ if (index == 0)
+ index = 14; // D31:F0 bit is an exception
+
+ } else if (PCI_SLOT(dev->path.pci.devfn) == 29) {
+ index = 8 + PCI_FUNC(dev->path.pci.devfn);
+
+ if ((PCI_FUNC(dev->path.pci.devfn) < 3) || (PCI_FUNC(dev->path.pci.devfn) == 7))
+ bHasDisableBit = 1;
+ }
+
+ if (bHasDisableBit) {
+ cur_disable_mask = pci_read_config16(lpc_dev, FUNC_DIS);
+ new_disable_mask = cur_disable_mask & ~(1<<index); // enable it
+ if (!dev->enabled) {
+ new_disable_mask |= (1<<index); // disable it
+ }
+ if (new_disable_mask != cur_disable_mask) {
+ pci_write_config16(lpc_dev, FUNC_DIS, new_disable_mask);
+ }
+ }
+}
+
+struct chip_operations southbridge_intel_i82801dx_ops = {
+ CHIP_NAME("Intel ICH4/ICH4-M (82801Dx) Series Southbridge")
+ .enable_dev = i82801dx_enable,
+};
diff --git a/src/southbridge/intel/i82801dx/i82801dx.h b/src/southbridge/intel/i82801dx/i82801dx.h
new file mode 100644
index 0000000..d4e1aa0
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/i82801dx.h
@@ -0,0 +1,163 @@
+/* the problem: we have 82801dbm support in fb1, and 82801er in fb2.
+ * fb1 code is what we want, fb2 structure is needed however.
+ * so we need to get fb1 code for 82801dbm into fb2 structure.
+ */
+/* What I did: took the 80801er stuff from fb2, verify it against the
+ * db stuff in fb1, and made sure it was right.
+ */
+
+#ifndef I82801DX_H
+#define I82801DX_H
+
+#if !defined( __ROMCC__ ) && !defined(__PRE_RAM__)
+#include "chip.h"
+extern void i82801dx_enable(device_t dev);
+#endif
+
+#define MAINBOARD_POWER_OFF 0
+#define MAINBOARD_POWER_ON 1
+#define MAINBOARD_POWER_KEEP 2
+
+#ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL
+#define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
+#endif
+
+/*
+000 = Non-combined. P0 is primary master. P1 is secondary master.
+001 = Non-combined. P0 is secondary master. P1 is primary master.
+100 = Combined. P0 is primary master. P1 is primary slave. IDE is secondary; Primary IDE channel
+disabled.
+101 = Combined. P0 is primary slave. P1 is primary master. IDE is secondary.
+110 = Combined. IDE is primary. P0 is secondary master. P1 is secondary slave; Secondary IDE
+channel disabled.
+111 = Combined. IDE is primary. P0 is secondary slave. P1 is secondary master.
+*/
+
+#define PCI_DMA_CFG 0x90
+#define SERIRQ_CNTL 0x64
+#define GEN_CNTL 0xd0
+#define GEN_STS 0xd4
+#define RTC_CONF 0xd8
+#define GEN_PMCON_3 0xa4
+
+#define PCICMD 0x04
+#define PMBASE 0x40
+#define PMBASE_ADDR 0x0400
+#define ACPI_CNTL 0x44
+#define BIOS_CNTL 0x4E
+#define GPIO_BASE 0x58
+#define GPIO_CNTL 0x5C
+#define PIRQA_ROUT 0x60
+#define PIRQE_ROUT 0x68
+#define COM_DEC 0xE0
+#define LPC_EN 0xE6
+#define FUNC_DIS 0xF2
+
+/* 1e f0 244e */
+
+#define CMD 0x04
+#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
+
+#define RTC_FAILED (1 <<2)
+
+
+#define SMBUS_IO_BASE 0x1000
+
+#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
+
+/* Between 1-10 seconds, We should never timeout normally
+ * Longer than this is just painful when a timeout condition occurs.
+ */
+#define SMBUS_TIMEOUT (100*1000)
+
+#define PM1_STS 0x00
+#define WAK_STS (1 << 15)
+#define PCIEXPWAK_STS (1 << 14)
+#define PRBTNOR_STS (1 << 11)
+#define RTC_STS (1 << 10)
+#define PWRBTN_STS (1 << 8)
+#define GBL_STS (1 << 5)
+#define BM_STS (1 << 4)
+#define TMROF_STS (1 << 0)
+#define PM1_EN 0x02
+#define PCIEXPWAK_DIS (1 << 14)
+#define RTC_EN (1 << 10)
+#define PWRBTN_EN (1 << 8)
+#define GBL_EN (1 << 5)
+#define TMROF_EN (1 << 0)
+#define PM1_CNT 0x04
+#define SLP_EN (1 << 13)
+#define SLP_TYP (7 << 10)
+#define GBL_RLS (1 << 2)
+#define BM_RLD (1 << 1)
+#define SCI_EN (1 << 0)
+#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 PME_B0_STS (1 << 13)
+#define USB3_STS (1 << 12)
+#define PME_STS (1 << 11)
+#define BATLOW_STS (1 << 10)
+#define GST_STS (1 << 9)
+#define RI_STS (1 << 8)
+#define SMB_WAK_STS (1 << 7)
+#define TCOSCI_STS (1 << 6)
+#define AC97_STS (1 << 5)
+#define USB2_STS (1 << 4)
+#define USB1_STS (1 << 3)
+#define SWGPE_STS (1 << 2)
+#define HOT_PLUG_STS (1 << 1)
+#define THRM_STS (1 << 0)
+#define GPE0_EN 0x2c
+#define PME_B0_EN (1 << 13)
+#define PME_EN (1 << 11)
+#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
+
+#define TCOBASE 0x60 /* TCO Base Address Register */
+#define TCO1_CNT 0x08 /* TCO1 Control Register */
+
+#endif /* I82801DX_H */
diff --git a/src/southbridge/intel/i82801dx/i82801dx_ac97.c b/src/southbridge/intel/i82801dx/i82801dx_ac97.c
new file mode 100644
index 0000000..7524498
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/i82801dx_ac97.c
@@ -0,0 +1,41 @@
+/*
+ * (C) 2003 Linux Networx
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "i82801dx.h"
+
+
+static struct device_operations ac97audio_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .enable = i82801dx_enable,
+ .init = 0,
+ .scan_bus = 0,
+};
+
+static const struct pci_driver ac97audio_driver __pci_driver = {
+ .ops = &ac97audio_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801DBM_AC97_AUDIO,
+};
+
+
+static struct device_operations ac97modem_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .enable = i82801dx_enable,
+ .init = 0,
+ .scan_bus = 0,
+};
+
+static const struct pci_driver ac97modem_driver __pci_driver = {
+ .ops = &ac97modem_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801DBM_AC97_MODEM,
+};
diff --git a/src/southbridge/intel/i82801dx/i82801dx_early_smbus.c b/src/southbridge/intel/i82801dx/i82801dx_early_smbus.c
new file mode 100644
index 0000000..0a0ff91
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/i82801dx_early_smbus.c
@@ -0,0 +1,180 @@
+
+//#define SMBUS_IO_BASE 0x1000
+//#define SMBUS_IO_BASE 0x0f00
+
+#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
+
+/* Between 1-10 seconds, We should never timeout normally
+ * Longer than this is just painful when a timeout condition occurs.
+ */
+//#define SMBUS_TIMEOUT (100*1000*10)
+
+static void enable_smbus(void)
+{
+ device_t dev = PCI_DEV(0x0, 0x1f, 0x3);
+
+ print_debug("SMBus controller enabled\r\n");
+ /* set smbus iobase */
+ pci_write_config32(dev, 0x20, SMBUS_IO_BASE | 1);
+ /* Set smbus enable */
+ pci_write_config8(dev, 0x40, 0x01);
+ /* Set smbus iospace enable */
+ pci_write_config16(dev, 0x4, 0x01);
+ /* Disable interrupt generation */
+ outb(0, SMBUS_IO_BASE + SMBHSTCTL);
+ /* clear any lingering errors, so the transaction will run */
+ outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
+}
+
+
+static inline void smbus_delay(void)
+{
+ outb(0x80, 0x80);
+}
+
+static int smbus_wait_until_active(void)
+{
+ unsigned long loops;
+ loops = SMBUS_TIMEOUT;
+ do {
+ unsigned char val;
+ smbus_delay();
+ val = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+ if ((val & 1)) {
+ break;
+ }
+ } while(--loops);
+ return loops?0:-4;
+}
+
+static int smbus_wait_until_ready(void)
+{
+ unsigned long loops;
+ loops = SMBUS_TIMEOUT;
+ do {
+ unsigned char val;
+ smbus_delay();
+ val = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+ if ((val & 1) == 0) {
+ break;
+ }
+ if(loops == (SMBUS_TIMEOUT / 2)) {
+ outb(inb(SMBUS_IO_BASE + SMBHSTSTAT),
+ SMBUS_IO_BASE + SMBHSTSTAT);
+ }
+ } while(--loops);
+ return loops?0:-2;
+}
+
+static int smbus_wait_until_done(void)
+{
+ unsigned long loops;
+ loops = SMBUS_TIMEOUT;
+ do {
+ unsigned char val;
+ smbus_delay();
+
+ val = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+ if ( (val & 1) == 0) {
+ break;
+ }
+ if ((val & ~((1<<6)|(1<<0)) ) != 0 ) {
+ break;
+ }
+ } while(--loops);
+ return loops?0:-3;
+}
+
+static int smbus_read_byte(unsigned device, unsigned address)
+{
+ unsigned char global_control_register;
+ unsigned char global_status_register;
+ unsigned char byte;
+
+ /*print_err("smbus_read_byte\r\n");*/
+ if (smbus_wait_until_ready() < 0) {
+ print_err_hex8(-2);
+ return -2;
+ }
+
+ /* setup transaction */
+ /* disable interrupts */
+ outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xfe, SMBUS_IO_BASE + SMBHSTCTL);
+ /* set the device I'm talking too */
+ 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 a byte read, with interrupts disabled */
+ outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL);
+ /* poll for it to start */
+ if (smbus_wait_until_active() < 0) {
+ print_err_hex8(-4);
+ return -4;
+ }
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done() < 0) {
+ print_err_hex8(-3);
+ return -3;
+ }
+
+ global_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT) & ~(1<<6); /* Ignore the In Use Status... */
+
+ /* read results of transaction */
+ byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
+
+ if (global_status_register != 2) {
+ print_err_hex8(-1);
+ return -1;
+ }
+/*
+ print_err("smbus_read_byte: ");
+ print_err_hex32(device); print_err(" ad "); print_err_hex32(address);
+ print_err("value "); print_err_hex8(byte); print_err("\r\n");
+ */
+ return byte;
+}
+#if 0
+static void smbus_write_byte(unsigned device, unsigned address, unsigned char val)
+{
+ if (smbus_wait_until_ready() < 0) {
+ return;
+ }
+
+ /* by LYH */
+ outb(0x37,SMBUS_IO_BASE + SMBHSTSTAT);
+ /* set the device I'm talking too */
+ outw(((device & 0x7f) << 1) | 0, SMBUS_IO_BASE + SMBHSTADDR);
+
+ /* data to send */
+ outb(val, SMBUS_IO_BASE + SMBHSTDAT);
+
+ outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
+
+ /* start the command */
+ outb(0xa, SMBUS_IO_BASE + SMBHSTCTL);
+
+ /* poll for transaction completion */
+ smbus_wait_until_done();
+ return;
+}
+#endif
diff --git a/src/southbridge/intel/i82801dx/i82801dx_ide.c b/src/southbridge/intel/i82801dx/i82801dx_ide.c
new file mode 100644
index 0000000..bb35107
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/i82801dx_ide.c
@@ -0,0 +1,53 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "i82801dx.h"
+
+
+static void ide_init(struct device *dev)
+{
+#if ICH5_SATA_ADDRESS_MAP<=1
+ /* Enable ide devices so the linux ide driver will work */
+ uint16_t word;
+ uint8_t byte;
+ int enable_a=1, enable_b=1;
+
+
+ word = pci_read_config16(dev, 0x40);
+ word &= ~((1 << 15));
+ if (enable_a) {
+ /* Enable first ide interface */
+ word |= (1<<15);
+ printk_debug("IDE0 ");
+ }
+ pci_write_config16(dev, 0x40, word);
+
+ word = pci_read_config16(dev, 0x42);
+ word &= ~((1 << 15));
+ if (enable_b) {
+ /* Enable secondary ide interface */
+ word |= (1<<15);
+ printk_debug("IDE1 ");
+ }
+ pci_write_config16(dev, 0x42, word);
+#endif
+
+}
+
+static struct device_operations ide_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = ide_init,
+ .scan_bus = 0,
+ .enable = i82801dx_enable,
+};
+
+static const struct pci_driver ide_driver __pci_driver = {
+ .ops = &ide_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801DBM_IDE,
+};
+
diff --git a/src/southbridge/intel/i82801dx/i82801dx_lpc.c b/src/southbridge/intel/i82801dx/i82801dx_lpc.c
new file mode 100644
index 0000000..59225d2
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/i82801dx_lpc.c
@@ -0,0 +1,226 @@
+/*
+ * (C) 2003 Linux Networx, SuSE Linux AG
+ * (C) 2004 Tyan Computer
+ */
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <pc80/mc146818rtc.h>
+#include <pc80/isa-dma.h>
+#include <arch/io.h>
+#include "i82801dx.h"
+
+
+
+#define NMI_OFF 0
+
+void i82801dx_enable_ioapic( struct device *dev)
+{
+ uint32_t dword;
+ volatile uint32_t *ioapic_sba = (volatile uint32_t *)0xfec00000;
+ volatile uint32_t *ioapic_sbd = (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("");
+
+
+}
+void i82801dx_enable_serial_irqs( struct device *dev)
+{
+ pci_write_config8(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0<< 0));
+}
+void i82801dx_lpc_route_dma( struct device *dev, uint8_t mask)
+{
+ uint16_t 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);
+ }
+ pci_write_config16(dev, PCI_DMA_CFG, word);
+}
+void i82801dx_rtc_init(struct device *dev)
+{
+ uint8_t byte;
+ uint32_t dword;
+ int rtc_failed;
+ byte = pci_read_config8(dev, GEN_PMCON_3);
+ rtc_failed = byte & RTC_FAILED;
+ if (rtc_failed) {
+ byte &= ~(1 << 1); /* preserve the power fail state */
+ pci_write_config8(dev, GEN_PMCON_3, byte);
+ }
+ dword = pci_read_config32(dev, GEN_STS);
+ rtc_failed |= dword & (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);
+ 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)
+{
+ const unsigned long hpet_address = 0xfed0000;
+
+ uint32_t dword;
+ uint32_t code = (0 & 0x3);
+
+ 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*/
+
+ dword &= ~(3 << 15); /* clear it */
+ dword |= (code<<15);
+
+ printk_debug("enabling HPET @0x%x\n", hpet_address | (code <<12) );
+}
+
+static void lpc_init(struct device *dev)
+{
+ uint8_t byte;
+ int pwr_on=-1;
+ int nmi_option;
+
+ /* IO APIC initialization */
+ i82801dx_enable_ioapic(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.
+
+ /* posted memory write enable */
+ byte = pci_read_config8(dev, 0x46);
+ pci_write_config8(dev, 0x46, byte | (1<<0));
+#endif
+
+ /* 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 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 */
+ i82801dx_rtc_init(dev);
+
+ i82801dx_lpc_route_dma(dev, 0xff);
+
+ /* Initialize isa dma */
+ isa_dma_init();
+
+ i82801dx_1f0_misc(dev);
+ /* Initialize the High Precision Event Timers */
+ enable_hpet(dev);
+}
+
+static void i82801dx_lpc_read_resources(device_t 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->base = 0;
+ res->size = 0x1000;
+ res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
+ IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+
+ res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
+ res->base = 0xff800000;
+ res->size = 0x00800000; /* 8 MB for flash */
+ res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
+ IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+
+ res = new_resource(dev, 3); /* IOAPIC */
+ res->base = 0xfec00000;
+ res->size = 0x00001000;
+ res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+}
+
+static void i82801dx_lpc_enable_resources(device_t dev)
+{
+ pci_dev_enable_resources(dev);
+ enable_childrens_resources(dev);
+}
+
+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,
+};
+
+static const struct pci_driver lpc_driver __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801DBM_LPC,
+};
diff --git a/src/southbridge/intel/i82801dx/i82801dx_nic.c b/src/southbridge/intel/i82801dx/i82801dx_nic.c
new file mode 100644
index 0000000..6221ba488
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/i82801dx_nic.c
@@ -0,0 +1,21 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "i82801dx.h"
+
+
+static struct device_operations nic_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = 0,
+ .scan_bus = 0,
+};
+
+static const struct pci_driver nic_driver __pci_driver = {
+ .ops = &nic_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x103a,
+};
diff --git a/src/southbridge/intel/i82801dx/i82801dx_pci.c b/src/southbridge/intel/i82801dx/i82801dx_pci.c
new file mode 100644
index 0000000..0c88bf2
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/i82801dx_pci.c
@@ -0,0 +1,33 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "i82801dx.h"
+
+static void pci_init(struct device *dev)
+{
+ /* Enable pci error detecting */
+ uint32_t dword;
+ /* System error enable */
+ dword = pci_read_config32(dev, 0x04);
+ dword |= (1<<8); /* SERR# Enable */
+ dword |= (1<<6); /* Parity Error Response */
+ pci_write_config32(dev, 0x04, dword);
+
+}
+
+static struct device_operations pci_ops = {
+ .read_resources = pci_bus_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_bus_enable_resources,
+ .init = pci_init,
+ .scan_bus = pci_scan_bridge,
+};
+
+static const struct pci_driver pci_driver __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801DBM_PCI,
+};
+
diff --git a/src/southbridge/intel/i82801dx/i82801dx_reset.c b/src/southbridge/intel/i82801dx/i82801dx_reset.c
new file mode 100644
index 0000000..3d7a4b7
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/i82801dx_reset.c
@@ -0,0 +1,7 @@
+#include <arch/io.h>
+
+void hard_reset(void)
+{
+ /* Try rebooting through port 0xcf9 */
+ outb((0 <<3)|(1<<2)|(1<<1), 0xcf9);
+}
diff --git a/src/southbridge/intel/i82801dx/i82801dx_sata.c b/src/southbridge/intel/i82801dx/i82801dx_sata.c
new file mode 100644
index 0000000..22c6cd7
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/i82801dx_sata.c
@@ -0,0 +1,75 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "i82801dx.h"
+
+static void sata_init(struct device *dev)
+{
+
+ uint16_t word;
+ uint8_t byte;
+ int enable_c=1, enable_d=1;
+ // int i;
+
+ //Enable Serial ATA port
+ byte = pci_read_config8(dev,0x90);
+ byte &= 0xf8;
+ byte |= ICH5_SATA_ADDRESS_MAP & 7;
+ pci_write_config8(dev,0x90,byte);
+
+// for(i=0;i<10;i++) {
+ word = pci_read_config16(dev,0x92);
+ word &= 0xfffc;
+// if( (word & 0x0003) == 0x0003) break;
+ word |= 0x0003; // enable P0/P1
+ pci_write_config16(dev,0x92,word);
+// }
+
+// for(i=0;i<10;i++) {
+ /* enable ide0 */
+ word = pci_read_config16(dev, 0x40);
+ word &= ~(1 << 15);
+ if(enable_c==0) {
+// if( (word & 0x8000) == 0x0000) break;
+ word |= 0x0000;
+ }
+ else {
+// if( (word & 0x8000) == 0x8000) break;
+ word |= 0x8000;
+ }
+ pci_write_config16(dev, 0x40, word);
+// }
+ /* enable ide1 */
+// for(i=0;i<10;i++) {
+ word = pci_read_config16(dev, 0x42);
+ word &= ~(1 << 15);
+ if(enable_d==0) {
+// if( (word & 0x8000) == 0x0000) break;
+ word |= 0x0000;
+ }
+ else {
+// if( (word & 0x8000) == 0x8000) break;
+ word |= 0x8000;
+ }
+ pci_write_config16(dev, 0x42, word);
+// }
+
+}
+
+static struct device_operations sata_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = sata_init,
+ .scan_bus = 0,
+ .enable = i82801dx_enable,
+};
+
+static const struct pci_driver stat_driver __pci_driver = {
+ .ops = &sata_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801DBM_SATA,
+};
+
diff --git a/src/southbridge/intel/i82801dx/i82801dx_smbus.c b/src/southbridge/intel/i82801dx/i82801dx_smbus.c
new file mode 100644
index 0000000..e56a67c
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/i82801dx_smbus.c
@@ -0,0 +1,95 @@
+#include "i82801dx.h"
+#include <smbus.h>
+#include <pci.h>
+#include <arch/io.h>
+
+#define PM_BUS 0
+#define PM_DEVFN PCI_DEVFN(0x1f,3)
+
+#if 0
+#define SMBUS_IO_BASE 0x1000
+#define SMBHSTSTAT 0
+#define SMBHSTCTL 2
+#define SMBHSTCMD 3
+#define SMBHSTADD 4
+#define SMBHSTDAT0 5
+#define SMBHSTDAT1 6
+#define SMBBLKDAT 7
+#endif
+
+void smbus_enable(void)
+{
+ unsigned char byte;
+ /* iobase addr */
+ pcibios_write_config_dword(PM_BUS, PM_DEVFN, 0x20, SMBUS_IO_BASE | 1);
+ /* smbus enable */
+ pcibios_write_config_byte(PM_BUS, PM_DEVFN, 0x40, 1);
+ /* iospace enable */
+ pcibios_write_config_word(PM_BUS, PM_DEVFN, 0x4, 1);
+
+ /* Disable interrupt generation */
+ outb(0, SMBUS_IO_BASE + SMBHSTCTL);
+
+}
+
+void smbus_setup(void)
+{
+ outb(0, SMBUS_IO_BASE + SMBHSTSTAT);
+}
+
+static void smbus_wait_until_ready(void)
+{
+ while((inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1) == 1) {
+ /* nop */
+ }
+}
+
+static void smbus_wait_until_done(void)
+{
+ unsigned char byte;
+ do {
+ byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+ }
+ while((byte &1) == 1);
+ while( (byte & ~1) == 0) {
+ byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+ }
+}
+
+int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
+{
+ unsigned char host_status_register;
+ unsigned char byte;
+
+ smbus_wait_until_ready();
+
+ /* setup transaction */
+ /* disable interrupts */
+ outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
+ /* set the device I'm talking too */
+ outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBHSTADD);
+ /* 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 */
+ smbus_wait_until_done();
+
+ host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+
+ /* read results of transaction */
+ byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
+
+ *result = byte;
+ return host_status_register != 0x02;
+}
diff --git a/src/southbridge/intel/i82801dx/i82801dx_usb.c b/src/southbridge/intel/i82801dx/i82801dx_usb.c
new file mode 100644
index 0000000..2e60193
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/i82801dx_usb.c
@@ -0,0 +1,49 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "i82801dx.h"
+
+static void usb_init(struct device *dev)
+{
+
+
+#if 0
+ uint32_t cmd;
+ printk_debug("USB: Setting up controller.. ");
+ cmd = pci_read_config32(dev, PCI_COMMAND);
+ pci_write_config32(dev, PCI_COMMAND,
+ cmd | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
+
+
+ printk_debug("done.\n");
+#endif
+
+}
+
+static struct device_operations usb_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = usb_init,
+ .scan_bus = 0,
+ .enable = i82801dx_enable,
+};
+
+static const struct pci_driver usb_driver_1 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801DBM_USB1,
+};
+static const struct pci_driver usb_driver_2 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801DBM_USB2,
+};
+static const struct pci_driver usb_driver_3 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801DBM_USB3,
+};
diff --git a/src/southbridge/intel/i82801dx/i82801dx_usb2.c b/src/southbridge/intel/i82801dx/i82801dx_usb2.c
new file mode 100644
index 0000000..ca13e92
--- /dev/null
+++ b/src/southbridge/intel/i82801dx/i82801dx_usb2.c
@@ -0,0 +1,40 @@
+//2003 Copywright Tyan
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "i82801dx.h"
+
+static void usb2_init(struct device *dev)
+{
+
+
+#if 0
+ uint32_t cmd;
+ printk_debug("USB: Setting up controller.. ");
+ cmd = pci_read_config32(dev, PCI_COMMAND);
+ pci_write_config32(dev, PCI_COMMAND,
+ cmd | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
+
+
+ printk_debug("done.\n");
+#endif
+}
+
+static struct device_operations usb2_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = usb2_init,
+ .scan_bus = 0,
+ .enable = i82801dx_enable,
+};
+
+static const struct pci_driver usb2_driver __pci_driver = {
+ .ops = &usb2_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801DBM_EHCI,
+};