Support Intel SCH (Poulsbo) and add iwave/iWRainbowG6 board
authorPatrick Georgi <patrick.georgi@coresystems.de>
Sat, 18 Dec 2010 07:48:43 +0000 (07:48 +0000)
committerPatrick Georgi <patrick.georgi@coresystems.de>
Sat, 18 Dec 2010 07:48:43 +0000 (07:48 +0000)
which uses it.

Compiles, but not boot tested lately.
Many things missing (eg. SMM support, proper ACPI, ...)

Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>
Acked-by: Peter Stuge <peter@stuge.se>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6198 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

81 files changed:
src/cpu/x86/smm/smmrelocate.S
src/mainboard/Kconfig
src/mainboard/iwave/Kconfig [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/Kconfig [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/Makefile.inc [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/acpi/cpu.asl [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/acpi/ec.asl [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/acpi/globalnvs.asl [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/acpi/northbridge_pci_irqs.asl [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/acpi/platform.asl [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/acpi/sleepstates.asl [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/acpi/southbridge_pci_irqs.asl [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/acpi/superio.asl [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/acpi/thermal.asl [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/acpi/video.asl [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/acpi_tables.c [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/chip.h [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/cmos.layout [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/devicetree.cb [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/dmi.h [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/dsdt.asl [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/fadt.c [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/hda_verb.h [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/irq_tables.c [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/mainboard.c [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/mainboard_smi.c [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/mptable.c [new file with mode: 0644]
src/mainboard/iwave/iWRainbowG6/romstage.c [new file with mode: 0644]
src/northbridge/intel/Kconfig
src/northbridge/intel/Makefile.inc
src/northbridge/intel/sch/Kconfig [new file with mode: 0644]
src/northbridge/intel/sch/Makefile.inc [new file with mode: 0644]
src/northbridge/intel/sch/acpi.c [new file with mode: 0644]
src/northbridge/intel/sch/acpi/hostbridge.asl [new file with mode: 0644]
src/northbridge/intel/sch/acpi/igd.asl [new file with mode: 0644]
src/northbridge/intel/sch/acpi/peg.asl [new file with mode: 0644]
src/northbridge/intel/sch/acpi/sch.asl [new file with mode: 0644]
src/northbridge/intel/sch/chip.h [new file with mode: 0644]
src/northbridge/intel/sch/early_init.c [new file with mode: 0644]
src/northbridge/intel/sch/gma.c [new file with mode: 0644]
src/northbridge/intel/sch/northbridge.c [new file with mode: 0644]
src/northbridge/intel/sch/nvs.h [new file with mode: 0644]
src/northbridge/intel/sch/pcie_config.c [new file with mode: 0644]
src/northbridge/intel/sch/port_access.c [new file with mode: 0644]
src/northbridge/intel/sch/raminit.c [new file with mode: 0644]
src/northbridge/intel/sch/raminit.h [new file with mode: 0644]
src/northbridge/intel/sch/sch.h [new file with mode: 0644]
src/southbridge/intel/Kconfig
src/southbridge/intel/Makefile.inc
src/southbridge/intel/sch/Kconfig [new file with mode: 0644]
src/southbridge/intel/sch/Makefile.inc [new file with mode: 0644]
src/southbridge/intel/sch/acpi/ac97.asl [new file with mode: 0644]
src/southbridge/intel/sch/acpi/audio.asl [new file with mode: 0644]
src/southbridge/intel/sch/acpi/globalnvs.asl [new file with mode: 0644]
src/southbridge/intel/sch/acpi/irqlinks.asl [new file with mode: 0644]
src/southbridge/intel/sch/acpi/lpc.asl [new file with mode: 0644]
src/southbridge/intel/sch/acpi/pata.asl [new file with mode: 0644]
src/southbridge/intel/sch/acpi/pci.asl [new file with mode: 0644]
src/southbridge/intel/sch/acpi/pcie.asl [new file with mode: 0644]
src/southbridge/intel/sch/acpi/sch.asl [new file with mode: 0644]
src/southbridge/intel/sch/acpi/sleepstates.asl [new file with mode: 0644]
src/southbridge/intel/sch/acpi/smbus.asl [new file with mode: 0644]
src/southbridge/intel/sch/acpi/usb.asl [new file with mode: 0644]
src/southbridge/intel/sch/audio.c [new file with mode: 0644]
src/southbridge/intel/sch/chip.h [new file with mode: 0644]
src/southbridge/intel/sch/early_smbus.c [new file with mode: 0644]
src/southbridge/intel/sch/ide.c [new file with mode: 0644]
src/southbridge/intel/sch/lpc.c [new file with mode: 0644]
src/southbridge/intel/sch/mmc.c [new file with mode: 0644]
src/southbridge/intel/sch/pcie.c [new file with mode: 0644]
src/southbridge/intel/sch/reset.c [new file with mode: 0644]
src/southbridge/intel/sch/sch.h [new file with mode: 0644]
src/southbridge/intel/sch/smbus.c [new file with mode: 0644]
src/southbridge/intel/sch/smbus.h [new file with mode: 0644]
src/southbridge/intel/sch/smi.c [new file with mode: 0644]
src/southbridge/intel/sch/smihandler.c [new file with mode: 0644]
src/southbridge/intel/sch/south.c [new file with mode: 0644]
src/southbridge/intel/sch/usb.c [new file with mode: 0644]
src/southbridge/intel/sch/usb_client.c [new file with mode: 0644]
src/southbridge/intel/sch/usb_debug.c [new file with mode: 0644]
src/southbridge/intel/sch/usb_ehci.c [new file with mode: 0644]

index e795359783d7d5902e1833504bf78f287dbe379d..b1f3290f500224f76663368c5d713034d4d7a4e8 100644 (file)
@@ -30,6 +30,8 @@
 #include "../../../southbridge/intel/i82801gx/i82801gx.h"
 #elif defined(CONFIG_SOUTHBRIDGE_INTEL_I82801DX)
 #include "../../../southbridge/intel/i82801dx/i82801dx.h"
+#elif defined(CONFIG_SOUTHBRIDGE_INTEL_SCH)
+#include "../../../southbridge/intel/sch/sch.h"
 #else
 #error "Southbridge needs SMM handler support."
 #endif
index ca0d74d45deeca956426c745394f86e0c84b70e0..cbee0a01f1b6ce9801b50b1a2efc4233fa8db227 100644 (file)
@@ -58,6 +58,8 @@ config VENDOR_IEI
        bool "IEI"
 config VENDOR_INTEL
        bool "Intel"
+config VENDOR_IWAVE
+       bool "iWave"
 config VENDOR_IWILL
        bool "IWILL"
 config VENDOR_JETWAY
@@ -140,6 +142,7 @@ source "src/mainboard/ibase/Kconfig"
 source "src/mainboard/ibm/Kconfig"
 source "src/mainboard/iei/Kconfig"
 source "src/mainboard/intel/Kconfig"
+source "src/mainboard/iwave/Kconfig"
 source "src/mainboard/iwill/Kconfig"
 source "src/mainboard/jetway/Kconfig"
 source "src/mainboard/kontron/Kconfig"
diff --git a/src/mainboard/iwave/Kconfig b/src/mainboard/iwave/Kconfig
new file mode 100644 (file)
index 0000000..9bd2c11
--- /dev/null
@@ -0,0 +1,18 @@
+if VENDOR_IWAVE
+
+choice
+       prompt "Mainboard model"
+       depends on VENDOR_IWAVE
+
+config BOARD_IWAVE_RAINBOW_G6
+       bool "iWRainbowG6"
+
+endchoice
+
+source "src/mainboard/iwave/iWRainbowG6/Kconfig"
+
+config MAINBOARD_VENDOR
+       string
+       default "iWave"
+
+endif # VENDOR_IWAVE
diff --git a/src/mainboard/iwave/iWRainbowG6/Kconfig b/src/mainboard/iwave/iWRainbowG6/Kconfig
new file mode 100644 (file)
index 0000000..fdd7db6
--- /dev/null
@@ -0,0 +1,46 @@
+if BOARD_IWAVE_RAINBOW_G6
+
+# TODO: move options to chipset components as appropriate
+config BOARD_SPECIFIC_OPTIONS # dummy
+       def_bool y
+       select ARCH_X86
+       select CPU_INTEL_CORE # FIXME
+       select CPU_INTEL_SOCKET_441
+       select NORTHBRIDGE_INTEL_SCH
+       select SOUTHBRIDGE_INTEL_SCH
+       select BOARD_HAS_FADT
+       select HAVE_PIRQ_TABLE
+#      select HAVE_MP_TABLE
+       select MMCONF_SUPPORT
+       select USE_PRINTK_IN_CAR
+       select AP_IN_SIPI_WAIT
+       select UDELAY_LAPIC
+       select HAVE_ACPI_TABLES
+       select HAVE_SMI_HANDLER
+       select BOARD_ROMSIZE_KB_1024
+       select USE_DCACHE_RAM
+       select GFXUMA
+       select HAVE_HARD_RESET
+
+config MAINBOARD_DIR
+       string
+       default iwave/iWRainbowG6
+
+config MAINBOARD_PART_NUMBER
+       string
+       default "iWRainbowG6"
+
+config MMCONF_BASE_ADDRESS
+       hex
+       default 0xf0000000
+
+config IRQ_SLOT_COUNT
+       int
+       default 10
+
+# WTF, is this 19200?
+config TTYS0_DIV
+       int
+       default 6
+
+endif
diff --git a/src/mainboard/iwave/iWRainbowG6/Makefile.inc b/src/mainboard/iwave/iWRainbowG6/Makefile.inc
new file mode 100644 (file)
index 0000000..e9f851a
--- /dev/null
@@ -0,0 +1,21 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007-2008 coresystems GmbH
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; version 2 of the License.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+
+smm-$(CONFIG_HAVE_SMI_HANDLER) += mainboard_smi.c
+
diff --git a/src/mainboard/iwave/iWRainbowG6/acpi/cpu.asl b/src/mainboard/iwave/iWRainbowG6/acpi/cpu.asl
new file mode 100644 (file)
index 0000000..6f8d312
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* Intel Core (2) Duo CPU node support
+ *
+ * Note: The ACPI P_BLK on the ICH7 (and probably others) lives at
+ * PMBASE + 0x10, and it's 0x06 bytes long. On ICH8 it's 8 bytes.
+ *
+ * The second CPU core does not need its own P_BLK.
+ */
+
+Scope(\_PR)
+{
+       Processor(
+               CPU1,   // name of cpu/core 0
+               1,      // numeric id of cpu/core
+               0x510,  // ACPI P_BLK base address
+               6       // ACPI P_BLK size
+       )
+       {
+               // TODO: _PDT
+       }
+
+       Processor(
+               CPU2,   // name of cpu/core 1
+               2,      // numeric id of cpu/core 1
+               0,      // ACPI P_BLK base address
+               0)      // ACPI P_BLK size
+       {
+               // TODO: _PDT
+       }
+}      // End _PR
+
diff --git a/src/mainboard/iwave/iWRainbowG6/acpi/ec.asl b/src/mainboard/iwave/iWRainbowG6/acpi/ec.asl
new file mode 100644 (file)
index 0000000..680f6cb
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Device(EC0)
+{
+       Name (_HID, EISAID("PNP0C09"))
+       Name (_UID, 1)
+
+       Method (_CRS, 0)
+       {
+               Name (ECMD, ResourceTemplate()
+               {
+                       IO (Decode16, 0x62, 0x62, 0, 1)
+                       IO (Decode16, 0x66, 0x66, 0, 1)
+               })
+
+               Return (ECMD)
+       }
+
+       Method (_REG, 2)
+       {
+               // This method is needed by Windows XP/2000
+               // for EC initialization before a driver
+               // is loaded
+       }
+
+       Name (_GPE, 23) // GPI07 / GPE23 -> Runtime SCI
+
+       // TODO EC Query methods
+
+       // TODO Scope _SB devices for AC power, LID, Power button
+
+}
diff --git a/src/mainboard/iwave/iWRainbowG6/acpi/globalnvs.asl b/src/mainboard/iwave/iWRainbowG6/acpi/globalnvs.asl
new file mode 100644 (file)
index 0000000..70c2dac
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* Global Variables */
+
+Name(\PICM,0)                  // IOAPIC/8259
+
+/* Global ACPI memory region. This region is used for passing information
+ * between coreboot (aka "the system bios"), ACPI, and the SMI handler.
+ * Since we don't know where this will end up in memory at ACPI compile time,
+ * we have to fix it up in coreboot's ACPI creation phase.
+ */
+
+
+OperationRegion (GNVS, SystemMemory, 0xC0DEBABE, 0xFF)
+Field (GNVS, ByteAcc, NoLock, Preserve)
+{
+       Offset (0x00),
+       OSYS,   16,     // 0x00 Operating System
+       SMIF,    8,     // 0x02 SMI function
+       Offset (0x10),
+       MPEN,    8,     // 0x10 Multi Processor Enable
+
+}
diff --git a/src/mainboard/iwave/iWRainbowG6/acpi/northbridge_pci_irqs.asl b/src/mainboard/iwave/iWRainbowG6/acpi/northbridge_pci_irqs.asl
new file mode 100644 (file)
index 0000000..e466658
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* This is board specific information: IRQ routing for the
+ * i945
+ */
+
+
+// PCI Interrupt Routing
+Method(_PRT)
+{
+       If (PICM) {
+               Return (Package() {
+                       // PCIe Graphics                0:1.0
+                       Package() { 0x0001ffff, 0, 0, 16 },
+                       Package() { 0x0001ffff, 1, 0, 17 },
+                       Package() { 0x0001ffff, 2, 0, 18 },
+                       Package() { 0x0001ffff, 3, 0, 19 },
+                       // Onboard graphics (IGD)       0:2.0
+                       Package() { 0x0002ffff, 0, 0, 16 },
+                       // High Definition Audio        0:1b.0
+                       Package() { 0x001bffff, 0, 0, 16 },
+                       // PCIe Root Ports              0:1c.x
+                       Package() { 0x001cffff, 0, 0, 16 },
+                       Package() { 0x001cffff, 1, 0, 17 },
+                       Package() { 0x001cffff, 2, 0, 18 },
+                       Package() { 0x001cffff, 3, 0, 19 },
+                       // USB and EHCI                 0:1d.x
+                       Package() { 0x001dffff, 0, 0, 23 },
+                       Package() { 0x001dffff, 1, 0, 19 },
+                       Package() { 0x001dffff, 2, 0, 18 },
+                       Package() { 0x001dffff, 3, 0, 16 },
+                       // AC97/IDE                             0:1e.2, 0:1e.3
+                       Package() { 0x001effff, 0, 0, 17 },
+                       Package() { 0x001effff, 1, 0, 20 },
+                       // LPC device                   0:1f.0
+                       Package() { 0x001fffff, 0, 0, 18 },
+                       Package() { 0x001fffff, 1, 0, 19},
+               })
+       } Else {
+               Return (Package() {
+                       // PCIe Graphics                0:1.0
+                       Package() { 0x0001ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
+                       Package() { 0x0001ffff, 1, \_SB.PCI0.LPCB.LNKB, 0 },
+                       Package() { 0x0001ffff, 2, \_SB.PCI0.LPCB.LNKC, 0 },
+                       Package() { 0x0001ffff, 3, \_SB.PCI0.LPCB.LNKD, 0 },
+                       // Onboard graphics (IGD)       0:2.0
+                       Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
+                       // High Definition Audio        0:1b.0
+                       Package() { 0x001bffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
+                       // PCIe Root Ports              0:1c.x
+                       Package() { 0x001cffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
+                       Package() { 0x001cffff, 1, \_SB.PCI0.LPCB.LNKB, 0 },
+                       Package() { 0x001cffff, 2, \_SB.PCI0.LPCB.LNKC, 0 },
+                       Package() { 0x001cffff, 3, \_SB.PCI0.LPCB.LNKD, 0 },
+                       // USB and EHCI                 0:1d.x
+                       Package() { 0x001dffff, 0, \_SB.PCI0.LPCB.LNKH, 0 },
+                       Package() { 0x001dffff, 1, \_SB.PCI0.LPCB.LNKD, 0 },
+                       Package() { 0x001dffff, 2, \_SB.PCI0.LPCB.LNKC, 0 },
+                       Package() { 0x001dffff, 3, \_SB.PCI0.LPCB.LNKA, 0 },
+                       // AC97/IDE                     0:1e.2, 0:1e.3
+                       Package() { 0x001effff, 0, \_SB.PCI0.LPCB.LNKB, 0 },
+                       Package() { 0x001effff, 1, \_SB.PCI0.LPCB.LNKE, 0 },
+                       // LPC device                   0:1f.0
+                       Package() { 0x001fffff, 0, \_SB.PCI0.LPCB.LNKC, 0 },
+                       Package() { 0x001fffff, 1, \_SB.PCI0.LPCB.LNKD, 0 },
+               })
+       }
+}
+
diff --git a/src/mainboard/iwave/iWRainbowG6/acpi/platform.asl b/src/mainboard/iwave/iWRainbowG6/acpi/platform.asl
new file mode 100644 (file)
index 0000000..fe2ba93
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* The APM port can be used for generating software SMIs */
+
+OperationRegion (APMP, SystemIO, 0xb2, 2)
+Field (APMP, ByteAcc, NoLock, Preserve)
+{
+       APMC, 8,        // APM command
+       APMS, 8         // APM status
+}
+
+/* Port 80 POST */
+
+OperationRegion (POST, SystemIO, 0x80, 1)
+Field (POST, ByteAcc, Lock, Preserve)
+{
+       DBG0, 8
+}
+
+/* SMI I/O Trap */
+Method(TRAP, 1, Serialized)
+{
+       Store (Arg0, SMIF)      // SMI Function
+       //Store (0, TRP0)               // Generate trap
+       Return (SMIF)           // Return value of SMI handler
+}
+
+/* The _PIC method is called by the OS to choose between interrupt
+ * routing via the i8259 interrupt controller or the APIC.
+ *
+ * _PIC is called with a parameter of 0 for i8259 configuration and
+ * with a parameter of 1 for Local Apic/IOAPIC configuration.
+ */
+
+Method(_PIC, 1)
+{
+       // Remember the OS' IRQ routing choice.
+       Store(Arg0, PICM)
+}
+
+/* The _PTS method (Prepare To Sleep) is called before the OS is
+ * entering a sleep state. The sleep state number is passed in Arg0
+ */
+
+Method(_PTS,1)
+{
+       // Call a trap so SMI can prepare for Sleep as well.
+       // TRAP(0x55)
+}
+
+/* The _WAK method is called on system wakeup */
+
+Method(_WAK,1)
+{
+       // CPU specific part
+
+       // Notify PCI Express slots in case a card
+       // was inserted while a sleep state was active.
+
+       // Are we going to S3?
+       If (LEqual(Arg0, 3)) {
+               // ..
+       }
+
+       // Are we going to S4?
+       If (LEqual(Arg0, 4)) {
+               // ..
+       }
+
+       // TODO: Windows XP SP2 P-State restore
+
+       Return(Package(){0,0})
+}
+
diff --git a/src/mainboard/iwave/iWRainbowG6/acpi/sleepstates.asl b/src/mainboard/iwave/iWRainbowG6/acpi/sleepstates.asl
new file mode 100644 (file)
index 0000000..6159585
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Name(\_S0, Package(4){0x0,0x0,0,0})
+Name(\_S1, Package(4){0x1,0x0,0,0})
+Name(\_S3, Package(4){0x5,0x0,0,0})
+Name(\_S4, Package(4){0x6,0x0,0,0})
+Name(\_S5, Package(4){0x7,0x0,0,0})
+
diff --git a/src/mainboard/iwave/iWRainbowG6/acpi/southbridge_pci_irqs.asl b/src/mainboard/iwave/iWRainbowG6/acpi/southbridge_pci_irqs.asl
new file mode 100644 (file)
index 0000000..c108d3f
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* This is board specific information: IRQ routing for the
+ * 0:1e.0 PCI bridge of the ICH7
+ */
+
+If (PICM) {
+       Return (Package() {
+               Package() { 0x0000ffff, 0, 0, 16},
+
+               Package() { 0x0001ffff, 0, 0, 20},
+               Package() { 0x0001ffff, 1, 0, 21},
+               Package() { 0x0001ffff, 2, 0, 22},
+               Package() { 0x0001ffff, 3, 0, 23},
+
+               Package() { 0x0002ffff, 0, 0, 21},
+               Package() { 0x0002ffff, 1, 0, 22},
+               Package() { 0x0002ffff, 2, 0, 23},
+               Package() { 0x0002ffff, 3, 0, 20},
+
+               Package() { 0x0003ffff, 0, 0, 22},
+               Package() { 0x0003ffff, 1, 0, 23},
+               Package() { 0x0003ffff, 2, 0, 20},
+               Package() { 0x0003ffff, 3, 0, 21},
+
+               Package() { 0x0004ffff, 0, 0, 23},
+               Package() { 0x0004ffff, 1, 0, 20},
+               Package() { 0x0004ffff, 2, 0, 21},
+               Package() { 0x0004ffff, 3, 0, 22},
+
+               Package() { 0x0005ffff, 0, 0, 19},
+               Package() { 0x0005ffff, 1, 0, 18},
+               Package() { 0x0005ffff, 2, 0, 17},
+               Package() { 0x0005ffff, 3, 0, 16},
+
+               Package() { 0x0006ffff, 0, 0, 18},
+               Package() { 0x0006ffff, 1, 0, 17},
+               Package() { 0x0006ffff, 2, 0, 16},
+               Package() { 0x0006ffff, 3, 0, 19},
+
+               Package() { 0x0009ffff, 0, 0, 21},
+               Package() { 0x0009ffff, 1, 0, 22},
+               Package() { 0x0009ffff, 2, 0, 23},
+               Package() { 0x0009ffff, 3, 0, 20},
+       })
+} Else {
+       Return (Package() {
+               Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKA, 0},
+
+               Package() { 0x0001ffff, 0, \_SB.PCI0.LPCB.LNKE, 0},
+               Package() { 0x0001ffff, 1, \_SB.PCI0.LPCB.LNKF, 0},
+               Package() { 0x0001ffff, 2, \_SB.PCI0.LPCB.LNKG, 0},
+               Package() { 0x0001ffff, 3, \_SB.PCI0.LPCB.LNKH, 0},
+
+               Package() { 0x0002ffff, 0, \_SB.PCI0.LPCB.LNKF, 0},
+               Package() { 0x0002ffff, 1, \_SB.PCI0.LPCB.LNKG, 0},
+               Package() { 0x0002ffff, 2, \_SB.PCI0.LPCB.LNKH, 0},
+               Package() { 0x0002ffff, 3, \_SB.PCI0.LPCB.LNKE, 0},
+
+               Package() { 0x0003ffff, 0, \_SB.PCI0.LPCB.LNKG, 0},
+               Package() { 0x0003ffff, 1, \_SB.PCI0.LPCB.LNKH, 0},
+               Package() { 0x0003ffff, 2, \_SB.PCI0.LPCB.LNKE, 0},
+               Package() { 0x0003ffff, 3, \_SB.PCI0.LPCB.LNKF, 0},
+
+               Package() { 0x0004ffff, 0, \_SB.PCI0.LPCB.LNKH, 0},
+               Package() { 0x0004ffff, 1, \_SB.PCI0.LPCB.LNKE, 0},
+               Package() { 0x0004ffff, 2, \_SB.PCI0.LPCB.LNKF, 0},
+               Package() { 0x0004ffff, 3, \_SB.PCI0.LPCB.LNKG, 0},
+
+               Package() { 0x0005ffff, 0, \_SB.PCI0.LPCB.LNKD, 0},
+               Package() { 0x0005ffff, 1, \_SB.PCI0.LPCB.LNKC, 0},
+               Package() { 0x0005ffff, 2, \_SB.PCI0.LPCB.LNKB, 0},
+               Package() { 0x0005ffff, 3, \_SB.PCI0.LPCB.LNKA, 0},
+
+               Package() { 0x0006ffff, 0, \_SB.PCI0.LPCB.LNKC, 0},
+               Package() { 0x0006ffff, 1, \_SB.PCI0.LPCB.LNKB, 0},
+               Package() { 0x0006ffff, 2, \_SB.PCI0.LPCB.LNKA, 0},
+               Package() { 0x0006ffff, 3, \_SB.PCI0.LPCB.LNKD, 0},
+
+               Package() { 0x0009ffff, 0, \_SB.PCI0.LPCB.LNKF, 0},
+               Package() { 0x0009ffff, 1, \_SB.PCI0.LPCB.LNKG, 0},
+               Package() { 0x0009ffff, 2, \_SB.PCI0.LPCB.LNKH, 0},
+               Package() { 0x0009ffff, 3, \_SB.PCI0.LPCB.LNKE, 0},
+       })
+}
+
diff --git a/src/mainboard/iwave/iWRainbowG6/acpi/superio.asl b/src/mainboard/iwave/iWRainbowG6/acpi/superio.asl
new file mode 100644 (file)
index 0000000..d2498d4
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+
+Device (SIO1)
+{
+       Name (_HID, EISAID("PNP0A05"))
+       Name (_UID, 1)
+
+       Device (UAR1)
+       {
+               Name(_HID, EISAID("PNP0501"))
+               Name(_UID, 1)
+
+               // Some methods need an implementation here:
+               // missing: _STA, _DIS, _CRS, _PRS,
+               // missing: _SRS, _PS0, _PS3
+       }
+
+       Device (UAR2)
+       {
+               Name(_HID, EISAID("PNP0501"))
+               Name(_UID, 2)
+
+               // Some methods need an implementation here:
+               // missing: _STA, _DIS, _CRS, _PRS,
+               // missing: _SRS, _PS0, _PS3
+       }
+}
+
diff --git a/src/mainboard/iwave/iWRainbowG6/acpi/thermal.asl b/src/mainboard/iwave/iWRainbowG6/acpi/thermal.asl
new file mode 100644 (file)
index 0000000..b7a6e82
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+// Thermal Zone
+
+Scope (\_TZ)
+{
+       ThermalZone (THRM)
+       {
+
+               // FIXME these could/should be read from the
+               // GNVS area, so they can be controlled by
+               // coreboot
+               Name(TC1V, 0x04)
+               Name(TC2V, 0x03)
+               Name(TSPV, 0x64)
+
+               // At which temperature should the OS start
+               // active cooling?
+               Method (_AC0, 0, Serialized)
+               {
+                       Return (0xf5c) // Value for Rocky
+               }
+
+               // Method (_AC1, 0, Serialized)
+               // {
+               //      Return (0xf5c)
+               // }
+
+               // Critical shutdown temperature
+               Method (_CRT, 0, Serialized)
+               {
+                       Return (Add (0x0aac, 0x50)) // FIXME
+               }
+
+               // CPU throttling start temperature
+               Method (_PSV, 0, Serialized)
+               {
+                       Return (0xaaf) // FIXME
+               }
+
+               // Get DTS Temperature
+               Method (_TMP, 0, Serialized)
+               {
+                       Return (0xaac) // FIXME
+               }
+
+               // Processors used for active cooling
+               Method (_PSL, 0, Serialized)
+               {
+                       If (MPEN) {
+                               Return (Package() {\_PR.CPU1, \_PR.CPU2})
+                       }
+                       Return (Package() {\_PR.CPU1})
+               }
+
+               // TC1 value for passive cooling
+               Method (_TC1, 0, Serialized)
+               {
+                       Return (TC1V)
+               }
+
+               // TC2 value for passive cooling
+               Method (_TC2, 0, Serialized)
+               {
+                       Return (TC2V)
+               }
+
+               // Sampling period for passive cooling
+               Method (_TSP, 0, Serialized)
+               {
+                       Return (TSPV)
+               }
+
+
+       }
+}
+
diff --git a/src/mainboard/iwave/iWRainbowG6/acpi/video.asl b/src/mainboard/iwave/iWRainbowG6/acpi/video.asl
new file mode 100644 (file)
index 0000000..507a390
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+// Brightness write
+Method (BRTW, 1, Serialized)
+{
+       // TODO
+}
+
+// Hot Key Display Switch
+Method (HKDS, 1, Serialized)
+{
+       // TODO
+}
+
+// Lid Switch Display Switch
+Method (LSDS, 1, Serialized)
+{
+       // TODO
+}
+
+// Brightness Notification
+Method(BRTN,1,Serialized)
+{
+       // TODO (no displays defined yet)
+}
+
diff --git a/src/mainboard/iwave/iWRainbowG6/acpi_tables.c b/src/mainboard/iwave/iWRainbowG6/acpi_tables.c
new file mode 100644 (file)
index 0000000..37b0a0b
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <types.h>
+#include <string.h>
+#include <console/console.h>
+#include <arch/acpi.h>
+#include <arch/ioapic.h>
+#include <arch/acpigen.h>
+#include <arch/smp/mpspec.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <cpu/x86/msr.h>
+#include "dmi.h"
+
+extern const unsigned char AmlCode[];
+#if CONFIG_HAVE_ACPI_SLIC
+unsigned long acpi_create_slic(unsigned long current);
+#endif
+
+#include "southbridge/intel/i82801gx/nvs.h" // FIXME: our own copy of nvs would be nice
+static void acpi_create_gnvs(global_nvs_t *gnvs)
+{
+       memset((void *)gnvs, 0, sizeof(*gnvs));
+       gnvs->apic = 1;
+       gnvs->mpen = 1; /* Enable Multi Processing */
+
+       /* Enable both COM ports */
+       gnvs->cmap = 0x01;
+       gnvs->cmbp = 0x01;
+
+       /* IGD Displays */
+       gnvs->ndid = 3;
+       gnvs->did[0] = 0x80000100;
+       gnvs->did[1] = 0x80000240;
+       gnvs->did[2] = 0x80000410;
+       gnvs->did[3] = 0x80000410;
+       gnvs->did[4] = 0x00000005;
+}
+
+static void acpi_create_intel_hpet(acpi_hpet_t * hpet)
+{
+#define HPET_ADDR  0xfed00000ULL
+       acpi_header_t *header = &(hpet->header);
+       acpi_addr_t *addr = &(hpet->addr);
+
+       memset((void *) hpet, 0, sizeof(acpi_hpet_t));
+
+       /* fill out header fields */
+       memcpy(header->signature, "HPET", 4);
+       memcpy(header->oem_id, OEM_ID, 6);
+       memcpy(header->oem_table_id, "COREBOOT", 8);
+       memcpy(header->asl_compiler_id, ASLC, 4);
+
+       header->length = sizeof(acpi_hpet_t);
+       header->revision = 1;
+
+       /* fill out HPET address */
+       addr->space_id = 0;     /* Memory */
+       addr->bit_width = 64;
+       addr->bit_offset = 0;
+       addr->addrl = HPET_ADDR & 0xffffffff;
+       addr->addrh = HPET_ADDR >> 32;
+
+       hpet->id = 0x8086a201;  /* Intel */
+       hpet->number = 0x00;
+       hpet->min_tick = 0x0080;
+
+       header->checksum =
+           acpi_checksum((void *) hpet, sizeof(acpi_hpet_t));
+}
+
+unsigned long acpi_fill_madt(unsigned long current)
+{
+       /* Local APICs */
+       current = acpi_create_madt_lapics(current);
+
+       /* IOAPIC */
+       current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
+                               2, IO_APIC_ADDR, 0);
+
+       /* INT_SRC_OVR */
+       current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
+                current, 0, 0, 2, 0);
+       current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
+                current, 0, 9, 9, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH);
+
+       return current;
+}
+
+unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id)
+{
+       generate_cpu_entries();
+       return (unsigned long) (acpigen_get_current());
+}
+
+unsigned long acpi_fill_slit(unsigned long current)
+{
+       // Not implemented
+       return current;
+}
+
+unsigned long acpi_fill_srat(unsigned long current)
+{
+       /* No NUMA, no SRAT */
+       return current;
+}
+
+void smm_setup_structures(void *gnvs, void *tcg, void *smi1);
+
+#define ALIGN_CURRENT current = ((current + 0x0f) & -0x10)
+unsigned long write_acpi_tables(unsigned long start)
+{
+       unsigned long current;
+       int i;
+       acpi_rsdp_t *rsdp;
+       acpi_rsdt_t *rsdt;
+       acpi_xsdt_t *xsdt;
+       acpi_hpet_t *hpet;
+       acpi_madt_t *madt;
+       acpi_mcfg_t *mcfg;
+       acpi_fadt_t *fadt;
+       acpi_facs_t *facs;
+#if CONFIG_HAVE_ACPI_SLIC
+       acpi_header_t *slic;
+#endif
+       acpi_header_t *ssdt;
+       acpi_header_t *dsdt;
+
+       current = start;
+
+       /* Align ACPI tables to 16byte */
+       ALIGN_CURRENT;
+
+       printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start);
+
+       /* We need at least an RSDP and an RSDT Table */
+       rsdp = (acpi_rsdp_t *) current;
+       current += sizeof(acpi_rsdp_t);
+       ALIGN_CURRENT;
+       rsdt = (acpi_rsdt_t *) current;
+       current += sizeof(acpi_rsdt_t);
+       ALIGN_CURRENT;
+       xsdt = (acpi_xsdt_t *) current;
+       current += sizeof(acpi_xsdt_t);
+       ALIGN_CURRENT;
+
+       /* clear all table memory */
+       memset((void *) start, 0, current - start);
+
+       acpi_write_rsdp(rsdp, rsdt, xsdt);
+       acpi_write_rsdt(rsdt);
+       acpi_write_xsdt(xsdt);
+
+       /*
+        * We explicitly add these tables later on:
+        */
+       printk(BIOS_DEBUG, "ACPI:    * HPET\n");
+
+       hpet = (acpi_hpet_t *) current;
+       current += sizeof(acpi_hpet_t);
+       ALIGN_CURRENT;
+       acpi_create_intel_hpet(hpet);
+       acpi_add_table(rsdp, hpet);
+
+       /* If we want to use HPET Timers Linux wants an MADT */
+       printk(BIOS_DEBUG, "ACPI:    * MADT\n");
+
+       madt = (acpi_madt_t *) current;
+       acpi_create_madt(madt);
+       current += madt->header.length;
+       ALIGN_CURRENT;
+       acpi_add_table(rsdp, madt);
+
+       printk(BIOS_DEBUG, "ACPI:    * MCFG\n");
+       mcfg = (acpi_mcfg_t *) current;
+       acpi_create_mcfg(mcfg);
+       current += mcfg->header.length;
+       ALIGN_CURRENT;
+       acpi_add_table(rsdp, mcfg);
+
+       printk(BIOS_DEBUG, "ACPI:     * FACS\n");
+       facs = (acpi_facs_t *) current;
+       current += sizeof(acpi_facs_t);
+       ALIGN_CURRENT;
+       acpi_create_facs(facs);
+
+       dsdt = (acpi_header_t *) current;
+       memcpy(dsdt, &AmlCode, sizeof(acpi_header_t));
+       current += dsdt->length;
+       memcpy(dsdt, &AmlCode, dsdt->length);
+
+       ALIGN_CURRENT;
+
+       /* Pack GNVS into the ACPI table area */
+       for (i=0; i < dsdt->length; i++) {
+               if (*(u32*)(((u32)dsdt) + i) == 0xC0DEBABE) {
+                       printk(BIOS_DEBUG, "ACPI: Patching up global NVS in DSDT at offset 0x%04x -> 0x%08lx\n", i, current);
+                       *(u32*)(((u32)dsdt) + i) = current; // 0x92 bytes
+                       break;
+               }
+       }
+
+       /* And fill it */
+       acpi_create_gnvs((global_nvs_t *)current);
+
+       current += 0x100;
+       ALIGN_CURRENT;
+
+       /* And tell SMI about it */
+       smm_setup_structures((void *)current, NULL, NULL);
+
+       /* We patched up the DSDT, so we need to recalculate the checksum */
+       dsdt->checksum = 0;
+       dsdt->checksum = acpi_checksum((void *)dsdt, dsdt->length);
+
+       printk(BIOS_DEBUG, "ACPI:     * DSDT @ %p Length %x\n", dsdt,
+                    dsdt->length);
+
+#if CONFIG_HAVE_ACPI_SLIC
+       printk(BIOS_DEBUG, "ACPI:     * SLIC\n");
+       slic = (acpi_header_t *)current;
+       current += acpi_create_slic(current);
+       ALIGN_CURRENT;
+       acpi_add_table(rsdp, slic);
+#endif
+
+       printk(BIOS_DEBUG, "ACPI:     * FADT\n");
+       fadt = (acpi_fadt_t *) current;
+       current += sizeof(acpi_fadt_t);
+       ALIGN_CURRENT;
+
+       acpi_create_fadt(fadt, facs, dsdt);
+       acpi_add_table(rsdp, fadt);
+
+       printk(BIOS_DEBUG, "ACPI:     * SSDT\n");
+       ssdt = (acpi_header_t *)current;
+       acpi_create_ssdt_generator(ssdt, "COREBOOT");
+       current += ssdt->length;
+       acpi_add_table(rsdp, ssdt);
+       ALIGN_CURRENT;
+
+       printk(BIOS_DEBUG, "current = %lx\n", current);
+
+       printk(BIOS_DEBUG, "ACPI:     * DMI (Linux workaround)\n");
+       memcpy((void *)0xfff80, dmi_table, DMI_TABLE_SIZE);
+#if CONFIG_WRITE_HIGH_TABLES == 1
+       memcpy((void *)current, dmi_table, DMI_TABLE_SIZE);
+       current += DMI_TABLE_SIZE;
+       ALIGN_CURRENT;
+#endif
+
+       printk(BIOS_INFO, "ACPI: done.\n");
+       return current;
+}
diff --git a/src/mainboard/iwave/iWRainbowG6/chip.h b/src/mainboard/iwave/iWRainbowG6/chip.h
new file mode 100644 (file)
index 0000000..831a973
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2008 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+extern struct chip_operations mainboard_ops;
+struct mainboard_config {};
diff --git a/src/mainboard/iwave/iWRainbowG6/cmos.layout b/src/mainboard/iwave/iWRainbowG6/cmos.layout
new file mode 100644 (file)
index 0000000..ce98ffd
--- /dev/null
@@ -0,0 +1,149 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2007-2009 coresystems GmbH
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; version 2 of
+# the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+# MA 02110-1301 USA
+#
+
+# -----------------------------------------------------------------
+entries
+
+#start-bit length  config config-ID    name
+#0            8       r       0        seconds
+#8            8       r       0        alarm_seconds
+#16           8       r       0        minutes
+#24           8       r       0        alarm_minutes
+#32           8       r       0        hours
+#40           8       r       0        alarm_hours
+#48           8       r       0        day_of_week
+#56           8       r       0        day_of_month
+#64           8       r       0        month
+#72           8       r       0        year
+# -----------------------------------------------------------------
+# Status Register A
+#80           4       r       0        rate_select
+#84           3       r       0        REF_Clock
+#87           1       r       0        UIP
+# -----------------------------------------------------------------
+# Status Register B
+#88           1       r       0        auto_switch_DST
+#89           1       r       0        24_hour_mode
+#90           1       r       0        binary_values_enable
+#91           1       r       0        square-wave_out_enable
+#92           1       r       0        update_finished_enable
+#93           1       r       0        alarm_interrupt_enable
+#94           1       r       0        periodic_interrupt_enable
+#95           1       r       0        disable_clock_updates
+# -----------------------------------------------------------------
+# Status Register C
+#96           4       r       0        status_c_rsvd
+#100          1       r       0        uf_flag
+#101          1       r       0        af_flag
+#102          1       r       0        pf_flag
+#103          1       r       0        irqf_flag
+# -----------------------------------------------------------------
+# Status Register D
+#104          7       r       0        status_d_rsvd
+#111          1       r       0        valid_cmos_ram
+# -----------------------------------------------------------------
+# Diagnostic Status Register
+#112          8       r       0        diag_rsvd1
+
+# -----------------------------------------------------------------
+0          120       r       0        reserved_memory
+#120        264       r       0        unused
+
+# -----------------------------------------------------------------
+# RTC_BOOT_BYTE (coreboot hardcoded)
+384          1       e       4        boot_option
+385          1       e       4        last_boot
+388          4       r       0        reboot_bits
+#390          2       r       0        unused?
+
+# -----------------------------------------------------------------
+# coreboot config options: console
+392          3       e       5        baud_rate
+395          4       e       6        debug_level
+#399          1       r       0        unused
+
+# coreboot config options: cpu
+400          1       e       2        hyper_threading
+#401          7       r       0        unused
+
+# coreboot config options: southbridge
+408          1       e       1        nmi
+409          2       e       7        power_on_after_fail
+#411          5       r       0        unused
+
+# coreboot config options: bootloader
+416        512       s       0        boot_devices
+#928         40       r       0        unused
+
+968          1       e       2        ethernet1
+969          1       e       2        ethernet2
+970          1       e       2        ethernet3
+
+#971          13       r       0        unused
+
+# coreboot config options: check sums
+984         16       h       0        check_sum
+#1000        24       r       0        amd_reserved
+
+# ram initialization internal data
+1024         8       r       0        C0WL0REOST
+1032         8       r       0        C1WL0REOST
+1040         8       r       0        RCVENMT
+1048         4       r       0        C0DRT1
+1052         4       r       0        C1DRT1
+
+# -----------------------------------------------------------------
+
+enumerations
+
+#ID value   text
+1     0     Disable
+1     1     Enable
+2     0     Enable
+2     1     Disable
+4     0     Fallback
+4     1     Normal
+5     0     115200
+5     1     57600
+5     2     38400
+5     3     19200
+5     4     9600
+5     5     4800
+5     6     2400
+5     7     1200
+6     1     Emergency
+6     2     Alert
+6     3     Critical
+6     4     Error
+6     5     Warning
+6     6     Notice
+6     7     Info
+6     8     Debug
+6     9     Spew
+7     0     Disable
+7     1     Enable
+7     2     Keep
+# -----------------------------------------------------------------
+checksums
+
+checksum 392 983 984
+
+
diff --git a/src/mainboard/iwave/iWRainbowG6/devicetree.cb b/src/mainboard/iwave/iWRainbowG6/devicetree.cb
new file mode 100644 (file)
index 0000000..efae82b
--- /dev/null
@@ -0,0 +1,39 @@
+chip northbridge/intel/sch
+
+       device lapic_cluster 0 on
+               chip cpu/intel/socket_441
+                       device lapic 0 on end
+               end
+       end
+
+       device pci_domain 0 on
+               device pci 00.0 on end # host bridge
+               device pci 02.0 on end # Integrated Graphics and Video Device
+
+               chip southbridge/intel/sch
+                       register "pirqa_routing" = "0xa"
+                       register "pirqb_routing" = "0xb"
+                       register "pirqc_routing" = "0x5"
+                       register "pirqd_routing" = "0xf"
+                       register "pirqe_routing" = "0x80"
+                       register "pirqf_routing" = "0x80"
+                       register "pirqg_routing" = "0x80"
+                       register "pirqh_routing" = "0x80"
+
+                       device pci 1a.0 on end  # 26 0 USB Client
+                       device pci 1b.0 on end  # 27 0 HD Audio Controller
+                       device pci 1c.0 on end  # 28 0 PCI Express Port 1
+                       device pci 1c.1 on end  # 28 1 PCI Express Port 2
+                       device pci 1d.0 on end  # USB Classic UHCI Controller 1
+                       device pci 1d.1 on end  # USB Classic UHCI Controller 2
+                       device pci 1d.2 on end  # USB Classic UHCI Controller 3
+                       device pci 1d.7 on end  # USB2 EHCI Controller
+                       device pci 1e.0 on end  # SDIO/MMC Port 0
+                       device pci 1e.1 on end  # SDIO/MMC Port 1
+                       device pci 1e.2 on end  # SDIO/MMC Port 2
+                       device pci 1f.0 on end  # LPC bridge
+                       device pci 1f.1 on end  # PATA Controller
+               end
+       end
+end
+
diff --git a/src/mainboard/iwave/iWRainbowG6/dmi.h b/src/mainboard/iwave/iWRainbowG6/dmi.h
new file mode 100644 (file)
index 0000000..cb48d72
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define DMI_TABLE_SIZE 0x55
+
+static u8 dmi_table[DMI_TABLE_SIZE] = {
+       0x5f, 0x53, 0x4d, 0x5f, 0x2d, 0x1f, 0x02, 0x03, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x5f, 0x44, 0x4d, 0x49, 0x5f, 0xeb, 0xa8, 0x03, 0xa0, 0xff, 0x0f, 0x00, 0x01, 0x00, 0x23, 0x00,
+       0x00, 0x14, 0x00, 0x00, 0x01, 0x02, 0x00, 0xe0, 0x03, 0x07, 0x90, 0xde, 0xcb, 0x7f, 0x00, 0x00,
+       0x00, 0x00, 0x37, 0x01, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+       0x47, 0x6d, 0x62, 0x48, 0x00, 0x32, 0x2e, 0x30, 0x00, 0x30, 0x33, 0x2f, 0x31, 0x33, 0x2f, 0x32,
+       0x30, 0x30, 0x38, 0x00, 0x00
+};
diff --git a/src/mainboard/iwave/iWRainbowG6/dsdt.asl b/src/mainboard/iwave/iWRainbowG6/dsdt.asl
new file mode 100644 (file)
index 0000000..f19ffb9
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+DefinitionBlock(
+       "dsdt.aml",
+       "DSDT",
+       0x02,           // DSDT revision: ACPI v2.0
+       "COREv2",       // OEM id
+       "COREBOOT",     // OEM table id
+       0x20090419      // OEM revision
+)
+{
+       // Some generic macros
+       #include "acpi/platform.asl"
+
+       // global NVS and variables
+       #include "../../../southbridge/intel/sch/acpi/globalnvs.asl"
+
+       // General Purpose Events
+       //#include "acpi/gpe.asl"
+
+       //#include "acpi/thermal.asl"
+
+       Scope (\_SB) {
+               Device (PCI0)
+               {
+                       #include "../../../northbridge/intel/sch/acpi/sch.asl"
+                       #include "../../../southbridge/intel/sch/acpi/sch.asl"
+               }
+       }
+
+       /* Chipset specific sleep states */
+       #include "../../../southbridge/intel/sch/acpi/sleepstates.asl"
+}
diff --git a/src/mainboard/iwave/iWRainbowG6/fadt.c b/src/mainboard/iwave/iWRainbowG6/fadt.c
new file mode 100644 (file)
index 0000000..a0e381f
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+#include <device/pci.h>
+#include <arch/acpi.h>
+
+/* FIXME: This needs to go into a separate .h file
+ * to be included by the ich7 smi handler, ich7 smi init
+ * code and the mainboard fadt.
+ */
+#define APM_CNT                0xb2
+#define   CST_CONTROL  0x85
+#define   PST_CONTROL  0x80
+#define   ACPI_DISABLE 0x1e
+#define   ACPI_ENABLE  0xe1
+#define   GNVS_UPDATE   0xea
+
+void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt)
+{
+       acpi_header_t *header = &(fadt->header);
+       u16 pmbase = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x1f,0)), 0x40) & 0xfffe;
+
+       memset((void *) fadt, 0, sizeof(acpi_fadt_t));
+       memcpy(header->signature, "FACP", 4);
+       header->length = sizeof(acpi_fadt_t);
+       header->revision = 3;
+       memcpy(header->oem_id, "CORE  ", 6);
+       memcpy(header->oem_table_id, "COREBOOT", 8);
+       memcpy(header->asl_compiler_id, "CORE", 4);
+       header->asl_compiler_revision = 1;
+
+       fadt->firmware_ctrl = (unsigned long) facs;
+       fadt->dsdt = (unsigned long) dsdt;
+       fadt->model = 1;
+       fadt->preferred_pm_profile = PM_MOBILE;
+
+       fadt->sci_int = 0x9;
+       fadt->smi_cmd = APM_CNT;
+       fadt->acpi_enable = ACPI_ENABLE;
+       fadt->acpi_disable = ACPI_DISABLE;
+       fadt->s4bios_req = 0x0;
+       fadt->pstate_cnt = PST_CONTROL;
+
+       fadt->pm1a_evt_blk = pmbase;
+       fadt->pm1b_evt_blk = 0x0;
+       fadt->pm1a_cnt_blk = pmbase + 0x4;
+       fadt->pm1b_cnt_blk = 0x0;
+       fadt->pm2_cnt_blk = pmbase + 0x20;
+       fadt->pm_tmr_blk = pmbase + 0x8;
+       fadt->gpe0_blk = pmbase + 0x28;
+       fadt->gpe1_blk = 0;
+
+       fadt->pm1_evt_len = 4;
+       fadt->pm1_cnt_len = 2;
+       // XXX: pm2_cnt_len is probably wrong. find out right value (hint: it's != 0)
+       fadt->pm2_cnt_len = 2;
+       fadt->pm_tmr_len = 4;
+       fadt->gpe0_blk_len = 8;
+       fadt->gpe1_blk_len = 0;
+       fadt->gpe1_base = 0;
+       fadt->cst_cnt = CST_CONTROL;
+       fadt->p_lvl2_lat = 1;
+       fadt->p_lvl3_lat = 85;
+       fadt->flush_size = 1024;
+       fadt->flush_stride = 16;
+       fadt->duty_offset = 1;
+       fadt->duty_width = 0;
+       fadt->day_alrm = 0xd;
+       fadt->mon_alrm = 0x00;
+       fadt->century = 0x00;
+       fadt->iapc_boot_arch = 0x03;
+
+       fadt->flags = ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
+                       ACPI_FADT_C2_MP_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
+                       ACPI_FADT_S4_RTC_WAKE | ACPI_FADT_PLATFORM_CLOCK;
+
+       fadt->reset_reg.space_id = 0;
+       fadt->reset_reg.bit_width = 0;
+       fadt->reset_reg.bit_offset = 0;
+       fadt->reset_reg.resv = 0;
+       fadt->reset_reg.addrl = 0x0;
+       fadt->reset_reg.addrh = 0x0;
+
+       fadt->reset_value = 0;
+       fadt->x_firmware_ctl_l = (unsigned long)facs;
+       fadt->x_firmware_ctl_h = 0;
+       fadt->x_dsdt_l = (unsigned long)dsdt;
+       fadt->x_dsdt_h = 0;
+
+       fadt->x_pm1a_evt_blk.space_id = 1;
+       fadt->x_pm1a_evt_blk.bit_width = 32;
+       fadt->x_pm1a_evt_blk.bit_offset = 0;
+       fadt->x_pm1a_evt_blk.resv = 0;
+       fadt->x_pm1a_evt_blk.addrl = pmbase;
+       fadt->x_pm1a_evt_blk.addrh = 0x0;
+
+       fadt->x_pm1b_evt_blk.space_id = 1;
+       fadt->x_pm1b_evt_blk.bit_width = 0;
+       fadt->x_pm1b_evt_blk.bit_offset = 0;
+       fadt->x_pm1b_evt_blk.resv = 0;
+       fadt->x_pm1b_evt_blk.addrl = 0x0;
+       fadt->x_pm1b_evt_blk.addrh = 0x0;
+
+       fadt->x_pm1a_cnt_blk.space_id = 1;
+       fadt->x_pm1a_cnt_blk.bit_width = 16;
+       fadt->x_pm1a_cnt_blk.bit_offset = 0;
+       fadt->x_pm1a_cnt_blk.resv = 0;
+       fadt->x_pm1a_cnt_blk.addrl = pmbase + 0x4;
+       fadt->x_pm1a_cnt_blk.addrh = 0x0;
+
+       fadt->x_pm1b_cnt_blk.space_id = 1;
+       fadt->x_pm1b_cnt_blk.bit_width = 0;
+       fadt->x_pm1b_cnt_blk.bit_offset = 0;
+       fadt->x_pm1b_cnt_blk.resv = 0;
+       fadt->x_pm1b_cnt_blk.addrl = 0x0;
+       fadt->x_pm1b_cnt_blk.addrh = 0x0;
+
+       fadt->x_pm2_cnt_blk.space_id = 1;
+       fadt->x_pm2_cnt_blk.bit_width = 8;
+       fadt->x_pm2_cnt_blk.bit_offset = 0;
+       fadt->x_pm2_cnt_blk.resv = 0;
+       fadt->x_pm2_cnt_blk.addrl = pmbase + 0x20;
+       fadt->x_pm2_cnt_blk.addrh = 0x0;
+
+       fadt->x_pm_tmr_blk.space_id = 1;
+       fadt->x_pm_tmr_blk.bit_width = 32;
+       fadt->x_pm_tmr_blk.bit_offset = 0;
+       fadt->x_pm_tmr_blk.resv = 0;
+       fadt->x_pm_tmr_blk.addrl = pmbase + 0x8;
+       fadt->x_pm_tmr_blk.addrh = 0x0;
+
+       fadt->x_gpe0_blk.space_id = 1;
+       fadt->x_gpe0_blk.bit_width = 64;
+       fadt->x_gpe0_blk.bit_offset = 0;
+       fadt->x_gpe0_blk.resv = 0;
+       fadt->x_gpe0_blk.addrl = pmbase + 0x28;
+       fadt->x_gpe0_blk.addrh = 0x0;
+
+       fadt->x_gpe1_blk.space_id = 1;
+       fadt->x_gpe1_blk.bit_width = 0;
+       fadt->x_gpe1_blk.bit_offset = 0;
+       fadt->x_gpe1_blk.resv = 0;
+       fadt->x_gpe1_blk.addrl = 0x0;
+       fadt->x_gpe1_blk.addrh = 0x0;
+
+       header->checksum =
+           acpi_checksum((void *) fadt, header->length);
+}
diff --git a/src/mainboard/iwave/iWRainbowG6/hda_verb.h b/src/mainboard/iwave/iWRainbowG6/hda_verb.h
new file mode 100644 (file)
index 0000000..0542b4e
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+static u32 mainboard_cim_verb_data[] = {
+        /* coreboot specific header */
+        0x111d76d5,     // Codec Vendor / Device ID: IDT / 92HD81
+        0x00000000,     // Subsystem ID
+        0x0000000a,     // Number of jacks
+
+       //Codec 92HD81 Yangtze 4ch Pin Port A, data = 0x02a11040
+       0x0A71C40,
+       0x0A71D10,
+       0x0A71EA1,
+       0x0A71F02,
+
+       //;Codec 92HD81 Yangtze 4ch Pin Port B, data = 0x0221101f
+       0x0B71C1F,
+       0x0B71D10,
+       0x0B71E21,
+       0x0B71F02,
+
+       //;Codec 92HD81 Yangtze 4ch Pin Port C, data = 0x400000f0
+       0x0C71CF0,
+       0x0C71D00,
+       0x0C71E00,
+       0x0C71F40,
+
+       //;Codec 92HD81 Yangtze 4ch Pin Port D, data = 0x10104110
+       0x0D71C10,
+       0x0D71D41,
+       0x0D71E10,
+       0x0D71F10,
+
+       //;Codec 92HD81 Yangtze 4ch Pin Port E, data = 0x400000f0
+       0x0E71CF0,
+       0x0E71D00,
+       0x0E71E00,
+       0x0E71F40,
+
+       //;Codec 92HD81 Yangtze 4ch Pin Port F, data = 0x400000f0
+       0x0F71CF0,
+       0x0F71D00,
+       0x0F71E00,
+       0x0F71F40,
+
+       //;Codec 92HD81 Yangtze 4ch Pin MonoOut, data = 0x40f000f0
+       0x1071CF0,
+       0x1071D00,
+       0x1071EF0,
+       0x1071F40,
+
+       //;Codec 92HD81 Yangtze 4ch Pin DMic0, data = 0x400000f0
+       0x1171CF0,
+       0x1171D00,
+       0x1171E00,
+       0x1171F40,
+
+       //;Codec 92HD81 Yangtze 4ch Pin Dig0Pin, data = 0x10402150
+       0x1F71C50,
+       0x1F71D21,
+       0x1F71E40,
+       0x1F71F10,
+
+       //;Codec 92HD81 Yangtze 4ch Pin Dig1Pin, data = 0x400000f0
+       0x2071CF0,
+       0x2071D00,
+       0x2071E00,
+       0x2071F40,
+
+       //; BTL Gain
+       0x017F417
+       // ; Gain = 16.79dB
+};
+
+extern const u32 *cim_verb_data;
+extern u32 cim_verb_data_size;
+
diff --git a/src/mainboard/iwave/iWRainbowG6/irq_tables.c b/src/mainboard/iwave/iWRainbowG6/irq_tables.c
new file mode 100644 (file)
index 0000000..12daec9
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2008 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/pirq_routing.h>
+
+const struct irq_routing_table intel_irq_routing_table = {
+        PIRQ_SIGNATURE,         /* u32 signature */
+        PIRQ_VERSION,           /* u16 version */
+        32+16*CONFIG_IRQ_SLOT_COUNT,     /* Max. number of devices on the bus */
+        0x00,                   /* Interrupt router bus */
+        (0x1f << 3) | 0x0,      /* Interrupt router dev */
+        0,                      /* IRQs devoted exclusively to PCI usage */
+        0x8086,                 /* Vendor */
+        0x8119,                 /* Device*/
+       0,                      /* Miniport */
+        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
+        0xdf,                   /* Checksum (has to be set to some value that
+                                 * would give 0 after the sum of all bytes
+                                 * for this structure (including checksum).
+                                 */
+        {
+                /* bus,        dev | fn,   {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */
+                {0x00, (0x02 << 3) | 0x0, {{0x60, 0x5cb8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+                {0x00, (0x1e << 3) | 0x0, {{0x60, 0x5cb8}, {0x61, 0x5cb8}, {0x62, 0x5cb8}, {0x00, 0x0000}}, 0x0, 0x0},
+                {0x00, (0x1f << 3) | 0x0, {{0x62, 0x5cb8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+                {0x00, (0x1a << 3) | 0x0, {{0x60, 0x5cb8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+                {0x00, (0x1d << 3) | 0x0, {{0x64, 0x8200}, {0x65, 0x8200}, {0x66, 0x8200}, {0x67, 0x8200}}, 0x0, 0x0},
+                {0x00, (0x1b << 3) | 0x0, {{0x60, 0x5cb8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+                {0x00, (0x1c << 3) | 0x0, {{0x60, 0x5cb8}, {0x61, 0x5cb8}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+                {0x01, (0x00 << 3) | 0x0, {{0x60, 0x5cb8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+                {0x02, (0x00 << 3) | 0x0, {{0x61, 0x5cb8}, {0x62, 0x5cb8}, {0x63, 0x5cb8}, {0x60, 0x5cb8}}, 0x2, 0x0},
+                {0x00, (0x00 << 3) | 0x0, {{0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+        }
+};
+
+unsigned long write_pirq_routing_table(unsigned long addr)
+{
+        return copy_pirq_routing_table(addr);
+}
+
diff --git a/src/mainboard/iwave/iWRainbowG6/mainboard.c b/src/mainboard/iwave/iWRainbowG6/mainboard.c
new file mode 100644 (file)
index 0000000..2096be2
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ * Copyright (C) 2010 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <device/device.h>
+#include <console/console.h>
+#include <boot/tables.h>
+#include "chip.h"
+#include "hda_verb.h"
+
+static void verb_setup(void)
+{
+       cim_verb_data = mainboard_cim_verb_data;
+       cim_verb_data_size = sizeof(mainboard_cim_verb_data);
+}
+
+static void mainboard_enable(device_t dev)
+{
+       verb_setup();
+}
+
+struct chip_operations mainboard_ops = {
+       CHIP_NAME("iW Rainbow G6 Mainboard")
+       .enable_dev = mainboard_enable,
+};
+
diff --git a/src/mainboard/iwave/iWRainbowG6/mainboard_smi.c b/src/mainboard/iwave/iWRainbowG6/mainboard_smi.c
new file mode 100644 (file)
index 0000000..020e2c3
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <cpu/x86/smm.h>
+#include "southbridge/intel/i82801gx/nvs.h" // FIXME: this should point to its own copy of nvs
+
+/* The southbridge SMI handler checks whether gnvs has a
+ * valid pointer before calling the trap handler
+ */
+//extern global_nvs_t *gnvs;
+
+int mainboard_io_trap_handler(int smif)
+{
+       switch (smif) {
+       case 0x99:
+               printk(BIOS_DEBUG, "Sample\n");
+               //gnvs->smif = 0;
+               break;
+       default:
+               return 0;
+       }
+
+       /* On success, the IO Trap Handler returns 0
+        * On failure, the IO Trap Handler returns a value != 0
+        *
+        * For now, we force the return value to 0 and log all traps to
+        * see what's going on.
+        */
+       //gnvs->smif = 0;
+       return 1;
+}
+
+
diff --git a/src/mainboard/iwave/iWRainbowG6/mptable.c b/src/mainboard/iwave/iWRainbowG6/mptable.c
new file mode 100644 (file)
index 0000000..09d9d9a
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2008 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <arch/smp/mpspec.h>
+#include <device/pci.h>
+#include <string.h>
+#include <stdint.h>
+
+void *smp_write_config_table(void *v)
+{
+       struct mp_config_table *mc;
+       int isa_bus;
+
+       mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
+       mptable_init(mc, "IWRAINBOWG6", LAPIC_ADDR);
+
+       smp_write_processors(mc);
+       mptable_write_buses(mc, NULL, &isa_bus);
+
+       smp_write_ioapic(mc, 2, 0x20, 0xfec00000);
+       {
+               device_t dev;
+               struct resource *res;
+               dev = dev_find_slot(1, PCI_DEVFN(0x1e,0));
+               if (dev) {
+                       res = find_resource(dev, PCI_BASE_ADDRESS_0);
+                       if (res) {
+                               smp_write_ioapic(mc, 3, 0x20, res->base);
+                       }
+               }
+               dev = dev_find_slot(1, PCI_DEVFN(0x1c,0));
+               if (dev) {
+                       res = find_resource(dev, PCI_BASE_ADDRESS_0);
+                       if (res) {
+                               smp_write_ioapic(mc, 4, 0x20, res->base);
+                       }
+               }
+               dev = dev_find_slot(4, PCI_DEVFN(0x1e,0));
+               if (dev) {
+                       res = find_resource(dev, PCI_BASE_ADDRESS_0);
+                       if (res) {
+                               smp_write_ioapic(mc, 5, 0x20, res->base);
+                       }
+               }
+               dev = dev_find_slot(4, PCI_DEVFN(0x1c,0));
+               if (dev) {
+                       res = find_resource(dev, PCI_BASE_ADDRESS_0);
+                       if (res) {
+                               smp_write_ioapic(mc, 8, 0x20, res->base);
+                       }
+               }
+       }
+/*I/O Ints:    Type    Polarity    Trigger     Bus ID   IRQ    APIC ID PIN#
+*/     smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_DEFAULT, 0x1, 0x0, 0x1, 0x0);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x1, 0x1, 0x1, 0x1);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x1, 0x0, 0x1, 0x2);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x1, 0x3, 0x1, 0x3);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x1, 0x4, 0x1, 0x4);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x1, 0x6, 0x1, 0x6);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x1, 0x7, 0x1, 0x7);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x1, 0x8, 0x1, 0x8);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x1, 0x9, 0x1, 0x9);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x1, 0xc, 0x1, 0xc);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x1, 0xd, 0x1, 0xd);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, 0x1, 0xe, 0x1, 0xe);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x8, 0x1, 0x10);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x74, 0x1, 0x10);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x75, 0x1, 0x11);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x76, 0x1, 0x12);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x77, 0x1, 0x13);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x6c, 0x1, 0x10);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x78, 0x1, 0x10);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x79, 0x1, 0x11);
+       smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x0, 0x7a, 0x1, 0x12);
+/*Local Ints:  Type    Polarity    Trigger     Bus ID   IRQ    APIC ID PIN#*/
+       smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0x0, MP_APIC_ALL, 0x0);
+       smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT, isa_bus, 0x0, MP_APIC_ALL, 0x1);
+       /* There is no extension information... */
+
+       /* Compute the checksums */
+       mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);
+       mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
+       printk(BIOS_DEBUG, "Wrote the mp table end at: %p - %p\n",
+               mc, smp_next_mpe_entry(mc));
+       return smp_next_mpe_entry(mc);
+}
+
+unsigned long write_smp_table(unsigned long addr)
+{
+       void *v;
+       v = smp_write_floating_table(addr);
+       return (unsigned long)smp_write_config_table(v);
+}
diff --git a/src/mainboard/iwave/iWRainbowG6/romstage.c b/src/mainboard/iwave/iWRainbowG6/romstage.c
new file mode 100644 (file)
index 0000000..339a8f5
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <device/pci_def.h>
+#include <device/pnp_def.h>
+#include <cpu/x86/lapic.h>
+#include <cpu/x86/cache.h>
+#include <arch/cpu.h>
+
+#include <console/console.h>
+#if 0
+#include "ram/ramtest.c"
+#include "southbridge/intel/sch/early_smbus.c"
+#endif
+
+//#include "pc80/mc146818rtc_early.c"
+//#include "pc80/serial.c"
+
+#define RFID_TEST 0
+
+#if RFID_TEST
+#define RFID_ADDR 0xA0
+#define RFID_SELECT_CARD_COMMAND 0x01
+#define SELECT_COMMAND_LENGTH 0x01
+
+#define SMBUS_BASE_ADDRESS 0x400
+
+static u32 sch_SMbase_read(void)
+{
+       u32 SMBusBase;
+       SMBusBase = pci_read_config32(PCI_DEV(0, 0x1f, 0), 0x40);       /*SM Bus Address */
+       SMBusBase &= 0xFFFF;
+       printk(BIOS_DEBUG, "SM Bus Base. =%x\r\n", SMBusBase);
+       return SMBusBase;
+}
+
+static void sch_SMbase_init(void)
+{
+       u32 SMBusBase;
+       SMBusBase = sch_SMbase_read();
+       outb(0x3F, SMBusBase + SMBCLKDIV);
+}
+
+static void sch_SMbus_regs(void)
+{
+       u32 SMBusBase;
+       SMBusBase = sch_SMbase_read();
+       printk(BIOS_DEBUG, "SMBHSTCNT. =%x\r\n", inb(SMBusBase + SMBHSTCNT));
+       printk(BIOS_DEBUG, "SMBHSTSTS. =%x\r\n", inb(SMBusBase + SMBHSTSTS));
+       printk(BIOS_DEBUG, "SMBCLKDIV. =%x\r\n", inb(SMBusBase + SMBCLKDIV));
+
+       printk(BIOS_DEBUG, "SMBHSTADD. =%x\r\n", inb(SMBusBase + SMBHSTADD));
+       printk(BIOS_DEBUG, "SMBHSTCMD. =%x\r\n", inb(SMBusBase + SMBHSTCMD));
+}
+
+void smb_clear()
+{
+       u32 SMBusBase;
+       SMBusBase = sch_SMbase_read();
+       outb(0x00, SMBusBase + SMBHSTCNT);
+       outb(0x07, SMBusBase + SMBHSTSTS);
+}
+
+void data_clear()
+{
+       u32 SMBusBase;
+       SMBusBase = sch_SMbase_read();
+       outb(0x00, SMBusBase + SMBHSTDAT0);
+       outb(0x00, SMBusBase + SMBHSTCMD);
+       outb(0x00, SMBusBase + SMBHSTDAT1);
+       outb(0x00, SMBusBase + SMBHSTDATB);
+       outb(0x00, SMBusBase + (SMBHSTDATB + 0x1));
+       outb(0x00, SMBusBase + (SMBHSTDATB + 0x2));
+       outb(0x00, SMBusBase + (SMBHSTDATB + 0x3));
+       outb(0x00, SMBusBase + (SMBHSTDATB + 0x4));
+       outb(0x00, SMBusBase + (SMBHSTDATB + 0x5));
+       outb(0x00, SMBusBase + (SMBHSTDATB + 0x6));
+}
+
+void transaction1(unsigned char dev_addr)
+{
+       int temp, a;
+       u32 SMBusBase;
+       SMBusBase = sch_SMbase_read();
+       printk(BIOS_DEBUG, "Transaction 1");
+       //clear the control and status registers
+       smb_clear();
+       //clear the data register
+       data_clear();
+       //program TSA register
+       outb(dev_addr, SMBusBase + SMBHSTADD);
+       //program command register
+       outb(0x04, SMBusBase + SMBHSTCMD);
+       //write data register
+       outb(0x04, SMBusBase + SMBHSTDAT0);
+       outb(0x04, SMBusBase + SMBHSTDATB);
+
+       outb(0x09, SMBusBase + (SMBHSTDATB + 0x1));
+       outb(0x11, SMBusBase + (SMBHSTDATB + 0x2));
+       outb(0x22, SMBusBase + (SMBHSTDATB + 0x3));
+
+       //set the control register
+       outb(0x15, SMBusBase + SMBHSTCNT);
+       //check the status register for busy state
+       //sch_SMbus_regs ();
+       temp = inb(SMBusBase + SMBHSTSTS);
+       //printk(BIOS_DEBUG, "SM Bus Busy.. status =%x\r\n",temp);
+       //printk(BIOS_DEBUG, "SMBHSTSTS. =%x\r\n",inb(SMBusBase+SMBHSTSTS));
+       do {
+               temp = inb(SMBusBase + SMBHSTSTS);
+               printk(BIOS_DEBUG, "SM Bus Busy.. status =%x\r\n", temp);
+               //sch_SMbus_regs ();
+               printk(BIOS_DEBUG, "SMBHSTSTS. =%x\r\n",
+                            inb(SMBusBase + SMBHSTSTS));
+               if (temp > 0)
+                       break;
+       } while (1);
+
+       switch (temp) {
+       case 1:
+               printk(BIOS_DEBUG, "SM Bus Success");
+               break;
+       default:
+               printk(BIOS_DEBUG, "SM Bus error %d", temp);
+               break;
+
+       }
+       sch_SMbus_regs();
+       printk(BIOS_DEBUG, "Command in TRansaction 1=%x\r\n\n",
+                    inb(SMBusBase + SMBHSTCMD));
+}
+
+void transaction2(unsigned char dev_addr)
+{
+       int temp, a;
+       u32 SMBusBase;
+       SMBusBase = sch_SMbase_read();
+       printk(BIOS_DEBUG, "Transaction 2");
+       //clear the control and status registers
+       smb_clear();
+       //clear the data register
+       data_clear();
+       //program TSA register
+       outb(dev_addr, SMBusBase + SMBHSTADD);
+       //program command register
+       outb(0x03, SMBusBase + SMBHSTCMD);
+       //write data register
+       outb(0x02, SMBusBase + SMBHSTDAT0);
+       outb(0x03, SMBusBase + SMBHSTDATB);
+       outb(0x09, SMBusBase + (SMBHSTDATB + 0x1));
+       outb(0x15, SMBusBase + SMBHSTCNT);
+       //check the status register for busy state
+       //sch_SMbus_regs ();
+       temp = inb(SMBusBase + SMBHSTSTS);
+       //printk(BIOS_DEBUG, "SM Bus Busy.. status =%x\r\n",temp);
+       //printk(BIOS_DEBUG, "SMBHSTSTS. =%x\r\n",inb(SMBusBase+SMBHSTSTS));
+       do {
+               temp = inb(SMBusBase + SMBHSTSTS);
+               printk(BIOS_DEBUG, "SM Bus Busy.. status =%x\r\n", temp);
+               //sch_SMbus_regs ();
+               printk(BIOS_DEBUG, "SMBHSTSTS. =%x\r\n",
+                            inb(SMBusBase + SMBHSTSTS));
+               if (temp > 0)
+                       break;
+       } while (1);
+
+       switch (temp) {
+       case 1:
+               printk(BIOS_DEBUG, "SM Bus Success");
+               break;
+       default:
+               printk(BIOS_DEBUG, "SM Bus error %d", temp);
+               break;
+
+       }
+       sch_SMbus_regs();
+
+       printk(BIOS_DEBUG, "Command in TRansaction 2=%x\r\n\n",
+                    inb(SMBusBase + SMBHSTCMD));
+}
+
+void transaction3(unsigned char dev_addr)
+{
+       int temp, index, length;
+       u32 SMBusBase;
+       SMBusBase = sch_SMbase_read();
+       printk(BIOS_DEBUG, "smb_read_multiple_bytes");
+       smb_clear();
+       data_clear();
+       outb(dev_addr, SMBusBase + SMBHSTADD);
+       outb(0x03, SMBusBase + SMBHSTCMD);
+       outb(0x11, SMBusBase + SMBHSTCNT);
+
+       //data_clear();
+       outb(dev_addr + 1, SMBusBase + SMBHSTADD);
+
+       outb(0x15, SMBusBase + SMBHSTCNT);
+
+       // sch_SMbus_regs ();
+       //check the status register for busy state
+       //temp=inb(SMBusBase+SMBHSTSTS);
+       //printk(BIOS_DEBUG, "SM Bus Busy.. status =%x\r\n",temp);
+       //sch_SMbus_regs ();
+       //printk(BIOS_DEBUG, "SMBHSTSTS. =%x\r\n",inb(SMBusBase+SMBHSTSTS));
+       do {
+               temp = inb(SMBusBase + SMBHSTSTS);
+               printk(BIOS_DEBUG, "SMBHSTSTS. =%x\r\n",
+                            inb(SMBusBase + SMBHSTSTS));
+               //sch_SMbus_regs ();
+               if (temp > 0)
+                       break;
+       } while (1);
+
+       switch (temp) {
+       case 1:
+               printk(BIOS_DEBUG, "SM Bus Success\n");
+               break;
+       default:
+               printk(BIOS_DEBUG, "SM Bus error %d", temp);
+               break;
+
+       }
+
+       sch_SMbus_regs();
+       printk(BIOS_DEBUG, "ADDRESS is.. %x\r\n", inb(SMBusBase + SMBHSTADD));
+       length = inb(SMBusBase + SMBHSTDAT0);
+
+       printk(BIOS_DEBUG, "Length is.. %x\r\n", inb(SMBusBase + SMBHSTDAT0));
+
+       printk(BIOS_DEBUG, "Command is... %x\r\n", inb(SMBusBase + SMBHSTDATB));
+       printk(BIOS_DEBUG, "Status .. %x\r\n", inb(SMBusBase + SMBHSTDATB + 1));
+       for (index = 0; index < length; index++)
+               printk(BIOS_DEBUG, "Serial Byte[%x]..%x\r\n", index,
+                            inb(SMBusBase + SMBHSTDATB + index));
+}
+
+int selectcard(void)
+{
+       int i;
+       printk(BIOS_DEBUG, "%s", "\r\nCase 9....... \n\r");
+       // send the length byte and command code through RFID interface
+
+       transaction1(RFID_ADDR);
+       transaction2(RFID_ADDR);
+       transaction3(RFID_ADDR);
+       return (1);
+}
+#endif
+
+#include "northbridge/intel/sch/early_init.c"
+#include "northbridge/intel/sch/raminit.h"
+#include "northbridge/intel/sch/raminit.c"
+
+
+static void sch_enable_lpc(void)
+{
+       /* Initialize the FWH decode/Enable registers according to platform design */
+       pci_write_config32(PCI_DEV(0, 0x1f, 0), 0xD0, 0x00112233);
+       pci_write_config32(PCI_DEV(0, 0x1f, 0), 0xD4, 0xC0000000);
+       pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x60, 0x808A8B8B);
+       pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x64, 0x8F898F89);
+}
+
+static void sch_shadow_CMC(void)
+{
+       u32 reg32;
+       /* FIXME: proper dest, proper src, and wbinvd, too */
+       memcpy((void *)CMC_SHADOW, (void *)0xfffd0000, 64 * 1024);
+       // __asm__ volatile ("wbinvd \n"
+       //);
+       printk(BIOS_DEBUG, "copy done ");
+       memcpy((void *)0x3f5f0000, (void *)0x3faf0000, 64 * 1024);
+       printk(BIOS_DEBUG, "copy 2 done ");
+       reg32 = cpuid_eax(0x00000001);
+       printk(BIOS_INFO, "CPU ID: %d.\n", reg32);
+
+       reg32 = cpuid_eax(0x80000008);
+       printk(BIOS_INFO, "Physical Address size: %d.\n", (reg32 & 0xFF));
+       printk(BIOS_INFO, "Virtual Address size: %d.\n", ((reg32 & 0xFF00) >> 8));
+       sch_port_access_write_ram_cmd(0xB8, 4, 0, 0x3faf0000);
+       printk(BIOS_DEBUG, "1 ");
+       sch_port_access_write_ram_cmd(0xBA, 4, 0, reg32);
+       printk(BIOS_DEBUG, "2 ");
+}
+
+static void poulsbo_setup_Stage1Regs(void)
+{
+       u32 reg32;
+
+       printk(BIOS_DEBUG, "E000/F000 Routing ");
+       reg32 = sch_port_access_read(2, 3, 4);
+       sch_port_access_write(2, 3, 4, (reg32 | 0x6));
+}
+
+static void poulsbo_setup_Stage2Regs(void)
+{
+       u32 reg32;
+       printk(BIOS_DEBUG, "Reserved");
+       reg32 = pci_read_config32(PCI_DEV(0, 0x2, 0), 0x62);
+       pci_write_config32(PCI_DEV(0, 0x2, 0), 0x62, (reg32 | 0x3));
+       /*Slot capabilities */
+       pci_write_config32(PCI_DEV(0, 28, 0), 0x54, 0x80500);
+       pci_write_config32(PCI_DEV(0, 28, 1), 0x54, 0x100500);
+       /* FIXME: CPU ID identification */
+       printk(BIOS_DEBUG, " done.\n");
+}
+
+void main(unsigned long bist)
+{
+       int boot_mode = 0;
+
+       if (bist == 0) {
+               enable_lapic();
+       }
+
+       sch_enable_lpc();
+       /* Set up the console */
+       uart_init();
+       console_init();
+
+       /* Halt if there was a built in self test failure */
+       // report_bist_failure(bist);
+       // outl (0x00,0x1088);
+
+       /* Perform some early chipset initialization required
+        * before RAM initialization can work
+        */
+       sch_early_initialization();
+       sdram_initialize(boot_mode);
+
+       sch_shadow_CMC();
+       poulsbo_setup_Stage1Regs();
+       poulsbo_setup_Stage2Regs();
+#if 0
+       sch_SMbase_init ();
+
+       /* Perform some initialization that must run before stage2 */
+#endif
+
+       /* This should probably go away. Until now it is required
+        * and mainboard specific
+        */
+
+       /* Chipset Errata! */
+       pci_write_config16(PCI_DEV(0, 0x2, 0), GGC, 0x20);
+       pci_write_config32(PCI_DEV(0, 0x2, 0), 0xc4, 0x00000002);
+       pci_write_config32(PCI_DEV(0, 0x2, 0), 0xe0, 0x00008000);
+       pci_write_config32(PCI_DEV(0, 0x2, 0), 0xf0, 0x00000005);
+       pci_write_config16(PCI_DEV(0, 0x2, 0), 0xf7, 0x80);
+       pci_write_config16(PCI_DEV(0, 0x2, 0), 0x4, 0x7);
+
+#if RFID_TEST
+       sch_SMbase_init();
+       selectcard();
+#endif
+}
index 1f2c5edb0a087097baf8f0d40b8c0c6d7aaf955c..409eb5ec3f232ffe3089c98a8a05f0aeaa76cf8d 100644 (file)
@@ -8,3 +8,4 @@ source src/northbridge/intel/i82810/Kconfig
 source src/northbridge/intel/i82830/Kconfig
 source src/northbridge/intel/i855/Kconfig
 source src/northbridge/intel/i945/Kconfig
+source src/northbridge/intel/sch/Kconfig
index 8042bf04b65d85c60630bf1ddda329144fafc171..266f6f8ad6ce326181bb3bae00bf6c58198664d3 100644 (file)
@@ -9,3 +9,4 @@ subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I82830) += i82830
 subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I855) += i855
 subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I945GC) += i945
 subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I945GM) += i945
+subdirs-$(CONFIG_NORTHBRIDGE_INTEL_SCH) += sch
diff --git a/src/northbridge/intel/sch/Kconfig b/src/northbridge/intel/sch/Kconfig
new file mode 100644 (file)
index 0000000..3c9115e
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2007-2009 coresystems GmbH
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+#
+
+config NORTHBRIDGE_INTEL_SCH
+       bool
+       select HAVE_HIGH_TABLES
+
+if NORTHBRIDGE_INTEL_SCH
+
+config FALLBACK_VGA_BIOS_ID
+       string
+       default "8086,8108"
+endif
diff --git a/src/northbridge/intel/sch/Makefile.inc b/src/northbridge/intel/sch/Makefile.inc
new file mode 100644 (file)
index 0000000..ecd2a27
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2007-2009 coresystems GmbH
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+#
+
+driver-y += northbridge.c
+driver-y += gma.c
+driver-y += port_access.c
+ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += acpi.c
diff --git a/src/northbridge/intel/sch/acpi.c b/src/northbridge/intel/sch/acpi.c
new file mode 100644 (file)
index 0000000..dbdaf2f
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <types.h>
+#include <string.h>
+#include <console/console.h>
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+unsigned long acpi_fill_mcfg(unsigned long current)
+{
+       device_t dev;
+       u32 pciexbar = 0;
+       u32 pciexbar_reg;
+       int max_buses;
+
+       dev = dev_find_device(0x8086, 0x27a0, 0);
+       if (!dev)
+               return current;
+
+       pciexbar_reg=pci_read_config32(dev, 0x48);
+
+       // MMCFG not supported or not enabled.
+       if (!(pciexbar_reg & (1 << 0)))
+               return current;
+
+       switch ((pciexbar_reg >> 1) & 3) {
+       case 0: // 256MB
+               pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28));
+               max_buses = 256;
+               break;
+       case 1: // 128M
+               pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27));
+               max_buses = 128;
+               break;
+       case 2: // 64M
+               pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27)|(1 << 26));
+               max_buses = 64;
+               break;
+       default: // RSVD
+               return current;
+       }
+
+       if (!pciexbar)
+               return current;
+#if CONFIG_GENERATE_ACPI_TABLES
+       current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current,
+                       pciexbar, 0x0, 0x0, max_buses - 1);
+#endif
+       return current;
+}
+
+
diff --git a/src/northbridge/intel/sch/acpi/hostbridge.asl b/src/northbridge/intel/sch/acpi/hostbridge.asl
new file mode 100644 (file)
index 0000000..a029ef5
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+
+Name(_HID,EISAID("PNP0A08"))   // PCIe
+Name(_CID,EISAID("PNP0A03"))   // PCI
+
+Device (MCHC)
+{
+       Name(_ADR, 0x00000000)  // 0:0.0
+
+       OperationRegion(MCHP, PCI_Config, 0x00, 0x100)
+       Field (MCHP, DWordAcc, NoLock, Preserve)
+       {
+               Offset (0x40),  // EPBAR
+               EPEN,    1,     // Enable
+               ,       11,     //
+               EPBR,   20,     // EPBAR
+
+               Offset (0x44),  // MCHBAR
+               MHEN,    1,     // Enable
+               ,       13,     //
+               MHBR,   18,     // MCHBAR
+
+               Offset (0x48),  // PCIe BAR
+               PXEN,    1,     // Enable
+               PXSZ,    2,     // BAR size
+               ,       23,     //
+               PXBR,    6,     // PCIe BAR
+
+               Offset (0x4c),  // DMIBAR
+               DMEN,    1,     // Enable
+               ,       11,     //
+               DMBR,   20,     // DMIBAR
+
+               // ...
+
+               Offset (0x90),  // PAM0
+               ,        4,
+               PM0H,    2,
+               ,        2,
+               Offset (0x91),  // PAM1
+               PM1L,    2,
+               ,        2,
+               PM1H,    2,
+               ,        2,
+               Offset (0x92),  // PAM2
+               PM2L,    2,
+               ,        2,
+               PM2H,    2,
+               ,        2,
+               Offset (0x93),  // PAM3
+               PM3L,    2,
+               ,        2,
+               PM3H,    2,
+               ,        2,
+               Offset (0x94),  // PAM4
+               PM4L,    2,
+               ,        2,
+               PM4H,    2,
+               ,        2,
+               Offset (0x95),  // PAM5
+               PM5L,    2,
+               ,        2,
+               PM5H,    2,
+               ,        2,
+               Offset (0x96),  // PAM6
+               PM6L,    2,
+               ,        2,
+               PM6H,    2,
+               ,        2,
+
+               Offset (0x9c),  // Top of Low Used Memory
+               ,        3,
+               TLUD,    5,
+
+               Offset (0xa0),  // Top of Used Memory
+               TOM,    16,
+       }
+
+}
+
+
+// Current Resource Settings
+
+Method (_CRS, 0, Serialized)
+{
+       Name (MCRS, ResourceTemplate()
+       {
+               // Bus Numbers
+               WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+                               0x0000, 0x0000, 0x00ff, 0x0000, 0x0100,,, PB00)
+
+               // IO Region 0
+               DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+                               0x0000, 0x0000, 0x0cf7, 0x0000, 0x0cf8,,, PI00)
+
+               // PCI Config Space
+               Io (Decode16, 0x0cf8, 0x0cf8, 0x0001, 0x0008)
+
+               // IO Region 1
+               DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+                               0x0000, 0x0d00, 0xffff, 0x0000, 0xf300,,, PI01)
+
+               // VGA memory (0xa0000-0xbffff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000a0000, 0x000bffff, 0x00000000,
+                               0x00020000,,, ASEG)
+
+               // OPROM reserved (0xc0000-0xc3fff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000c0000, 0x000c3fff, 0x00000000,
+                               0x00004000,,, OPR0)
+
+               // OPROM reserved (0xc4000-0xc7fff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000c4000, 0x000c7fff, 0x00000000,
+                               0x00004000,,, OPR1)
+
+               // OPROM reserved (0xc8000-0xcbfff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000c8000, 0x000cbfff, 0x00000000,
+                               0x00004000,,, OPR2)
+
+               // OPROM reserved (0xcc000-0xcffff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000cc000, 0x000cffff, 0x00000000,
+                               0x00004000,,, OPR3)
+
+               // OPROM reserved (0xd0000-0xd3fff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000d0000, 0x000d3fff, 0x00000000,
+                               0x00004000,,, OPR4)
+
+               // OPROM reserved (0xd4000-0xd7fff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000d4000, 0x000d7fff, 0x00000000,
+                               0x00004000,,, OPR5)
+
+               // OPROM reserved (0xd8000-0xdbfff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000d8000, 0x000dbfff, 0x00000000,
+                               0x00004000,,, OPR6)
+
+               // OPROM reserved (0xdc000-0xdffff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000dc000, 0x000dffff, 0x00000000,
+                               0x00004000,,, OPR7)
+
+               // BIOS Extension (0xe0000-0xe3fff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000e0000, 0x000e3fff, 0x00000000,
+                               0x00004000,,, ESG0)
+
+               // BIOS Extension (0xe4000-0xe7fff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000e4000, 0x000e7fff, 0x00000000,
+                               0x00004000,,, ESG1)
+
+               // BIOS Extension (0xe8000-0xebfff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000e8000, 0x000ebfff, 0x00000000,
+                               0x00004000,,, ESG2)
+
+               // BIOS Extension (0xec000-0xeffff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000ec000, 0x000effff, 0x00000000,
+                               0x00004000,,, ESG3)
+
+               // System BIOS (0xf0000-0xfffff)
+               DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                               Cacheable, ReadWrite,
+                               0x00000000, 0x000f0000, 0x000fffff, 0x00000000,
+                               0x00010000,,, FSEG)
+
+                // PCI Memory Region (Top of memory-0xfebfffff)
+                DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                                Cacheable, ReadWrite,
+                                0x00000000, 0x00000000, 0xfebfffff, 0x00000000,
+                                0x00000000,,, PM01)
+
+                // TPM Area (0xfed40000-0xfed44fff)
+                DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                                Cacheable, ReadWrite,
+                                0x00000000, 0xfed40000, 0xfed44fff, 0x00000000,
+                                0x00000000,,, TPMR)
+       })
+
+       // Find PCI resource area in MCRS
+       CreateDwordField(MCRS, PM01._MIN, PMIN)
+       CreateDwordField(MCRS, PM01._MAX, PMAX)
+       CreateDwordField(MCRS, PM01._LEN, PLEN)
+
+       // Fix up PCI memory region:
+       // Enter actual TOLUD. The TOLUD register contains bits 27-31 of
+       // the top of memory address.
+       ShiftLeft (^MCHC.TLUD, 27, PMIN)
+       Add(Subtract(PMAX, PMIN), 1, PLEN)
+
+       Return (MCRS)
+}
+
+/* IRQ assignment is mainboard specific. Get it from mainboard ACPI code */
+#include "acpi/northbridge_pci_irqs.asl"
+
+
diff --git a/src/northbridge/intel/sch/acpi/igd.asl b/src/northbridge/intel/sch/acpi/igd.asl
new file mode 100644 (file)
index 0000000..a6804ad
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Device (GFX0)
+{
+       Name (_ADR, 0x00020000)
+
+       /* Display Output Switching */
+       Method (_DOS, 1)
+       {
+               /* Windows 2000 and Windows XP call _DOS to enable/disable
+                * Display Output Switching during init and while a switch
+                * is already active
+                */
+               Store (And(Arg0, 7), DSEN)
+       }
+
+       /* We try to support as many i945 systems as possible,
+        * so keep the number of DIDs flexible.
+        */
+       Method (_DOD, 0)
+       {
+               If (LEqual(NDID, 1)) {
+                       Name(DOD1, Package() {
+                               0xffffffff
+                       })
+                       Store (Or(0x00010000, DID1), Index(DOD1, 0))
+                       Return(DOD1)
+               }
+
+               If (LEqual(NDID, 2)) {
+                       Name(DOD2, Package() {
+                               0xffffffff,
+                               0xffffffff
+                       })
+                       Store (Or(0x00010000, DID2), Index(DOD2, 0))
+                       Store (Or(0x00010000, DID2), Index(DOD2, 1))
+                       Return(DOD2)
+               }
+
+               If (LEqual(NDID, 3)) {
+                       Name(DOD3, Package() {
+                               0xffffffff,
+                               0xffffffff,
+                               0xffffffff
+                       })
+                       Store (Or(0x00010000, DID3), Index(DOD3, 0))
+                       Store (Or(0x00010000, DID3), Index(DOD3, 1))
+                       Store (Or(0x00010000, DID3), Index(DOD3, 2))
+                       Return(DOD3)
+               }
+
+               If (LEqual(NDID, 4)) {
+                       Name(DOD4, Package() {
+                               0xffffffff,
+                               0xffffffff,
+                               0xffffffff,
+                               0xffffffff
+                       })
+                       Store (Or(0x00010000, DID4), Index(DOD4, 0))
+                       Store (Or(0x00010000, DID4), Index(DOD4, 1))
+                       Store (Or(0x00010000, DID4), Index(DOD4, 2))
+                       Store (Or(0x00010000, DID4), Index(DOD4, 3))
+                       Return(DOD4)
+               }
+
+               If (LGreater(NDID, 4)) {
+                       Name(DOD5, Package() {
+                               0xffffffff,
+                               0xffffffff,
+                               0xffffffff,
+                               0xffffffff,
+                               0xffffffff
+                       })
+                       Store (Or(0x00010000, DID5), Index(DOD5, 0))
+                       Store (Or(0x00010000, DID5), Index(DOD5, 1))
+                       Store (Or(0x00010000, DID5), Index(DOD5, 2))
+                       Store (Or(0x00010000, DID5), Index(DOD5, 3))
+                       Store (Or(0x00010000, DID5), Index(DOD5, 4))
+                       Return(DOD5)
+               }
+
+               /* Some error happened, but we have to return something */
+               Return (Package() {0x00000400})
+       }
+
+       Device(DD01)
+       {
+               /* Device Unique ID */
+               Method(_ADR, 0, Serialized)
+               {
+                       If(LEqual(DID1, 0)) {
+                               Return (1)
+                       } Else {
+                               Return (And(0xffff, DID1))
+                       }
+               }
+
+               /* Device Current Status */
+               Method(_DCS, 0)
+               {
+                       TRAP(1)
+                       If (And(CSTE, 1)) {
+                               Return (0x1f)
+                       }
+                       Return(0x1d)
+               }
+
+               /* Query Device Graphics State */
+               Method(_DGS, 0)
+               {
+                       If (And(NSTE, 1)) {
+                               Return(1)
+                       }
+                       Return(0)
+               }
+
+               /* Device Set State */
+               Method(_DSS, 1)
+               {
+                       /* If Parameter Arg0 is (1 << 31) | (1 << 30), the
+                        * display switch was completed
+                        */
+                       If (LEqual(And(Arg0, 0xc0000000), 0xc0000000)) {
+                               Store (NSTE, CSTE)
+                       }
+               }
+       }
+
+       Device(DD02)
+       {
+               /* Device Unique ID */
+               Method(_ADR, 0, Serialized)
+               {
+                       If(LEqual(DID2, 0)) {
+                               Return (2)
+                       } Else {
+                               Return (And(0xffff, DID2))
+                       }
+               }
+
+               /* Device Current Status */
+               Method(_DCS, 0)
+               {
+                       TRAP(1)
+                       If (And(CSTE, 2)) {
+                               Return (0x1f)
+                       }
+                       Return(0x1d)
+               }
+
+               /* Query Device Graphics State */
+               Method(_DGS, 0)
+               {
+                       If (And(NSTE, 2)) {
+                               Return(1)
+                       }
+                       Return(0)
+               }
+
+               /* Device Set State */
+               Method(_DSS, 1)
+               {
+                       /* If Parameter Arg0 is (1 << 31) | (1 << 30), the
+                        * display switch was completed
+                        */
+                       If (LEqual(And(Arg0, 0xc0000000), 0xc0000000)) {
+                               Store (NSTE, CSTE)
+                       }
+               }
+       }
+
+
+       Device(DD03)
+       {
+               /* Device Unique ID */
+               Method(_ADR, 0, Serialized)
+               {
+                       If(LEqual(DID3, 0)) {
+                               Return (3)
+                       } Else {
+                               Return (And(0xffff, DID3))
+                       }
+               }
+
+               /* Device Current Status */
+               Method(_DCS, 0)
+               {
+                       TRAP(1)
+                       If (And(CSTE, 4)) {
+                               Return (0x1f)
+                       }
+                       Return(0x1d)
+               }
+
+               /* Query Device Graphics State */
+               Method(_DGS, 0)
+               {
+                       If (And(NSTE, 4)) {
+                               Return(1)
+                       }
+                       Return(0)
+               }
+
+               /* Device Set State */
+               Method(_DSS, 1)
+               {
+                       /* If Parameter Arg0 is (1 << 31) | (1 << 30), the
+                        * display switch was completed
+                        */
+                       If (LEqual(And(Arg0, 0xc0000000), 0xc0000000)) {
+                               Store (NSTE, CSTE)
+                       }
+               }
+       }
+
+
+       Device(DD04)
+       {
+               /* Device Unique ID */
+               Method(_ADR, 0, Serialized)
+               {
+                       If(LEqual(DID4, 0)) {
+                               Return (4)
+                       } Else {
+                               Return (And(0xffff, DID4))
+                       }
+               }
+
+               /* Device Current Status */
+               Method(_DCS, 0)
+               {
+                       TRAP(1)
+                       If (And(CSTE, 8)) {
+                               Return (0x1f)
+                       }
+                       Return(0x1d)
+               }
+
+               /* Query Device Graphics State */
+               Method(_DGS, 0)
+               {
+                       If (And(NSTE, 4)) {
+                               Return(1)
+                       }
+                       Return(0)
+               }
+
+               /* Device Set State */
+               Method(_DSS, 1)
+               {
+                       /* If Parameter Arg0 is (1 << 31) | (1 << 30), the
+                        * display switch was completed
+                        */
+                       If (LEqual(And(Arg0, 0xc0000000), 0xc0000000)) {
+                               Store (NSTE, CSTE)
+                       }
+               }
+       }
+
+
+       Device(DD05)
+       {
+               /* Device Unique ID */
+               Method(_ADR, 0, Serialized)
+               {
+                       If(LEqual(DID5, 0)) {
+                               Return (5)
+                       } Else {
+                               Return (And(0xffff, DID5))
+                       }
+               }
+
+               /* Device Current Status */
+               Method(_DCS, 0)
+               {
+                       TRAP(1)
+                       If (And(CSTE, 16)) {
+                               Return (0x1f)
+                       }
+                       Return(0x1d)
+               }
+
+               /* Query Device Graphics State */
+               Method(_DGS, 0)
+               {
+                       If (And(NSTE, 4)) {
+                               Return(1)
+                       }
+                       Return(0)
+               }
+
+               /* Device Set State */
+               Method(_DSS, 1)
+               {
+                       /* If Parameter Arg0 is (1 << 31) | (1 << 30), the
+                        * display switch was completed
+                        */
+                       If (LEqual(And(Arg0, 0xc0000000), 0xc0000000)) {
+                               Store (NSTE, CSTE)
+                       }
+               }
+       }
+
+}
+
diff --git a/src/northbridge/intel/sch/acpi/peg.asl b/src/northbridge/intel/sch/acpi/peg.asl
new file mode 100644 (file)
index 0000000..bc7f8f7
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Device (PEGP)
+{
+       Name (_ADR, 0x00010000)
+
+       // PCI Interrupt Routing.
+       Method (_PRT)
+       {
+               If (PICM) {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, 0, 16 },
+                               Package() { 0x0000ffff, 1, 0, 17 },
+                               Package() { 0x0000ffff, 2, 0, 18 },
+                               Package() { 0x0000ffff, 3, 0, 19 }
+                       })
+               } Else {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
+                               Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKB, 0 },
+                               Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKC, 0 },
+                               Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }
+                       })
+               }
+
+       }
+}
+
diff --git a/src/northbridge/intel/sch/acpi/sch.asl b/src/northbridge/intel/sch/acpi/sch.asl
new file mode 100644 (file)
index 0000000..0a11851
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include "../../../northbridge/intel/sch/acpi/hostbridge.asl"
+
+/* PCI Device Resource Consumption */
+Device (PDRC)
+{
+       Name (_HID, EISAID("PNP0C02"))
+       Name (_UID, 1)
+
+       // This does not seem to work correctly yet - set values statically for
+       // now.
+
+       //Name (PDRS, ResourceTemplate() {
+       //      Memory32Fixed(ReadWrite, 0x00000000, 0x00004000, RCRB) // RCBA
+       //      Memory32Fixed(ReadWrite, 0x00000000, 0x00004000, MCHB) // MCHBAR
+       //      Memory32Fixed(ReadWrite, 0x00000000, 0x00001000, DMIB) // DMIBAR
+       //      Memory32Fixed(ReadWrite, 0x00000000, 0x00001000, EGPB) // EPBAR
+       //      Memory32Fixed(ReadWrite, 0x00000000, 0x00000000, PCIE) // PCIE BAR
+       //      Memory32Fixed(ReadWrite, 0xfed20000, 0x00070000, ICHB) // Misc ICH
+       //})
+
+       Name (PDRS, ResourceTemplate() {
+               Memory32Fixed(ReadWrite, 0xfed1c000, 0x00004000) // RCBA
+               Memory32Fixed(ReadWrite, 0xfed14000, 0x00004000) // MCHBAR
+               Memory32Fixed(ReadWrite, 0xfed18000, 0x00001000) // DMIBAR
+               Memory32Fixed(ReadWrite, 0xfed19000, 0x00001000) // EPBAR
+               Memory32Fixed(ReadWrite, 0xf0000000, 0x04000000) // PCIE BAR
+               Memory32Fixed(ReadWrite, 0xfed20000, 0x00020000) // Misc ICH
+               Memory32Fixed(ReadWrite, 0xfed40000, 0x00005000) // Misc ICH
+               Memory32Fixed(ReadWrite, 0xfed45000, 0x0004b000) // Misc ICH
+       })
+
+       // Current Resource Settings
+       Method (_CRS, 0, Serialized)
+       {
+               //CreateDwordField(PDRS, ^RCRB._BAS, RBR0)
+               //ShiftLeft(\_SB.PCI0.LPCB.RCBA, 14, RBR0)
+
+               //CreateDwordField(PDRS, ^MCHB._BAS, MBR0)
+               //ShiftLeft(\_SB.PCI0.MCHC.MHBR, 14, MBR0)
+
+               //CreateDwordField(PDRS, ^DMIB._BAS, DBR0)
+               //ShiftLeft(\_SB.PCI0.MCHC.DMBR, 12, DBR0)
+
+               //CreateDwordField(PDRS, ^EGPB._BAS, EBR0)
+               //ShiftLeft(\_SB.PCI0.MCHC.EPBR, 12, EBR0)
+
+               //CreateDwordField(PDRS, ^PCIE._BAS, PBR0)
+               //ShiftLeft(\_SB.PCI0.MCHC.PXBR, 26, PBR0)
+
+               //CreateDwordField(PDRS, ^PCIE._LEN, PSZ0)
+               //ShiftLeft(0x10000000, \_SB.PCI0.MCHC.PXSZ, PSZ0)
+
+               Return(PDRS)
+       }
+}
+
+// PCIe graphics port 0:1.0
+#include "../../../northbridge/intel/sch/acpi/peg.asl"
+
+// Integrated graphics 0:2.0
+#include "../../../northbridge/intel/sch/acpi/igd.asl"
+
+Scope (\)
+{
+       // backlight control, display switching, lid
+       #include "acpi/video.asl"
+}
diff --git a/src/northbridge/intel/sch/chip.h b/src/northbridge/intel/sch/chip.h
new file mode 100644 (file)
index 0000000..52c2b16
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2010 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+struct northbridge_intel_sch_config {
+};
+
+extern struct chip_operations northbridge_intel_sch_ops;
diff --git a/src/northbridge/intel/sch/early_init.c b/src/northbridge/intel/sch/early_init.c
new file mode 100644 (file)
index 0000000..6ec0169
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include "sch.h"
+#include "southbridge/intel/sch/sch.h"
+
+#if 0
+static void sch_set_mtrr (void)
+{
+       msr_t msr;
+       printk(BIOS_DEBUG, "1");
+       msr.hi = 0x06060606;
+       msr.lo = 0x06060606;
+       wrmsr (0x250, msr);
+       printk(BIOS_DEBUG, "2");
+       msr.hi = 0x06060606;
+       msr.lo = 0x06060606;
+       wrmsr (0x258, msr);
+       printk(BIOS_DEBUG, "3");
+       msr.hi = 0x0;
+       msr.lo = 0x0;
+       wrmsr (0x259, msr);
+       printk(BIOS_DEBUG, "4");
+       msr.hi = 0x04040404;
+       msr.lo = 0x04040404;
+       wrmsr (0x268, msr);
+       printk(BIOS_DEBUG, "5");
+       msr.hi = 0x04040404;
+       msr.lo = 0x04040404;
+       wrmsr (0x269, msr);
+       printk(BIOS_DEBUG, "6");
+       msr.hi = 0x04040404;
+       msr.lo = 0x04040404;
+       wrmsr (0x26A, msr);
+       printk(BIOS_DEBUG, "7");
+       msr.hi = 0x04040404;
+       msr.lo = 0x04040404;
+       wrmsr (0x26B, msr);
+       printk(BIOS_DEBUG, "8");
+       msr.hi = 0x04040404;
+       msr.lo = 0x04040404;
+       wrmsr (0x26C, msr);
+       printk(BIOS_DEBUG, "9");
+       msr.hi = 0x05050505;
+       msr.lo = 0x05050505;
+       wrmsr (0x26D, msr);
+       printk(BIOS_DEBUG, "10");
+       msr.hi = 0x05050505;
+       msr.lo = 0x05050505;
+       wrmsr (0x26E, msr);
+       printk(BIOS_DEBUG, "11");
+       msr.hi = 0x05050505;
+       msr.lo = 0x05050505;
+       wrmsr (0x26f, msr);
+       printk(BIOS_DEBUG, "12");
+       msr.hi = 0x0;
+       msr.lo = 0x6;
+       wrmsr (0x202, msr);
+       printk(BIOS_DEBUG, "13");
+       msr.hi = 0x0;
+       msr.lo = 0xC0000800;
+       wrmsr (0x203, msr);
+       printk(BIOS_DEBUG, "14");
+       msr.hi = 0x0;
+       msr.lo = 0x3FAF0000;
+       wrmsr (0x204, msr);
+       printk(BIOS_DEBUG, "15");
+       msr.hi = 0x0;
+       msr.lo = 0xFFFF0800;
+       wrmsr (0x205, msr);
+       printk(BIOS_DEBUG, "16");
+       msr.hi = 0x0;
+       msr.lo = 0x3FB00000;
+       wrmsr (0x206, msr);
+       printk(BIOS_DEBUG, "16");
+       msr.hi = 0x0;
+       msr.lo = 0xFFF00800;
+       wrmsr (0x207, msr);
+       printk(BIOS_DEBUG, "17");
+       msr.hi = 0x0;
+       msr.lo = 0x3FC00000;
+       wrmsr (0x208, msr);
+       printk(BIOS_DEBUG, "18");
+       msr.hi = 0x0;
+       msr.lo = 0xFFC00800;
+       wrmsr (0x209, msr);
+       printk(BIOS_DEBUG, "19");
+       msr.hi = 0x0;
+       msr.lo = 0x0;
+       wrmsr (0x20A, msr);
+       printk(BIOS_DEBUG, "20");
+       msr.hi = 0x0;
+       msr.lo = 0x0;
+       wrmsr (0x20B, msr);
+       printk(BIOS_DEBUG, "21");
+       msr.hi = 0x0;
+       msr.lo = 0x0;
+       wrmsr (0x20a, msr);
+       printk(BIOS_DEBUG, "22");
+       msr.hi = 0x0;
+       msr.lo = 0x0;
+       wrmsr (0x20B, msr);
+       printk(BIOS_DEBUG, "23");
+       msr.hi = 0x0;
+       msr.lo = 0x0;
+       wrmsr (0x20c, msr);
+       msr.hi = 0x0;
+       msr.lo = 0x0;
+       wrmsr (0x20d, msr);
+       msr.hi = 0x0;
+       msr.lo = 0x0;
+       wrmsr (0x20E, msr);
+       msr.hi = 0x0;
+       msr.lo = 0x0;
+       wrmsr (0x20F, msr);
+       msr.hi = 0x0;
+       msr.lo = 0XC00;
+       wrmsr (0x2FF, msr);
+       printk(BIOS_DEBUG, "end");
+}
+#endif
+
+static void sch_detect_chipset(void)
+{
+       u16 reg16;
+       u8 reg8;
+       printk(BIOS_INFO, "\n");
+       reg16 = pci_read_config16(PCI_DEV(0, 0x00, 0), 0x2);
+       switch (reg16)
+       {
+         case 0x8101:
+                 printk(BIOS_INFO, "UL11L/US15L");
+                 break;
+         case 0x8100:
+                 printk(BIOS_INFO, "US15W");
+                 break;
+         default:
+                 printk(BIOS_INFO, "Unknown (%02x)", reg16);   /* Others reserved. */
+       }
+       printk(BIOS_INFO, " Chipset\n");
+
+
+       reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0x8);
+       switch (reg8)
+       {
+         case 3:
+                 printk(BIOS_INFO, "Qual. Sample ES1, Stepping B1");
+                 break;
+    case 4:
+                 printk(BIOS_INFO, "Qual. Sample ES2, Stepping C0");
+                 break;
+         case 5:
+                 printk(BIOS_INFO, "Qual. Sample ES2-Prime, Stepping D0");
+                 break;
+    case 6:
+                 printk(BIOS_INFO, "Qual. Sample QS, Stepping D1");
+                 break;
+
+         default:
+                 printk(BIOS_INFO, "Unknown (%02x)", reg8);    /* Others reserved. */
+       }
+
+}
+
+static void sch_setup_non_standard_bars(void)
+{
+       printk(BIOS_DEBUG, "Setting up ACPI PM1 block ");
+       pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x48, (0x80000000 |DEFAULT_PMBASE)); /*Address 1000 size 16B*/
+       printk(BIOS_DEBUG, "Setting up ACPI P block ");
+       sch_port_access_write(4,0x70,4,0x80001010);/*Address 1010 size 16B*/
+       pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x40, 0x80001040); /*SM Bus Address 1040 size 64B*/
+       pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x44, 0x80001080); /*GPIO Address 1080 size 64B*/
+       pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x4C, 0x800010C0); /*GPE0 Address 10C0 size 64B*/
+       sch_port_access_write(2,4,4,0x3F703F76); /* FIXME: SMM Control */
+       pci_write_config32(PCI_DEV(0, 0x02, 0), 0x5C, 0x3F800000); /*Base of Stolen memory Address 1080 size 64B*/
+
+       sch_port_access_write(0,0,4, DEFAULT_PCIEXBAR | 1); // pre-b1
+       sch_port_access_write(2,9,4, DEFAULT_PCIEXBAR | 1); // b1+
+
+       /*RCBA*/
+       pci_write_config32(PCI_DEV(0, 0x1f, 0), 0xF0, (DEFAULT_RCBABASE| 1 ));
+       printk(BIOS_DEBUG, " done.\n");
+
+}
+
+static void sch_early_initialization(void)
+{
+       /* Print some chipset specific information */
+       sch_detect_chipset();
+
+       /* Setup all non standard BARs */
+       sch_setup_non_standard_bars();
+}
diff --git a/src/northbridge/intel/sch/gma.c b/src/northbridge/intel/sch/gma.c
new file mode 100644 (file)
index 0000000..28b4624
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+static void gma_func0_init(struct device *dev)
+{
+       u32 reg32;
+
+       /* IGD needs to be Bus Master */
+       reg32 = pci_read_config32(dev, PCI_COMMAND);
+       pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER);
+
+       pci_dev_init(dev);
+}
+
+static void gma_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
+}
+
+static struct pci_operations gma_pci_ops = {
+       .set_subsystem    = gma_set_subsystem,
+};
+
+static struct device_operations gma_func0_ops = {
+       .read_resources         = pci_dev_read_resources,
+       .set_resources          = pci_dev_set_resources,
+       .enable_resources       = pci_dev_enable_resources,
+       .init                   = gma_func0_init,
+       .scan_bus               = 0,
+       .enable                 = 0,
+       .ops_pci                = &gma_pci_ops,
+};
+
+
+static const struct pci_driver sch_gma_func0_driver __pci_driver = {
+       .ops    = &gma_func0_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x8108,
+};
+
diff --git a/src/northbridge/intel/sch/northbridge.c b/src/northbridge/intel/sch/northbridge.c
new file mode 100644 (file)
index 0000000..bf2870a
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <arch/io.h>
+#include <stdint.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/hypertransport.h>
+#include <stdlib.h>
+#include <string.h>
+#include <bitops.h>
+#include <cpu/cpu.h>
+#include <boot/tables.h>
+#include "chip.h"
+#include "sch.h"
+
+static int get_pcie_bar(u32 *base, u32 *len)
+{
+       device_t dev;
+       u32 pciexbar_reg;
+
+       dev = dev_find_slot(0, PCI_DEVFN(0, 0));
+       if (!dev)
+               return 0;
+
+       // FIXME: determine at runtime
+#ifdef POULSBO_PRE_B1
+       pciexbar_reg = sch_port_access_read(0,0,4);
+#else
+       pciexbar_reg = sch_port_access_read(2,9,4);
+#endif
+
+       if (!(pciexbar_reg & (1 << 0)))
+               return 0;
+
+       switch ((pciexbar_reg >> 1) & 3) {
+       case 0: // 256MB
+               *base = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28));
+               *len = 256 * 1024 * 1024;
+               return 1;
+       case 1: // 128M
+               *base = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27));
+               *len = 128 * 1024 * 1024;
+               return 1;
+       case 2: // 64M
+               *base = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27)|(1 << 26));
+               *len = 64 * 1024 * 1024;
+               return 1;
+       }
+
+       return 0;
+}
+
+/* IDG memory */
+uint64_t uma_memory_base=0, uma_memory_size=0;
+
+static void add_fixed_resources(struct device *dev, int index)
+{
+       struct resource *resource;
+       u32 pcie_config_base, pcie_config_size;
+
+       printk(BIOS_DEBUG, "Adding UMA memory area\n");
+       resource = new_resource(dev, index);
+       resource->base = (resource_t) uma_memory_base;
+       resource->size = (resource_t) uma_memory_size;
+       resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
+           IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+
+       if (get_pcie_bar(&pcie_config_base, &pcie_config_size)) {
+               printk(BIOS_DEBUG, "Adding PCIe config bar\n");
+               resource = new_resource(dev, index+1);
+               resource->base = (resource_t) pcie_config_base;
+               resource->size = (resource_t) pcie_config_size;
+               resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
+                   IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+       }
+
+       printk(BIOS_DEBUG, "Adding CMC shadow area\n");
+       resource = new_resource(dev, index+1);
+       resource->base = (resource_t) CMC_SHADOW;
+       resource->size = (resource_t) (64 * 1024);
+       resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
+           IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+}
+
+
+#if CONFIG_WRITE_HIGH_TABLES==1
+#include <cbmem.h>
+#endif
+
+static void pci_domain_set_resources(device_t dev)
+{
+       uint32_t pci_tolm;
+       uint8_t  reg8;
+       uint16_t reg16;
+       unsigned long long tomk, tolud;
+       /* Can we find out how much memory we can use at most
+        * this way?
+        */
+       pci_tolm = find_pci_tolm(dev->link_list);
+       printk(BIOS_DEBUG, "pci_tolm: 0x%x\n", pci_tolm);
+       printk(BIOS_SPEW, "Base of stolen memory: 0x%08x\n",
+                   pci_read_config32(dev_find_slot(0, PCI_DEVFN(2, 0)), 0x5c));
+
+       tolud = pci_read_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), 0x9c);
+        printk(BIOS_SPEW, "Top of Low Used DRAM: 0x%08llx\n", tolud << 24);
+
+        tomk = tolud << 14;
+
+       /* Note: subtract IGD device and TSEG */
+       reg8 = pci_read_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), 0x9e);
+       if (reg8 & 1)
+        {
+               int tseg_size = 0;
+               printk(BIOS_DEBUG, "TSEG decoded, subtracting ");
+               reg8 >>= 1;
+               reg8 &= 3;
+               switch (reg8) {
+               case 0:
+                       tseg_size = 1024;
+                       break;  /* TSEG = 1M */
+               case 1:
+                       tseg_size = 2048;
+                       break;  /* TSEG = 2M */
+               case 2:
+                       tseg_size = 8192;
+                       break;  /* TSEG = 8M */
+               }
+
+               printk(BIOS_DEBUG, "%dM\n", tseg_size >> 10);
+               tomk -= tseg_size;
+       }
+
+       reg16 = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0, 0)), GGC);
+       if (!(reg16 & 2))
+       {
+               int uma_size = 0;
+               printk(BIOS_DEBUG, "IGD decoded, subtracting ");
+               reg16 >>= 4;
+               reg16 &= 7;
+               switch (reg16)
+               {
+                       case 1:
+                               uma_size = 1024;
+                               break;
+                       case 2:
+                               uma_size = 4096;
+                               break;
+                       case 3:
+                               uma_size = 8192;
+                               break;
+               }
+               printk(BIOS_DEBUG, "%dM UMA\n", uma_size >> 10);
+               tomk -= uma_size;
+
+               /* For reserving UMA memory in the memory map */
+               uma_memory_base = tomk * 1024ULL;
+               uma_memory_size = uma_size * 1024ULL;
+       }
+
+       /* The following needs to be 2 lines, otherwise the second
+        * number is always 0
+        */
+       printk(BIOS_INFO, "Available memory: %dK", (uint32_t)tomk);
+       printk(BIOS_INFO, " (%dM)\n", (uint32_t)(tomk >> 10));
+
+       /* Report the memory regions */
+       ram_resource(dev, 3, 0, 640);
+       ram_resource(dev, 4, 768, (tomk - 768));
+       if (tomk > 4 * 1024 * 1024) {
+               ram_resource(dev, 5, 4096 * 1024, tomk - 4 * 1024 * 1024);
+       }
+
+       add_fixed_resources(dev, 6);
+
+       assign_resources(dev->link_list);
+
+#if CONFIG_WRITE_HIGH_TABLES==1
+       /* Leave some space for ACPI, PIRQ and MP tables */
+       high_tables_base = (tomk * 1024) - HIGH_MEMORY_SIZE;
+       high_tables_size = HIGH_MEMORY_SIZE;
+#endif
+}
+
+       /* TODO We could determine how many PCIe busses we need in
+        * the bar. For now that number is hardcoded to a max of 64.
+        * See e7525/northbridge.c for an example.
+        */
+static struct device_operations pci_domain_ops = {
+       .read_resources   = pci_domain_read_resources,
+       .set_resources    = pci_domain_set_resources,
+       .enable_resources = NULL,
+       .init             = NULL,
+       .scan_bus         = pci_domain_scan_bus,
+#if CONFIG_MMCONF_SUPPORT_DEFAULT
+       .ops_pci_bus      = &pci_ops_mmconf,
+#else
+       .ops_pci_bus      = &pci_cf8_conf1,
+#endif
+};
+
+static void mc_read_resources(device_t dev)
+{
+       struct resource *resource;
+
+       pci_dev_read_resources(dev);
+
+       /* So, this is one of the big mysteries in the coreboot resource
+        * allocator. This resource should make sure that the address space
+        * of the PCIe memory mapped config space bar. But it does not.
+        */
+
+       /* We use 0xcf as an unused index for our PCIe bar so that we find it again */
+       resource = new_resource(dev, 0xcf);
+       resource->flags =
+           IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
+           IORESOURCE_ASSIGNED;
+       get_pcie_bar((u32*)&resource->base, (u32*)&resource->size);
+       printk(BIOS_DEBUG, "Adding PCIe enhanced config space BAR 0x%08lx-0x%08lx.\n",
+                    (unsigned long)(resource->base), (unsigned long)(resource->base + resource->size));
+}
+
+static void mc_set_resources(device_t dev)
+{
+       struct resource *resource;
+
+       /* Report the PCIe BAR */
+       resource = find_resource(dev, 0xcf);
+       if (resource) {
+               report_resource_stored(dev, resource, "<mmconfig>");
+       }
+
+       /* And call the normal set_resources */
+       pci_dev_set_resources(dev);
+}
+
+static void intel_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
+}
+
+#if CONFIG_HAVE_ACPI_RESUME
+extern u8 acpi_slp_type;
+
+static void northbridge_init(struct device *dev)
+{
+       switch (pci_read_config32(dev, SKPAD)) {
+       case 0xcafebabe:
+               printk(BIOS_DEBUG, "Normal boot.\n");
+               acpi_slp_type=0;
+               break;
+       case 0xcafed00d:
+               printk(BIOS_DEBUG, "S3 Resume.\n");
+               acpi_slp_type=3;
+               break;
+       default:
+               printk(BIOS_DEBUG, "Unknown boot method, assuming normal.\n");
+               acpi_slp_type=0;
+               break;
+       }
+}
+#endif
+
+static struct pci_operations intel_pci_ops = {
+       .set_subsystem    = intel_set_subsystem,
+};
+
+static struct device_operations mc_ops = {
+       .read_resources   = mc_read_resources,
+       .set_resources    = mc_set_resources,
+       .enable_resources = pci_dev_enable_resources,
+#if CONFIG_HAVE_ACPI_RESUME
+       .init             = northbridge_init,
+#endif
+       .scan_bus         = 0,
+       .ops_pci          = &intel_pci_ops,
+};
+
+static const struct pci_driver mc_driver __pci_driver = {
+       .ops    = &mc_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x8100,
+};
+
+static void cpu_bus_init(device_t dev)
+{
+       initialize_cpus(dev->link_list);
+}
+
+static void cpu_bus_noop(device_t dev)
+{
+}
+
+static struct device_operations cpu_bus_ops = {
+       .read_resources   = cpu_bus_noop,
+       .set_resources    = cpu_bus_noop,
+       .enable_resources = cpu_bus_noop,
+       .init             = cpu_bus_init,
+       .scan_bus         = 0,
+};
+
+static void enable_dev(device_t dev)
+{
+       /* Set the operations if it is a special bus type */
+       if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
+               dev->ops = &pci_domain_ops;
+       } else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
+               dev->ops = &cpu_bus_ops;
+       }
+}
+
+struct chip_operations northbridge_intel_sch_ops = {
+       CHIP_NAME("Intel SCH Northbridge")
+       .enable_dev = enable_dev,
+};
diff --git a/src/northbridge/intel/sch/nvs.h b/src/northbridge/intel/sch/nvs.h
new file mode 100644 (file)
index 0000000..3f01f2a
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+typedef struct {
+       u16     osys;
+       u8      smif;
+       u8      prm0;
+       u8      prm1;
+       u8      scif;
+       u8      prm2;
+       u8      prm3;
+       u8      lckf;
+       u8      prm4;
+       u8      prm5;
+       u32     p80d;
+       u8      lids;
+       u8      pwrs;
+       u8      dbgs;
+       u8      linxs;
+       u8      rsvd;
+       u8      actt;
+       u8      psvt;
+       u8      tc1v;
+       u8      tc2v;
+       u8      tspv;
+       u8      crtt;
+       u8      dtse;
+       u8      dts1;
+       u8      dts2;
+       u8      rsvd2;
+       u8      bnum;
+       u8      b0sc, b1sc, b2sc;
+       u8      b0ss, b1ss, b2ss;
+       u8      rsvd3[3];
+       u8      apic;
+       u8      mpen;
+       u8      bten;
+       u8      ppcm;
+       u8      pcp0;
+       u8      pcp1;
+       u8      rsvd4[4];
+       u8      natp;
+       u8      cmap;
+       u8      cmbp;
+       u8      lptp;
+       u8      fdcp;
+       u8      rfdv;
+       u8      hotk;
+       u8      rtcf;
+       u8      util;
+       u8      acin;
+       u8      igds;
+       u8      tlst;
+       u8      cadl;
+       u8      padl;
+       u16     cste;
+       u16     pste;
+       u16     nste;
+       u16     sste;
+       u8      ndid;
+       u32     did1;
+       u32     did2;
+       u32     did3;
+       u32     did4;
+       u32     did5;
+       u8      rsvd5[0xb];
+       u8      brtl;
+       u8      odds;
+       u8      alse;
+       u8      alaf;
+       u8      llow;
+       u8      lhih;
+       u8      rsvd6;
+       u8      emae;
+       u16     emap;
+       u16     emal;
+       u8      rsvd7;
+       u8      mefe;
+       u8      igps;
+       u8      rsvd8[2];
+       u8      tpmp;
+       u8      tpme;
+       u8      rsvd9[8];
+       u8      gtf0[7];
+       u8      gtf2[7];
+       u8      idem;
+       u8      idet;
+       u8      dock;
+} global_nvs_t;
+
diff --git a/src/northbridge/intel/sch/pcie_config.c b/src/northbridge/intel/sch/pcie_config.c
new file mode 100644 (file)
index 0000000..5cc46a7
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+static inline __attribute__ ((always_inline))
+u8 pcie_read_config8(device_t dev, unsigned int where)
+{
+       unsigned long addr;
+       addr = DEFAULT_PCIEXBAR | dev | where;
+       return read8(addr);
+}
+
+static inline __attribute__ ((always_inline))
+u16 pcie_read_config16(device_t dev, unsigned int where)
+{
+       unsigned long addr;
+       addr = DEFAULT_PCIEXBAR | dev | where;
+       return read16(addr);
+}
+
+static inline __attribute__ ((always_inline))
+u32 pcie_read_config32(device_t dev, unsigned int where)
+{
+       unsigned long addr;
+       addr = DEFAULT_PCIEXBAR | dev | where;
+       return read32(addr);
+}
+
+static inline __attribute__ ((always_inline))
+void pcie_write_config8(device_t dev, unsigned int where, u8 value)
+{
+       unsigned long addr;
+       addr = DEFAULT_PCIEXBAR | dev | where;
+       write8(addr, value);
+}
+
+static inline __attribute__ ((always_inline))
+void pcie_write_config16(device_t dev, unsigned int where, u16 value)
+{
+       unsigned long addr;
+       addr = DEFAULT_PCIEXBAR | dev | where;
+       write16(addr, value);
+}
+
+static inline __attribute__ ((always_inline))
+void pcie_write_config32(device_t dev, unsigned int where, u32 value)
+{
+       unsigned long addr;
+       addr = DEFAULT_PCIEXBAR | dev | where;
+       write32(addr, value);
+}
diff --git a/src/northbridge/intel/sch/port_access.c b/src/northbridge/intel/sch/port_access.c
new file mode 100644 (file)
index 0000000..73e03c8
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <device/pci_def.h>
+#include <device/pnp_def.h>
+#include <cpu/x86/lapic.h>
+#include "sch.h"
+
+/*
+ * Restricted Access Regions:
+ *
+ * MCR - Message Control Register
+ * 31        24              16                 8              4              0
+ * ----------------------------------------------------------------------------
+ * |          |               |    Target       |   Write      |              |
+ * | Opcode   |  Port         |    register     |   byte       |   Reserved   |
+ * |          |               |    Address      |   Enables    |              |
+ * ----------------------------------------------------------------------------
+ *
+ * MDR - Message Data Register
+ * 31                                                                         0
+ * ----------------------------------------------------------------------------
+ * |                                                                          |
+ * |                            Data                                          |
+ * |                                                                          |
+ * ----------------------------------------------------------------------------
+ *
+ */
+#define MSG_OPCODE_READ  0xD0000000
+#define MSG_OPCODE_WRITE 0xE0000000
+
+#define MCR 0xD0
+#define MDR 0xD4
+
+int sch_port_access_read(int port,int reg, int bytes)
+{
+       pci_write_config32(PCI_DEV(0, 0, 0), MCR, (MSG_OPCODE_READ |(port <<16) | (reg << 8) ));
+       return pci_read_config32(PCI_DEV(0, 0, 0), MDR);
+}
+
+void sch_port_access_write(int port,int reg,int bytes,long data)
+{
+       pci_write_config32(PCI_DEV(0, 0, 0), MDR,data);
+       pci_write_config32(PCI_DEV(0, 0, 0), MCR, (MSG_OPCODE_WRITE |(port <<16) | (reg << 8) ));
+       pci_read_config32(PCI_DEV(0, 0, 0), MDR);
+}
+
+void sch_port_access_write_ram_cmd(int cmd,int port,int reg,int data)
+{
+
+       pci_write_config32(PCI_DEV(0, 0, 0), MDR,data);
+       pci_write_config32(PCI_DEV(0, 0, 0), MCR, ((cmd << 24) |(port <<16) | (reg << 8)));
+       pci_read_config32(PCI_DEV(0, 0, 0), MDR);
+}
+
diff --git a/src/northbridge/intel/sch/raminit.c b/src/northbridge/intel/sch/raminit.c
new file mode 100644 (file)
index 0000000..d2e8af8
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <string.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/cache.h>
+#include <spd.h>
+#include "raminit.h"
+#include "sch.h"
+#define DEBUG_RAM_SETUP
+#define SOFTSTRSP(base, off) *((volatile u8 *)((base) + (off)))
+
+/* Debugging macros. */
+#if defined(DEBUG_RAM_SETUP)
+#define PRINTK_DEBUG(x...)     printk(BIOS_DEBUG, x)
+#else
+#define PRINTK_DEBUG(x...)
+#endif
+
+#define BOOT_MODE_RESUME       1
+#define BOOT_MODE_NORMAL       0
+
+#include "port_access.c"
+
+static void detect_fsb(struct sys_info *sysinfo)
+{
+       u32 reg32;
+       reg32 = sch_port_access_read(5, 3, 4);
+       if (reg32 & BIT(3)) {
+               sysinfo->fsb_frequency = 533;
+       } else {
+               sysinfo->fsb_frequency = 400;
+       }
+}
+
+static u32 detect_softstrap_base(void)
+{
+       u32 reg32, base_addr;
+       reg32 = sch_port_access_read(4, 0x71, 2);
+       reg32 &= 0x700;
+       reg32 = reg32 >> 7;
+       switch (reg32) {
+       case 7:
+               base_addr = 0xFFFB0000;
+               break;
+       case 6:
+               base_addr = 0xFFFC0000;
+               break;
+       case 5:
+               base_addr = 0xFFFD0000;
+               break;
+       case 4:
+               base_addr = 0xFFFE0000;
+               break;
+       }
+       return base_addr;
+}
+
+static void detect_softstraps(struct sys_info *sysinfo)
+{
+       u8 reg8, temp;
+       u32 sbase = detect_softstrap_base();
+
+       reg8 = SOFTSTRSP(sbase, 0x87f2);
+       sysinfo->ranks = reg8;
+       if (reg8 == 0) {
+               sysinfo->ram_param_source = RAM_PARAM_SOURCE_SPD;
+               /* FIXME: implement SPD reading */
+               die("no support for reading DIMM config from SPD yet!");
+               return;
+       } else {
+               sysinfo->ram_param_source = RAM_PARAM_SOURCE_SOFTSTRAP;
+               /*Timings from soft strap */
+               reg8 = SOFTSTRSP(sbase, 0x87f0);
+               temp = reg8 & 0x30;
+               temp = temp >> 4;
+               sysinfo->cl = temp;
+               temp = reg8 & 0x0c;
+               temp = temp >> 2;
+               sysinfo->trcd = temp;
+               temp = reg8 & 0x03;
+               sysinfo->trp = temp;
+
+               /*Geometry from Softstrap */
+               reg8 = SOFTSTRSP(sbase, 0x87f1);
+
+               temp = reg8 & 0x06;
+               temp = temp >> 1;
+               sysinfo->device_density = temp;
+
+               temp = reg8 & 0x01;
+               sysinfo->data_width = temp;
+
+               /*Refresh rate default 7.8us */
+               sysinfo->refresh = 3;
+       }
+}
+
+static void program_sch_dram_data(struct sys_info *sysinfo)
+{
+       u32 reg32;
+
+       /* Program DRP DRAM Rank Population and Interface Register
+        * as per data in sysinfo SCH port 1 register 0 .. 0XFF
+        */
+       reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+       reg32 &= ~(DRP_FIELDS); /* Clear all DRP fields we'll change */
+       /* Rank0 Device Width, Density, Enable */
+       reg32 |= (sysinfo->data_width) | ((sysinfo->device_density) << 1) | (1 << 3);
+       /* Rank1 Device Width, Density, Enable */
+       reg32 |= (sysinfo->data_width << 4) | ((sysinfo->device_density) << 5) | (1 << 7);
+       sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4, reg32);
+
+       /*
+        Program  DTR DRAM Timing Register as per data in sysinfo SCH port 1 register 1
+        tRD_dly = 2 (15:13 = 010b)
+        0X3F
+       */
+       reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DTR, 4);
+       reg32 &= ~(DTR_FIELDS); /* Clear all DTR fields we'll change */
+
+       reg32 = (sysinfo->trp);
+       reg32 |= (sysinfo->trcd) << 2;
+       reg32 |= (sysinfo->cl) << 4;
+       reg32 |= 0X4000;        /* tRD_dly = 2 (15:13 = 010b) */
+       sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DTR, 4, reg32);
+
+
+       /* DCO DRAM Controller Operation Register as per data in sysinfo SCH port 1 register 2  0XF */
+       reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4);
+       reg32 &= ~(DCO_FIELDS); /*Clear all DTR fields we'll change */
+
+       if (sysinfo->fsb_frequency == 533) {
+               reg32 |= 1;
+       } else {
+               reg32 &= ~(BIT(0));
+       }
+       reg32 = 0x006911c; // FIXME ?
+
+       sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4, reg32);
+}
+
+static void program_dll_config(struct sys_info *sysinfo)
+{
+       if (sysinfo->fsb_frequency == 533) {
+               sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x21, 4, 0x46464646);
+               sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x22, 4, 0x46464646);
+       } else {
+               sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x21, 4, 0x58585858);
+               sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x22, 4, 0x58585858);
+       }
+       sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x23, 4, 0x2222);
+       if (sysinfo->fsb_frequency == 533) {
+               sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x20, 4, 0x993B);
+       } else {
+               sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x20, 4, 0xCC3B);
+       }
+}
+
+static void do_jedec_init(struct sys_info *sysinfo)
+{
+       u32 reg32, rank, cmd, temp, num_ranks;
+       /* Performs JEDEC memory initializattion for all memory rows */
+       /* Set CKE0/1 low */
+       reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+       reg32 |= DRP_CKE_DIS;
+       sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4, reg32);
+       reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+       rank = 0;
+       num_ranks = sysinfo->ranks;
+       do {
+
+               /* Start clocks */
+               reg32 =
+                   sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+               reg32 &= ~(DRP_SCK_DIS);        /* Enable all SCK/SCKB by def. */
+               sch_port_access_write(1, SCH_MSG_DUNIT_REG_DRP, 4, reg32);
+               /* Program miscellaneous SCH registers on rank 0 initialization */
+               reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+               if (rank == 0) {
+                       program_dll_config(sysinfo);
+
+               }
+               printk(BIOS_DEBUG, "Setting up RAM \n");
+               /*
+                  Wait 200us
+                  reg32 = inb(ACPI_BASE + 8); PM1 Timer
+                  reg32 &=0xFFFFFF;
+                  reg32 +=0x2EE;
+                  do
+                  {
+                  reg32 = inb(ACPI_BASE + 8);PM1 Timer
+                  reg32 &= 0xFFFFFF;
+                  }while (reg32 < 0x2EE); */
+               /* Apply NOP */
+               cmd = rank;
+               cmd |= SCH_DRAMINIT_CMD_NOP;
+               sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+               /* Set CKE=high */
+               reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+               reg32 &= 0xFFFF9FFF;    /* Clear both the CKE static disables */
+               sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4, reg32);
+               /*   Wait 400ns (not needed when executing from flash)
+                  Precharge all
+                */
+               reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+               cmd = rank;
+               cmd |= SCH_DRAMINIT_CMD_PALL;
+               sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+
+               /*EMRS(2); High temp self refresh=disabled, partial array self refresh=full */
+               cmd = rank;
+               cmd |= SCH_DRAMINIT_CMD_EMRS2;
+               sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+               /*EMRS(3) (no command) */
+               cmd = rank;
+               cmd |= SCH_DRAMINIT_CMD_EMRS3;
+               sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+               /*EMRS(1); Enable DLL (Leave all bits in the command at 0) */
+               cmd = rank;
+               cmd |= SCH_DRAMINIT_CMD_EMRS1;
+               sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+               /*MRS; Reset DLL (Set memory address bit 8) */
+               cmd = rank;
+               cmd |= SCH_DRAMINIT_CMD_MRS;
+               cmd |= (SCH_JEDEC_DLLRESET << SCH_DRAMINIT_ADDR_OFFSET);
+               sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+               /*Precharge all */
+               cmd = rank;
+               cmd |= SCH_DRAMINIT_CMD_PALL;
+               sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+               /*Issue 2 auto-refresh commands */
+               cmd = rank;
+               cmd |= SCH_DRAMINIT_CMD_AREF;
+               sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+               sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+               /*MRS command including tCL, tWR, burst length (always 4) */
+               cmd = rank;
+               cmd |= (SCH_DRAMINIT_CMD_MRS + JEDEC_STATIC_PARAM);     /*Static param */
+               temp = sysinfo->cl;
+               temp += TCL_LOW;        /*Adjust for the TCL base */
+               temp = temp << ((SCH_JEDEC_CL_OFFSET + SCH_DRAMINIT_ADDR_OFFSET));      /*Ready the CAS latency */
+               cmd |= temp;
+               sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+               /* Wait 200 clocks (max of 1us, so no need to delay)
+                  Issue EMRS(1):OCD default
+                */
+               cmd = rank;
+               cmd |= SCH_DRAMINIT_CMD_EMRS1;
+               cmd |= (SCH_JEDEC_OCD_DEFAULT << SCH_DRAMINIT_ADDR_OFFSET);
+               sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+               /*Issue EMRS(1): OCD cal. mode exit. */
+               cmd = rank;
+               cmd |= SCH_DRAMINIT_CMD_EMRS1;
+               cmd |= (SCH_JEDEC_DQS_DIS << SCH_DRAMINIT_ADDR_OFFSET);
+               sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+               rank += SCH_DRAMINIT_RANK_MASK;
+               num_ranks--;
+       } while (num_ranks);
+}
+
+/**
+ * @param boot_mode: 0 = normal, 1 = resume
+ */
+
+void sdram_initialize(int boot_mode)
+{
+       struct sys_info sysinfo;
+       u32 reg32;
+
+       printk(BIOS_DEBUG, "Setting up RAM controller.\n");
+
+       memset(&sysinfo, 0, sizeof(sysinfo));
+
+
+       detect_fsb(&sysinfo);
+       detect_softstraps(&sysinfo);
+
+       program_sch_dram_data(&sysinfo);
+
+       /* cold boot */
+       if (boot_mode == BOOT_MODE_NORMAL) {
+               do_jedec_init(&sysinfo);
+       } else {
+               program_dll_config(&sysinfo);
+       }
+
+       /* raminit complete */
+       reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4);
+       reg32 |= DCO_IC;
+       reg32 |= ((sysinfo.refresh) << 2);
+       reg32 = 0x006919c;
+       sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4, reg32);
+
+       /* setting up TOM */
+       reg32 = 0x10000000;
+       reg32 = reg32 >> sysinfo.data_width;
+       reg32 = reg32 << sysinfo.device_density;
+       reg32 = reg32 << sysinfo.ranks;
+       reg32 = 0x40000000;
+       sch_port_access_write(2, 8, 4, reg32);
+
+       /* resume mode */
+       if (boot_mode == BOOT_MODE_RESUME) {
+               sch_port_access_write_ram_cmd(SCH_OPCODE_WAKEFULLON,
+                                             SCH_MSG_DUNIT_PORT, 0, 0);
+       }
+
+       sch_port_access_write(2, 0, 4, 0x98);
+       sch_port_access_write(2, 3, 4, 0x7);
+       sch_port_access_write(3, 2, 4, 0x408);
+       sch_port_access_write(4, 0x71, 4, 0x600);
+}
+
diff --git a/src/northbridge/intel/sch/raminit.h b/src/northbridge/intel/sch/raminit.h
new file mode 100644 (file)
index 0000000..6766674
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#ifndef RAMINIT_H
+#define RAMINIT_H
+
+/**
+ * Bit Equates
+ **/
+#define BIT(x)                        (1<<x)
+
+#define   EBP_TRP_MASK               (BIT(1) | BIT(0))
+#define   TRP_LOW                    3h
+#define   TRP_HIGH                   5h
+#define   EBP_TRP_OFFSET             0           /* Start of TRP field in EBP*/
+#define   EBP_TRCD_MASK              (BIT(3) | BIT(2))
+#define   TRCD_LOW                   3h
+#define   TRCD_HIGH                  5h
+#define   EBP_TRCD_OFFSET            2           /* Start of TRCD field in EBP*/
+#define   EBP_TCL_MASK               (BIT(5) | BIT(4))
+#define   TCL_LOW                    3           /* Minimum supported CL*/
+#define   TCL_HIGH                   5           /* Maximum supported CL*/
+#define   EBP_TCL_OFFSET             4           /* EBP bit( )for CL mask*/
+#define   EBP_DDR2_CL_5_0            BIT(5)        /* CL 5.0 = 10b*/
+#define   EBP_DDR2_CL_4_0            BIT(4)        /* CL 4.0 = 01b*/
+#define   EBP_DDR2_CL_3_0            00h         /* CL 3.0 = 00b*/
+#define   EBP_FREQ_MASK              (BIT(10)| BIT(9))
+#define   EBP_FREQ_OFFSET            9           /* EBP bit( )for frequency mask*/
+#define   EBP_FREQ_400               0           /* 400MHz EBP[10:9] = 00b*/
+#define   EBP_FREQ_533               BIT(9)        /* 533MHz EBP[10:9] = 01b*/
+#define   EBP_REFRESH_MASK           (BIT(12)| BIT(11))
+#define   EBP_REFRESH_OFFSET         11          /* Bit offset of refresh field*/
+#define   EBP_REF_DIS                00h         /* Mask for refresh disabled*/
+#define   EBP_REF_128CLK             BIT(11)       /* Mask for 128 clks referesh rate*/
+#define   EBP_REF_3_9                BIT(12)       /* Mask for 3.9us refresh rate*/
+#define   EBP_REF_7_8                (BIT(12)| BIT(11))/* Mask for 7.8us refresh rate*/
+#define   EBP_WIDTH_MASK             BIT(15)
+#define   EBP_WIDTH_OFFSET           15          /* Bit offset of EBP width field*/
+#define   EBP_SOCKET_X16             BIT(15)       /* Bit mask of x8/x16 bit*/
+#define   EBP_DENSITY_MASK           (BIT(17)| BIT(16))
+#define   EBP_DENSITY_OFFSET         16
+#define   EBP_DENSITY_512            BIT(16)       /* 512Mbit density*/
+#define   EBP_DENSITY_1024           BIT(17)       /* 1024Mbit density*/
+#define   EBP_DENSITY_2048           (BIT(17)| BIT(16))/* 2048Mbit density*/
+#define   EBP_RANKS_MASK             BIT(18)
+#define   EBP_RANKS_OFFSET           18
+#define   EBP_RANKS                  BIT(18)       /* Bit offset of # of ranks bit*/
+#define   EBP_PACKAGE_TYPE             BIT(19)       /* Package type (stacked or not)*/
+#define   EBP_2X_MASK                  BIT(20)
+#define   EBP_2X_OFFSET              20          /* Bit offset of ebp 2x refresh field*/
+#define   EBP_2X_AUTO_REFRESH        BIT(20)       /* Bit mask of 2x refresh field*/
+#define   EBP_DRAM_PARM_MASK           BIT(21)
+#define   EBP_DRAM_PARM_OFFSET       21
+#define   EBP_DRAM_PARM_SPD          0           /* Use SPD to get DRAM parameters*/
+#define   EBP_DRAM_PARM_CMC          BIT(21)       /* DRAM parameters in CMC binary*/
+#define   EBP_BOOT_PATH                BIT(31)
+
+
+
+
+#define HB_REG_MCR                   0xD0         /* Message Control Register              */
+#define HB_REG_MCR_OP_OFFSET         24           /* Offset of the opcode field in MCR     */
+#define HB_REG_MCR_PORT_OFFSET       16           /* Offset of the port field in MCR       */
+#define HB_REG_MCR_REG_OFFSET        8            /* Offset of the register field in MCR   */
+#define HB_REG_MDR                   0xD4         /* Message Data Register                 */
+
+/* SCH Message OpCodes and Attributes*/
+#define SCH_OPCODE_WAKEFULLON         0x2           /* SCH message bus "Wake Full On" opcode*/
+#define SCH_OPCODE_DRAMINIT           0xA0          /* SCH message bus "DRAM Init" opcode   */
+#define SCH_DRAMINIT_CMD_MRS          0x4000           /* MRS command                          */
+#define SCH_DRAMINIT_CMD_EMRS1        0x8           /* EMRS 1 command                       */
+#define SCH_DRAMINIT_CMD_EMRS2        0x10           /* EMRS 2 command                       */
+#define SCH_DRAMINIT_CMD_EMRS3        0x18           /* EMRS 3 command                       */
+#define SCH_DRAMINIT_CMD_CBR          0x1           /* CBR command                          */
+#define SCH_DRAMINIT_CMD_AREF         0x10001        /* Refresh command, MA10=0->All         */
+#define SCH_DRAMINIT_CMD_PALL         0x10002        /* Precharge command, MA10=1->All       */
+#define SCH_DRAMINIT_CMD_BACT         0x3           /* Bank activate command                */
+#define SCH_DRAMINIT_CMD_NOP          0x7           /* NOP command                          */
+#define SCH_DRAMINIT_RANK_OFFSET      21            /* Offset of the rank selection bit     */
+#define SCH_DRAMINIT_RANK_MASK        BIT(21)
+#define SCH_DRAMINIT_ADDR_OFFSET      6            /* Offset of the address field in MDR    */
+#define SCH_DRAMINIT_INTLV            BIT(3)         /* Interleave burst type                 */
+#define SCH_DRAMINIT_BL4              2         /* Burst Length = 4                      */
+#define SCH_DRAMINIT_CL_OFFSET        4            /* CAS Latency bit offset                */
+#define SCH_DRAMINIT_OCD_DEFAULT      0xE000       /* OCD Default command                   */
+#define SCH_DRAMINIT_DQS_DIS          BIT(16)        /* DQS Disable command                   */
+#define SCH_OPCODE_READ                 0xD0         /* SCH message bus "read" opcode         */
+#define SCH_OPCODE_WRITE                0xE0         /* SCH message bus "write" opcode        */
+
+/* SCH Message Ports and Registers*/
+
+#define  SCH_MSG_DUNIT_PORT            0x1          /* DRAM unit port                        */
+#define  SCH_MSG_DUNIT_REG_DRP         0x0          /* DRAM Rank Population and Interface    */
+#define  DRP_FIELDS                    0xFF         /* Pertinent fields in DRP               */
+#define  DRP_RANK0_OFFSET              3            /* Rank 0 enable offset                  */
+#define  DRP_RANK1_OFFSET              7            /* Rank 1 enable offset                  */
+#define  DRP_DENSITY0_OFFSET           1            /* Density offset - Rank 0               */
+#define  DRP_DENSITY1_OFFSET           5            /* Density offset - Rank 1               */
+#define  DRP_WIDTH0_OFFSET             0            /* Width offset - Rank 0                 */
+#define  DRP_WIDTH1_OFFSET             4            /* Width offset - Rank 1                 */
+#define  DRP_CKE_DIS                   (BIT(14)| BIT(13))  /* CKE disable bits for both ranks       */
+#define  DRP_CKE_DIS0                  BIT(13)        /* CKE disable bit - Rank 0              */
+#define  DRP_CKE_DIS1                  BIT(14)        /* CKE disable bit - Rank 1              */
+#define  DRP_SCK_DIS                   (BIT(11)| BIT(10))  /* SCK/SCKB disable bits                 */
+#define  DRP_SCK_DIS1                  BIT(11)        /* SCK[1]/SCKB[1] disable                */
+#define  DRP_SCK_DIS0                  BIT(10)        /* SCK[0]/SCKB[0] disable                */
+#define  SCH_MSG_DUNIT_REG_DTR         0x01          /* DRAM Timing Register                  */
+#define  DTR_FIELDS                    0x3F          /* Pertinent fields in DTR               */
+#define  DTR_TCL_OFFSET                4            /* CAS latency offset                    */
+#define  DTR_TRCD_OFFSET               2            /* RAS CAS Delay Offset                  */
+#define  DTR_TRP_OFFSET                0            /* RAS Precharge Delay Offset            */
+#define  SCH_MSG_DUNIT_REG_DCO         0x2          /* DRAM Control Register                 */
+#define  DCO_FIELDS                    0xF          /* Pertinent fields in DCO               */
+#define  DCO_REFRESH_OFFSET            2            /* Refresh Rate Field Offset             */
+#define  DCO_FREQ_OFFSET               0            /* DRAM Frequency Field Offset           */
+#define  DCO_IC                        BIT(7)         /* Initialization complete bit           */
+#define  SCH_MSG_PUNIT_PORT            04h          /* Punit Port                            */
+#define  SCH_MSG_PUNIT_REG_PCR         71h          /* Punit Control Register                */
+#define  SCH_MSG_TEST_PORT             05h          /* Test port                             */
+#define  SCH_MSG_TEST_REG_MSR          03h          /* Mode and Status Register              */
+
+
+/* Jedec initialization mapping into the MDR address field for DRAM init messages*/
+
+
+#define SCH_JEDEC_DLLRESET             BIT(8)             /* DLL Reset bit( )                    */
+#define SCH_JEDEC_INTLV                BIT(3)             /* Interleave/NOT(Sequential) bit( )   */
+#define SCH_JEDEC_CL_OFFSET            4                /* Offset of the CAS latency field   */
+#define SCH_JEDEC_OCD_DEFAULT          (BIT(7)| BIT(8)| BIT(9))   /* OCD default value                 */
+#define SCH_JEDEC_DQS_DIS              BIT(10)            /* DQS disable bit                   */
+#define SCH_JEDEC_BL4                  BIT(1)             /* Burst length 4 value              */
+/*static values used during JEDEC iniatialization.  These values are not
+dependent on memory or chipset configuration.*/
+#define JEDEC_STATIC_PARAM   ((SCH_JEDEC_INTLV << SCH_DRAMINIT_ADDR_OFFSET) + (SCH_JEDEC_BL4 << SCH_DRAMINIT_ADDR_OFFSET))
+
+#define DIMM_SOCKETS 2
+
+#define DIMM_SPD_BASE 0x50
+#define DIMM_TCO_BASE 0x30
+
+/* Burst length is always 8 */
+#define BURSTLENGTH     8
+#define RAM_PARAM_SOURCE_SOFTSTRAP 1
+#define RAM_PARAM_SOURCE_SPD       0
+struct sys_info {
+
+       u16 memory_frequency;     /* 400 or 533*/
+       u16 fsb_frequency;          /* 400 or 533*/
+
+       u8 trp;                 /*3,4,5 DRAM clocks */
+       u8 trcd;                /*3,4,5 DRAM clocks */
+       u8 cl;                  /*CAS Latency 3,4,5*/
+
+       u8 refresh;             /*Refresh rate disabled,128 DRAM clocks,3.9us,7.8us */
+
+       u8 data_width;          /*x8/x16 data width */
+       u8 device_density;      /*SDRAM Device Density 512/1024/2048Mbit */
+        u8 ranks;               /*Single/Double */
+       u8 ram_param_source;    /*DRAM Parameter Source SPD/SoftStraps(R) Block (down memory) */
+       u8 boot_path;
+
+} __attribute__ ((packed));
+
+void sdram_initialize(int boot_mode);
+
+#endif                         /* RAMINIT_H */
diff --git a/src/northbridge/intel/sch/sch.h b/src/northbridge/intel/sch/sch.h
new file mode 100644 (file)
index 0000000..f4f334c
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2008 coresystems GmbH
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#ifndef __SCH_PULSBO_H__
+#define __SCH_PULSBO_H__ 1
+
+int sch_port_access_read(int port,int reg, int bytes);
+void sch_port_access_write(int port,int reg,int bytes,long data);
+void sch_port_access_write_ram_cmd(int cmd,int port,int reg,int data);
+
+/* Southbridge IO BARs */
+/* TODO Make sure these don't get changed by stage2 */
+#define SCH_ENABLE_BIT                        (1<<31)
+#define DEFAULT_ACPIPBLKBASE                 0x510
+
+#define DEFAULT_SMBUSBASE                    0x540
+#define DEFAULT_GPIOBASE                     0x588
+#define DEFAULT_GPE0BASE                     0x5C0
+#define DEFAULT_SMMCNTRLBASE                 0x3F703F76
+
+#define DEFAULT_RCBABASE                      0xfed1c000
+
+#define DEFAULT_PCIEXBAR       0xe0000000      /* 4 KB per PCIe device */
+
+/* IGD */
+#define GGC    0x52
+
+/* Root Complex Register Block */
+#define RCBA8(x) *((volatile u8 *)(DEFAULT_RCBABASE + x))
+#define RCBA16(x) *((volatile u16 *)(DEFAULT_RCBABASE + x))
+#define RCBA32(x) *((volatile u32 *)(DEFAULT_RCBABASE + x))
+
+/* FIXME: should probably be in southbridge, but is setup in romstage, too */
+#define CMC_SHADOW 0x3faf0000
+
+#endif
index 61cd79696bc5623fe996b75928da5c0b5d3cadb6..e6ffac96947caddb52f6962273a82d8ad9450060 100644 (file)
@@ -9,3 +9,4 @@ source src/southbridge/intel/i82801ex/Kconfig
 source src/southbridge/intel/i82801gx/Kconfig
 source src/southbridge/intel/i82870/Kconfig
 source src/southbridge/intel/pxhd/Kconfig
