aboutsummaryrefslogtreecommitdiff
path: root/src/southbridge/intel/esb6300
diff options
context:
space:
mode:
authorYinghai Lu <yinghailu@gmail.com>2005-07-08 02:49:49 +0000
committerYinghai Lu <yinghailu@gmail.com>2005-07-08 02:49:49 +0000
commit13f1c2af8be2cd7f7e99a678f5d428a65b771811 (patch)
tree27cad5581f1fa150f573149d48e82f70ba1b1d9f /src/southbridge/intel/esb6300
parent14cde9e96a777f9d75016a13b23fab0480515f58 (diff)
eric patch
1. x86_setup_mtrr take address bit. 2. generic ht, pcix, pcie beidge... 3. scan bus and reset_bus 4. ht read ctrl to decide if the ht chain is ready 5. Intel e7520 and e7525 support 6. new ich5r support 7. intel sb 6300 support. yhlu patch 1. split x86_setup_mtrrs to fixed and var 2. if (resource->flags & IORESOURCE_FIXED ) return; in device.c pick_largest_resource 3. in_conherent.c K8_SCAN_PCI_BUS git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1982 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/southbridge/intel/esb6300')
-rw-r--r--src/southbridge/intel/esb6300/Config.lb12
-rw-r--r--src/southbridge/intel/esb6300/chip.h30
-rw-r--r--src/southbridge/intel/esb6300/esb6300.c48
-rw-r--r--src/southbridge/intel/esb6300/esb6300.h7
-rw-r--r--src/southbridge/intel/esb6300/esb6300_ac97.c37
-rw-r--r--src/southbridge/intel/esb6300/esb6300_bridge1c.c51
-rw-r--r--src/southbridge/intel/esb6300/esb6300_early_smbus.c107
-rw-r--r--src/southbridge/intel/esb6300/esb6300_ehci.c50
-rw-r--r--src/southbridge/intel/esb6300/esb6300_ide.c56
-rw-r--r--src/southbridge/intel/esb6300/esb6300_lpc.c410
-rw-r--r--src/southbridge/intel/esb6300/esb6300_pci.c37
-rw-r--r--src/southbridge/intel/esb6300/esb6300_pic.c109
-rw-r--r--src/southbridge/intel/esb6300/esb6300_sata.c77
-rw-r--r--src/southbridge/intel/esb6300/esb6300_smbus.c45
-rw-r--r--src/southbridge/intel/esb6300/esb6300_smbus.h105
-rw-r--r--src/southbridge/intel/esb6300/esb6300_uhci.c56
16 files changed, 1237 insertions, 0 deletions
diff --git a/src/southbridge/intel/esb6300/Config.lb b/src/southbridge/intel/esb6300/Config.lb
new file mode 100644
index 0000000000..9674c1f818
--- /dev/null
+++ b/src/southbridge/intel/esb6300/Config.lb
@@ -0,0 +1,12 @@
+config chip.h
+driver esb6300.o
+driver esb6300_uhci.o
+driver esb6300_lpc.o
+driver esb6300_ide.o
+driver esb6300_sata.o
+driver esb6300_ehci.o
+driver esb6300_smbus.o
+driver esb6300_pci.o
+driver esb6300_pic.o
+driver esb6300_bridge1c.o
+driver esb6300_ac97.o
diff --git a/src/southbridge/intel/esb6300/chip.h b/src/southbridge/intel/esb6300/chip.h
new file mode 100644
index 0000000000..ff74e615fd
--- /dev/null
+++ b/src/southbridge/intel/esb6300/chip.h
@@ -0,0 +1,30 @@
+struct southbridge_intel_esb6300_config
+{
+#define ESB6300_GPIO_USE_MASK 0x03
+#define ESB6300_GPIO_USE_DEFAULT 0x00
+#define ESB6300_GPIO_USE_AS_NATIVE 0x01
+#define ESB6300_GPIO_USE_AS_GPIO 0x02
+
+#define ESB6300_GPIO_SEL_MASK 0x0c
+#define ESB6300_GPIO_SEL_DEFAULT 0x00
+#define ESB6300_GPIO_SEL_OUTPUT 0x04
+#define ESB6300_GPIO_SEL_INPUT 0x08
+
+#define ESB6300_GPIO_LVL_MASK 0x30
+#define ESB6300_GPIO_LVL_DEFAULT 0x00
+#define ESB6300_GPIO_LVL_LOW 0x10
+#define ESB6300_GPIO_LVL_HIGH 0x20
+#define ESB6300_GPIO_LVL_BLINK 0x30
+
+#define ESB6300_GPIO_INV_MASK 0xc0
+#define ESB6300_GPIO_INV_DEFAULT 0x00
+#define ESB6300_GPIO_INV_OFF 0x40
+#define ESB6300_GPIO_INV_ON 0x80
+
+ /* GPIO use select */
+ unsigned char gpio[64];
+ unsigned int pirq_a_d;
+ unsigned int pirq_e_h;
+};
+extern struct chip_operations southbridge_intel_esb6300_ops;
+
diff --git a/src/southbridge/intel/esb6300/esb6300.c b/src/southbridge/intel/esb6300/esb6300.c
new file mode 100644
index 0000000000..3551a59ea6
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300.c
@@ -0,0 +1,48 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include "esb6300.h"
+
+void esb6300_enable(device_t dev)
+{
+ device_t lpc_dev;
+ unsigned index = 0;
+ uint16_t reg_old, reg;
+
+ /* See if we are on the behind the 6300 pci bridge */
+ lpc_dev = dev_find_slot(dev->bus->secondary, PCI_DEVFN(0x1f, 0));
+ if((dev->path.u.pci.devfn &0xf8)== 0xf8) {
+ index = dev->path.u.pci.devfn & 7;
+ }
+ else if((dev->path.u.pci.devfn &0xf8)== 0xe8) {
+ index = (dev->path.u.pci.devfn & 7) +8;
+ }
+ if ((!lpc_dev) || (index >= 16) || ((1<<index)&0x3091)) {
+ return;
+ }
+ if ((lpc_dev->vendor != PCI_VENDOR_ID_INTEL) ||
+ (lpc_dev->device != PCI_DEVICE_ID_INTEL_6300ESB_ISA)) {
+ uint32_t id;
+ id = pci_read_config32(lpc_dev, PCI_VENDOR_ID);
+ if (id != (PCI_VENDOR_ID_INTEL |
+ (PCI_DEVICE_ID_INTEL_6300ESB_ISA << 16))) {
+ return;
+ }
+ }
+
+ reg = reg_old = pci_read_config16(lpc_dev, 0xf2);
+ reg &= ~(1 << index);
+ if (!dev->enabled) {
+ reg |= (1 << index);
+ }
+ if (reg != reg_old) {
+ pci_write_config16(lpc_dev, 0xf2, reg);
+ }
+
+}
+
+struct chip_operations southbridge_intel_esb6300_ops = {
+ CHIP_NAME("INTEL 6300ESB")
+ .enable_dev = esb6300_enable,
+};
diff --git a/src/southbridge/intel/esb6300/esb6300.h b/src/southbridge/intel/esb6300/esb6300.h
new file mode 100644
index 0000000000..2c91fcba98
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300.h
@@ -0,0 +1,7 @@
+#ifndef ESB6300_H
+#define ESB6300_H
+#include "chip.h"
+
+void esb6300_enable(device_t dev);
+
+#endif /* ESB6300 */
diff --git a/src/southbridge/intel/esb6300/esb6300_ac97.c b/src/southbridge/intel/esb6300/esb6300_ac97.c
new file mode 100644
index 0000000000..cc221f6e64
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_ac97.c
@@ -0,0 +1,37 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void ac97_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ /* Write the subsystem vendor and device id */
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = ac97_set_subsystem,
+};
+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 = esb6300_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver ac97_audio_driver __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_AC97_AUDIO,
+};
+static struct pci_driver ac97_modem_driver __pci_driver = {
+ .ops = &ac97_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_AC97_MODEM,
+};
diff --git a/src/southbridge/intel/esb6300/esb6300_bridge1c.c b/src/southbridge/intel/esb6300/esb6300_bridge1c.c
new file mode 100644
index 0000000000..49e3b056a0
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_bridge1c.c
@@ -0,0 +1,51 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void bridge1c_init(struct device *dev)
+{
+
+ uint16_t word;
+
+ /* configuration */
+ pci_write_config8(dev, 0x1b, 0x30);
+// pci_write_config8(dev, 0x3e, 0x07);
+ pci_write_config8(dev, 0x3e, 0x04); /* parity ignore */
+ pci_write_config8(dev, 0x6c, 0x0c); /* undocumented */
+ pci_write_config8(dev, 0xe0, 0x20);
+
+ /* SRB enable */
+ pci_write_config16(dev, 0xe4, 0x0232);
+
+ /* Burst size */
+ pci_write_config8(dev, 0xf0, 0x02);
+
+ /* prefetch threshold size */
+ pci_write_config16(dev, 0xf8, 0x2121);
+
+ /* primary latency */
+ pci_write_config8(dev, 0x0d, 0x28);
+
+ /* multi transaction timer */
+ pci_write_config8(dev, 0x42, 0x08);
+
+}
+
+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 = bridge1c_init,
+ .scan_bus = pci_scan_bridge,
+ .ops_pci = 0,
+};
+
+static struct pci_driver pci_driver __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_BRIDGE1C,
+};
+
diff --git a/src/southbridge/intel/esb6300/esb6300_early_smbus.c b/src/southbridge/intel/esb6300/esb6300_early_smbus.c
new file mode 100644
index 0000000000..e115e3a2fa
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_early_smbus.c
@@ -0,0 +1,107 @@
+#include "esb6300_smbus.h"
+
+#define SMBUS_IO_BASE 0x0f00
+
+static void enable_smbus(void)
+{
+ device_t dev;
+ dev = pci_locate_device(PCI_ID(0x8086, 0x25a4), 0);
+ if (dev == PCI_DEV_INVALID) {
+ die("SMBUS controller not found\r\n");
+ }
+ uint8_t enable;
+ print_spew("SMBus controller enabled\r\n");
+ pci_write_config32(dev, 0x20, SMBUS_IO_BASE | 1);
+ pci_write_config8(dev, 0x40, 1);
+ pci_write_config8(dev, 0x4, 1);
+ /* SMBALERT_DIS */
+ pci_write_config8(dev, 0x11, 4);
+
+ /* Disable interrupt generation */
+ outb(0, SMBUS_IO_BASE + SMBHSTCTL);
+
+ dev = pci_locate_device(PCI_ID(0x8086, 0x25a1), 0);
+ if (dev == PCI_DEV_INVALID) {
+ die("ISA bridge not found\r\n");
+ }
+}
+
+static int smbus_read_byte(unsigned device, unsigned address)
+{
+ return do_smbus_read_byte(SMBUS_IO_BASE, device, address);
+}
+
+static void smbus_write_byte(unsigned device, unsigned address, unsigned char val)
+{
+ if (smbus_wait_until_ready(SMBUS_IO_BASE) < 0) {
+ return;
+ }
+ return;
+}
+
+static int smbus_write_block(unsigned device, unsigned length, unsigned cmd,
+ unsigned data1, unsigned data2)
+{
+ unsigned char global_control_register;
+ unsigned char global_status_register;
+ unsigned char byte;
+ unsigned char stat;
+ int i;
+
+ /* chear 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;
+}
+
diff --git a/src/southbridge/intel/esb6300/esb6300_ehci.c b/src/southbridge/intel/esb6300/esb6300_ehci.c
new file mode 100644
index 0000000000..58dcd9593c
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_ehci.c
@@ -0,0 +1,50 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void ehci_init(struct device *dev)
+{
+ 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 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 = &ehci_set_subsystem,
+};
+static struct device_operations ehci_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = ehci_init,
+ .scan_bus = 0,
+ .enable = esb6300_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver ehci_driver __pci_driver = {
+ .ops = &ehci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_EHCI,
+};
diff --git a/src/southbridge/intel/esb6300/esb6300_ide.c b/src/southbridge/intel/esb6300/esb6300_ide.c
new file mode 100644
index 0000000000..bb77ad7726
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_ide.c
@@ -0,0 +1,56 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void ide_init(struct device *dev)
+{
+
+ /* Enable ide devices so the linux ide driver will work */
+ uint16_t word;
+
+ /* Enable IDE devices */
+ pci_write_config16(dev, 0x40, 0x0a307);
+ pci_write_config16(dev, 0x42, 0x0a307);
+ pci_write_config8(dev, 0x48, 0x05);
+ pci_write_config16(dev, 0x4a, 0x0101);
+ pci_write_config16(dev, 0x54, 0x5055);
+
+#if 0
+ word = pci_read_config16(dev, 0x40);
+ word |= (1 << 15);
+ pci_write_config16(dev, 0x40, word);
+ word = pci_read_config16(dev, 0x42);
+ word |= (1 << 15);
+ pci_write_config16(dev, 0x42, word);
+#endif
+ printk_debug("IDE Enabled\n");
+}
+
+static void esb6300_ide_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ /* This value is also visible in uchi[0-2] and smbus functions */
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = esb6300_ide_set_subsystem,
+};
+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,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver ide_driver __pci_driver = {
+ .ops = &ide_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_IDE,
+};
+
diff --git a/src/southbridge/intel/esb6300/esb6300_lpc.c b/src/southbridge/intel/esb6300/esb6300_lpc.c
new file mode 100644
index 0000000000..caef888d2a
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_lpc.c
@@ -0,0 +1,410 @@
+/*
+ * (C) 2004 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 <pc80/mc146818rtc.h>
+#include <pc80/isa-dma.h>
+#include <arch/io.h>
+#include "esb6300.h"
+
+#define ACPI_BAR 0x40
+#define GPIO_BAR 0x58
+
+#define NMI_OFF 0
+#define MAINBOARD_POWER_OFF 0
+#define MAINBOARD_POWER_ON 1
+
+#ifndef MAINBOARD_POWER_ON_AFTER_FAIL
+#define MAINBOARD_POWER_ON_AFTER_FAIL MAINBOARD_POWER_ON
+#endif
+
+#define ALL (0xff << 24)
+#define NONE (0)
+#define DISABLED (1 << 16)
+#define ENABLED (0 << 16)
+#define TRIGGER_EDGE (0 << 15)
+#define TRIGGER_LEVEL (1 << 15)
+#define POLARITY_HIGH (0 << 13)
+#define POLARITY_LOW (1 << 13)
+#define PHYSICAL_DEST (0 << 11)
+#define LOGICAL_DEST (1 << 11)
+#define ExtINT (7 << 8)
+#define NMI (4 << 8)
+#define SMI (2 << 8)
+#define INT (1 << 8)
+
+static void setup_ioapic(device_t dev)
+{
+ int i;
+ unsigned long value_low, value_high;
+ unsigned long ioapic_base = 0xfec00000;
+ volatile unsigned long *l;
+ unsigned interrupts;
+
+ l = (unsigned long *) ioapic_base;
+
+ l[0] = 0x01;
+ interrupts = (l[04] >> 16) & 0xff;
+ for (i = 0; i < interrupts; i++) {
+ l[0] = (i * 2) + 0x10;
+ l[4] = DISABLED;
+ value_low = l[4];
+ l[0] = (i * 2) + 0x11;
+ l[4] = NONE; /* Should this be an address? */
+ value_high = l[4];
+ if (value_low == 0xffffffff) {
+ printk_warning("%d IO APIC not responding.\n",
+ dev_path(dev));
+ return;
+ }
+ }
+
+ /* Put the ioapic in virtual wire mode */
+ l[0] = 0 + 0x10;
+ l[4] = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
+}
+
+#define SERIRQ_CNTL 0x64
+static void esb6300_enable_serial_irqs(device_t 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));
+}
+
+#define PCI_DMA_CFG 0x90
+static void esb6300_pci_dma_cfg(device_t dev)
+{
+ /* Set PCI DMA CFG to lpc I/F DMA */
+ pci_write_config16(dev, PCI_DMA_CFG, 0xfcff);
+}
+
+#define LPC_EN 0xe6
+static void esb6300_enable_lpc(device_t dev)
+{
+ /* lpc i/f enable */
+ pci_write_config8(dev, LPC_EN, 0x0d);
+}
+
+typedef struct southbridge_intel_esb6300_config config_t;
+
+static void set_esb6300_gpio_use_sel(
+ device_t dev, struct resource *res, config_t *config)
+{
+ uint32_t gpio_use_sel, gpio_use_sel2;
+ int i;
+
+// gpio_use_sel = 0x1B003100;
+// gpio_use_sel2 = 0x03000000;
+ gpio_use_sel = 0x1BBC31C0;
+ gpio_use_sel2 = 0x03000FE1;
+#if 0
+ for(i = 0; i < 64; i++) {
+ int val;
+ switch(config->gpio[i] & ESB6300_GPIO_USE_MASK) {
+ case ESB6300_GPIO_USE_AS_NATIVE: val = 0; break;
+ case ESB6300_GPIO_USE_AS_GPIO: val = 1; break;
+ default:
+ continue;
+ }
+ /* The caller is responsible for not playing with unimplemented bits */
+ if (i < 32) {
+ gpio_use_sel &= ~( 1 << i);
+ gpio_use_sel |= (val << i);
+ } else {
+ gpio_use_sel2 &= ~( 1 << (i - 32));
+ gpio_use_sel2 |= (val << (i - 32));
+ }
+ }
+#endif
+ outl(gpio_use_sel, res->base + 0x00);
+ outl(gpio_use_sel2, res->base + 0x30);
+}
+
+static void set_esb6300_gpio_direction(
+ device_t dev, struct resource *res, config_t *config)
+{
+ uint32_t gpio_io_sel, gpio_io_sel2;
+ int i;
+
+// gpio_io_sel = 0x0000ffff;
+// gpio_io_sel2 = 0x00000000;
+ gpio_io_sel = 0x1900ffff;
+ gpio_io_sel2 = 0x00000fe1;
+#if 0
+ for(i = 0; i < 64; i++) {
+ int val;
+ switch(config->gpio[i] & ESB6300_GPIO_SEL_MASK) {
+ case ESB6300_GPIO_SEL_OUTPUT: val = 0; break;
+ case ESB6300_GPIO_SEL_INPUT: val = 1; break;
+ default:
+ continue;
+ }
+ /* The caller is responsible for not playing with unimplemented bits */
+ if (i < 32) {
+ gpio_io_sel &= ~( 1 << i);
+ gpio_io_sel |= (val << i);
+ } else {
+ gpio_io_sel2 &= ~( 1 << (i - 32));
+ gpio_io_sel2 |= (val << (i - 32));
+ }
+ }
+#endif
+ outl(gpio_io_sel, res->base + 0x04);
+ outl(gpio_io_sel2, res->base + 0x34);
+}
+
+static void set_esb6300_gpio_level(
+ device_t dev, struct resource *res, config_t *config)
+{
+ uint32_t gpio_lvl, gpio_lvl2;
+ uint32_t gpio_blink;
+ int i;
+
+// gpio_lvl = 0x1b3f0000;
+// gpio_blink = 0x00040000;
+// gpio_lvl2 = 0x00000fff;
+ gpio_lvl = 0x19370000;
+ gpio_blink = 0x00000000;
+ gpio_lvl2 = 0x00000fff;
+#if 0
+ for(i = 0; i < 64; i++) {
+ int val, blink;
+ switch(config->gpio[i] & ESB6300_GPIO_LVL_MASK) {
+ case ESB6300_GPIO_LVL_LOW: val = 0; blink = 0; break;
+ case ESB6300_GPIO_LVL_HIGH: val = 1; blink = 0; break;
+ case ESB6300_GPIO_LVL_BLINK: val = 1; blink = 1; break;
+ default:
+ continue;
+ }
+ /* The caller is responsible for not playing with unimplemented bits */
+ if (i < 32) {
+ gpio_lvl &= ~( 1 << i);
+ gpio_blink &= ~( 1 << i);
+ gpio_lvl |= ( val << i);
+ gpio_blink |= (blink << i);
+ } else {
+ gpio_lvl2 &= ~( 1 << (i - 32));
+ gpio_lvl2 |= (val << (i - 32));
+ }
+ }
+#endif
+ outl(gpio_lvl, res->base + 0x0c);
+ outl(gpio_blink, res->base + 0x18);
+ outl(gpio_lvl2, res->base + 0x38);
+}
+
+static void set_esb6300_gpio_inv(
+ device_t dev, struct resource *res, config_t *config)
+{
+ uint32_t gpio_inv;
+ int i;
+
+ gpio_inv = 0x00003100;
+#if 0
+ for(i = 0; i < 32; i++) {
+ int val;
+ switch(config->gpio[i] & ESB6300_GPIO_INV_MASK) {
+ case ESB6300_GPIO_INV_OFF: val = 0; break;
+ case ESB6300_GPIO_INV_ON: val = 1; break;
+ default:
+ continue;
+ }
+ gpio_inv &= ~( 1 << i);
+ gpio_inv |= (val << i);
+ }
+#endif
+ outl(gpio_inv, res->base + 0x2c);
+}
+
+static void esb6300_pirq_init(device_t dev)
+{
+ config_t *config;
+
+ /* Get the chip configuration */
+ config = dev->chip_info;
+
+ if(config->pirq_a_d) {
+ pci_write_config32(dev, 0x60, config->pirq_a_d);
+ }
+ if(config->pirq_e_h) {
+ pci_write_config32(dev, 0x68, config->pirq_e_h);
+ }
+}
+
+
+static void esb6300_gpio_init(device_t dev)
+{
+ struct resource *res;
+ config_t *config;
+
+ /* Skip if I don't have any configuration */
+ if (!dev->chip_info) {
+ return;
+ }
+ /* The programmer is responsible for ensuring
+ * a valid gpio configuration.
+ */
+
+ /* Get the chip configuration */
+ config = dev->chip_info;
+ /* Find the GPIO bar */
+ res = find_resource(dev, GPIO_BAR);
+ if (!res) {
+ return;
+ }
+
+ /* Set the use selects */
+ set_esb6300_gpio_use_sel(dev, res, config);
+
+ /* Set the IO direction */
+ set_esb6300_gpio_direction(dev, res, config);
+
+ /* Setup the input inverters */
+ set_esb6300_gpio_inv(dev, res, config);
+
+ /* Set the value on the GPIO output pins */
+ set_esb6300_gpio_level(dev, res, config);
+
+}
+
+
+static void lpc_init(struct device *dev)
+{
+ uint8_t byte;
+ uint32_t value;
+ int pwr_on=MAINBOARD_POWER_ON_AFTER_FAIL;
+
+ /* sata settings */
+ pci_write_config32(dev, 0x58, 0x00001181);
+
+ /* IO APIC initialization */
+ value = pci_read_config32(dev, 0xd0);
+ value |= (1 << 8)|(1<<7);
+ value |= (6 << 0)|(1<<13)|(1<<11);
+ pci_write_config32(dev, 0xd0, value);
+ setup_ioapic(dev);
+
+ /* disable reset timer */
+ pci_write_config8(dev, 0xd4, 0x02);
+
+ /* cmos ram 2nd 128 */
+ pci_write_config8(dev, 0xd8, 0x04);
+
+ /* comm 2 */
+ pci_write_config8(dev, 0xe0, 0x10);
+
+ /* fwh sellect */
+ pci_write_config32(dev, 0xe8, 0x00112233);
+
+ /* fwh decode */
+ pci_write_config8(dev, 0xf0, 0x0f);
+
+ /* av disable, sata controller */
+ pci_write_config8(dev, 0xf2, 0xc0);
+
+ /* undocumented */
+ pci_write_config8(dev, 0xa0, 0x20);
+ pci_write_config8(dev, 0xad, 0x03);
+ pci_write_config8(dev, 0xbb, 0x09);
+
+ /* apic1 rout */
+ pci_write_config8(dev, 0xf4, 0x40);
+
+ /* undocumented */
+ pci_write_config8(dev, 0xa0, 0x20);
+ pci_write_config8(dev, 0xad, 0x03);
+ pci_write_config8(dev, 0xbb, 0x09);
+
+ esb6300_enable_serial_irqs(dev);
+
+ esb6300_pci_dma_cfg(dev);
+
+ esb6300_enable_lpc(dev);
+
+ get_option(&pwr_on, "power_on_after_fail");
+ byte = pci_read_config8(dev, 0xa4);
+ byte &= 0xfe;
+ if (!pwr_on) {
+ byte |= 1;
+ }
+ pci_write_config8(dev, 0xa4, byte);
+ printk_info("set power %s after power fail\n", pwr_on?"on":"off");
+
+ /* Set up the PIRQ */
+ esb6300_pirq_init(dev);
+
+ /* Set the state of the gpio lines */
+ esb6300_gpio_init(dev);
+
+ /* Initialize the real time clock */
+ rtc_init(0);
+
+ /* Initialize isa dma */
+ isa_dma_init();
+}
+
+static void esb6300_lpc_read_resources(device_t dev)
+{
+ struct resource *res;
+
+ /* Get the normal pci resources of this device */
+ pci_dev_read_resources(dev);
+
+ /* Add the ACPI BAR */
+ res = pci_get_resource(dev, ACPI_BAR);
+
+ /* Add the GPIO BAR */
+ res = pci_get_resource(dev, GPIO_BAR);
+
+ /* 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 esb6300_lpc_enable_resources(device_t dev)
+{
+ uint8_t acpi_cntl, gpio_cntl;
+
+ /* Enable the normal pci resources */
+ pci_dev_enable_resources(dev);
+
+ /* Enable the ACPI bar */
+ acpi_cntl = pci_read_config8(dev, 0x44);
+ acpi_cntl |= (1 << 4);
+ pci_write_config8(dev, 0x44, acpi_cntl);
+
+ /* Enable the GPIO bar */
+ gpio_cntl = pci_read_config8(dev, 0x5c);
+ gpio_cntl |= (1 << 4);
+ pci_write_config8(dev, 0x5c, gpio_cntl);
+
+ enable_childrens_resources(dev);
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = 0,
+};
+
+static struct device_operations lpc_ops = {
+ .read_resources = esb6300_lpc_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = esb6300_lpc_enable_resources,
+ .init = lpc_init,
+ .scan_bus = scan_static_bus,
+ .enable = esb6300_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver lpc_driver __pci_driver = {
+ .ops = &lpc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_ISA,
+};
diff --git a/src/southbridge/intel/esb6300/esb6300_pci.c b/src/southbridge/intel/esb6300/esb6300_pci.c
new file mode 100644
index 0000000000..1131941728
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_pci.c
@@ -0,0 +1,37 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void pci_init(struct device *dev)
+{
+
+ uint16_t word;
+
+ /* Clear system errors */
+ word = pci_read_config16(dev, 0x06);
+ word |= 0xf900; /* Clear possible errors */
+ pci_write_config16(dev, 0x06, word);
+
+ word = pci_read_config16(dev, 0x1e);
+ word |= 0xf800; /* Clear possible errors */
+ pci_write_config16(dev, 0x1e, word);
+}
+
+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,
+ .ops_pci = 0,
+};
+
+static struct pci_driver pci_driver __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_PCI,
+};
+
diff --git a/src/southbridge/intel/esb6300/esb6300_pic.c b/src/southbridge/intel/esb6300/esb6300_pic.c
new file mode 100644
index 0000000000..024c7e2980
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_pic.c
@@ -0,0 +1,109 @@
+/*
+ * (C) 2004 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 "esb6300.h"
+
+#define ALL (0xff << 24)
+#define NONE (0)
+#define DISABLED (1 << 16)
+#define ENABLED (0 << 16)
+#define TRIGGER_EDGE (0 << 15)
+#define TRIGGER_LEVEL (1 << 15)
+#define POLARITY_HIGH (0 << 13)
+#define POLARITY_LOW (1 << 13)
+#define PHYSICAL_DEST (0 << 11)
+#define LOGICAL_DEST (1 << 11)
+#define ExtINT (7 << 8)
+#define NMI (4 << 8)
+#define SMI (2 << 8)
+#define INT (1 << 8)
+
+static void setup_ioapic(device_t dev)
+{
+ int i;
+ unsigned long value_low, value_high;
+ unsigned long ioapic_base = 0xfec10000;
+ volatile unsigned long *l;
+ unsigned interrupts;
+
+ l = (unsigned long *) ioapic_base;
+
+ l[0] = 0x01;
+ interrupts = (l[04] >> 16) & 0xff;
+ for (i = 0; i < interrupts; i++) {
+ l[0] = (i * 2) + 0x10;
+ l[4] = DISABLED;
+ value_low = l[4];
+ l[0] = (i * 2) + 0x11;
+ l[4] = NONE; /* Should this be an address? */
+ value_high = l[4];
+ if (value_low == 0xffffffff) {
+ printk_warning("%s IO APIC not responding.\n",
+ dev_path(dev));
+ return;
+ }
+ }
+}
+
+static void pic_init(struct device *dev)
+{
+
+ uint16_t word;
+
+ /* Clear system errors */
+ word = pci_read_config16(dev, 0x06);
+ word |= 0xf900; /* Clear possible errors */
+ pci_write_config16(dev, 0x06, word);
+
+ /* enable interrupt lines */
+ pci_write_config8(dev, 0x3c, 0xff);
+
+ /* Setup the ioapic */
+ setup_ioapic(dev);
+}
+
+static void pic_read_resources(device_t dev)
+{
+ struct resource *res;
+
+ /* Get the normal pci resources of this device */
+ pci_dev_read_resources(dev);
+
+ /* Report the pic1 mbar resource */
+ res = new_resource(dev, 0x44);
+ res->base = 0xfec10000;
+ res->size = 256;
+ res->limit = res->base + res->size -1;
+ res->align = 8;
+ res->gran = 8;
+ res->flags = IORESOURCE_MEM | IORESOURCE_FIXED |
+ IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+ dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+}
+
+static struct pci_operations lops_pci = {
+ /* Can we set the pci subsystem and device id? */
+ .set_subsystem = 0,
+};
+
+static struct device_operations pci_ops = {
+ .read_resources = pic_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = pic_init,
+ .scan_bus = 0,
+ .enable = esb6300_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver pci_driver __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_PIC1,
+};
+
diff --git a/src/southbridge/intel/esb6300/esb6300_sata.c b/src/southbridge/intel/esb6300/esb6300_sata.c
new file mode 100644
index 0000000000..9d8fb759fc
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_sata.c
@@ -0,0 +1,77 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void sata_init(struct device *dev)
+{
+
+ /* Enable sata devices so the linux sata driver will work */
+ uint16_t word;
+
+ /* Enable SATA devices */
+
+ printk_debug("SATA init\n");
+ /* 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);
+
+ printk_debug("SATA Enabled\n");
+}
+
+static void esb6300_sata_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ /* This value is also visible in usb1, usb2 and smbus functions */
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = esb6300_sata_set_subsystem,
+};
+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,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver sata_driver __pci_driver = {
+ .ops = &sata_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_SATA,
+};
+
+static struct pci_driver sata_driver_nr __pci_driver = {
+ .ops = &sata_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_SATA_R,
+};
+
diff --git a/src/southbridge/intel/esb6300/esb6300_smbus.c b/src/southbridge/intel/esb6300/esb6300_smbus.c
new file mode 100644
index 0000000000..6cb6f2d9bb
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_smbus.c
@@ -0,0 +1,45 @@
+#include <device/device.h>
+#include <device/path.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <device/smbus.h>
+#include <arch/io.h>
+#include "esb6300.h"
+#include "esb6300_smbus.h"
+
+static int lsmbus_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 = lsmbus_read_byte,
+};
+static struct pci_operations lops_pci = {
+ /* The subsystem id follows the ide controller */
+ .set_subsystem = 0,
+};
+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 = esb6300_enable,
+ .ops_pci = &lops_pci,
+ .ops_smbus_bus = &lops_smbus_bus,
+};
+
+static struct pci_driver smbus_driver __pci_driver = {
+ .ops = &smbus_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_SMB,
+};
+
diff --git a/src/southbridge/intel/esb6300/esb6300_smbus.h b/src/southbridge/intel/esb6300/esb6300_smbus.h
new file mode 100644
index 0000000000..861230e130
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_smbus.h
@@ -0,0 +1,105 @@
+#include <device/smbus_def.h>
+
+#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 (100*1000*10)
+
+
+static void smbus_delay(void)
+{
+ outb(0x80, 0x80);
+}
+
+static int smbus_wait_until_ready(unsigned smbus_io_base)
+{
+ 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(unsigned smbus_io_base)
+{
+ 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(unsigned smbus_io_base)
+{
+ 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 smbus_io_base, unsigned device, unsigned address)
+{
+ unsigned char global_status_register;
+ unsigned char byte;
+
+ if (smbus_wait_until_ready(smbus_io_base) < 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(smbus_io_base) < 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;
+}
+
diff --git a/src/southbridge/intel/esb6300/esb6300_uhci.c b/src/southbridge/intel/esb6300/esb6300_uhci.c
new file mode 100644
index 0000000000..835a39c2e4
--- /dev/null
+++ b/src/southbridge/intel/esb6300/esb6300_uhci.c
@@ -0,0 +1,56 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "esb6300.h"
+
+static void uhci_init(struct device *dev)
+{
+ uint32_t cmd;
+
+#if 1
+ printk_debug("UHCI: Setting up controller.. ");
+ cmd = pci_read_config32(dev, PCI_COMMAND);
+ pci_write_config32(dev, PCI_COMMAND,
+ cmd | PCI_COMMAND_MASTER);
+
+
+ printk_debug("done.\n");
+#endif
+
+}
+
+static struct pci_operations lops_pci = {
+ /* The subsystem id follows the ide controller */
+ .set_subsystem = 0,
+};
+
+static struct device_operations uhci_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = uhci_init,
+ .scan_bus = 0,
+ .enable = esb6300_enable,
+ .ops_pci = &lops_pci,
+};
+
+static struct pci_driver uhci_driver __pci_driver = {
+ .ops = &uhci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_USB,
+};
+
+static struct pci_driver usb2_driver __pci_driver = {
+ .ops = &uhci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_USB2,
+};
+
+static struct pci_driver usb3_driver __pci_driver = {
+ .ops = &uhci_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_6300ESB_USB3,
+};
+