summaryrefslogtreecommitdiff
path: root/src/southbridge
diff options
context:
space:
mode:
authorCorey Osgood <corey.osgood@gmail.com>2007-06-14 06:10:57 +0000
committerStefan Reinauer <stepan@openbios.org>2007-06-14 06:10:57 +0000
commite99bd105af97ad905114bd76ae09326a10def8cf (patch)
tree22ef962a20d86a4362bc6a2620b72e2a8a344457 /src/southbridge
parentbd88057f73b83e5bfd9d0fe57b28c87c98d73b12 (diff)
downloadcoreboot-e99bd105af97ad905114bd76ae09326a10def8cf.tar.xz
This patch adds support for the Intel i82810 northbridge and various i82801xx
southbridges, along with the Asus MEW-VM. With this, my machine attempts to boot linux, but does so very slowly and fails during the boot process, probably because of the irq tables. Signed-off-by: Corey Osgood <corey.osgood@gmail.com> Acked-by: Joseph Smith <joe@smittys.pointclark.net> Acked-by: Stefan Reinauer <stepan@coresystems.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2719 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/southbridge')
-rw-r--r--src/southbridge/intel/i82801xx/Config.lb30
-rw-r--r--src/southbridge/intel/i82801xx/chip.h39
-rw-r--r--src/southbridge/intel/i82801xx/cmos_failover.c32
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx.c67
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx.h106
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx_ac97.c113
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx_early_smbus.c74
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx_ide.c113
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx_lpc.c289
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx_nic.c44
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx_pci.c80
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx_reset.c27
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx_sata.c82
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx_smbus.c94
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx_smbus.h181
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx_usb.c130
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx_usb_ehci.c81
-rw-r--r--src/southbridge/intel/i82801xx/i82801xx_watchdog.c51
18 files changed, 1633 insertions, 0 deletions
diff --git a/src/southbridge/intel/i82801xx/Config.lb b/src/southbridge/intel/i82801xx/Config.lb
new file mode 100644
index 0000000000..5f18ef89c3
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/Config.lb
@@ -0,0 +1,30 @@
+##
+## This file is part of the LinuxBIOS project.
+##
+## Copyright (C) 2007 Corey Osgood <corey.osgood@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
+##
+driver i82801xx.o
+driver i82801xx_usb.o
+driver i82801xx_lpc.o
+driver i82801xx_ide.o
+driver i82801xx_usb_ehci.o
+driver i82801xx_ac97.o
+driver i82801xx_nic.o
+driver i82801xx_pci.o
+driver i82801xx_sata.o
+object i82801xx_reset.o
+object i82801xx_watchdog.o
diff --git a/src/southbridge/intel/i82801xx/chip.h b/src/southbridge/intel/i82801xx/chip.h
new file mode 100644
index 0000000000..3c1a3fd6d9
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/chip.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Corey Osgood <corey_osgood@verizon.net>
+ *
+ * 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 IGNORE_I82801XX_DEVICE_LIST
+#warning "The i82801xx code currently supports, on a testing/experimental basis,"
+#warning "these devices:"
+#warning "i82801aa, i82801ab, i82801ba, i82801ca, i82801db, i82801dbm, i82801eb,"
+#warning "and i82801er."
+#warning "Using this without modification on any other i82801 version will probably"
+#warning "work until ram init, but will fail after that"
+#endif
+
+#ifndef SOUTHBRIDGE_INTEL_I82801XX_CHIP_H
+#define SOUTHBRIDGE_INTEL_I82801XX_CHIP_H
+
+struct southbridge_intel_i82801xx_config
+{
+};
+
+extern struct chip_operations southbridge_intel_i82801xx_ops;
+
+#endif /* SOUTHBRIDGE_INTEL_I82801XX_CHIP_H */
diff --git a/src/southbridge/intel/i82801xx/cmos_failover.c b/src/southbridge/intel/i82801xx/cmos_failover.c
new file mode 100644
index 0000000000..2e1d84adb8
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/cmos_failover.c
@@ -0,0 +1,32 @@
+/*
+ * This file is part of the LinuxBIOS 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 "i82801xx.h"
+
+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 |= MAX_REBOOT_CNT << 4;
+ cmos_write(byte, RTC_BOOT_BYTE);
+ }
+}
diff --git a/src/southbridge/intel/i82801xx/i82801xx.c b/src/southbridge/intel/i82801xx/i82801xx.c
new file mode 100644
index 0000000000..5cceab9b9b
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx.c
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2005 Digital Design Corporation
+ * (Written by Steven J. Magnani <steve@digidescorp.com> for Digital Design Corp)
+ * Copyright (C) 2007 Corey Osgood <corey.osgood@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 <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include "i82801xx.h"
+
+void i82801xx_enable(device_t dev)
+{
+ unsigned int index = 0;
+ uint16_t cur_disable_mask, new_disable_mask;
+
+ // All 82801 devices should be on bus 0
+ unsigned int devfn = PCI_DEVFN(0x1f, 0); // lpc
+ device_t lpc_dev = dev_find_slot(0, devfn); // 0
+ if (!lpc_dev)
+ return;
+
+ /* We're going to assume, perhaps incorrectly, that if a function exists
+ it can be disabled. Workarounds for ICH variants that don't follow this
+ should be done by checking the device ID */
+
+ if (PCI_SLOT(dev->path.u.pci.devfn) == 31) {
+ index = PCI_FUNC(dev->path.u.pci.devfn);
+ } else if (PCI_SLOT(dev->path.u.pci.devfn) == 29) {
+ index = 8 + PCI_FUNC(dev->path.u.pci.devfn);
+ }
+
+ /* Function 0 is a bit of an exception */
+ if(index == 0)
+ {
+ index = 14;
+ }
+ 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 desired
+ }
+ if (new_disable_mask != cur_disable_mask) {
+ pci_write_config16(lpc_dev, FUNC_DIS, new_disable_mask);
+ }
+}
+
+struct chip_operations southbridge_intel_i82801xx_ops = {
+ CHIP_NAME("Intel i82801 Series Southbridge")
+ .enable_dev = i82801xx_enable,
+};
diff --git a/src/southbridge/intel/i82801xx/i82801xx.h b/src/southbridge/intel/i82801xx/i82801xx.h
new file mode 100644
index 0000000000..273767949e
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx.h
@@ -0,0 +1,106 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Corey Osgood <corey.osgood@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
+ */
+
+#ifndef I82801XX_H
+#define I82801XX_H
+
+#ifndef __ROMCC__
+#include "chip.h"
+extern void i82801xx_enable(device_t dev);
+#endif
+
+#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 PM_BASE_ADDR 0x1100
+#define ACPI_CNTL 0x44
+#define BIOS_CNTL 0x4E
+#define GPIO_BASE 0x58
+#define GPIO_BASE_ADDR 0x1180
+#define GPIO_CNTL 0x5C
+#define PIRQA_ROUT 0x60
+#define PIRQE_ROUT 0x68
+#define COM_DEC 0xE0
+#define LPC_EN 0xE6
+#define FUNC_DIS 0xF2
+
+#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
+
+// 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 IDE_TIM_PRI 0x40 // IDE timings, primary
+#define IDE_TIM_SEC 0x42 // IDE timings, secondary
+
+// IDE_TIM bits
+#define IDE_DECODE_ENABLE (1 << 15)
+
+// 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 IO bits
+/* TODO: Does it matter where we put the SMBus IO base, as long as we keep
+ consistent and don't interfere with anything else? */
+//#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
+
+#define SMBUS_TIMEOUT (10 * 1000 * 100)
+
+//HPET, if present
+#define HPET_ADDR 0xfed0000
+
+#endif /* I82801XX_H */
diff --git a/src/southbridge/intel/i82801xx/i82801xx_ac97.c b/src/southbridge/intel/i82801xx/i82801xx_ac97.c
new file mode 100644
index 0000000000..f61e069e96
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx_ac97.c
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2005 Tyan Computer
+ * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer)
+ *
+ * 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 <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include "i82801xx.h"
+
+static struct device_operations ac97_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = 0,
+ .scan_bus = 0,
+ .enable = i82801xx_enable,
+};
+
+/* i82801aa */
+static struct pci_driver i82801aa_ac97_audio __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2415,
+};
+
+static struct pci_driver i82801aa_ac97_modem __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2416,
+};
+
+/* i82801ab */
+static struct pci_driver i82801ab_ac97_audio __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2425,
+};
+
+static struct pci_driver i82801ab_ac97_modem __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2426,
+};
+
+/* i82801ba */
+static struct pci_driver i82801ba_ac97_audio __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2445,
+};
+
+static struct pci_driver i82801ba_ac97_modem __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2446,
+};
+
+/* i82801ca */
+static struct pci_driver i82801ca_ac97_audio __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2485,
+};
+
+static struct pci_driver i82801ca_ac97_modem __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2486,
+};
+
+/* i82801db & i82801dbm */
+static struct pci_driver i82801db_ac97_audio __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24c5,
+};
+
+static struct pci_driver i82801db_ac97_modem __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24c6,
+};
+
+/* i82801eb & i82801er */
+static struct pci_driver i82801ex_ac97_audio __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24d5,
+};
+
+static struct pci_driver i82801ex_ac97_modem __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24d6,
+};
diff --git a/src/southbridge/intel/i82801xx/i82801xx_early_smbus.c b/src/southbridge/intel/i82801xx/i82801xx_early_smbus.c
new file mode 100644
index 0000000000..070cc22a00
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx_early_smbus.c
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2005 Tyan Computer
+ * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer)
+ * Copyright (C) 2007 Corey Osgood <corey.osgood@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/pci_ids.h>
+#include "i82801xx.h"
+#include "i82801xx_smbus.h"
+
+static void enable_smbus(void)
+{
+ device_t dev;
+ uint16_t device_id;
+
+ /* Set the SMBus device staticly */
+ dev = PCI_DEV(0x0, 0x1f, 0x3);
+
+ /* Check to make sure we've got the right device */
+ device_id = pci_read_config16(dev, 0x2);
+
+ /* Clear bits 7-4, since those are the only bits that vary between models */
+ device_id &= 0xff0f;
+
+ if(device_id != 0x2403)
+ {
+ die("Device not found, Corey probably screwed up!");
+ }
+
+ /* Set SMBus I/O base */
+ pci_write_config32(dev, SMB_BASE, SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO);
+ /* Set SMBus enable */
+ pci_write_config8(dev, HOSTC, HST_EN);
+ /* Set SMBus I/O space enable */
+ pci_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");
+}
+
+static inline int smbus_read_byte(unsigned device, unsigned address)
+{
+ return do_smbus_read_byte(device, address);
+}
+
+static void smbus_write_byte(unsigned device, unsigned address, unsigned char val)
+{
+ print_err("Unimplemented smbus_write_byte() called\r\n");
+ return;
+}
+
+static inline int smbus_write_block(unsigned device, unsigned length, unsigned cmd,
+ unsigned data1, unsigned data2)
+{
+ return do_smbus_write_block(device, length, cmd, data1, data2);
+}
diff --git a/src/southbridge/intel/i82801xx/i82801xx_ide.c b/src/southbridge/intel/i82801xx/i82801xx_ide.c
new file mode 100644
index 0000000000..f9bb403014
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx_ide.c
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2005 Tyan Computer
+ * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer)
+ * Copyright (C) 2005 Digital Design Corporation
+ * (Written by Steven J. Magnani <steve@digidescorp.com> for Digital Design Corp)
+ *
+ * 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 <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include "i82801xx.h"
+
+static void ide_init(struct device *dev)
+{
+ /* TODO: Needs to be tested for compatibility with ICH5(R) */
+ /* Enable ide devices so the linux ide driver will work */
+ uint16_t ideTimingConfig;
+ int enable_primary = 1;
+ int enable_secondary = 1;
+
+ ideTimingConfig = pci_read_config16(dev, IDE_TIM_PRI);
+ ideTimingConfig &= ~IDE_DECODE_ENABLE;
+ if (enable_primary) {
+ /* Enable primary ide interface */
+ ideTimingConfig |= IDE_DECODE_ENABLE;
+ printk_debug("IDE0 ");
+ }
+ pci_write_config16(dev, IDE_TIM_PRI, ideTimingConfig);
+
+ ideTimingConfig = pci_read_config16(dev, IDE_TIM_SEC);
+ ideTimingConfig &= ~IDE_DECODE_ENABLE;
+ if (enable_secondary) {
+ /* Enable secondary ide interface */
+ ideTimingConfig |= IDE_DECODE_ENABLE;
+ printk_debug("IDE1 ");
+ }
+ pci_write_config16(dev, IDE_TIM_SEC, ideTimingConfig);
+}
+
+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 = i82801xx_enable,
+};
+
+/* i82801aa */
+static struct pci_driver i82801aa_ide __pci_driver = {
+ .ops = &ide_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2411,
+};
+
+/* i82801ab */
+static struct pci_driver i82801ab_ide __pci_driver = {
+ .ops = &ide_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2421,
+};
+
+/* i82801ba */
+static struct pci_driver i82801ba_ide __pci_driver = {
+ .ops = &ide_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x244b,
+};
+
+/* i82801ca */
+static struct pci_driver i82801ca_ide __pci_driver = {
+ .ops = &ide_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x248b,
+};
+
+/* i82801db */
+static struct pci_driver i82801db_ide __pci_driver = {
+ .ops = &ide_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24cb,
+};
+
+/* i82801dbm */
+static struct pci_driver i82801dbm_ide __pci_driver = {
+ .ops = &ide_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24ca,
+};
+
+/* i82801eb & i82801er */
+static struct pci_driver i82801ex_ide __pci_driver = {
+ .ops = &ide_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24db,
+};
diff --git a/src/southbridge/intel/i82801xx/i82801xx_lpc.c b/src/southbridge/intel/i82801xx/i82801xx_lpc.c
new file mode 100644
index 0000000000..3f9044c87a
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx_lpc.c
@@ -0,0 +1,289 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2003 Linux Networx
+ * Copyright (C) 2003 SuSE Linux AG
+ * Copyright (C) 2005 Tyan Computer
+ * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer)
+ *
+ * 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
+ */
+
+/* from i82801dbm, needs to be fixed to support everything the i82801er does */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <pc80/mc146818rtc.h>
+#include <pc80/isa-dma.h>
+#include <arch/io.h>
+#include "i82801xx.h"
+
+#define NMI_OFF 0
+
+void i82801xx_enable_ioapic( struct device *dev)
+{
+ uint32_t reg32;
+ volatile uint32_t *ioapic_index = (volatile uint32_t *)0xfec00000;
+ volatile uint32_t *ioapic_data = (volatile uint32_t *)0xfec00010;
+
+ 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 i82801xx_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));
+ /* TODO: Explain/#define the real meaning of these magic numbers ^^^ */
+}
+
+void i82801xx_lpc_route_dma( struct device *dev, uint8_t mask)
+{
+ uint16_t reg16;
+ int i;
+ 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);
+}
+
+void i82801xx_rtc_init(struct device *dev)
+{//todo:needs serious cleanup/comments
+ uint8_t reg8;
+ uint32_t reg32;
+ int rtc_failed;
+ byte = pci_read_config8(dev, GEN_PMCON_3);
+ rtc_failed = byte & RTC_BATTERY_DEAD;
+ if (rtc_failed) {
+ reg8 &= ~(1 << 1); /* preserve the power fail state */
+ pci_write_config8(dev, GEN_PMCON_3, reg8);
+ }
+ reg32 = pci_read_config32(dev, GEN_STS);
+ rtc_failed |= reg32 & (1 << 2);
+ rtc_init(rtc_failed);
+}
+
+
+void i82801xx_1f0_misc(struct device *dev)
+{
+ /* TODO: break this down into smaller functions */
+
+ //move to acpi_enable or something
+ /* Set ACPI base address to 0x1100 (I/O space) */
+ pci_write_config32(dev, PMBASE, PM_BASE_ADDR | 1);
+ /* Enable ACPI I/O and power management */
+ pci_write_config8(dev, ACPI_CNTL, 0x10);
+ /* Set GPIO base address to 0x1180 (I/O space) */
+ pci_write_config32(dev, GPIO_BASE, GPIO_BASE_ADDR | 1);
+ /* Enable GPIO */
+ pci_write_config8(dev, GPIO_CNTL, 0x10);
+
+ //get rid of?
+ /* Route PIRQA to IRQ11, PIRQB to IRQ3, PIRQC to IRQ5, PIRQD to IRQ10 */
+ pci_write_config32(dev, PIRQA_ROUT, 0x0A05030B);
+ /* Route PIRQE to IRQ7. Leave PIRQF - PIRQH unrouted */
+ pci_write_config8(dev, PIRQE_ROUT, 0x07);
+
+ //move to i82801xx_init
+ /* Prevent LPC disabling, enable parity errors, and SERR# (System Error) */
+ pci_write_config16(dev, PCI_COMMAND, 0x014f);
+ /* Enable access to the upper 128 byte bank of CMOS RAM */
+ pci_write_config8(dev, RTC_CONF, 0x04);
+ /* Decode 0x3F8-0x3FF (COM1) for COMA port, 0x2F8-0x2FF (COM2) for COMB */
+ pci_write_config8(dev, COM_DEC, 0x10);
+ /* LPT decode defaults to 0x378-0x37F and 0x778-0x77F
+ * Floppy decode defaults to 0x3F0-0x3F5, 0x3F7 */
+ /* Enable: COMA, COMB, LPT, Floppy
+ * Disable: Microcontroller, Sound, Gameport */
+ pci_write_config16(dev, LPC_EN, 0x000F);
+}
+
+static void enable_hpet(struct device *dev)
+{
+#ifdef HPET_PRESENT
+ uint32_t reg32;
+ uint32_t 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);
+ /* 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)
+{
+ uint8_t byte;
+ int pwr_on = -1;
+ int nmi_option;
+
+ /* IO APIC initialization */
+ i82801xx_enable_ioapic(dev);
+
+ i82801xx_enable_serial_irqs(dev);
+
+ /* TODO: Find out if this is being used/works */
+#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 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);
+ }
+
+ /* Initialize the real time clock */
+ i82801xx_rtc_init(dev);
+
+ i82801xx_lpc_route_dma(dev, 0xff);
+
+ /* Initialize isa dma */
+ isa_dma_init();
+
+ i82801xx_1f0_misc(dev);
+ /* Initialize the High Precision Event Timers, if present */
+ enable_hpet(dev);
+}
+
+static void i82801xx_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->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 i82801xx_lpc_enable_resources(device_t dev)
+{
+ pci_dev_enable_resources(dev);
+ enable_childrens_resources(dev);
+}
+
+static struct device_operations lpc_ops = {
+ .read_resources = i82801xx_lpc_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = i82801xx_lpc_enable_resources,
+ .init = lpc_init,
+ .scan_bus = scan_static_bus,
+ .enable = i82801xx_enable,
+};
+
+static struct pci_driver i82801aa_lpc __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2410,
+};
+
+static struct pci_driver i82801ab_lpc __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2420,
+};
+
+static struct pci_driver i82801ba_lpc __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2440,
+};
+
+static struct pci_driver i82801ca_lpc __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2480,
+};
+
+static struct pci_driver i82801db_lpc __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24c0,
+};
+
+static struct pci_driver i82801dbm_lpc __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24cc,
+};
+
+/* i82801eb and er */
+static struct pci_driver i82801ex_lpc __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24d0,
+};
diff --git a/src/southbridge/intel/i82801xx/i82801xx_nic.c b/src/southbridge/intel/i82801xx/i82801xx_nic.c
new file mode 100644
index 0000000000..fe2ee9fbb3
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx_nic.c
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Corey Osgood <corey.osgood@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 <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.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 struct pci_driver i82801dbm_nic __pci_driver = {
+ .ops = &nic_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x103a,
+};
+
+static struct pci_driver i82801ex_nic __pci_driver = {
+ .ops = &nic_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x1051,
+};
diff --git a/src/southbridge/intel/i82801xx/i82801xx_pci.c b/src/southbridge/intel/i82801xx/i82801xx_pci.c
new file mode 100644
index 0000000000..3d27f7f545
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx_pci.c
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2005 Tyan Computer
+ * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer)
+ *
+ * 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 <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+static void pci_init(struct device *dev)
+{
+ uint32_t reg32;
+ uint16_t reg16;
+
+ /* Clear system errors */
+ reg16 = pci_read_config16(dev, 0x06);
+ reg16 |= 0xf900; /* Clear possible errors */
+ pci_write_config16(dev, 0x06, reg16);
+
+ /* i82801er has this commented out, wonder why? */
+ /* System error enable */
+ reg32 = pci_read_config32(dev, 0x04);
+ reg32 |= (1 << 8); /* SERR# Enable */
+ reg32 |= (1 << 6); /* Parity Error Response */
+ pci_write_config32(dev, 0x04, reg32);
+
+ reg16 = pci_read_config16(dev, 0x1e);
+ reg16 |= 0xf800; /* Clear possible errors */
+ pci_write_config16(dev, 0x1e, reg16);
+}
+
+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 struct pci_driver i82801aa_pci __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2418,
+};
+
+static struct pci_driver i82801ab_pci __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2428,
+};
+
+/* i82801ba, ca, db, eb, and er */
+static struct pci_driver i82801misc_pci __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x244e,
+};
+
+static struct pci_driver i82801dbm_pci __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2448,
+};
diff --git a/src/southbridge/intel/i82801xx/i82801xx_reset.c b/src/southbridge/intel/i82801xx/i82801xx_reset.c
new file mode 100644
index 0000000000..7a9f6de492
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx_reset.c
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2002 Eric Biederman <ebiederm@xmission.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 <arch/io.h>
+
+void hard_reset(void)
+{
+ /* Try rebooting through port 0xcf9 */
+ outb((1 << 2)|(1 << 1), 0xcf9);
+}
diff --git a/src/southbridge/intel/i82801xx/i82801xx_sata.c b/src/southbridge/intel/i82801xx/i82801xx_sata.c
new file mode 100644
index 0000000000..33dfc329ac
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx_sata.c
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2005 Tyan Computer
+ * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer)
+ *
+ * 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 <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "i82801xx.h"
+
+/* TODO: set dynamically, if the user only wants one sata channel or none at all */
+
+static void sata_init(struct device *dev)
+{
+ /* SATA configuration */
+ pci_write_config8(dev, 0x04, 0x07);
+ pci_write_config8(dev, 0x09, 0x8f);
+
+ /* Set timmings */
+ pci_write_config16(dev, 0x40, 0x0a307);
+ pci_write_config16(dev, 0x42, 0x0a307);
+
+ /* Sync DMA */
+ pci_write_config16(dev, 0x48, 0x000f);
+ pci_write_config16(dev, 0x4a, 0x1111);
+
+ /* 66 mhz */
+ pci_write_config16(dev, 0x54, 0xf00f);
+
+ /* Combine ide - sata configuration */
+ pci_write_config8(dev, 0x90, 0x0);
+
+ /* port 0 & 1 enable */
+ pci_write_config8(dev, 0x92, 0x33);
+
+ /* initialize SATA */
+ pci_write_config16(dev, 0xa0, 0x0018);
+ pci_write_config32(dev, 0xa4, 0x00000264);
+ pci_write_config16(dev, 0xa0, 0x0040);
+ pci_write_config32(dev, 0xa4, 0x00220043);
+}
+
+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 = i82801xx_enable,
+};
+
+/* i82801eb */
+static struct pci_driver i82801eb_sata_driver __pci_driver = {
+ .ops = &sata_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24d1,
+};
+
+/* i82801er */
+static struct pci_driver i82801er_sata_driver __pci_driver = {
+ .ops = &sata_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24df,
+};
diff --git a/src/southbridge/intel/i82801xx/i82801xx_smbus.c b/src/southbridge/intel/i82801xx/i82801xx_smbus.c
new file mode 100644
index 0000000000..67a746666c
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx_smbus.c
@@ -0,0 +1,94 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2005 Yinghai Lu <yinghailu@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 <smbus.h>
+#include <pci.h>
+#include <arch/io.h>
+#include "i82801_model_specific.h"
+#include "i82801xx.h"
+#include "i82801_smbus.h"
+
+static int smbus_read_byte(struct bus *bus, device_t dev, uint8_t address)
+{
+ unsigned 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,
+};
+
+static struct device_operations smbus_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = 0,
+ .scan_bus = scan_static_bus,
+ .enable = i82801er_enable,
+ .ops_smbus_bus = &lops_smbus_bus,
+};
+
+/* i82801aa */
+static struct pci_driver smbus_driver __pci_driver = {
+ .ops = &smbus_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2413,
+};
+
+/* i82801ab */
+static struct pci_driver smbus_driver __pci_driver = {
+ .ops = &smbus_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2423,
+};
+
+/* i82801ba */
+static struct pci_driver smbus_driver __pci_driver = {
+ .ops = &smbus_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2443,
+};
+
+/* i82801ca */
+static struct pci_driver smbus_driver __pci_driver = {
+ .ops = &smbus_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2483,
+};
+
+/* i82801db and i82801dbm */
+static struct pci_driver smbus_driver __pci_driver = {
+ .ops = &smbus_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24c3,
+};
+
+/* i82801eb and i82801er */
+static struct pci_driver smbus_driver __pci_driver = {
+ .ops = &smbus_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24d3,
+};
+
diff --git a/src/southbridge/intel/i82801xx/i82801xx_smbus.h b/src/southbridge/intel/i82801xx/i82801xx_smbus.h
new file mode 100644
index 0000000000..d0226046da
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx_smbus.h
@@ -0,0 +1,181 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2005 Yinghai Lu <yinghailu@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 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 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)
+{
+#warning "do_smbus_write_block is commented out"
+ print_err("Untested smbus_write_block called\r\n");
+#if 0
+ unsigned char global_control_register;
+ unsigned char global_status_register;
+ unsigned char byte;
+ unsigned char stat;
+ int i;
+
+ /* Clear the PM timeout flags, SECOND_TO_STS */
+ outw(inw(0x0400 + 0x66), 0x0400 + 0x66);
+
+ if (smbus_wait_until_ready(SMBUS_IO_BASE) < 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(SMBUS_IO_BASE) < 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);
+ }
+
+ print_debug("SMBUS Block complete\r\n");
+ return 0;
+#endif
+}
diff --git a/src/southbridge/intel/i82801xx/i82801xx_usb.c b/src/southbridge/intel/i82801xx/i82801xx_usb.c
new file mode 100644
index 0000000000..27c09e089e
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx_usb.c
@@ -0,0 +1,130 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2007 Corey Osgood <corey.osgood@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 <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "i82801xx.h"
+
+static void usb_init(struct device *dev)
+{
+/* TODO: Any init needed? Some ports have it, others don't */
+}
+
+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 = i82801xx_enable,
+};
+
+/* i82801aa */
+static struct pci_driver i82801aa_usb_1 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2412,
+};
+
+/* i82801ab */
+static struct pci_driver i82801ab_usb_1 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2422,
+};
+
+/* i82801ba */
+static struct pci_driver i82801ba_usb_1 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2442,
+};
+
+static struct pci_driver i82801ba_usb_2 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2444,
+};
+
+/* i82801ca */
+static struct pci_driver i82801ca_usb_1 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2482,
+};
+
+static struct pci_driver i82801ca_usb_2 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2484,
+};
+
+static struct pci_driver i82801ca_usb_3 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2487,
+};
+
+/* i82801db and i82801dbm */
+static struct pci_driver i82801db_usb_1 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24c2,
+};
+
+static struct pci_driver i82801db_usb_2 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24c4,
+};
+
+static struct pci_driver i82801db_usb_3 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24c7,
+};
+
+/* i82801eb and i82801er */
+static struct pci_driver i82801ex_usb_1 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24d2,
+};
+
+static struct pci_driver i82801ex_usb_2 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24d4,
+};
+
+static struct pci_driver i82801ex_usb_3 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24d7,
+};
+
+static struct pci_driver i82801ex_usb_4 __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24de,
+};
diff --git a/src/southbridge/intel/i82801xx/i82801xx_usb_ehci.c b/src/southbridge/intel/i82801xx/i82801xx_usb_ehci.c
new file mode 100644
index 0000000000..7577da19df
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx_usb_ehci.c
@@ -0,0 +1,81 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2005 Tyan Computer
+ * (Written by Yinghai Lu <yinghailu@gmail.com> for Tyan Computer>
+ *
+ * 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 <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "i82801xx.h"
+
+static void usb_ehci_init(struct device *dev)
+{
+ /* TODO: Is any special init really needed? */
+ uint32_t cmd;
+
+ printk_debug("EHCI: Setting up controller.. ");
+ cmd = pci_read_config32(dev, PCI_COMMAND);
+ pci_write_config32(dev, PCI_COMMAND,
+ cmd | PCI_COMMAND_MASTER);
+
+ printk_debug("done.\n");
+}
+
+static void usb_ehci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ uint8_t 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,
+};
+
+static struct device_operations usb_ehci_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = usb_ehci_init,
+ .scan_bus = 0,
+ .enable = i82801xx_enable,
+ .ops_pci = &lops_pci,
+};
+
+/* i82801db and i82801dbm */
+static struct pci_driver i82801db_usb_ehci __pci_driver = {
+ .ops = &usb_ehci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24cd,
+};
+
+/* i82801eb and i82801er */
+static struct pci_driver i82801ex_usb_ehci __pci_driver = {
+ .ops = &usb_ehci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x24dd,
+};
diff --git a/src/southbridge/intel/i82801xx/i82801xx_watchdog.c b/src/southbridge/intel/i82801xx/i82801xx_watchdog.c
new file mode 100644
index 0000000000..e2a95156eb
--- /dev/null
+++ b/src/southbridge/intel/i82801xx/i82801xx_watchdog.c
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the LinuxBIOS project.
+ *
+ * Copyright (C) 2006 John Dufresne <jon.dufresne@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 <console/console.h>
+#include <arch/io.h>
+#include <device/device.h>
+#include <device/pci.h>
+
+/* TODO: I'm fairly sure the same functionality is provided elsewhere */
+
+void watchdog_off(void)
+{
+ device_t dev;
+ unsigned long value,base;
+
+ /* turn off the ICH5 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_debug("ICH Watchdog disabled\r\n");
+}
+
+