+source src/southbridge/intel/sch/Kconfig
index 12ba7108bafb3471600087d7e77a6a0e602467f1..b399955744178f82dd0f09bdef5a6f88a1883977 100644 (file)
@@ -9,4 +9,4 @@ subdirs-$(CONFIG_SOUTHBRIDGE_INTEL_I82801EX) += i82801ex
 subdirs-$(CONFIG_SOUTHBRIDGE_INTEL_I82801GX) += i82801gx
 subdirs-$(CONFIG_SOUTHBRIDGE_INTEL_I82870) += i82870
 subdirs-$(CONFIG_SOUTHBRIDGE_INTEL_PXHD) += pxhd
-
+subdirs-$(CONFIG_SOUTHBRIDGE_INTEL_SCH) += sch
diff --git a/src/southbridge/intel/sch/Kconfig b/src/southbridge/intel/sch/Kconfig
new file mode 100644 (file)
index 0000000..525db06
--- /dev/null
@@ -0,0 +1,32 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2010 coresystems GmbH
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; version 2 of the License.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+##
+
+config SOUTHBRIDGE_INTEL_SCH
+       bool
+       select TINY_BOOTBLOCK
+       select HAVE_USBDEBUG
+
+config EHCI_BAR
+       hex
+       default 0xfef00000 if SOUTHBRIDGE_INTEL_SCH
+
+config EHCI_DEBUG_OFFSET
+       hex
+       default 0xa0 if SOUTHBRIDGE_INTEL_SCH
+
diff --git a/src/southbridge/intel/sch/Makefile.inc b/src/southbridge/intel/sch/Makefile.inc
new file mode 100644 (file)
index 0000000..2d4d80e
--- /dev/null
@@ -0,0 +1,41 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2010 coresystems GmbH
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; version 2 of the License.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+##
+
+driver-y += south.c
+driver-y += audio.c
+driver-y += lpc.c
+driver-y += ide.c
+driver-y += pcie.c
+driver-y += usb.c
+driver-y += usb_ehci.c
+driver-y += usb_client.c
+driver-y += mmc.c
+driver-y += smbus.c
+
+ramstage-y += reset.c
+
+ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi.c
+smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c
+
+romstage-$(CONFIG_USBDEBUG) += usb_debug.c
+
+cbfs-files-y += cmc.bin
+cmc.bin-name := cmc.bin
+cmc.bin-type := 0xaa
+cmc.bin-position := 0xfffd0000
diff --git a/src/southbridge/intel/sch/acpi/ac97.asl b/src/southbridge/intel/sch/acpi/ac97.asl
new file mode 100644 (file)
index 0000000..29d0f7d
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* Intel i82801G AC'97 Audio and Modem */
+
+// Intel AC'97 Audio 0:1e.2
+
+Device (AUD0)
+{
+       Name (_ADR, 0x001e0002)
+}
+
+// Intel AC'97 Modem 0:1e.3
+
+Device (MODM)
+{
+       Name (_ADR, 0x001e0003)
+
+       Name (_PRW, Package(){ 5, 4 })
+}
+
diff --git a/src/southbridge/intel/sch/acpi/audio.asl b/src/southbridge/intel/sch/acpi/audio.asl
new file mode 100644 (file)
index 0000000..d03be4f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* Intel i82801G HDA */
+
+// Intel High Definition Audio (Azalia) 0:1b.0
+
+Device (HDEF)
+{
+       Name (_ADR, 0x001b0000)
+
+       // Power Resources for Wake
+       Name (_PRW, Package(){
+               5,  // Bit 5 of GPE
+               4   // Can wake from S4 state.
+       })
+}
+
diff --git a/src/southbridge/intel/sch/acpi/globalnvs.asl b/src/southbridge/intel/sch/acpi/globalnvs.asl
new file mode 100644 (file)
index 0000000..5ac1c83
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* Global Variables */
+
+Name(\PICM, 0)         // IOAPIC/8259
+Name(\DSEN, 1)         // Display Output Switching Enable
+
+/* Global ACPI memory region. This region is used for passing information
+ * between coreboot (aka "the system bios"), ACPI, and the SMI handler.
+ * Since we don't know where this will end up in memory at ACPI compile time,
+ * we have to fix it up in coreboot's ACPI creation phase.
+ */
+
+
+OperationRegion (GNVS, SystemMemory, 0xC0DEBABE, 0x100)
+Field (GNVS, ByteAcc, NoLock, Preserve)
+{
+       /* Miscellaneous */
+       Offset (0x00),
+       OSYS,   16,     // 0x00 - Operating System
+       SMIF,    8,     // 0x02 - SMI function
+       PRM0,    8,     // 0x03 - SMI function parameter
+       PRM1,    8,     // 0x04 - SMI function parameter
+       SCIF,    8,     // 0x05 - SCI function
+       PRM2,    8,     // 0x06 - SCI function parameter
+       PRM3,    8,     // 0x07 - SCI function parameter
+       LCKF,    8,     // 0x08 - Global Lock function for EC
+       PRM4,    8,     // 0x09 - Lock function parameter
+       PRM5,    8,     // 0x0a - Lock function parameter
+       P80D,   32,     // 0x0b - Debug port (IO 0x80) value
+       LIDS,    8,     // 0x0f - LID state (open = 1)
+       PWRS,    8,     // 0x10 - Power State (AC = 1)
+       DBGS,    8,     // 0x11 - Debug State
+       LINX,    8,     // 0x12 - Linux OS
+       DCKN,    8,     // 0x13 - PCIe docking state
+       /* Thermal policy */
+       Offset (0x14),
+       ACTT,    8,     // 0x14 - active trip point
+       PSVT,    8,     // 0x15 - passive trip point
+       TC1V,    8,     // 0x16 - passive trip point TC1
+       TC2V,    8,     // 0x17 - passive trip point TC2
+       TSPV,    8,     // 0x18 - passive trip point TSP
+       CRTT,    8,     // 0x19 - critical trip point
+       DTSE,    8,     // 0x1a - Digital Thermal Sensor enable
+       DTS1,    8,     // 0x1b - DT sensor 1
+       DTS2,    8,     // 0x1c - DT sensor 2
+       /* Battery Support */
+       Offset (0x1e),
+       BNUM,    8,     // 0x1e - number of batteries
+       B0SC,    8,     // 0x1f - BAT0 stored capacity
+       B1SC,    8,     // 0x20 - BAT1 stored capacity
+       B2SC,    8,     // 0x21 - BAT2 stored capacity
+       B0SS,    8,     // 0x22 - BAT0 stored status
+       B1SS,    8,     // 0x23 - BAT1 stored status
+       B2SS,    8,     // 0x24 - BAT2 stored status
+       /* Processor Identification */
+       Offset (0x28),
+       APIC,    8,     // 0x28 - APIC Enabled by coreboot
+       MPEN,    8,     // 0x29 - Multi Processor Enable
+       PCP0,    8,     // 0x2a - PDC CPU/CORE 0
+       PCP1,    8,     // 0x2b - PDC CPU/CORE 1
+       PPCM,    8,     // 0x2c - Max. PPC state
+       /* Super I/O & CMOS config */
+       Offset (0x32),
+       NATP,    8,     // 0x32 - ...
+       /* Integrated Graphics Device */
+       Offset (0x3c),
+       IGDS,    8,     // 0x3c - IGD state (primary = 1)
+       TLST,    8,     // 0x3d - Display Toggle List pointer
+       CADL,    8,     // 0x3e - Currently Attached Devices List
+       PADL,    8,     // 0x3f - Previously Attached Devices List
+       CSTE,   16,     // 0x40 - Current display state
+       NSTE,   16,     // 0x42 - Next display state
+       SSTE,   16,     // 0x44 - Set display state
+       Offset (0x46),
+       NDID,    8,     // 0x46 - Number of Device IDs
+       DID1,   32,     // 0x47 - Device ID 1
+       DID2,   32,     // 0x4b - Device ID 2
+       DID3,   32,     // 0x4f - Device ID 3
+       DID4,   32,     // 0x53 - Device ID 4
+       DID5,   32,     // 0x57 - Device ID 5
+       /* Backlight Control */
+       Offset (0x64),
+       BLCS,    8,     // 0x64 - Backlight control possible?
+       BRTL,    8,     // 0x65 - Brightness Level
+       ODDS,    8,     // 0x66
+       /* Ambient Light Sensors */
+       Offset (0x6e),
+       ALSE,    8,     // 0x6e - ALS enable
+       ALAF,    8,     // 0x6f - Ambient light adjustment factor
+       LLOW,    8,     // 0x70 - LUX Low
+       LHIH,    8,     // 0x71 - LUX High
+       /* EMA */
+       Offset (0x78),
+       EMAE,    8,     // 0x78 - EMA enable
+       EMAP,   16,     // 0x79 - EMA pointer
+       EMAL,   16,     // 0x7b - EMA length
+       /* MEF */
+       Offset (0x82),
+       MEFE,    8,     // 0x82 - MEF enable
+       /* TPM support */
+       Offset (0x8c),
+       TPMP,    8,     // 0x8c - TPM
+       TPME,    8,     // 0x8d - TPM enable
+       /* SATA */
+       Offset (0x96),
+       GTF0,   56,     // 0x96 - GTF task file buffer for port 0
+       GTF1,   56,     // 0x9d - GTF task file buffer for port 1
+       GTF2,   56,     // 0xa4 - GTF task file buffer for port 2
+       IDEM,    8,     // 0xab - IDE mode (compatible / enhanced)
+       IDET,    8,     // 0xac - IDE
+       /* IGD OpRegion */
+       Offset (0xb4),
+       ASLB,   32,     // 0xb4 - IGD OpRegion Base Address
+       IBTT,    8,     // 0xb8 - IGD boot panel device
+       IPAT,    8,     // 0xb9 - IGD panel type cmos option
+       ITVF,    8,     // 0xba - IGD TV format cmos option
+       ITVM,    8,     // 0xbb - IGD TV minor format option
+       IPSC,    8,     // 0xbc - IGD panel scaling
+       IBLC,    8,     // 0xbd - IGD BLC config
+       IBIA,    8,     // 0xbe - IGD BIA config
+       ISSC,    8,     // 0xbf - IGD SSC config
+       I409,    8,     // 0xc0 - IGD 0409 modified settings
+       I509,    8,     // 0xc1 - IGD 0509 modified settings
+       I609,    8,     // 0xc2 - IGD 0609 modified settings
+       I709,    8,     // 0xc3 - IGD 0709 modified settings
+       IDMM,    8,     // 0xc4 - IGD DVMT Mode
+       IDMS,    8,     // 0xc5 - IGD DVMT memory size
+       IF1E,    8,     // 0xc6 - IGD function 1 enable
+       HVCO,    8,     // 0xc7 - IGD HPLL VCO
+       NXD1,   32,     // 0xc8 - IGD _DGS next DID1
+       NXD2,   32,     // 0xcc - IGD _DGS next DID2
+       NXD3,   32,     // 0xd0 - IGD _DGS next DID3
+       NXD4,   32,     // 0xd4 - IGD _DGS next DID4
+       NXD5,   32,     // 0xd8 - IGD _DGS next DID5
+       NXD6,   32,     // 0xdc - IGD _DGS next DID6
+       NXD7,   32,     // 0xe0 - IGD _DGS next DID7
+       NXD8,   32,     // 0xe4 - IGD _DGS next DID8
+       /* Mainboard Specific (TODO move elsewhere) */
+       Offset (0xf0),
+       DOCK,    8,     // 0xf0 - Docking Status
+}
diff --git a/src/southbridge/intel/sch/acpi/irqlinks.asl b/src/southbridge/intel/sch/acpi/irqlinks.asl
new file mode 100644 (file)
index 0000000..5fcee45
--- /dev/null
@@ -0,0 +1,493 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Device (LNKA)
+{
+       Name (_HID, EISAID("PNP0C0F"))
+       Name (_UID, 1)
+
+       // Disable method
+       Method (_DIS, 0, Serialized)
+       {
+               Store (0x80, PRTA)
+       }
+
+       // Possible Resource Settings for this Link
+       Name (_PRS, ResourceTemplate()
+       {
+               IRQ(Level, ActiveLow, Shared)
+                       { 1, 3, 4, 5, 6, 7, 10, 12, 14, 15 }
+       })
+
+       // Current Resource Settings for this link
+       Method (_CRS, 0, Serialized)
+       {
+               Name (RTLA, ResourceTemplate()
+               {
+                       IRQ(Level, ActiveLow, Shared) {}
+               })
+               CreateWordField(RTLA, 1, IRQ0)
+
+               // Clear the WordField
+               Store (Zero, IRQ0)
+
+               // Set the bit from PRTA
+               ShiftLeft(1, And(PRTA, 0x0f), IRQ0)
+
+               Return (RTLA)
+       }
+
+       // Set Resource Setting for this IRQ link
+       Method (_SRS, 1, Serialized)
+       {
+               CreateWordField(Arg0, 1, IRQ0)
+
+               // Which bit is set?
+               FindSetRightBit(IRQ0, Local0)
+
+               Decrement(Local0)
+               Store(Local0, PRTA)
+       }
+
+       // Status
+       Method (_STA, 0, Serialized)
+       {
+               If(And(PRTA, 0x80)) {
+                       Return (0x9)
+               } Else {
+                       Return (0xb)
+               }
+       }
+}
+
+Device (LNKB)
+{
+       Name (_HID, EISAID("PNP0C0F"))
+       Name (_UID, 2)
+
+       // Disable method
+       Method (_DIS, 0, Serialized)
+       {
+               Store (0x80, PRTB)
+       }
+
+       // Possible Resource Settings for this Link
+       Name (_PRS, ResourceTemplate()
+       {
+               IRQ(Level, ActiveLow, Shared)
+                       { 1, 3, 4, 5, 6, 7, 11, 12, 14, 15 }
+       })
+
+       // Current Resource Settings for this link
+       Method (_CRS, 0, Serialized)
+       {
+               Name (RTLB, ResourceTemplate()
+               {
+                       IRQ(Level, ActiveLow, Shared) {}
+               })
+               CreateWordField(RTLB, 1, IRQ0)
+
+               // Clear the WordField
+               Store (Zero, IRQ0)
+
+               // Set the bit from PRTB
+               ShiftLeft(1, And(PRTB, 0x0f), IRQ0)
+
+               Return (RTLB)
+       }
+
+       // Set Resource Setting for this IRQ link
+       Method (_SRS, 1, Serialized)
+       {
+               CreateWordField(Arg0, 1, IRQ0)
+
+               // Which bit is set?
+               FindSetRightBit(IRQ0, Local0)
+
+               Decrement(Local0)
+               Store(Local0, PRTB)
+       }
+
+       // Status
+       Method (_STA, 0, Serialized)
+       {
+               If(And(PRTB, 0x80)) {
+                       Return (0x9)
+               } Else {
+                       Return (0xb)
+               }
+       }
+}
+
+Device (LNKC)
+{
+       Name (_HID, EISAID("PNP0C0F"))
+       Name (_UID, 3)
+
+       // Disable method
+       Method (_DIS, 0, Serialized)
+       {
+               Store (0x80, PRTC)
+       }
+
+       // Possible Resource Settings for this Link
+       Name (_PRS, ResourceTemplate()
+       {
+               IRQ(Level, ActiveLow, Shared)
+                       { 1, 3, 4, 5, 6, 7, 10, 12, 14, 15 }
+       })
+
+       // Current Resource Settings for this link
+       Method (_CRS, 0, Serialized)
+       {
+               Name (RTLC, ResourceTemplate()
+               {
+                       IRQ(Level, ActiveLow, Shared) {}
+               })
+               CreateWordField(RTLC, 1, IRQ0)
+
+               // Clear the WordField
+               Store (Zero, IRQ0)
+
+               // Set the bit from PRTC
+               ShiftLeft(1, And(PRTC, 0x0f), IRQ0)
+
+               Return (RTLC)
+       }
+
+       // Set Resource Setting for this IRQ link
+       Method (_SRS, 1, Serialized)
+       {
+               CreateWordField(Arg0, 1, IRQ0)
+
+               // Which bit is set?
+               FindSetRightBit(IRQ0, Local0)
+
+               Decrement(Local0)
+               Store(Local0, PRTC)
+       }
+
+       // Status
+       Method (_STA, 0, Serialized)
+       {
+               If(And(PRTC, 0x80)) {
+                       Return (0x9)
+               } Else {
+                       Return (0xb)
+               }
+       }
+}
+
+Device (LNKD)
+{
+       Name (_HID, EISAID("PNP0C0F"))
+       Name (_UID, 4)
+
+       // Disable method
+       Method (_DIS, 0, Serialized)
+       {
+               Store (0x80, PRTD)
+       }
+
+       // Possible Resource Settings for this Link
+       Name (_PRS, ResourceTemplate()
+       {
+               IRQ(Level, ActiveLow, Shared)
+                       { 1, 3, 4, 5, 6, 7, 11, 12, 14, 15 }
+       })
+
+       // Current Resource Settings for this link
+       Method (_CRS, 0, Serialized)
+       {
+               Name (RTLD, ResourceTemplate()
+               {
+                       IRQ(Level, ActiveLow, Shared) {}
+               })
+               CreateWordField(RTLD, 1, IRQ0)
+
+               // Clear the WordField
+               Store (Zero, IRQ0)
+
+               // Set the bit from PRTD
+               ShiftLeft(1, And(PRTD, 0x0f), IRQ0)
+
+               Return (RTLD)
+       }
+
+       // Set Resource Setting for this IRQ link
+       Method (_SRS, 1, Serialized)
+       {
+               CreateWordField(Arg0, 1, IRQ0)
+
+               // Which bit is set?
+               FindSetRightBit(IRQ0, Local0)
+
+               Decrement(Local0)
+               Store(Local0, PRTD)
+       }
+
+       // Status
+       Method (_STA, 0, Serialized)
+       {
+               If(And(PRTD, 0x80)) {
+                       Return (0x9)
+               } Else {
+                       Return (0xb)
+               }
+       }
+}
+
+Device (LNKE)
+{
+       Name (_HID, EISAID("PNP0C0F"))
+       Name (_UID, 5)
+
+       // Disable method
+       Method (_DIS, 0, Serialized)
+       {
+               Store (0x80, PRTE)
+       }
+
+       // Possible Resource Settings for this Link
+       Name (_PRS, ResourceTemplate()
+       {
+               IRQ(Level, ActiveLow, Shared)
+                       { 1, 3, 4, 5, 6, 7, 10, 12, 14, 15 }
+       })
+
+       // Current Resource Settings for this link
+       Method (_CRS, 0, Serialized)
+       {
+               Name (RTLE, ResourceTemplate()
+               {
+                       IRQ(Level, ActiveLow, Shared) {}
+               })
+               CreateWordField(RTLE, 1, IRQ0)
+
+               // Clear the WordField
+               Store (Zero, IRQ0)
+
+               // Set the bit from PRTE
+               ShiftLeft(1, And(PRTE, 0x0f), IRQ0)
+
+               Return (RTLE)
+       }
+
+       // Set Resource Setting for this IRQ link
+       Method (_SRS, 1, Serialized)
+       {
+               CreateWordField(Arg0, 1, IRQ0)
+
+               // Which bit is set?
+               FindSetRightBit(IRQ0, Local0)
+
+               Decrement(Local0)
+               Store(Local0, PRTE)
+       }
+
+       // Status
+       Method (_STA, 0, Serialized)
+       {
+               If(And(PRTE, 0x80)) {
+                       Return (0x9)
+               } Else {
+                       Return (0xb)
+               }
+       }
+}
+
+Device (LNKF)
+{
+       Name (_HID, EISAID("PNP0C0F"))
+       Name (_UID, 6)
+
+       // Disable method
+       Method (_DIS, 0, Serialized)
+       {
+               Store (0x80, PRTF)
+       }
+
+       // Possible Resource Settings for this Link
+       Name (_PRS, ResourceTemplate()
+       {
+               IRQ(Level, ActiveLow, Shared)
+                       { 1, 3, 4, 5, 6, 7, 11, 12, 14, 15 }
+       })
+
+       // Current Resource Settings for this link
+       Method (_CRS, 0, Serialized)
+       {
+               Name (RTLF, ResourceTemplate()
+               {
+                       IRQ(Level, ActiveLow, Shared) {}
+               })
+               CreateWordField(RTLF, 1, IRQ0)
+
+               // Clear the WordField
+               Store (Zero, IRQ0)
+
+               // Set the bit from PRTF
+               ShiftLeft(1, And(PRTF, 0x0f), IRQ0)
+
+               Return (RTLF)
+       }
+
+       // Set Resource Setting for this IRQ link
+       Method (_SRS, 1, Serialized)
+       {
+               CreateWordField(Arg0, 1, IRQ0)
+
+               // Which bit is set?
+               FindSetRightBit(IRQ0, Local0)
+
+               Decrement(Local0)
+               Store(Local0, PRTF)
+       }
+
+       // Status
+       Method (_STA, 0, Serialized)
+       {
+               If(And(PRTF, 0x80)) {
+                       Return (0x9)
+               } Else {
+                       Return (0xb)
+               }
+       }
+}
+
+Device (LNKG)
+{
+       Name (_HID, EISAID("PNP0C0F"))
+       Name (_UID, 7)
+
+       // Disable method
+       Method (_DIS, 0, Serialized)
+       {
+               Store (0x80, PRTG)
+       }
+
+       // Possible Resource Settings for this Link
+       Name (_PRS, ResourceTemplate()
+       {
+               IRQ(Level, ActiveLow, Shared)
+                       { 1, 3, 4, 5, 6, 7, 10, 12, 14, 15 }
+       })
+
+       // Current Resource Settings for this link
+       Method (_CRS, 0, Serialized)
+       {
+               Name (RTLG, ResourceTemplate()
+               {
+                       IRQ(Level, ActiveLow, Shared) {}
+               })
+               CreateWordField(RTLG, 1, IRQ0)
+
+               // Clear the WordField
+               Store (Zero, IRQ0)
+
+               // Set the bit from PRTG
+               ShiftLeft(1, And(PRTG, 0x0f), IRQ0)
+
+               Return (RTLG)
+       }
+
+       // Set Resource Setting for this IRQ link
+       Method (_SRS, 1, Serialized)
+       {
+               CreateWordField(Arg0, 1, IRQ0)
+
+               // Which bit is set?
+               FindSetRightBit(IRQ0, Local0)
+
+               Decrement(Local0)
+               Store(Local0, PRTG)
+       }
+
+       // Status
+       Method (_STA, 0, Serialized)
+       {
+               If(And(PRTG, 0x80)) {
+                       Return (0x9)
+               } Else {
+                       Return (0xb)
+               }
+       }
+}
+
+Device (LNKH)
+{
+       Name (_HID, EISAID("PNP0C0F"))
+       Name (_UID, 8)
+
+       // Disable method
+       Method (_DIS, 0, Serialized)
+       {
+               Store (0x80, PRTH)
+       }
+
+       // Possible Resource Settings for this Link
+       Name (_PRS, ResourceTemplate()
+       {
+               IRQ(Level, ActiveLow, Shared)
+                       { 1, 3, 4, 5, 6, 7, 11, 12, 14, 15 }
+       })
+
+       // Current Resource Settings for this link
+       Method (_CRS, 0, Serialized)
+       {
+               Name (RTLH, ResourceTemplate()
+               {
+                       IRQ(Level, ActiveLow, Shared) {}
+               })
+               CreateWordField(RTLH, 1, IRQ0)
+
+               // Clear the WordField
+               Store (Zero, IRQ0)
+
+               // Set the bit from PRTH
+               ShiftLeft(1, And(PRTH, 0x0f), IRQ0)
+
+               Return (RTLH)
+       }
+
+       // Set Resource Setting for this IRQ link
+       Method (_SRS, 1, Serialized)
+       {
+               CreateWordField(Arg0, 1, IRQ0)
+
+               // Which bit is set?
+               FindSetRightBit(IRQ0, Local0)
+
+               Decrement(Local0)
+               Store(Local0, PRTH)
+       }
+
+       // Status
+       Method (_STA, 0, Serialized)
+       {
+               If(And(PRTH, 0x80)) {
+                       Return (0x9)
+               } Else {
+                       Return (0xb)
+               }
+       }
+}
+
diff --git a/src/southbridge/intel/sch/acpi/lpc.asl b/src/southbridge/intel/sch/acpi/lpc.asl
new file mode 100644 (file)
index 0000000..e847af4
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+// Intel LPC Bus Device  - 0:1f.0
+
+Device (LPCB)
+{
+       Name(_ADR, 0x001f0000)
+
+       OperationRegion(LPC0, PCI_Config, 0x00, 0x100)
+       Field (LPC0, AnyAcc, NoLock, Preserve)
+       {
+               Offset (0x40),
+               PMBS,   16,     // PMBASE
+               Offset (0x60),  // Interrupt Routing Registers
+               PRTA,   8,
+               PRTB,   8,
+               PRTC,   8,
+               PRTD,   8,
+               Offset (0x68),
+               PRTE,   8,
+               PRTF,   8,
+               PRTG,   8,
+               PRTH,   8,
+
+               Offset (0x80),  // IO Decode Ranges
+               IOD0,   8,
+               IOD1,   8,
+
+               Offset (0xf0),  // RCBA
+               RCEN,   1,
+               ,       13,
+               RCBA,   18,
+       }
+
+//     #include "../../../southbridge/intel/sch/acpi/irqlinks.asl"
+       #include "irqlinks.asl"
+
+       #include "acpi/ec.asl"
+
+       Device (DMAC)           // DMA Controller
+       {
+               Name(_HID, EISAID("PNP0200"))
+               Name(_CRS, ResourceTemplate()
+               {
+                       IO (Decode16, 0x00, 0x00, 0x01, 0x20)
+                       IO (Decode16, 0x81, 0x81, 0x01, 0x11)
+                       IO (Decode16, 0x93, 0x93, 0x01, 0x0d)
+                       IO (Decode16, 0xc0, 0xc0, 0x01, 0x20)
+                       DMA (Compatibility, NotBusMaster, Transfer8_16) { 4 }
+               })
+       }
+
+       Device (FWH)            // Firmware Hub
+       {
+               Name (_HID, EISAID("INT0800"))
+               Name (_CRS, ResourceTemplate()
+               {
+                       Memory32Fixed(ReadOnly, 0xff000000, 0x01000000)
+               })
+       }
+
+       Device (HPET)
+       {
+               Name (_HID, EISAID("PNP0103"))
+               Name (_CID, 0x010CD041)
+
+               Name(BUF0, ResourceTemplate()
+               {
+                       Memory32Fixed(ReadOnly, 0xfed00000, 0x400, FED0)
+               })
+
+               Method (_STA, 0)        // Device Status
+               {
+                       If (HPTE) {
+                               // Note: Ancient versions of Windows don't want
+                               // to see the HPET in order to work right
+                               If (LGreaterEqual(OSYS, 2001)) {
+                                       Return (0xf)    // Enable and show device
+                               } Else {
+                                       Return (0xb)    // Enable and don't show device
+                               }
+                       }
+
+                       Return (0x0)    // Not enabled, don't show.
+               }
+
+               Method (_CRS, 0, Serialized) // Current resources
+               {
+                       If (HPTE) {
+                               CreateDWordField(BUF0, \_SB.PCI0.LPCB.HPET.FED0._BAS, HPT0)
+                               If (Lequal(HPAS, 1)) {
+                                       Store(0xfed01000, HPT0)
+                               }
+
+                               If (Lequal(HPAS, 2)) {
+                                       Store(0xfed02000, HPT0)
+                               }
+
+                               If (Lequal(HPAS, 3)) {
+                                       Store(0xfed03000, HPT0)
+                               }
+                       }
+
+                       Return (BUF0)
+               }
+       }
+
+       Device(PIC)     // 8259 Interrupt Controller
+       {
+               Name(_HID,EISAID("PNP0000"))
+               Name(_CRS, ResourceTemplate()
+               {
+                       IO (Decode16, 0x20, 0x20, 0x01, 0x02)
+                       IO (Decode16, 0x24, 0x24, 0x01, 0x02)
+                       IO (Decode16, 0x28, 0x28, 0x01, 0x02)
+                       IO (Decode16, 0x2c, 0x2c, 0x01, 0x02)
+                       IO (Decode16, 0x30, 0x30, 0x01, 0x02)
+                       IO (Decode16, 0x34, 0x34, 0x01, 0x02)
+                       IO (Decode16, 0x38, 0x38, 0x01, 0x02)
+                       IO (Decode16, 0x3c, 0x3c, 0x01, 0x02)
+                       IO (Decode16, 0xa0, 0xa0, 0x01, 0x02)
+                       IO (Decode16, 0xa4, 0xa4, 0x01, 0x02)
+                       IO (Decode16, 0xa8, 0xa8, 0x01, 0x02)
+                       IO (Decode16, 0xac, 0xac, 0x01, 0x02)
+                       IO (Decode16, 0xb0, 0xb0, 0x01, 0x02)
+                       IO (Decode16, 0xb4, 0xb4, 0x01, 0x02)
+                       IO (Decode16, 0xb8, 0xb8, 0x01, 0x02)
+                       IO (Decode16, 0xbc, 0xbc, 0x01, 0x02)
+                       IO (Decode16, 0x4d0, 0x4d0, 0x01, 0x02)
+                       IRQNoFlags () { 2 }
+               })
+       }
+
+       Device(MATH)    // FPU
+       {
+               Name (_HID, EISAID("PNP0C04"))
+               Name (_CRS, ResourceTemplate()
+               {
+                       IO (Decode16, 0xf0, 0xf0, 0x01, 0x01)
+                       IRQNoFlags() { 13 }
+               })
+       }
+
+       Device(LDRC)    // LPC device: Resource consumption
+       {
+               Name (_HID, EISAID("PNP0C02"))
+               Name (_UID, 2)
+               Name (_CRS, ResourceTemplate()
+               {
+                       IO (Decode16, 0x2e, 0x2e, 0x1, 0x02)            // First SuperIO
+                       IO (Decode16, 0x4e, 0x4e, 0x1, 0x02)            // Second SuperIO
+                       IO (Decode16, 0x61, 0x61, 0x1, 0x01)            // NMI Status
+                       IO (Decode16, 0x63, 0x63, 0x1, 0x01)            // CPU Reserved
+                       IO (Decode16, 0x65, 0x65, 0x1, 0x01)            // CPU Reserved
+                       IO (Decode16, 0x67, 0x67, 0x1, 0x01)            // CPU Reserved
+                       IO (Decode16, 0x80, 0x80, 0x1, 0x01)            // Port 80 Post
+                       IO (Decode16, 0x92, 0x92, 0x1, 0x01)            // CPU Reserved
+                       IO (Decode16, 0xb2, 0xb2, 0x1, 0x02)            // SWSMI
+                       // IO (Decode16, 0x680, 0x680, 0x1, 0x70)       // IO ???
+                       IO (Decode16, 0x800, 0x800, 0x1, 0x10)          // ACPI I/O trap
+                       IO (Decode16, 0x0500, 0x0500, 0x1, 0x80)        // ICH7-M ACPI
+                       IO (Decode16, 0x0480, 0x0480, 0x1, 0x40)        // ICH7-M GPIO
+                       // IO (Decode16, 0x1640, 0x1640, 0x1, 0x10)     // IO ???
+               })
+       }
+
+       Device (RTC)    // Real Time Clock
+       {
+               Name (_HID, EISAID("PNP0B00"))
+               Name (_CRS, ResourceTemplate()
+               {
+                       IO (Decode16, 0x70, 0x70, 1, 8)
+                       IRQNoFlags() { 8 }
+               })
+       }
+
+       Device (TIMR)   // Intel 8254 timer
+       {
+               Name(_HID, EISAID("PNP0100"))
+               Name(_CRS, ResourceTemplate()
+               {
+                       IO (Decode16, 0x40, 0x40, 0x01, 0x04)
+                       IO (Decode16, 0x50, 0x50, 0x10, 0x04)
+                       IRQNoFlags() {0}
+               })
+       }
+
+       #include "acpi/superio.asl"
+
+       Device (PS2K)           // Keyboard
+       {
+               Name(_HID, EISAID("PNP0303"))
+               Name(_CID, EISAID("PNP030B"))
+
+               Name(_CRS, ResourceTemplate()
+               {
+                       IO (Decode16, 0x60, 0x60, 0x01, 0x01)
+                       IO (Decode16, 0x64, 0x64, 0x01, 0x01)
+                       IRQ (Edge, ActiveHigh, Exclusive) { 0x01 } // IRQ 1
+               })
+
+               Method (_STA, 0)
+               {
+                       Return (0xf)
+               }
+       }
+
+       Device (PS2M)           // Mouse
+       {
+               Name(_HID, EISAID("PNP0F13"))
+               Name(_CRS, ResourceTemplate()
+               {
+                       IRQ (Edge, ActiveHigh, Exclusive) { 0x0c } // IRQ 12
+               })
+
+               Method(_STA, 0)
+               {
+                       Return (0xf)
+               }
+       }
+
+       Device (FDC0)           // Floppy controller
+       {
+               Name (_HID, EisaId ("PNP0700"))
+               Method (_STA, 0, NotSerialized)
+               {
+                       Return (0x0f) // FIXME
+               }
+
+               Name(_CRS, ResourceTemplate()
+               {
+                       IO (Decode16, 0x03F0, 0x03F0, 0x01, 0x06)
+                       IO (Decode16, 0x03F7, 0x03F7, 0x01, 0x01)
+                       IRQNoFlags () {6}
+                       DMA (Compatibility, NotBusMaster, Transfer8) {2}
+               })
+
+               Name(_PRS, ResourceTemplate()
+               {
+                       IO (Decode16, 0x03F0, 0x03F0, 0x01, 0x06)
+                       IO (Decode16, 0x03F7, 0x03F7, 0x01, 0x01)
+                       IRQNoFlags () {6}
+                       DMA (Compatibility, NotBusMaster, Transfer8) {2}
+               })
+
+       }
+}
diff --git a/src/southbridge/intel/sch/acpi/pata.asl b/src/southbridge/intel/sch/acpi/pata.asl
new file mode 100644 (file)
index 0000000..1905ed2
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+// Intel PATA Controller 0:1f.1
+
+Device (PATA)
+{
+       Name (_ADR, 0x001f0001)
+
+       Device (PRID)
+       {
+               Name (_ADR, 0)
+
+               // Get Timing Mode
+               Method (_GTM)
+               {
+                       Name(PBUF, Buffer(20) {
+                               0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                               0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+                               0x00,0x00,0x00,0x00 })
+
+                       CreateDwordField (PBUF,  0, PIO0)
+                       CreateDwordField (PBUF,  4, DMA0)
+                       CreateDwordField (PBUF,  8, PIO1)
+                       CreateDwordField (PBUF, 12, DMA1)
+                       CreateDwordField (PBUF, 16, FLAG)
+
+                       // TODO fill return structure
+
+                       Return (PBUF)
+               }
+
+               // Set Timing Mode
+               Method (_STM, 3)
+               {
+                       CreateDwordField (Arg0,  0, PIO0)
+                       CreateDwordField (Arg0,  4, DMA0)
+                       CreateDwordField (Arg0,  8, PIO1)
+                       CreateDwordField (Arg0, 12, DMA1)
+                       CreateDwordField (Arg0, 16, FLAG)
+
+                       // TODO: Do the deed
+               }
+
+               Device (DSK0)
+               {
+                       Name (_ADR, 0)
+                       // TODO: _RMV ?
+                       // TODO: _GTF ?
+               }
+
+               Device (DSK1)
+               {
+                       Name (_ADR, 1)
+
+                       // TODO: _RMV ?
+                       // TODO: _GTF ?
+               }
+
+       }
+}
+
diff --git a/src/southbridge/intel/sch/acpi/pci.asl b/src/southbridge/intel/sch/acpi/pci.asl
new file mode 100644 (file)
index 0000000..6803835
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+// Intel PCI to PCI bridge 0:1e.0
+
+Device (PCIB)
+{
+       Name (_ADR, 0x001e0000)
+
+       Device (SLT1)
+       {
+               Name (_ADR, 0x00000000)
+               Name (_PRW, Package(){ 11, 4 })
+       }
+
+       Device (SLT2)
+       {
+               Name (_ADR, 0x00010000)
+               Name (_PRW, Package(){ 11, 4 })
+       }
+
+       Device (SLT3)
+       {
+               Name (_ADR, 0x00020000)
+               Name (_PRW, Package(){ 11, 4 })
+       }
+
+       Device (SLT6)
+       {
+               Name (_ADR, 0x00050000)
+               Name (_PRW, Package(){ 11, 4 })
+       }
+
+       Device (LANC)
+       {
+               Name (_ADR, 0x00080000)
+               Name (_PRW, Package(){ 11, 3 })
+       }
+
+       Device (LANR)
+       {
+               Name (_ADR, 0x00000000)
+               Name (_PRW, Package(){ 11, 3 })
+       }
+
+       // TODO: How many slots, where?
+
+       // PCI Interrupt Routing.
+       // If PICM is set, interrupts are routed over the i8259, otherwise
+       // over the IOAPIC. (Really? If they're above 15 they need to be routed
+       // fixed over the IOAPIC?)
+
+       Method (_PRT)
+       {
+               #include "acpi/southbridge_pci_irqs.asl"
+       }
+
+}
+
diff --git a/src/southbridge/intel/sch/acpi/pcie.asl b/src/southbridge/intel/sch/acpi/pcie.asl
new file mode 100644 (file)
index 0000000..a76c7fb
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* Intel i82801G PCIe support */
+
+// PCI Express Ports
+
+Device (RP01)
+{
+       NAME(_ADR, 0x001c0000) // FIXME: Have a macro for PCI Devices -> ACPI notation?
+       //#include "pcie_port.asl"
+       Method(_PRT)
+       {
+               If (PICM) {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, 0, 16 },
+                               Package() { 0x0000ffff, 1, 0, 17 },
+                               Package() { 0x0000ffff, 2, 0, 18 },
+                               Package() { 0x0000ffff, 3, 0, 19 }
+                       })
+               } Else {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
+                               Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKB, 0 },
+                               Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKC, 0 },
+                               Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }
+                       })
+
+               }
+
+       }
+}
+
+Device (RP02)
+{
+       NAME(_ADR, 0x001c0001) // FIXME: Have a macro for PCI Devices -> ACPI notation?
+       //#include "pcie_port.asl"
+       Method(_PRT)
+       {
+               If (PICM) {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, 0, 17 },
+                               Package() { 0x0000ffff, 1, 0, 18 },
+                               Package() { 0x0000ffff, 2, 0, 19 },
+                               Package() { 0x0000ffff, 3, 0, 16 }
+                       })
+               } Else {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKB, 0 },
+                               Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKC, 0 },
+                               Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKD, 0 },
+                               Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKA, 0 }
+                       })
+
+               }
+
+       }
+}
+
+
+Device (RP03)
+{
+       NAME(_ADR, 0x001c0002) // FIXME: Have a macro for PCI Devices -> ACPI notation?
+       //#include "pcie_port.asl"
+       Method(_PRT)
+       {
+               If (PICM) {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, 0, 18 },
+                               Package() { 0x0000ffff, 1, 0, 19 },
+                               Package() { 0x0000ffff, 2, 0, 16 },
+                               Package() { 0x0000ffff, 3, 0, 17 }
+                       })
+               } Else {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKC, 0 },
+                               Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKD, 0 },
+                               Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKA, 0 },
+                               Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKB, 0 }
+                       })
+
+               }
+
+       }
+}
+
+
+Device (RP04)
+{
+       NAME(_ADR, 0x001c0003) // FIXME: Have a macro for PCI Devices -> ACPI notation?
+       //#include "pcie_port.asl"
+       Method(_PRT)
+       {
+               If (PICM) {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, 0, 19 },
+                               Package() { 0x0000ffff, 1, 0, 16 },
+                               Package() { 0x0000ffff, 2, 0, 17 },
+                               Package() { 0x0000ffff, 3, 0, 18 }
+                       })
+               } Else {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKD, 0 },
+                               Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKA, 0 },
+                               Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKB, 0 },
+                               Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKC, 0 }
+                       })
+
+               }
+
+       }
+}
+
+
+Device (RP05)
+{
+       NAME(_ADR, 0x001c0004) // FIXME: Have a macro for PCI Devices -> ACPI notation?
+       //#include "pcie_port.asl"
+       Method(_PRT)
+       {
+               If (PICM) {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, 0, 16 },
+                               Package() { 0x0000ffff, 1, 0, 17 },
+                               Package() { 0x0000ffff, 2, 0, 18 },
+                               Package() { 0x0000ffff, 3, 0, 19 }
+                       })
+               } Else {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
+                               Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKB, 0 },
+                               Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKC, 0 },
+                               Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }
+                       })
+
+               }
+
+       }
+}
+
+
+Device (RP06)
+{
+       NAME(_ADR, 0x001c0005) // FIXME: Have a macro for PCI Devices -> ACPI notation?
+       //#include "pcie_port.asl"
+       Method(_PRT)
+       {
+               If (PICM) {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, 0, 17 },
+                               Package() { 0x0000ffff, 1, 0, 18 },
+                               Package() { 0x0000ffff, 2, 0, 19 },
+                               Package() { 0x0000ffff, 3, 0, 16 }
+                       })
+               } Else {
+                       Return (Package() {
+                               Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKB, 0 },
+                               Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKC, 0 },
+                               Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKD, 0 },
+                               Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKA, 0 }
+                       })
+
+               }
+
+       }
+}
+
+
diff --git a/src/southbridge/intel/sch/acpi/sch.asl b/src/southbridge/intel/sch/acpi/sch.asl
new file mode 100644 (file)
index 0000000..c1e6e44
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* Intel i82801G support
+ */
+
+Scope(\)
+{
+       // IO-Trap at 0x800. This is the ACPI->SMI communication interface.
+
+       OperationRegion(IO_T, SystemIO, 0x800, 0x10)
+       Field(IO_T, ByteAcc, NoLock, Preserve)
+       {
+               Offset(0x8),
+               TRP0, 8         // IO-Trap at 0x808
+       }
+
+       // ICH7 Power Management Registers, located at PMBASE (0x1f.0 0x40.l)
+       // this doesn't work as ACPI initializes regions and packages first, devices second.
+       // use dynamic operation region? if so, how? XXX
+        //OperationRegion(PMIO, SystemIO, And(\_SB_.PCI0.LPCB.PMBS, 0xfffc), 0x80)
+       OperationRegion(PMIO, SystemIO, 0x500, 0x80)
+       Field(PMIO, ByteAcc, NoLock, Preserve)
+       {
+               Offset(0x42),   // General Purpose Control
+               , 1,            // skip 1 bit
+               GPEC, 1,        // TCO status
+               , 9,            // skip 9 more bits
+               SCIS, 1,        // TCO DMI status
+               , 6             // To the end of the word
+       }
+
+       // ICH7 GPIO IO mapped registers (0x1f.0 reg 0x48.l)
+       OperationRegion(GPIO, SystemIO, 0x1180, 0x3c)
+       Field(GPIO, ByteAcc, NoLock, Preserve)
+       {
+               Offset(0x00),   // GPIO Use Select
+               GU00, 8,
+               GU01, 8,
+               GU02, 8,
+               GU03, 8,
+               Offset(0x04),   // GPIO IO Select
+               GIO0, 8,
+               GIO1, 8,
+               GIO2, 8,
+               GIO3, 8,
+               Offset(0x0c),   // GPIO Level
+               GL00, 8,
+               GL01, 8,
+               , 3,
+               GP27, 1,        // SATA_PWR_EN #0
+               GP28, 1,        // SATA_PWR_EN #1
+               , 3,
+               Offset(0x18),   // GPIO Blink
+               GB00, 8,
+               GB01, 8,
+               GB02, 8,
+               GB03, 8,
+               Offset(0x2c),   // GPIO Invert
+               GIV0, 8,
+               GIV1, 8,
+               GIV2, 8,
+               GIV3, 8,
+               Offset(0x30),   // GPIO Use Select 2
+               GU04, 8,
+               GU05, 8,
+               GU06, 8,
+               GU07, 8,
+               Offset(0x34),   // GPIO IO Select 2
+               GIO4, 8,
+               GIO5, 8,
+               GIO6, 8,
+               GIO7, 8,
+               Offset(0x38),   // GPIO Level 2
+               , 5,
+               GP37, 1,        // PATA_PWR_EN
+               GP38, 1,        // Battery / Power (?)
+               GP39, 1,        // ??
+               GL05, 8,
+               GL06, 8,
+               GL07, 8
+       }
+
+
+       // ICH7 Root Complex Register Block. Memory Mapped through RCBA)
+       OperationRegion(RCRB, SystemMemory, 0xfed1c000, 0x4000)
+       Field(RCRB, DWordAcc, Lock, Preserve)
+       {
+               Offset(0x0000), // Backbone
+               Offset(0x1000), // Chipset
+               Offset(0x3000), // Legacy Configuration Registers
+               Offset(0x3404), // High Performance Timer Configuration
+               HPAS, 2,        // Address Select
+               , 5,
+               HPTE, 1,        // Address Enable
+               Offset(0x3418), // FD (Function Disable)
+               , 1,            // Reserved
+               PATD, 1,        // PATA disable
+               SATD, 1,        // SATA disable
+               SMBD, 1,        // SMBUS disable
+               HDAD, 1,        // Azalia disable
+               A97D, 1,        // AC'97 disable
+               M97D, 1,        // AC'97 disable
+               ILND, 1,        // Internal LAN disable
+               US1D, 1,        // UHCI #1 disable
+               US2D, 1,        // UHCI #2 disable
+               US3D, 1,        // UHCI #3 disable
+               US4D, 1,        // UHCI #4 disable
+               , 2,            // Reserved
+               LPBD, 1,        // LPC bridge disable
+               EHCD, 1,        // EHCI disable
+               Offset(0x341a), // FD Root Ports
+               RP1D, 1,        // Root Port 1 disable
+               RP2D, 1,        // Root Port 2 disable
+               RP3D, 1,        // Root Port 3 disable
+               RP4D, 1,        // Root Port 4 disable
+               RP5D, 1,        // Root Port 5 disable
+               RP6D, 1         // Root Port 6 disable
+       }
+
+}
+
+// 0:1b.0 High Definition Audio (Azalia)
+#include "../../../southbridge/intel/sch/acpi/audio.asl"
+
+// PCI Express Ports
+#include "../../../southbridge/intel/sch/acpi/pcie.asl"
+
+// USB
+#include "../../../southbridge/intel/sch/acpi/usb.asl"
+
+// PCI Bridge
+#include "../../../southbridge/intel/sch/acpi/pci.asl"
+
+// AC97 Audio and Modem
+#include "../../../southbridge/intel/sch/acpi/ac97.asl"
+
+// LPC Bridge
+#include "../../../southbridge/intel/sch/acpi/lpc.asl"
+
+// PATA
+#include "../../../southbridge/intel/sch/acpi/pata.asl"
+
+// SMBus
+#include "../../../southbridge/intel/sch/acpi/smbus.asl"
+
+
diff --git a/src/southbridge/intel/sch/acpi/sleepstates.asl b/src/southbridge/intel/sch/acpi/sleepstates.asl
new file mode 100644 (file)
index 0000000..6159585
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Name(\_S0, Package(4){0x0,0x0,0,0})
+Name(\_S1, Package(4){0x1,0x0,0,0})
+Name(\_S3, Package(4){0x5,0x0,0,0})
+Name(\_S4, Package(4){0x6,0x0,0,0})
+Name(\_S5, Package(4){0x7,0x0,0,0})
+
diff --git a/src/southbridge/intel/sch/acpi/smbus.asl b/src/southbridge/intel/sch/acpi/smbus.asl
new file mode 100644 (file)
index 0000000..b7d807e
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+// Intel SMBus Controller 0:1f.3
+
+Device (SBUS)
+{
+       Name (_ADR, 0x001f0003)
+
+       OperationRegion (SMBP, PCI_Config, 0x00, 0x100)
+       Field(SMBP, DWordAcc, NoLock, Preserve)
+       {
+               Offset(0x40),
+               ,       2,
+               I2CE,   1
+       }
+
+       /*
+       OperationRegion (SMBI, SystemIO, 0x400, 0x20)
+       Field (SMBI, ByteAcc, NoLock, Preserve)
+       {
+               HSTS,   8,      // Host Status
+               ,       8,
+               HCNT,   8,      // Host Control
+               HCMD,   8,      // Host Command
+               TXSA,   8,      // Transmit Slave Address
+               DAT0,   8,      // Host Data 0
+               DAT1,   8,      // Host Data 1
+               HBDB,   8,      // Host Block Data Byte
+               PECK,   8,      // Packet Error Check
+               RXSA,   8,      // Receive Slave Address
+               RXDA,   16,     // Receive Slave Data
+               AUXS,   8,      // Auxiliary Status
+               AUXC,   8,      // Auxiliary Control
+               SLPC,   8,      // SMLink Pin Control
+               SBPC,   8,      // SMBus Pin Control
+               SSTS,   8,      // Slave Status
+               SCMD,   8,      // Slave Command
+               NADR,   8,      // Notify Device Address
+               NDLB,   8,      // Notify Data Low Byte
+               NDLH,   8,      // Notify Data High Byte
+       }
+
+       // Kill all SMBus communication
+       Method (KILL, 0, Serialized)
+       {
+               Or (HCNT, 0x02, HCNT)   // Send Kill
+               Or (HSTS, 0xff, HSTS)   // Clean Status
+       }
+
+       // Check if last operation completed
+       // return       Failure = 0, Success = 1
+       Method (CMPL, 0, Serialized)
+       {
+               Store (4000, Local0)            // Timeout 200ms in 50us steps
+               While (Local0) {
+                       If (And(HSTS, 0x02)) {  // Completion Status?
+                               Return (1)      // Operation Completed
+                       } Else {
+                               Stall (50)
+                               Decrement (Local0)
+                               If (LEqual(Local0, 0)) {
+                                       KILL()
+                               }
+                       }
+               }
+
+               Return (0)              //  Failure
+       }
+
+
+       // Wait for SMBus to become ready
+       Method (SRDY, 0, Serialized)
+       {
+               Store (200, Local0)     // Timeout 200ms
+               While (Local0) {
+                       If (And(HSTS, 0x40)) {          // IN_USE?
+                               Sleep(1)                // Wait 1ms
+                               Decrement(Local0)       // timeout--
+                               If (LEqual(Local0, 0)) {
+                                       Return (1)
+                               }
+                       } Else {
+                               Store (0, Local0)       // We're ready
+                       }
+               }
+
+               Store (4000, Local0)    // Timeout 200ms (50us * 4000)
+               While (Local0) {
+                       If (And (HSTS, 0x01)) {         // Host Busy?
+                               Stall(50)               // Wait 50us
+                               Decrement(Local0)       // timeout--
+                               If (LEqual(Local0, 0)) {
+                                       KILL()
+                               }
+                       } Else {
+                               Return (0)              // Success
+                       }
+               }
+
+               Return (1)              // Failure
+       }
+
+       // SMBus Send Byte
+       // Arg0:        Address
+       // Arg1:        Data
+       // Return:      1 = Success, 0=Failure
+
+       Method (SSXB, 2, Serialized)
+       {
+
+               // Is the SMBus Controller Ready?
+               If (SRDY()) {
+                       Return (0)
+               }
+
+               // Send Byte
+               Store (0, I2CE)         // SMBus Enable
+               Store (0xbf, HSTS)
+               Store (Arg0, TXSA)      // Write Address
+               Store (Arg1, HCMD)      // Write Data
+
+               Store (0x48, HCNT)      // Start + Byte Data Protocol
+
+               If (CMPL()) {
+                       Or (HSTS, 0xff, HSTS)   // Clean up
+                       Return (1)              // Success
+               }
+
+               Return (0)
+       }
+
+
+       // SMBus Receive Byte
+       // Arg0:        Address
+       // Return:      0xffff = Failure, Data (8bit) = Success
+
+       Method (SRXB, 2, Serialized)
+       {
+
+               // Is the SMBus Controller Ready?
+               If (SRDY()) {
+                       Return (0xffff)
+               }
+
+               // Receive Byte
+               Store (0, I2CE)         // SMBus Enable
+               Store (0xbf, HSTS)
+               Store (Or (Arg0, 1), TXSA)      // Write Address
+
+               Store (0x44, HCNT)      // Start
+
+               If (CMPL()) {
+                       Or (HSTS, 0xff, HSTS)   // Clean up
+                       Return (DAT0)           // Success
+               }
+
+               Return (0xffff)
+       }
+
+
+       // SMBus Write Byte
+       // Arg0:        Address
+       // Arg1:        Command
+       // Arg2:        Data
+       // Return:      1 = Success, 0=Failure
+
+       Method (SWRB, 3, Serialized)
+       {
+
+               // Is the SMBus Controller Ready?
+               If (SRDY()) {
+                       Return (0)
+               }
+
+               // Send Byte
+               Store (0, I2CE)         // SMBus Enable
+               Store (0xbf, HSTS)
+               Store (Arg0, TXSA)      // Write Address
+               Store (Arg1, HCMD)      // Write Command
+               Store (Arg2, DAT0)      // Write Data
+
+               Store (0x48, HCNT)      // Start + Byte Protocol
+
+               If (CMPL()) {
+                       Or (HSTS, 0xff, HSTS)   // Clean up
+                       Return (1)              // Success
+               }
+
+               Return (0)
+       }
+
+
+       // SMBus Read Byte
+       // Arg0:        Address
+       // Arg1:        Command
+       // Return:      0xffff = Failure, Data (8bit) = Success
+
+       Method (SRDB, 2, Serialized)
+       {
+
+               // Is the SMBus Controller Ready?
+               If (SRDY()) {
+                       Return (0xffff)
+               }
+
+               // Receive Byte
+               Store (0, I2CE)                 // SMBus Enable
+               Store (0xbf, HSTS)
+               Store (Or (Arg0, 1), TXSA)      // Write Address
+               Store (Arg1, HCMD)              // Command
+
+               Store (0x48, HCNT)              // Start
+
+               If (CMPL()) {
+                       Or (HSTS, 0xff, HSTS)   // Clean up
+                       Return (DAT0)           // Success
+               }
+
+               Return (0xffff)
+       }
+       */
+
+       // Todo: Does anyone ever use these?
+       // Missing: Read / Write Word
+       // Missing: Read / Write Block
+}
+
diff --git a/src/southbridge/intel/sch/acpi/usb.asl b/src/southbridge/intel/sch/acpi/usb.asl
new file mode 100644 (file)
index 0000000..9ae9909
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+/* Intel i82801G USB support */
+
+// USB Controller 0:1d.0
+
+Device (USB1)
+{
+       Name(_ADR, 0x001d0000)
+
+       OperationRegion(U01P, PCI_Config, 0, 256)
+       Field(U01P, DWordAcc, NoLock, Preserve)
+       {
+               Offset(0xc4),
+               U1WE, 2         // USB Wake Enable
+       }
+
+       Name (_PRW, Package(){ 3, 4 }) // Power Resources for Wake
+
+       Method (_PSW, 1)        // Power State Wake method
+       {
+               // USB Controller can wake OS from Sleep State
+               If (Arg0) {
+                       Store (3, U1WE)
+               } Else {
+                       Store (0, U1WE)
+               }
+       }
+
+       // Leave USB ports on for to allow Wake from USB
+
+       Method(_S3D,0)  // Highest D State in S3 State
+       {
+               Return (2)
+       }
+
+       Method(_S4D,0)  // Highest D State in S4 State
+       {
+               Return (2)
+       }
+}
+
+
+// USB Controller 0:1d.1
+
+Device (USB2)
+{
+       Name(_ADR, 0x001d0001)
+
+       OperationRegion(U02P, PCI_Config, 0, 256)
+       Field(U02P, DWordAcc, NoLock, Preserve)
+       {
+               Offset(0xc4),
+               U2WE, 2         // USB Wake Enable
+       }
+
+       Name (_PRW, Package(){ 3, 4 }) // Power Resources for Wake
+
+       Method (_PSW, 1)        // Power State Wake method
+       {
+               // USB Controller can wake OS from Sleep State
+               If (Arg0) {
+                       Store (3, U2WE)
+               } Else {
+                       Store (0, U2WE)
+               }
+       }
+
+       // Leave USB ports on for to allow Wake from USB
+
+       Method(_S3D,0)  // Highest D State in S3 State
+       {
+               Return (2)
+       }
+
+       Method(_S4D,0)  // Highest D State in S4 State
+       {
+               Return (2)
+       }
+
+}
+
+
+// USB Controller 0:1d.2
+
+Device (USB3)
+{
+       Name(_ADR, 0x001d0002)
+
+       OperationRegion(U03P, PCI_Config, 0, 256)
+       Field(U03P, DWordAcc, NoLock, Preserve)
+       {
+               Offset(0xc4),
+               U3WE, 2         // USB Wake Enable
+       }
+
+       Name (_PRW, Package(){ 3, 4 }) // Power Resources for Wake
+
+       Method (_PSW, 1)        // Power State Wake method
+       {
+               // USB Controller can wake OS from Sleep State
+               If (Arg0) {
+                       Store (3, U3WE)
+               } Else {
+                       Store (0, U3WE)
+               }
+       }
+
+       // Leave USB ports on for to allow Wake from USB
+
+       Method(_S3D,0)  // Highest D State in S3 State
+       {
+               Return (2)
+       }
+
+       Method(_S4D,0)  // Highest D State in S4 State
+       {
+               Return (2)
+       }
+
+}
+
+
+// USB Controller 0:1d.3
+
+Device (USB4)
+{
+       Name(_ADR, 0x001d0003)
+
+       OperationRegion(U04P, PCI_Config, 0, 256)
+       Field(U04P, DWordAcc, NoLock, Preserve)
+       {
+               Offset(0xc4),
+               U4WE, 2         // USB Wake Enable
+       }
+
+       Name (_PRW, Package(){ 3, 4 }) // Power Resources for Wake
+
+       Method (_PSW, 1)        // Power State Wake method
+       {
+               // USB Controller can wake OS from Sleep State
+               If (Arg0) {
+                       Store (3, U4WE)
+               } Else {
+                       Store (0, U4WE)
+               }
+       }
+
+       // Leave USB ports on for to allow Wake from USB
+
+       Method(_S3D,0)  // Highest D State in S3 State
+       {
+               Return (2)
+       }
+
+       Method(_S4D,0)  // Highest D State in S4 State
+       {
+               Return (2)
+       }
+
+}
+
+
+// EHCI Controller 0:1d.7
+
+Device (EHC1)
+{
+       Name(_ADR, 0x001d0007)
+
+       Name (_PRW, Package(){ 13, 4 }) // Power Resources for Wake
+
+       // Leave USB ports on for to allow Wake from USB
+
+       Method(_S3D,0)  // Highest D State in S3 State
+       {
+               Return (2)
+       }
+
+       Method(_S4D,0)  // Highest D State in S4 State
+       {
+               Return (2)
+       }
+
+       Device (HUB7)
+       {
+               Name (_ADR, 0x00000000)
+
+               // How many are there?
+               Device (PRT1) { Name (_ADR, 1) } // USB Port 0
+               Device (PRT2) { Name (_ADR, 2) } // USB Port 1
+               Device (PRT3) { Name (_ADR, 3) } // USB Port 2
+               Device (PRT4) { Name (_ADR, 4) } // USB Port 3
+               Device (PRT5) { Name (_ADR, 5) } // USB Port 4
+               Device (PRT6) { Name (_ADR, 6) } // USB Port 5
+       }
+}
+
+
diff --git a/src/southbridge/intel/sch/audio.c b/src/southbridge/intel/sch/audio.c
new file mode 100644 (file)
index 0000000..374e56c
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <arch/io.h>
+#include <delay.h>
+
+#define HDA_ICII_REG 0x68
+#define   HDA_ICII_BUSY (1 << 0)
+#define   HDA_ICII_VALID  (1 << 1)
+
+typedef struct southbridge_intel_sch_config config_t;
+
+static int set_bits(u32 port, u32 mask, u32 val)
+{
+       u32 reg32;
+       int count;
+
+       /* Write (val & mask) to port */
+       val &= mask;
+       reg32 = read32(port);
+       reg32 &= ~mask;
+       reg32 |= val;
+       write32(port, reg32);
+
+       /* Wait for readback of register to
+        * match what was just written to it
+        */
+       count = 50;
+       do {
+               /* Wait 1ms based on BKDG wait time */
+               mdelay(1);
+               reg32 = read32(port);
+               reg32 &= mask;
+       } while ((reg32 != val) && --count);
+
+       /* Timeout occurred */
+       if (!count)
+               return -1;
+       return 0;
+}
+
+static int codec_detect(u32 base)
+{
+       u32 reg32;
+       int count;
+
+       /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
+       if (set_bits(base + 0x08, 1, 1) == -1)
+               goto no_codec;
+
+       /* clear STATESTS bits (BAR + 0xE)[2:0] */
+       reg32 = read32(base + 0x0E);
+       reg32 |= 7;
+       write32(base + 0x0E, reg32);
+
+       /* Wait for readback of register to
+        * match what was just written to it
+        */
+       count = 50;
+       do {
+               /* Wait 1ms based on BKDG wait time */
+               mdelay(1);
+               reg32 = read32(base + 0x0E);
+       } while ((reg32 != 0) && --count);
+       /* Timeout occured */
+       if (!count)
+               goto no_codec;
+
+       /* Set Bit0 to 0 to enter reset state (BAR + 0x8)[0] */
+       if (set_bits(base + 0x08, 1, 0) == -1)
+               goto no_codec;
+
+       /* Set Bit 0 to 1 to exit reset state (BAR + 0x8)[0] */
+       if (set_bits(base + 0x08, 1, 1) == -1)
+               goto no_codec;
+
+       /* Read in Codec location (BAR + 0xe)[2..0]*/
+       reg32 = read32(base + 0xe);
+       reg32 &= 0x0f;
+       if (!reg32)
+               goto no_codec;
+
+       return reg32;
+
+no_codec:
+       /* Codec Not found */
+       /* Put HDA back in reset (BAR + 0x8) [0] */
+       set_bits(base + 0x08, 1, 0);
+       printk(BIOS_DEBUG, "sch_audio: No codec!\n");
+       return 0;
+}
+
+const u32 * cim_verb_data = NULL;
+u32 cim_verb_data_size = 0;
+
+static u32 find_verb(struct device *dev, u32 viddid, const u32 ** verb)
+{
+       printk(BIOS_DEBUG, "sch_audio: dev=%s\n", dev_path(dev));
+       printk(BIOS_DEBUG, "sch_audio: Reading viddid=%x\n", viddid);
+
+       int idx=0;
+
+       while (idx < (cim_verb_data_size / sizeof(u32))) {
+               u32 verb_size = 4 * cim_verb_data[idx+2]; // in u32
+               verb_size++; // we ship an additional gain value
+               if (cim_verb_data[idx] != viddid) {
+                       idx += verb_size + 3; // skip verb + header
+                       continue;
+               }
+               *verb = &cim_verb_data[idx+3];
+               return verb_size;
+       }
+
+       /* Not all codecs need to load another verb */
+       return 0;
+}
+
+/**
+ *  Wait 50usec for the codec to indicate it is ready
+ *  no response would imply that the codec is non-operative
+ */
+
+static int wait_for_ready(u32 base)
+{
+       /* Use a 50 usec timeout - the Linux kernel uses the
+        * same duration */
+
+       int timeout = 50;
+
+       while(timeout--) {
+               u32 reg32 = read32(base +  HDA_ICII_REG);
+               if (!(reg32 & HDA_ICII_BUSY))
+                       return 0;
+               udelay(1);
+       }
+
+       return -1;
+}
+
+/**
+ *  Wait 50usec for the codec to indicate that it accepted
+ *  the previous command.  No response would imply that the code
+ *  is non-operative
+ */
+
+static int wait_for_valid(u32 base)
+{
+       /* Use a 50 usec timeout - the Linux kernel uses the
+        * same duration */
+
+       int timeout = 25;
+
+       write32(base + 0x68, 1);
+       while(timeout--)
+       {
+               udelay(1);
+       }
+       timeout = 50;
+        while(timeout--)
+       {
+                u32 reg32 = read32(base + 0x68);
+                if ((reg32 & ((1 << 1) | (1 << 0))) ==(1 << 1))
+                {
+
+                       write32(base + 0x68, 2);
+                       return 0;
+               }
+                udelay(1);
+        }
+
+
+       return 1;
+}
+
+static void codec_init(struct device *dev, u32 base, int addr)
+{
+       u32 reg32;
+       const u32 *verb;
+       u32 verb_size;
+       int i;
+
+       printk(BIOS_DEBUG, "sch_audio: Initializing codec #%d\n", addr);
+
+       /* 1 */
+       if (wait_for_ready(base) == -1)
+               return;
+
+       reg32 = (addr << 28) | 0x000f0000;
+       write32(base + 0x60, reg32);
+
+       if (wait_for_valid(base) == -1)
+               return;
+
+
+       reg32 = read32(base + 0x0);
+       printk(BIOS_DEBUG, "sch_audio: GCAP: %08x\n", reg32);
+
+       reg32 = read32(base + 0x4);
+       printk(BIOS_DEBUG, "sch_audio: OUTPAY: %08x\n", reg32);
+       reg32 = read32(base + 0x6);
+       printk(BIOS_DEBUG, "sch_audio: INPAY: %08x\n", reg32);
+
+       reg32 = read32(base + 0x64);
+
+       /* 2 */
+       printk(BIOS_DEBUG, "sch_audio: codec viddid: %08x\n", reg32);
+       verb_size = find_verb(dev, reg32, &verb);
+
+       if (!verb_size) {
+               printk(BIOS_DEBUG, "sch_audio: No verb!\n");
+               return;
+       }
+       printk(BIOS_DEBUG, "sch_audio: verb_size: %d\n", verb_size);
+
+       /* 3 */
+       for (i = 0; i < verb_size; i++) {
+               if (wait_for_ready(base) == -1)
+                       return;
+
+               write32(base + 0x60, verb[i]);
+
+               if (wait_for_valid(base) == -1)
+                       return;
+       }
+       printk(BIOS_DEBUG, "sch_audio: verb loaded.\n");
+}
+
+static void codecs_init(struct device *dev, u32 base, u32 codec_mask)
+{
+       int i;
+       for (i = 2; i >= 0; i--) {
+               if (codec_mask & (1 << i))
+                       codec_init(dev, base, i);
+       }
+}
+
+static void sch_audio_init(struct device *dev)
+{
+       u32 base;
+       struct resource *res;
+       u32 codec_mask;
+       u32 reg32;
+
+
+
+       res = find_resource(dev, 0x10);
+       if (!res)
+               return;
+
+       reg32 = pci_read_config32(dev, PCI_COMMAND);
+       pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MEMORY);
+
+       // NOTE this will break as soon as the sch_audio get's a bar above
+       // 4G. Is there anything we can do about it?
+       base = (u32)res->base;
+       printk(BIOS_DEBUG, "sch_audio: base = %08x\n", (u32)base);
+       codec_mask = codec_detect(base);
+
+       if (codec_mask) {
+               printk(BIOS_DEBUG, "sch_audio: codec_mask = %02x\n", codec_mask);
+               codecs_init(dev, base, codec_mask);
+       }
+        else
+       {
+               /* No audio codecs found disable HD audio controller*/
+               pci_write_config32(dev, 0x10, 0);
+               pci_write_config32(dev, PCI_COMMAND, 0);
+               reg32 = pci_read_config32(dev, 0xFC);
+               pci_write_config32(dev, 0xFC, reg32 | 1);
+       }
+}
+
+static void sch_audio_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
+}
+
+static struct pci_operations sch_audio_pci_ops = {
+       .set_subsystem    = sch_audio_set_subsystem,
+};
+
+static struct device_operations sch_audio_ops = {
+       .read_resources         = pci_dev_read_resources,
+       .set_resources          = pci_dev_set_resources,
+       .enable_resources       = pci_dev_enable_resources,
+       .init                   = sch_audio_init,
+       .scan_bus               = 0,
+       .ops_pci                = &sch_audio_pci_ops,
+};
+
+/* SCH audio function */
+static const struct pci_driver sch_audio __pci_driver = {
+       .ops    = &sch_audio_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x811B,
+};
+
diff --git a/src/southbridge/intel/sch/chip.h b/src/southbridge/intel/sch/chip.h
new file mode 100644 (file)
index 0000000..116d382
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#ifndef SOUTHBRIDGE_INTEL_SCH_CHIP_H
+#define SOUTHBRIDGE_INTEL_SCH_CHIP_H
+
+struct southbridge_intel_sch_config {
+       /**
+        * Interrupt Routing configuration
+        * If bit7 is 1, the interrupt is disabled.
+        */
+       uint8_t pirqa_routing;
+       uint8_t pirqb_routing;
+       uint8_t pirqc_routing;
+       uint8_t pirqd_routing;
+       uint8_t pirqe_routing;
+       uint8_t pirqf_routing;
+       uint8_t pirqg_routing;
+       uint8_t pirqh_routing;
+};
+
+extern struct chip_operations southbridge_intel_sch_ops;
+
+#endif
diff --git a/src/southbridge/intel/sch/early_smbus.c b/src/southbridge/intel/sch/early_smbus.c
new file mode 100644 (file)
index 0000000..1fa8873
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <device/pci_ids.h>
+#include <device/pci_def.h>
+#include "i82801gx.h"
+#include "smbus.h"
+
+void enable_smbus(void)
+{
+       device_t dev;
+
+       /* Set the SMBus device statically. */
+       dev = PCI_DEV(0x0, 0x1f, 0x3);
+
+       /* Check to make sure we've got the right device. */
+       if (pci_read_config16(dev, 0x2) != 0x27da) {
+               die("SMBus controller not found!");
+       }
+
+       /* 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.\n");
+}
+
+int smbus_read_byte(unsigned device, unsigned address)
+{
+       return do_smbus_read_byte(SMBUS_IO_BASE, device, address);
+}
+
diff --git a/src/southbridge/intel/sch/ide.c b/src/southbridge/intel/sch/ide.c
new file mode 100644 (file)
index 0000000..0ca98e0
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+/* PCI Configuration Space (D31:F1): IDE */
+#define   INTR_LN                      0x3c
+#define   IDE_TIM_PRI          0x80    /* IDE timings, primary */
+
+extern int sch_port_access_read(int port,int reg, int bytes);
+static void ide_init(struct device *dev)
+{
+       u32 ideTimingConfig;
+       u32 reg32;
+       printk(BIOS_DEBUG, "sch_ide: initializing... ");
+
+       reg32 = pci_read_config32(dev, PCI_COMMAND);
+       pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_IO | PCI_COMMAND_MASTER);
+
+       /* Program the clock */
+
+       if (sch_port_access_read(5,3,4) & (1<<3))
+       {
+               /*533MHz
+               Read PCI MC register*/
+               reg32 = pci_read_config32(dev, 0x60);
+               pci_write_config32(dev,0x60,reg32 | 1);
+       }
+       else
+       {
+               /*400MHz*/
+               reg32 = pci_read_config32(dev, 0x60);
+               reg32 &=~(1);
+               pci_write_config32(dev,0x60,reg32);
+       }
+
+
+       /* Enable primary IDE interface.
+       80=04 81=00 82=02 83=80
+       */
+       ideTimingConfig = 0x80020000;
+       printk(BIOS_DEBUG, "IDE0 ");
+       pci_write_config32(dev, IDE_TIM_PRI, ideTimingConfig);
+
+       /* Set Interrupt Line */
+       /* Interrupt Pin is set by D31IP.PIP */
+       printk(BIOS_DEBUG, "\n");
+}
+
+static void ide_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
+}
+
+static struct pci_operations ide_pci_ops = {
+       .set_subsystem    = 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                = &ide_pci_ops,
+};
+
+static const struct pci_driver sch_ide __pci_driver = {
+       .ops    = &ide_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x811A,
+};
diff --git a/src/southbridge/intel/sch/lpc.c b/src/southbridge/intel/sch/lpc.c
new file mode 100644 (file)
index 0000000..a975018
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <arch/io.h>
+
+#include "chip.h"
+
+
+/*SCH LPC defines*/
+#define SCH_ACPI_CTL            0x58
+#define SCH_SIRQ_CTL           0x68
+#define PIRQA_ROUT             0x60
+#define PIRQB_ROUT             0x61
+#define PIRQC_ROUT             0x62
+#define PIRQD_ROUT             0x63
+#define PIRQE_ROUT             0x64
+#define PIRQF_ROUT             0x65
+#define PIRQG_ROUT             0x66
+#define PIRQH_ROUT             0x67
+
+typedef struct southbridge_intel_sch_config config_t;
+
+/* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control
+ * 0x00 - 0000 = Reserved
+ * 0x01 - 0001 = Reserved
+ * 0x02 - 0010 = Reserved
+ * 0x03 - 0011 = IRQ3
+ * 0x04 - 0100 = IRQ4
+ * 0x05 - 0101 = IRQ5
+ * 0x06 - 0110 = IRQ6
+ * 0x07 - 0111 = IRQ7
+ * 0x08 - 1000 = Reserved
+ * 0x09 - 1001 = IRQ9
+ * 0x0A - 1010 = IRQ10
+ * 0x0B - 1011 = IRQ11
+ * 0x0C - 1100 = IRQ12
+ * 0x0D - 1101 = Reserved
+ * 0x0E - 1110 = IRQ14
+ * 0x0F - 1111 = IRQ15
+ * PIRQ[n]_ROUT[7] - PIRQ Routing Control
+ * 0x80 - The PIRQ is not routed.
+ */
+
+#define PIRQA 0x03
+#define PIRQB 0x05
+#define PIRQC 0x06
+#define PIRQD 0x07
+#define PIRQE 0x09
+#define PIRQF 0x0A
+#define PIRQG 0x0B
+#define PIRQH 0x0C
+static void sch_pirq_init(device_t dev)
+{
+       device_t irq_dev;
+       /* Get the chip configuration */
+       config_t *config = dev->chip_info;
+
+       pci_write_config8(dev, PIRQA_ROUT, config->pirqa_routing);
+       pci_write_config8(dev, PIRQB_ROUT, config->pirqb_routing);
+       pci_write_config8(dev, PIRQC_ROUT, config->pirqc_routing);
+       pci_write_config8(dev, PIRQD_ROUT, config->pirqd_routing);
+
+       pci_write_config8(dev, PIRQE_ROUT, config->pirqe_routing);
+       pci_write_config8(dev, PIRQF_ROUT, config->pirqf_routing);
+       pci_write_config8(dev, PIRQG_ROUT, config->pirqg_routing);
+       pci_write_config8(dev, PIRQH_ROUT, config->pirqh_routing);
+
+       /* Eric Biederman once said we should let the OS do this.
+        * I am not so sure anymore he was right.
+        */
+
+       for(irq_dev = all_devices; irq_dev; irq_dev = irq_dev->next)
+        {
+               u8 int_pin=0, int_line=0;
+
+               if (!irq_dev->enabled || irq_dev->path.type != DEVICE_PATH_PCI)
+                       continue;
+
+               int_pin = pci_read_config8(irq_dev, PCI_INTERRUPT_PIN);
+
+               switch (int_pin)
+               {
+                       case 1: /* INTA# */ int_line = config->pirqa_routing; break;
+                       case 2: /* INTB# */ int_line = config->pirqb_routing; break;
+                       case 3: /* INTC# */ int_line = config->pirqc_routing; break;
+                       case 4: /* INTD# */ int_line = config->pirqd_routing; break;
+               }
+
+               if (!int_line)
+                       continue;
+
+               pci_write_config8(irq_dev, PCI_INTERRUPT_LINE, int_line);
+       }
+}
+static void sch_fixups(struct device *dev)
+{
+       u32 rcba_base;
+       /* This needs to happen after PCI enumeration
+       RCBA32(0x1d40) |= 1;*/
+       rcba_base = pci_read_config32(dev, 0xF0);
+        /*Remove the enable bit*/
+       rcba_base = rcba_base >> 1;
+       rcba_base = rcba_base << 1;
+       *((volatile u32 *)(rcba_base +0x104)) &= 0xFF00FFFF;
+}
+
+static void lpc_init(struct device *dev)
+{
+       printk(BIOS_DEBUG, "SCH: lpc_init\n");
+
+       /* Setup the PIRQ. */
+       sch_pirq_init(dev);
+       pci_write_config8(dev, SCH_SIRQ_CTL,0x80);
+       sch_fixups(dev);
+}
+
+static void sch_lpc_read_resources(device_t dev)
+{
+       struct resource *res;
+
+       /* Get the normal PCI resources of this device. */
+       pci_dev_read_resources(dev);
+
+       /* Add an extra subtractive resource for both memory and I/O. */
+       res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
+       res->base = 0;
+       res->size = 0xe000;
+       res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
+                    IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+
+       res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
+       res->base = 0xff800000;
+       res->size = 0x00800000; /* 8 MB for flash */
+       res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
+                    IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+
+       res = new_resource(dev, 3); /* IOAPIC */
+       res->base = 0xfec00000;
+       res->size = 0x00001000;
+       res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+}
+
+static void set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
+}
+
+static struct pci_operations pci_ops = {
+       .set_subsystem = set_subsystem,
+};
+
+static struct device_operations device_ops = {
+       .read_resources         = sch_lpc_read_resources,
+       .set_resources          = pci_dev_set_resources,
+       .enable_resources       = pci_dev_enable_resources,
+       .init                   = lpc_init,
+       .scan_bus               = scan_static_bus,
+       .ops_pci                = &pci_ops,
+};
+
+/* SCH LPC Interface */
+static const struct pci_driver sch_lpc __pci_driver = {
+       .ops    = &device_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x8119,
+};
diff --git a/src/southbridge/intel/sch/mmc.c b/src/southbridge/intel/sch/mmc.c
new file mode 100644 (file)
index 0000000..9d69f0f
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <arch/io.h>
+
+static void sch_mmc_init(struct device *dev)
+{
+       u32 reg32;
+
+       printk(BIOS_DEBUG, "MMC: Setting up controller.. ");
+       reg32 = pci_read_config32(dev, PCI_COMMAND);
+       reg32 |= PCI_COMMAND_MASTER;
+       reg32 |= PCI_COMMAND_MEMORY;
+       pci_write_config32(dev, PCI_COMMAND, reg32);
+       printk(BIOS_DEBUG, "done.\n");
+}
+
+static void sch_mmc_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
+
+}
+
+static struct pci_operations lops_pci = {
+       .set_subsystem  = &sch_mmc_set_subsystem,
+};
+
+static struct device_operations sch_mmc_ops = {
+       .read_resources         = pci_dev_read_resources,
+       .set_resources          = pci_dev_set_resources,
+       .enable_resources       = pci_dev_enable_resources,
+       .init                   = sch_mmc_init,
+       .scan_bus               = 0,
+       .ops_pci                = &lops_pci,
+};
+
+static const struct pci_driver sch_mmc1 __pci_driver = {
+       .ops    = &sch_mmc_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x811C,
+};
+
+static const struct pci_driver sch_mmc2 __pci_driver = {
+       .ops    = &sch_mmc_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x811D,
+};
+
+static const struct pci_driver sch_mmc3 __pci_driver = {
+       .ops    = &sch_mmc_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x811E,
+
+};
+
diff --git a/src/southbridge/intel/sch/pcie.c b/src/southbridge/intel/sch/pcie.c
new file mode 100644 (file)
index 0000000..a0ed7f9
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+static void pci_init(struct device *dev)
+{
+       u16 reg16;
+       u32 reg32;
+
+       printk(BIOS_DEBUG, "Initializing SCH PCIe bridge.\n");
+
+       /* Enable Bus Master */
+       reg32 = pci_read_config32(dev, PCI_COMMAND);
+       reg32 |= PCI_COMMAND_MASTER;
+       pci_write_config32(dev, PCI_COMMAND, reg32);
+
+       /* Set Cache Line Size to 0x10 */
+       // This has no effect but the OS might expect it
+       pci_write_config8(dev, 0x0c, 0x10);
+       //pci_write_config32(dev, 0x18, 0x11);
+
+       //reg16 = pci_read_config16(dev, 0x3e);
+       //reg16 &= ~(1 << 0); /* disable parity error response */
+       // reg16 &= ~(1 << 1); /* disable SERR */
+       //reg16 |= (1 << 2); /* ISA enable */
+       //pci_write_config16(dev, 0x3e, reg16);
+         /*Slot implimented*/
+       reg16 = pci_read_config16(dev, 0x42);
+       reg16 |= (1 << 8);
+       pci_write_config16(dev, 0x42, reg16);
+
+       reg16 = pci_read_config16(dev, 0x48);
+       reg16 |= 0xf;
+       pci_write_config16(dev, 0x48, reg16);
+
+}
+
+static void pcie_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       /* NOTE: This is not the default position! */
+       if (!vendor || !device) {
+               pci_write_config32(dev, 0x94,
+                               pci_read_config32(dev, 0));
+       } else {
+               pci_write_config32(dev, 0x94,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
+}
+
+static struct pci_operations pci_ops = {
+       .set_subsystem = pcie_set_subsystem,
+};
+
+static struct device_operations device_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                = &pci_ops,
+};
+
+/* Port 1 */
+static const struct pci_driver sch_pcie_port1 __pci_driver = {
+       .ops    = &device_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x8110,
+};
+
+/*Port 2 */
+static const struct pci_driver sch_pcie_port2 __pci_driver = {
+       .ops    = &device_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x8112,
+};
+
diff --git a/src/southbridge/intel/sch/reset.c b/src/southbridge/intel/sch/reset.c
new file mode 100644 (file)
index 0000000..af3dada
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <reset.h>
+
+void soft_reset(void)
+{
+        outb(0x04, 0xcf9);
+}
+
+void hard_reset(void)
+{
+        outb(0x02, 0xcf9);
+        outb(0x06, 0xcf9);
+}
+
diff --git a/src/southbridge/intel/sch/sch.h b/src/southbridge/intel/sch/sch.h
new file mode 100644 (file)
index 0000000..dd8be43
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#ifndef SOUTHBRIDGE_INTEL_SCH_SCH_H
+#define SOUTHBRIDGE_INTEL_SCH_SCH_H
+
+#define DEFAULT_PMBASE         0x500
+
+/* SMBus I/O bits. */
+#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)
+
+#endif
diff --git a/src/southbridge/intel/sch/smbus.c b/src/southbridge/intel/sch/smbus.c
new file mode 100644 (file)
index 0000000..2b32e50
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/path.h>
+#include <device/smbus.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <arch/io.h>
+#include "sch.h"
+#include "smbus.h"
+
+static int lsmbus_read_byte(device_t dev, u8 address)
+{
+       u16 device;
+       struct resource *res;
+       struct bus *pbus;
+
+       device = dev->path.i2c.device;
+       pbus = get_pbus_smbus(dev);
+       res = find_resource(pbus->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 void smbus_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
+}
+
+static struct pci_operations smbus_pci_ops = {
+       .set_subsystem    = smbus_set_subsystem,
+};
+
+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,
+       .ops_smbus_bus          = &lops_smbus_bus,
+       .ops_pci                = &smbus_pci_ops,
+};
+
+/* 82801GB/GR/GDH/GBM/GHM/GU (ICH7/ICH7R/ICH7DH/ICH7-M/ICH7-M DH/ICH7-U) */
+static const struct pci_driver i82801gx_smbus __pci_driver = {
+       .ops    = &smbus_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x27da,
+};
diff --git a/src/southbridge/intel/sch/smbus.h b/src/southbridge/intel/sch/smbus.h
new file mode 100644 (file)
index 0000000..c27eadb
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
+ * Copyright (C) 2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <device/smbus_def.h>
+
+static void smbus_delay(void)
+{
+       inb(0x80);
+}
+
+static int smbus_wait_until_ready(u16 smbus_base)
+{
+       unsigned loops = SMBUS_TIMEOUT;
+       unsigned char byte;
+       do {
+               smbus_delay();
+               if (--loops == 0)
+                       break;
+               byte = inb(smbus_base + SMBHSTSTAT);
+       } while (byte & 1);
+       return loops ? 0 : -1;
+}
+
+static int smbus_wait_until_done(u16 smbus_base)
+{
+       unsigned loops = SMBUS_TIMEOUT;
+       unsigned char byte;
+       do {
+               smbus_delay();
+               if (--loops == 0)
+                       break;
+               byte = inb(smbus_base + SMBHSTSTAT);
+       } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
+       return loops ? 0 : -1;
+}
+
+static int do_smbus_read_byte(unsigned smbus_base, unsigned device, unsigned address)
+{
+       unsigned char global_status_register;
+       unsigned char byte;
+
+       if (smbus_wait_until_ready(smbus_base) < 0) {
+               return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+       }
+       /* Setup transaction */
+       /* Disable interrupts */
+       outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
+       /* Set the device I'm talking too */
+       outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
+       /* Set the command/address... */
+       outb(address & 0xff, smbus_base + SMBHSTCMD);
+       /* Set up for a byte data read */
+       outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
+            (smbus_base + SMBHSTCTL));
+       /* Clear any lingering errors, so the transaction will run */
+       outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
+
+       /* Clear the data byte... */
+       outb(0, smbus_base + SMBHSTDAT0);
+
+       /* Start the command */
+       outb((inb(smbus_base + SMBHSTCTL) | 0x40),
+            smbus_base + SMBHSTCTL);
+
+       /* Poll for transaction completion */
+       if (smbus_wait_until_done(smbus_base) < 0) {
+               return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
+       }
+
+       global_status_register = inb(smbus_base + SMBHSTSTAT);
+
+       /* Ignore the "In Use" status... */
+       global_status_register &= ~(3 << 5);
+
+       /* Read results of transaction */
+       byte = inb(smbus_base + SMBHSTDAT0);
+       if (global_status_register != (1 << 1)) {
+               return SMBUS_ERROR;
+       }
+       return byte;
+}
+
diff --git a/src/southbridge/intel/sch/smi.c b/src/southbridge/intel/sch/smi.c
new file mode 100644 (file)
index 0000000..07a7df4
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+
+#include <device/device.h>
+#include <device/pci.h>
+#include <console/console.h>
+#include <arch/io.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include <cpu/cpu.h>
+#include <string.h>
+#include "chip.h"
+#include "sch.h"
+
+extern unsigned char _binary_smm_start;
+extern unsigned char _binary_smm_size;
+
+/* I945 */
+#define SMRAM          0x9d
+#define   D_OPEN       (1 << 6)
+#define   D_CLS                (1 << 5)
+#define   D_LCK                (1 << 4)
+#define   G_SMRAME     (1 << 3)
+#define   C_BASE_SEG   ((0 << 2) | (1 << 1) | (0 << 0))
+
+/* ICH7 */
+#define PM1_STS                0x00
+#define PM1_EN         0x02
+#define PM1_CNT                0x04
+#define PM1_TMR                0x08
+#define PROC_CNT       0x10
+#define LV2            0x14
+#define LV3            0x15
+#define LV4            0x16
+#define PM2_CNT                0x20 // mobile only
+#define GPE0_STS       0x28
+#define GPE0_EN                0x2c
+#define SMI_EN         0x30
+#define   EL_SMI_EN     (1 << 25) // Intel Quick Resume Technology
+#define   INTEL_USB2_EN         (1 << 18) // Intel-Specific USB2 SMI logic
+#define   LEGACY_USB2_EN (1 << 17) // Legacy USB2 SMI logic
+#define   PERIODIC_EN   (1 << 14) // SMI on PERIODIC_STS in SMI_STS
+#define   TCO_EN        (1 << 13) // Enable TCO Logic (BIOSWE et al)
+#define   MCSMI_EN      (1 << 11) // Trap microcontroller range access
+#define   BIOS_RLS      (1 <<  7) // asserts SCI on bit set
+#define   SWSMI_TMR_EN  (1 <<  6) // start software smi timer on bit set
+#define   APMC_EN       (1 <<  5) // Writes to APM_CNT cause SMI#
+#define   SLP_SMI_EN    (1 <<  4) // Write to SLP_EN in PM1_CNT asserts SMI#
+#define   LEGACY_USB_EN  (1 <<  3) // Legacy USB circuit SMI logic
+#define   BIOS_EN       (1 <<  2) // Assert SMI# on setting GBL_RLS bit
+#define   EOS           (1 <<  1) // End of SMI (deassert SMI#)
+#define   GBL_SMI_EN    (1 <<  0) // SMI# generation at all?
+#define SMI_STS                0x34
+#define ALT_GP_SMI_EN  0x38
+#define ALT_GP_SMI_STS 0x3a
+#define GPE_CNTL       0x42
+#define DEVACT_STS     0x44
+#define SS_CNT         0x50
+#define C3_RES         0x54
+
+/* While we read PMBASE dynamically in case it changed, let's
+ * initialize it with a sane value
+ */
+
+static u16 pmbase = DEFAULT_PMBASE;
+/**
+ * @brief read and clear PM1_STS
+ * @return PM1_STS register
+ */
+static u16 reset_pm1_status(void)
+{
+       u16 reg16;
+
+       reg16 = inw(pmbase + PM1_STS);
+       /* set status bits are cleared by writing 1 to them */
+       outw(reg16, pmbase + PM1_STS);
+
+       return reg16;
+}
+
+static void dump_pm1_status(u16 pm1_sts)
+{
+       printk(BIOS_DEBUG, "PM1_STS: ");
+       if (pm1_sts & (1 << 15)) printk(BIOS_DEBUG, "WAK ");
+       if (pm1_sts & (1 << 14)) printk(BIOS_DEBUG, "PCIEXPWAK ");
+       if (pm1_sts & (1 << 11)) printk(BIOS_DEBUG, "PRBTNOR ");
+       if (pm1_sts & (1 << 10)) printk(BIOS_DEBUG, "RTC ");
+       if (pm1_sts & (1 <<  8)) printk(BIOS_DEBUG, "PWRBTN ");
+       if (pm1_sts & (1 <<  5)) printk(BIOS_DEBUG, "GBL ");
+       if (pm1_sts & (1 <<  4)) printk(BIOS_DEBUG, "BM ");
+       if (pm1_sts & (1 <<  0)) printk(BIOS_DEBUG, "TMROF ");
+       printk(BIOS_DEBUG, "\n");
+}
+
+/**
+ * @brief read and clear SMI_STS
+ * @return SMI_STS register
+ */
+static u32 reset_smi_status(void)
+{
+       u32 reg32;
+
+       reg32 = inl(pmbase + SMI_STS);
+       /* set status bits are cleared by writing 1 to them */
+       outl(reg32, pmbase + SMI_STS);
+
+       return reg32;
+}
+
+static void dump_smi_status(u32 smi_sts)
+{
+       printk(BIOS_DEBUG, "SMI_STS: ");
+       if (smi_sts & (1 << 26)) printk(BIOS_DEBUG, "SPI ");
+       if (smi_sts & (1 << 25)) printk(BIOS_DEBUG, "EL_SMI ");
+       if (smi_sts & (1 << 21)) printk(BIOS_DEBUG, "MONITOR ");
+       if (smi_sts & (1 << 20)) printk(BIOS_DEBUG, "PCI_EXP_SMI ");
+       if (smi_sts & (1 << 18)) printk(BIOS_DEBUG, "INTEL_USB2 ");
+       if (smi_sts & (1 << 17)) printk(BIOS_DEBUG, "LEGACY_USB2 ");
+       if (smi_sts & (1 << 16)) printk(BIOS_DEBUG, "SMBUS_SMI ");
+       if (smi_sts & (1 << 15)) printk(BIOS_DEBUG, "SERIRQ_SMI ");
+       if (smi_sts & (1 << 14)) printk(BIOS_DEBUG, "PERIODIC ");
+       if (smi_sts & (1 << 13)) printk(BIOS_DEBUG, "TCO ");
+       if (smi_sts & (1 << 12)) printk(BIOS_DEBUG, "DEVMON ");
+       if (smi_sts & (1 << 11)) printk(BIOS_DEBUG, "MCSMI ");
+       if (smi_sts & (1 << 10)) printk(BIOS_DEBUG, "GPI ");
+       if (smi_sts & (1 <<  9)) printk(BIOS_DEBUG, "GPE0 ");
+       if (smi_sts & (1 <<  8)) printk(BIOS_DEBUG, "PM1 ");
+       if (smi_sts & (1 <<  6)) printk(BIOS_DEBUG, "SWSMI_TMR ");
+       if (smi_sts & (1 <<  5)) printk(BIOS_DEBUG, "APM ");
+       if (smi_sts & (1 <<  4)) printk(BIOS_DEBUG, "SLP_SMI ");
+       if (smi_sts & (1 <<  3)) printk(BIOS_DEBUG, "LEGACY_USB ");
+       if (smi_sts & (1 <<  2)) printk(BIOS_DEBUG, "BIOS ");
+       printk(BIOS_DEBUG, "\n");
+}
+
+
+/**
+ * @brief read and clear GPE0_STS
+ * @return GPE0_STS register
+ */
+static u32 reset_gpe0_status(void)
+{
+       u32 reg32;
+
+       reg32 = inl(pmbase + GPE0_STS);
+       /* set status bits are cleared by writing 1 to them */
+       outl(reg32, pmbase + GPE0_STS);
+
+       return reg32;
+}
+
+static void dump_gpe0_status(u32 gpe0_sts)
+{
+       int i;
+       printk(BIOS_DEBUG, "GPE0_STS: ");
+       for (i=31; i<= 16; i--) {
+               if (gpe0_sts & (1 << i)) printk(BIOS_DEBUG, "GPIO%d ", (i-16));
+       }
+       if (gpe0_sts & (1 << 14)) printk(BIOS_DEBUG, "USB4 ");
+       if (gpe0_sts & (1 << 13)) printk(BIOS_DEBUG, "PME_B0 ");
+       if (gpe0_sts & (1 << 12)) printk(BIOS_DEBUG, "USB3 ");
+       if (gpe0_sts & (1 << 11)) printk(BIOS_DEBUG, "PME ");
+       if (gpe0_sts & (1 << 10)) printk(BIOS_DEBUG, "EL_SCI/BATLOW ");
+       if (gpe0_sts & (1 <<  9)) printk(BIOS_DEBUG, "PCI_EXP ");
+       if (gpe0_sts & (1 <<  8)) printk(BIOS_DEBUG, "RI ");
+       if (gpe0_sts & (1 <<  7)) printk(BIOS_DEBUG, "SMB_WAK ");
+       if (gpe0_sts & (1 <<  6)) printk(BIOS_DEBUG, "TCO_SCI ");
+       if (gpe0_sts & (1 <<  5)) printk(BIOS_DEBUG, "AC97 ");
+       if (gpe0_sts & (1 <<  4)) printk(BIOS_DEBUG, "USB2 ");
+       if (gpe0_sts & (1 <<  3)) printk(BIOS_DEBUG, "USB1 ");
+       if (gpe0_sts & (1 <<  2)) printk(BIOS_DEBUG, "HOT_PLUG ");
+       if (gpe0_sts & (1 <<  0)) printk(BIOS_DEBUG, "THRM ");
+       printk(BIOS_DEBUG, "\n");
+}
+
+/**
+ * @brief read and clear TCOx_STS
+ * @return TCOx_STS registers
+ */
+static u32 reset_tco_status(void)
+{
+       u32 tcobase = pmbase + 0x60;
+       u32 reg32;
+
+       reg32 = inl(tcobase + 0x04);
+       /* set status bits are cleared by writing 1 to them */
+       outl(reg32 & ~(1<<18), tcobase + 0x04); //  Don't clear BOOT_STS before SECOND_TO_STS
+       if (reg32 & (1 << 18))
+               outl(reg32 & (1<<18), tcobase + 0x04); // clear BOOT_STS
+
+       return reg32;
+}
+
+
+static void dump_tco_status(u32 tco_sts)
+{
+       printk(BIOS_DEBUG, "TCO_STS: ");
+       if (tco_sts & (1 << 20)) printk(BIOS_DEBUG, "SMLINK_SLV ");
+       if (tco_sts & (1 << 18)) printk(BIOS_DEBUG, "BOOT ");
+       if (tco_sts & (1 << 17)) printk(BIOS_DEBUG, "SECOND_TO ");
+       if (tco_sts & (1 << 16)) printk(BIOS_DEBUG, "INTRD_DET ");
+       if (tco_sts & (1 << 12)) printk(BIOS_DEBUG, "DMISERR ");
+       if (tco_sts & (1 << 10)) printk(BIOS_DEBUG, "DMISMI ");
+       if (tco_sts & (1 <<  9)) printk(BIOS_DEBUG, "DMISCI ");
+       if (tco_sts & (1 <<  8)) printk(BIOS_DEBUG, "BIOSWR ");
+       if (tco_sts & (1 <<  7)) printk(BIOS_DEBUG, "NEWCENTURY ");
+       if (tco_sts & (1 <<  3)) printk(BIOS_DEBUG, "TIMEOUT ");
+       if (tco_sts & (1 <<  2)) printk(BIOS_DEBUG, "TCO_INT ");
+       if (tco_sts & (1 <<  1)) printk(BIOS_DEBUG, "SW_TCO ");
+       if (tco_sts & (1 <<  0)) printk(BIOS_DEBUG, "NMI2SMI ");
+       printk(BIOS_DEBUG, "\n");
+}
+
+
+
+/**
+ * @brief Set the EOS bit
+ */
+static void smi_set_eos(void)
+{
+// FIXME: disabled until SMM actually works
+#if 0
+       u8 reg8;
+
+       reg8 = inb(pmbase + SMI_EN);
+       reg8 |= EOS;
+       outb(reg8, pmbase + SMI_EN);
+#endif
+}
+
+extern uint8_t smm_relocation_start, smm_relocation_end;
+
+static void smm_relocate(void)
+{
+       u32 smi_en;
+
+       printk(BIOS_DEBUG, "Initializing SMM handler...");
+
+       pmbase = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x1f, 0)), 0x40) & 0xfffc;
+       printk(BIOS_SPEW, " ... pmbase = 0x%04x\n", pmbase);
+
+       smi_en = inl(pmbase + SMI_EN);
+       if (smi_en & APMC_EN) {
+               printk(BIOS_INFO, "SMI# handler already enabled?\n");
+               return;
+       }
+
+       /* copy the SMM relocation code */
+       memcpy((void *)0x38000, &smm_relocation_start,
+                       &smm_relocation_end - &smm_relocation_start);
+
+       printk(BIOS_DEBUG, "\n");
+       dump_smi_status(reset_smi_status());
+       dump_pm1_status(reset_pm1_status());
+       dump_gpe0_status(reset_gpe0_status());
+       dump_tco_status(reset_tco_status());
+
+       /* Enable SMI generation:
+        *  - on TCO events
+        *  - on APMC writes (io 0xb2)
+        *  - on writes to SLP_EN (sleep states)
+        *  - on writes to GBL_RLS (bios commands)
+        * No SMIs:
+        *  - on microcontroller writes (io 0x62/0x66)
+        */
+       outl(smi_en | (TCO_EN | APMC_EN | SLP_SMI_EN | BIOS_EN |
+                               EOS | GBL_SMI_EN), pmbase + SMI_EN);
+
+       /**
+        * There are several methods of raising a controlled SMI# via
+        * software, among them:
+        *  - Writes to io 0xb2 (APMC)
+        *  - Writes to the Local Apic ICR with Delivery mode SMI.
+        *
+        * Using the local apic is a bit more tricky. According to
+        * AMD Family 11 Processor BKDG no destination shorthand must be
+        * used.
+        * The whole SMM initialization is quite a bit hardware specific, so
+        * I'm not too worried about the better of the methods at the moment
+        */
+
+       /* raise an SMI interrupt */
+       printk(BIOS_SPEW, "  ... raise SMI#\n");
+       outb(0x00, 0xb2);
+}
+
+static void smm_install(void)
+{
+       /* enable the SMM memory window */
+       pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
+                               D_OPEN | G_SMRAME | C_BASE_SEG);
+
+       /* copy the real SMM handler */
+       memcpy((void *)0xa0000, &_binary_smm_start, (size_t)&_binary_smm_size);
+       wbinvd();
+
+       /* close the SMM memory window and enable normal SMM */
+       pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
+                       G_SMRAME | C_BASE_SEG);
+}
+
+void smm_init(void)
+{
+       smm_relocate();
+       smm_install();
+       smi_set_eos();
+}
+
+void smm_lock(void)
+{
+       /* LOCK the SMM memory window and enable normal SMM.
+        * After running this function, only a full reset can
+        * make the SMM registers writable again.
+        */
+       printk(BIOS_DEBUG, "Locking SMM.\n");
+       pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
+                       D_LCK | G_SMRAME | C_BASE_SEG);
+}
+
+void smm_setup_structures(void *gnvs, void *tcg, void *smi1)
+{
+       /* The GDT or coreboot table is going to live here. But a long time
+        * after we relocated the GNVS, so this is not troublesome.
+        */
+       *(u32 *)0x500 = (u32)gnvs;
+       *(u32 *)0x504 = (u32)tcg;
+       *(u32 *)0x508 = (u32)smi1;
+       outb(0xea, 0xb2);
+}
diff --git a/src/southbridge/intel/sch/smihandler.c b/src/southbridge/intel/sch/smihandler.c
new file mode 100644 (file)
index 0000000..127f627
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include "sch.h"
+
+#define DEBUG_SMI
+
+#define APM_CNT                0xb2
+#define APM_STS                0xb3
+#define   ACPI_DISABLE 0x1e
+#define   ACPI_ENABLE  0xe1
+
+/* I945 */
+#define SMRAM          0x9d
+#define   D_OPEN       (1 << 6)
+#define   D_CLS                (1 << 5)
+#define   D_LCK                (1 << 4)
+#define   G_SMRANE     (1 << 3)
+#define   C_BASE_SEG   ((0 << 2) | (1 << 1) | (0 << 0))
+
+/* ICH7 */
+#define PM1_STS                0x00
+#define PM1_EN         0x02
+#define PM1_CNT                0x04
+#define PM1_TMR                0x08
+#define PROC_CNT       0x10
+#define LV2            0x14
+#define LV3            0x15
+#define LV4            0x16
+#define PM2_CNT                0x20 // mobile only
+#define GPE0_STS       0x28
+#define GPE0_EN                0x2c
+#define SMI_EN         0x30
+#define   EL_SMI_EN     (1 << 25) // Intel Quick Resume Technology
+#define   INTEL_USB2_EN         (1 << 18) // Intel-Specific USB2 SMI logic
+#define   LEGACY_USB2_EN (1 << 17) // Legacy USB2 SMI logic
+#define   PERIODIC_EN   (1 << 14) // SMI on PERIODIC_STS in SMI_STS
+#define   TCO_EN        (1 << 13) // Enable TCO Logic (BIOSWE et al)
+#define   MCSMI_EN      (1 << 11) // Trap microcontroller range access
+#define   BIOS_RLS      (1 <<  7) // asserts SCI on bit set
+#define   SWSMI_TMR_EN  (1 <<  6) // start software smi timer on bit set
+#define   APMC_EN       (1 <<  5) // Writes to APM_CNT cause SMI#
+#define   SLP_SMI_EN    (1 <<  4) // Write to SLP_EN in PM1_CNT asserts SMI#
+#define   LEGACY_USB_EN  (1 <<  3) // Legacy USB circuit SMI logic
+#define   BIOS_EN       (1 <<  2) // Assert SMI# on setting GBL_RLS bit
+#define   EOS           (1 <<  1) // End of SMI (deassert SMI#)
+#define   GBL_SMI_EN    (1 <<  0) // SMI# generation at all?
+#define SMI_STS                0x34
+#define ALT_GP_SMI_EN  0x38
+#define ALT_GP_SMI_STS 0x3a
+#define GPE_CNTL       0x42
+#define DEVACT_STS     0x44
+#define SS_CNT         0x50
+#define C3_RES         0x54
+
+//#include "i82801gx_nvs.h"
+
+/* While we read PMBASE dynamically in case it changed, let's
+ * initialize it with a sane value
+ */
+static u16 pmbase = DEFAULT_PMBASE;
+
+// disabled because SMM doesn't actually work yet
+#if 0
+/**
+ * @brief read and clear PM1_STS
+ * @return PM1_STS register
+ */
+static u16 reset_pm1_status(void)
+{
+       u16 reg16;
+
+       reg16 = inw(pmbase + PM1_STS);
+       /* set status bits are cleared by writing 1 to them */
+       outw(reg16, pmbase + PM1_STS);
+
+       return reg16;
+}
+
+static void dump_pm1_status(u16 pm1_sts)
+{
+       printk(BIOS_DEBUG, "PM1_STS: ");
+       if (pm1_sts & (1 << 15)) printk(BIOS_DEBUG, "WAK ");
+       if (pm1_sts & (1 << 14)) printk(BIOS_DEBUG, "PCIEXPWAK ");
+       if (pm1_sts & (1 << 11)) printk(BIOS_DEBUG, "PRBTNOR ");
+       if (pm1_sts & (1 << 10)) printk(BIOS_DEBUG, "RTC ");
+       if (pm1_sts & (1 <<  8)) printk(BIOS_DEBUG, "PWRBTN ");
+       if (pm1_sts & (1 <<  5)) printk(BIOS_DEBUG, "GBL ");
+       if (pm1_sts & (1 <<  4)) printk(BIOS_DEBUG, "BM ");
+       if (pm1_sts & (1 <<  0)) printk(BIOS_DEBUG, "TMROF ");
+       printk(BIOS_DEBUG, "\n");
+}
+
+/**
+ * @brief read and clear SMI_STS
+ * @return SMI_STS register
+ */
+static u32 reset_smi_status(void)
+{
+       u32 reg32;
+
+       reg32 = inl(pmbase + SMI_STS);
+       /* set status bits are cleared by writing 1 to them */
+       outl(reg32, pmbase + SMI_STS);
+
+       return reg32;
+}
+
+static void dump_smi_status(u32 smi_sts)
+{
+       printk(BIOS_DEBUG, "SMI_STS: ");
+       if (smi_sts & (1 << 26)) printk(BIOS_DEBUG, "SPI ");
+       if (smi_sts & (1 << 25)) printk(BIOS_DEBUG, "EL_SMI ");
+       if (smi_sts & (1 << 21)) printk(BIOS_DEBUG, "MONITOR ");
+       if (smi_sts & (1 << 20)) printk(BIOS_DEBUG, "PCI_EXP_SMI ");
+       if (smi_sts & (1 << 18)) printk(BIOS_DEBUG, "INTEL_USB2 ");
+       if (smi_sts & (1 << 17)) printk(BIOS_DEBUG, "LEGACY_USB2 ");
+       if (smi_sts & (1 << 16)) printk(BIOS_DEBUG, "SMBUS_SMI ");
+       if (smi_sts & (1 << 15)) printk(BIOS_DEBUG, "SERIRQ_SMI ");
+       if (smi_sts & (1 << 14)) printk(BIOS_DEBUG, "PERIODIC ");
+       if (smi_sts & (1 << 13)) printk(BIOS_DEBUG, "TCO ");
+       if (smi_sts & (1 << 12)) printk(BIOS_DEBUG, "DEVMON ");
+       if (smi_sts & (1 << 11)) printk(BIOS_DEBUG, "MCSMI ");
+       if (smi_sts & (1 << 10)) printk(BIOS_DEBUG, "GPI ");
+       if (smi_sts & (1 <<  9)) printk(BIOS_DEBUG, "GPE0 ");
+       if (smi_sts & (1 <<  8)) printk(BIOS_DEBUG, "PM1 ");
+       if (smi_sts & (1 <<  6)) printk(BIOS_DEBUG, "SWSMI_TMR ");
+       if (smi_sts & (1 <<  5)) printk(BIOS_DEBUG, "APM ");
+       if (smi_sts & (1 <<  4)) printk(BIOS_DEBUG, "SLP_SMI ");
+       if (smi_sts & (1 <<  3)) printk(BIOS_DEBUG, "LEGACY_USB ");
+       if (smi_sts & (1 <<  2)) printk(BIOS_DEBUG, "BIOS ");
+       printk(BIOS_DEBUG, "\n");
+}
+
+
+/**
+ * @brief read and clear GPE0_STS
+ * @return GPE0_STS register
+ */
+static u32 reset_gpe0_status(void)
+{
+       u32 reg32;
+
+       reg32 = inl(pmbase + GPE0_STS);
+       /* set status bits are cleared by writing 1 to them */
+       outl(reg32, pmbase + GPE0_STS);
+
+       return reg32;
+}
+
+static void dump_gpe0_status(u32 gpe0_sts)
+{
+       int i;
+       printk(BIOS_DEBUG, "GPE0_STS: ");
+       for (i=31; i<= 16; i--) {
+               if (gpe0_sts & (1 << i)) printk(BIOS_DEBUG, "GPIO%d ", (i-16));
+       }
+       if (gpe0_sts & (1 << 14)) printk(BIOS_DEBUG, "USB4 ");
+       if (gpe0_sts & (1 << 13)) printk(BIOS_DEBUG, "PME_B0 ");
+       if (gpe0_sts & (1 << 12)) printk(BIOS_DEBUG, "USB3 ");
+       if (gpe0_sts & (1 << 11)) printk(BIOS_DEBUG, "PME ");
+       if (gpe0_sts & (1 << 10)) printk(BIOS_DEBUG, "EL_SCI/BATLOW ");
+       if (gpe0_sts & (1 <<  9)) printk(BIOS_DEBUG, "PCI_EXP ");
+       if (gpe0_sts & (1 <<  8)) printk(BIOS_DEBUG, "RI ");
+       if (gpe0_sts & (1 <<  7)) printk(BIOS_DEBUG, "SMB_WAK ");
+       if (gpe0_sts & (1 <<  6)) printk(BIOS_DEBUG, "TCO_SCI ");
+       if (gpe0_sts & (1 <<  5)) printk(BIOS_DEBUG, "AC97 ");
+       if (gpe0_sts & (1 <<  4)) printk(BIOS_DEBUG, "USB2 ");
+       if (gpe0_sts & (1 <<  3)) printk(BIOS_DEBUG, "USB1 ");
+       if (gpe0_sts & (1 <<  2)) printk(BIOS_DEBUG, "HOT_PLUG ");
+       if (gpe0_sts & (1 <<  0)) printk(BIOS_DEBUG, "THRM ");
+       printk(BIOS_DEBUG, "\n");
+}
+
+
+/**
+ * @brief read and clear TCOx_STS
+ * @return TCOx_STS registers
+ */
+static u32 reset_tco_status(void)
+{
+       u32 tcobase = pmbase + 0x60;
+       u32 reg32;
+
+       reg32 = inl(tcobase + 0x04);
+       /* set status bits are cleared by writing 1 to them */
+       outl(reg32 & ~(1<<18), tcobase + 0x04); //  Don't clear BOOT_STS before SECOND_TO_STS
+       if (reg32 & (1 << 18))
+               outl(reg32 & (1<<18), tcobase + 0x04); // clear BOOT_STS
+
+       return reg32;
+}
+
+
+static void dump_tco_status(u32 tco_sts)
+{
+       printk(BIOS_DEBUG, "TCO_STS: ");
+       if (tco_sts & (1 << 20)) printk(BIOS_DEBUG, "SMLINK_SLV ");
+       if (tco_sts & (1 << 18)) printk(BIOS_DEBUG, "BOOT ");
+       if (tco_sts & (1 << 17)) printk(BIOS_DEBUG, "SECOND_TO ");
+       if (tco_sts & (1 << 16)) printk(BIOS_DEBUG, "INTRD_DET ");
+       if (tco_sts & (1 << 12)) printk(BIOS_DEBUG, "DMISERR ");
+       if (tco_sts & (1 << 10)) printk(BIOS_DEBUG, "DMISMI ");
+       if (tco_sts & (1 <<  9)) printk(BIOS_DEBUG, "DMISCI ");
+       if (tco_sts & (1 <<  8)) printk(BIOS_DEBUG, "BIOSWR ");
+       if (tco_sts & (1 <<  7)) printk(BIOS_DEBUG, "NEWCENTURY ");
+       if (tco_sts & (1 <<  3)) printk(BIOS_DEBUG, "TIMEOUT ");
+       if (tco_sts & (1 <<  2)) printk(BIOS_DEBUG, "TCO_INT ");
+       if (tco_sts & (1 <<  1)) printk(BIOS_DEBUG, "SW_TCO ");
+       if (tco_sts & (1 <<  0)) printk(BIOS_DEBUG, "NMI2SMI ");
+       printk(BIOS_DEBUG, "\n");
+}
+#endif
+
+
+/* We are using PCIe accesses for now
+ *  1. the chipset can do it
+ *  2. we don't need to worry about how we leave 0xcf8/0xcfc behind
+ */
+//#include "../../../northbridge/intel/i945/pcie_config.c"
+
+int southbridge_io_trap_handler(int smif)
+{
+       //global_nvs_t *gnvs = (global_nvs_t *)0xc00;
+
+       switch (smif) {
+       case 0x32:
+               printk(BIOS_DEBUG, "OS Init\n");
+               //gnvs->smif = 0;
+               break;
+       default:
+               /* Not handled */
+               return 0;
+       }
+
+       /* On success, the IO Trap Handler returns 0
+        * On failure, the IO Trap Handler returns a value != 0
+        *
+        * For now, we force the return value to 0 and log all traps to
+        * see what's going on.
+        */
+       //gnvs->smif = 0;
+       return 1; /* IO trap handled */
+}
+
+/**
+ * @brief Set the EOS bit
+ */
+void southbridge_smi_set_eos(void)
+{
+       u8 reg8;
+
+       reg8 = inb(pmbase + SMI_EN);
+       reg8 |= EOS;
+       outb(reg8, pmbase + SMI_EN);
+}
+
+/**
+ * @brief Interrupt handler for SMI#
+ *
+ * @param smm_revision revision of the smm state save map
+ */
+
+void southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save)
+{
+// FIXME: the necessary magic isn't available yet. the code
+// below is a partially adapted ICH7 version of the handler
+#if 0
+       u8 reg8;
+       u16 pmctrl;
+       u16 pm1_sts;
+       u32 smi_sts, gpe0_sts, tco_sts;
+
+       pmbase = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0x48) & 0xfffc;
+       printk(BIOS_SPEW, "SMI#: pmbase = 0x%04x\n", pmbase);
+
+       /* We need to clear the SMI status registers, or we won't see what's
+        * happening in the following calls.
+        */
+       smi_sts = reset_smi_status();
+       dump_smi_status(smi_sts);
+
+       if (smi_sts & (1 << 21)) { // MONITOR
+               global_nvs_t *gnvs = (global_nvs_t *)0xc00;
+               u32 reg32;
+
+               reg32 = RCBA32(0x1e00);  TRSR - Trap Status Register
+//#if 0
+               /* Comment in for some useful debug */
+               for (i=0; i<4; i++) {
+                       if (reg32 & (1 << i)) {
+                               printk(BIOS_DEBUG, "  io trap #%d\n", i);
+                       }
+               }
+//#endif
+               RCBA32(0x1e00) = reg32;  TRSR
+
+               reg32 = RCBA32(0x1e10);
+
+               if ((reg32 & 0xfffc) != 0x808) {
+                       printk(BIOS_DEBUG, "  trapped io address = 0x%x\n", reg32 & 0xfffc);
+                       printk(BIOS_DEBUG, "  AHBE = %x\n", (reg32 >> 16) & 0xf);
+                       printk(BIOS_DEBUG, "  read/write: %s\n", (reg32 & (1 << 24)) ? "read" :
+                               "write");
+               }
+
+               if (!(reg32 & (1 << 24))) {
+                       /* Write Cycle */
+                       reg32 = RCBA32(0x1e18);
+                       printk(BIOS_DEBUG, "  iotrap written data = 0x%08x\n", reg32);
+
+               }
+
+               if (gnvs->smif)
+                       io_trap_handler(gnvs->smif); // call function smif
+       }
+
+       if (smi_sts & (1 << 13)) { // TCO
+               tco_sts = reset_tco_status();
+               dump_tco_status(tco_sts);
+
+               if (tco_sts & (1 << 8)) { // BIOSWR
+                       u8 bios_cntl;
+                       bios_cntl = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0xdc);
+                       if (bios_cntl & 1) {
+                               /* BWE is RW, so the SMI was caused by a
+                                * write to BWE, not by a write to the BIOS
+                                */
+
+                               /* This is the place where we notice someone
+                                * is trying to tinker with the BIOS. We are
+                                * trying to be nice and just ignore it. A more
+                                * resolute answer would be to power down the
+                                * box.
+                                */
+                               printk(BIOS_DEBUG, "Switching back to RO\n");
+                               pcie_write_config32(PCI_DEV(0, 0x1f, 0), 0xdc, (bios_cntl & ~1));
+                       } /* No else for now? */
+               }
+       }
+
+       if (smi_sts & (1 << 8)) { // PM1
+               pm1_sts = reset_pm1_status();
+               dump_pm1_status(pm1_sts);
+       }
+
+       if (smi_sts & (1 << 9)) { // GPE0
+               gpe0_sts = reset_gpe0_status();
+               dump_gpe0_status(gpe0_sts);
+       }
+
+       if (smi_sts & (1 << 5)) { // APM
+               /* Emulate B2 register as the FADT / Linux expects it */
+
+               reg8 = inb(0xb2);
+               switch (reg8) {
+               case ACPI_DISABLE:
+                       pmctrl = inw(pmbase + 0x04);
+                       pmctrl |= (1 << 0);
+                       outw(pmctrl, pmbase + 0x04);
+                       printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n");
+                       break;
+               case ACPI_ENABLE:
+                       pmctrl = inw(pmbase + 0x04);
+                       pmctrl &= ~(1 << 0);
+                       outw(pmctrl, pmbase + 0x04);
+                       printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n");
+                       break;
+               }
+       }
+
+       if (smi_sts & (1 << 4)) { // SLP_SMI
+               u32 reg32;
+
+               /* First, disable further SMIs */
+               reg8 = inb(pmbase + SMI_EN);
+               reg8 &= ~SLP_SMI_EN;
+               outb(reg8, pmbase + SMI_EN);
+
+               /* Next, do the deed, we should change
+                * power on after power loss bits here
+                * if we're going to S5
+                */
+
+               /* Write back to the SLP register to cause the
+                * originally intended event again. We need to set BIT13
+                * (SLP_EN) though to make the sleep happen.
+                */
+               reg32 = inl(pmbase + 0x04);
+               printk(BIOS_DEBUG, "SMI#: SLP = 0x%08x\n", reg32);
+               printk(BIOS_DEBUG, "SMI#: Powering off.\n");
+               outl(reg32 | (1 << 13), pmbase + 0x04);
+       }
+#endif
+}
diff --git a/src/southbridge/intel/sch/south.c b/src/southbridge/intel/sch/south.c
new file mode 100644 (file)
index 0000000..e7c283f
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+
+struct chip_operations southbridge_intel_sch_ops = {
+       CHIP_NAME("Intel SCH Southbridge")
+};
+
diff --git a/src/southbridge/intel/sch/usb.c b/src/southbridge/intel/sch/usb.c
new file mode 100644 (file)
index 0000000..95fc79b
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2010 coresystems GmbH
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+static void usb_init(struct device *dev)
+{
+       u32 reg32;
+
+       /* USB Specification says the device must be Bus Master */
+       printk(BIOS_DEBUG, "UHCI: Setting up controller.. ");
+
+       reg32 = pci_read_config32(dev, PCI_COMMAND);
+       pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER);
+       /*Disable clock gating*/
+       reg32 = pci_read_config32(dev, 0xFC);
+       reg32 |= (1 << 2);
+       pci_write_config32(dev, 0xFC, reg32);
+       pci_write_config8(dev,0xF8,0x86);
+       pci_write_config8(dev,0xF9,0x0F);
+       pci_write_config8(dev,0xFA,0x06);
+       reg32 = pci_read_config32(dev, 0x4);
+       printk(BIOS_DEBUG, "PCI_COMMAND %x.\n",reg32);
+       reg32 = pci_read_config32(dev, 0x20);
+       printk(BIOS_DEBUG, "PCI_BASE %x.\n",reg32);
+       reg32 = pci_read_config32(dev, 0xFC);
+       printk(BIOS_DEBUG, "PCI_FD %x.\n",reg32);
+       printk(BIOS_DEBUG, "done.\n");
+}
+
+static void usb_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
+}
+
+static struct pci_operations usb_pci_ops = {
+       .set_subsystem    = usb_set_subsystem,
+};
+
+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,
+       .ops_pci                = &usb_pci_ops,
+};
+
+/*  */
+static const struct pci_driver sch_usb0 __pci_driver = {
+       .ops    = &usb_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x8114,
+};
+static const struct pci_driver sch_usb1 __pci_driver = {
+       .ops    = &usb_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x8115,
+};
+static const struct pci_driver sch_usb2 __pci_driver = {
+       .ops    = &usb_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x8116,
+};
diff --git a/src/southbridge/intel/sch/usb_client.c b/src/southbridge/intel/sch/usb_client.c
new file mode 100644 (file)
index 0000000..ea20c12
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <arch/io.h>
+
+static void usb_client_init(struct device *dev)
+{
+       u32 reg32;
+
+       printk(BIOS_DEBUG, "USB Client: Setting up controller.. ");
+       reg32 = pci_read_config32(dev, PCI_COMMAND);
+       reg32 |= PCI_COMMAND_MASTER;
+       reg32 |= PCI_COMMAND_MEMORY;
+       pci_write_config32(dev, PCI_COMMAND, reg32);
+       printk(BIOS_DEBUG, "done.\n");
+}
+
+static void usb_client_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               ((device & 0xffff) << 16) | (vendor & 0xffff));
+       }
+}
+
+static struct pci_operations lops_pci = {
+       .set_subsystem  = &usb_client_set_subsystem,
+};
+
+static struct device_operations usb_client_ops = {
+       .read_resources         = pci_dev_read_resources,
+       .set_resources          = pci_dev_set_resources,
+       .enable_resources       = pci_dev_enable_resources,
+       .init                   = usb_client_init,
+       .scan_bus               = 0,
+       .ops_pci                = &lops_pci,
+};
+
+/*  */
+static const struct pci_driver sch_usb_client __pci_driver = {
+       .ops    = &usb_client_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x8118,
+};
diff --git a/src/southbridge/intel/sch/usb_debug.c b/src/southbridge/intel/sch/usb_debug.c
new file mode 100644 (file)
index 0000000..58e0c33
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <usbdebug.h>
+#include <device/pci_def.h>
+
+/* Required for successful build, but currently empty. */
+void set_debug_port(unsigned int port)
+{
+       /* Not needed, the southbridges hardcode physical USB port 1. */
+}
+
+void sch_enable_usbdebug(unsigned int port)
+{
+       u32 dbgctl;
+       device_t dev = PCI_DEV(0, 0x1d, 7); /* USB EHCI, D29:F7 */
+
+       /* Set the EHCI BAR address. */
+       pci_write_config32(dev, EHCI_BAR_INDEX, CONFIG_EHCI_BAR);
+
+       /* Enable access to the EHCI memory space registers. */
+       pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY);
+
+       /* Force ownership of the Debug Port to the EHCI controller. */
+       printk(BIOS_DEBUG, "Enabling OWNER_CNT\n");
+       dbgctl = read32(CONFIG_EHCI_BAR + CONFIG_EHCI_DEBUG_OFFSET);
+       dbgctl |= (1 << 30);
+       write32(CONFIG_EHCI_BAR + CONFIG_EHCI_DEBUG_OFFSET, dbgctl);
+}
diff --git a/src/southbridge/intel/sch/usb_ehci.c b/src/southbridge/intel/sch/usb_ehci.c
new file mode 100644 (file)
index 0000000..561a214
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2010 coresystems GmbH
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <arch/io.h>
+
+static void usb_ehci_init(struct device *dev)
+{
+       u32 reg32;
+
+       printk(BIOS_DEBUG, "EHCI: Setting up controller.. ");
+       reg32 = pci_read_config32(dev, PCI_COMMAND);
+       reg32 |= PCI_COMMAND_MASTER;
+       pci_write_config32(dev, PCI_COMMAND, reg32);
+       /*Disable clock gating
+       reg32 = pci_read_config32(dev, 0xc0);
+       reg32 |= (1 << 2);
+       pci_write_config32(dev, 0xc0, reg32);*/
+       //pci_write_config32(dev, 0x3c, 0x17);
+       reg32 = pci_read_config32(dev, 0xFC);
+       reg32 |= (1 << 28);
+       pci_write_config32(dev, 0xFC, reg32);
+
+       reg32 = pci_read_config32(dev, 0x4);
+       printk(BIOS_DEBUG, "PCI_COMMAND %x.\n",reg32);
+       reg32 = pci_read_config32(dev, 0x20);
+       printk(BIOS_DEBUG, "PCI_BASE %x.\n",reg32);
+       reg32 = pci_read_config32(dev, 0xC0);
+       printk(BIOS_DEBUG, "PCI_FD %x.\n",reg32);
+       printk(BIOS_DEBUG, "done.\n");
+}
+
+static void usb_ehci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+       u8 access_cntl;
+
+       access_cntl = pci_read_config8(dev, 0x80);
+
+       /* Enable writes to protected registers. */
+       pci_write_config8(dev, 0x80, access_cntl | 1);
+
+       if (!vendor || !device) {
+               pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+                               pci_read_config32(dev, PCI_VENDOR_ID));
+       } else {
+               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,
+       .ops_pci                = &lops_pci,
+};
+
+/*  */
+static const struct pci_driver sch_usb_ehci __pci_driver = {
+       .ops    = &usb_ehci_ops,
+       .vendor = PCI_VENDOR_ID_INTEL,
+       .device = 0x8117,
+};