summaryrefslogtreecommitdiff
path: root/src/southbridge/intel
diff options
context:
space:
mode:
authorPatrick Georgi <patrick.georgi@coresystems.de>2010-12-18 07:48:43 +0000
committerPatrick Georgi <patrick.georgi@coresystems.de>2010-12-18 07:48:43 +0000
commitbe61a173512ece32de01562995a91fbbf3f5b335 (patch)
treeacf01fc4637bc97ca0e395158254a57ae247a402 /src/southbridge/intel
parent312fc96874ff2b3fd1a839b72dd10edb1b8937b8 (diff)
Support Intel SCH (Poulsbo) and add iwave/iWRainbowG6 board
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
Diffstat (limited to 'src/southbridge/intel')
-rw-r--r--src/southbridge/intel/Kconfig1
-rw-r--r--src/southbridge/intel/Makefile.inc2
-rw-r--r--src/southbridge/intel/sch/Kconfig32
-rw-r--r--src/southbridge/intel/sch/Makefile.inc41
-rw-r--r--src/southbridge/intel/sch/acpi/ac97.asl39
-rw-r--r--src/southbridge/intel/sch/acpi/audio.asl36
-rw-r--r--src/southbridge/intel/sch/acpi/globalnvs.asl161
-rw-r--r--src/southbridge/intel/sch/acpi/irqlinks.asl493
-rw-r--r--src/southbridge/intel/sch/acpi/lpc.asl266
-rw-r--r--src/southbridge/intel/sch/acpi/pata.asl80
-rw-r--r--src/southbridge/intel/sch/acpi/pci.asl77
-rw-r--r--src/southbridge/intel/sch/acpi/pcie.asl186
-rw-r--r--src/southbridge/intel/sch/acpi/sch.asl165
-rw-r--r--src/southbridge/intel/sch/acpi/sleepstates.asl27
-rw-r--r--src/southbridge/intel/sch/acpi/smbus.asl246
-rw-r--r--src/southbridge/intel/sch/acpi/usb.asl217
-rw-r--r--src/southbridge/intel/sch/audio.c325
-rw-r--r--src/southbridge/intel/sch/chip.h40
-rw-r--r--src/southbridge/intel/sch/early_smbus.c63
-rw-r--r--src/southbridge/intel/sch/ide.c98
-rw-r--r--src/southbridge/intel/sch/lpc.c194
-rw-r--r--src/southbridge/intel/sch/mmc.c82
-rw-r--r--src/southbridge/intel/sch/pcie.c98
-rw-r--r--src/southbridge/intel/sch/reset.c34
-rw-r--r--src/southbridge/intel/sch/sch.h40
-rw-r--r--src/southbridge/intel/sch/smbus.c79
-rw-r--r--src/southbridge/intel/sch/smbus.h99
-rw-r--r--src/southbridge/intel/sch/smi.c348
-rw-r--r--src/southbridge/intel/sch/smihandler.c418
-rw-r--r--src/southbridge/intel/sch/south.c27
-rw-r--r--src/southbridge/intel/sch/usb.c91
-rw-r--r--src/southbridge/intel/sch/usb_client.c68
-rw-r--r--src/southbridge/intel/sch/usb_debug.c49
-rw-r--r--src/southbridge/intel/sch/usb_ehci.c93
34 files changed, 4314 insertions, 1 deletions
diff --git a/src/southbridge/intel/Kconfig b/src/southbridge/intel/Kconfig
index 61cd79696b..e6ffac9694 100644
--- a/src/southbridge/intel/Kconfig
+++ b/src/southbridge/intel/Kconfig
@@ -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
diff --git a/src/southbridge/intel/Makefile.inc b/src/southbridge/intel/Makefile.inc
index 12ba7108ba..b399955744 100644
--- a/src/southbridge/intel/Makefile.inc
+++ b/src/southbridge/intel/Makefile.inc
@@ -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
index 0000000000..525db06dc5
--- /dev/null
+++ b/src/southbridge/intel/sch/Kconfig
@@ -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
index 0000000000..2d4d80e234
--- /dev/null
+++ b/src/southbridge/intel/sch/Makefile.inc
@@ -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
index 0000000000..29d0f7d8d6
--- /dev/null
+++ b/src/southbridge/intel/sch/acpi/ac97.asl
@@ -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
index 0000000000..d03be4fdd3
--- /dev/null
+++ b/src/southbridge/intel/sch/acpi/audio.asl
@@ -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
index 0000000000..5ac1c83cd6
--- /dev/null
+++ b/src/southbridge/intel/sch/acpi/globalnvs.asl
@@ -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
index 0000000000..5fcee45f29
--- /dev/null
+++ b/src/southbridge/intel/sch/acpi/irqlinks.asl
@@ -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
index 0000000000..e847af4a45
--- /dev/null
+++ b/src/southbridge/intel/sch/acpi/lpc.asl
@@ -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
index 0000000000..1905ed26d2
--- /dev/null
+++ b/src/southbridge/intel/sch/acpi/pata.asl
@@ -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
index 0000000000..6803835ce3
--- /dev/null
+++ b/src/southbridge/intel/sch/acpi/pci.asl
@@ -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
index 0000000000..a76c7fbe4d
--- /dev/null
+++ b/src/southbridge/intel/sch/acpi/pcie.asl
@@ -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
index 0000000000..c1e6e44a5a
--- /dev/null
+++ b/src/southbridge/intel/sch/acpi/sch.asl
@@ -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
index 0000000000..61595854b2
--- /dev/null
+++ b/src/southbridge/intel/sch/acpi/sleepstates.asl
@@ -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
index 0000000000..b7d807ee44
--- /dev/null
+++ b/src/southbridge/intel/sch/acpi/smbus.asl
@@ -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
index 0000000000..9ae9909a9e
--- /dev/null
+++ b/src/southbridge/intel/sch/acpi/usb.asl
@@ -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
index 0000000000..374e56c32e
--- /dev/null
+++ b/src/southbridge/intel/sch/audio.c
@@ -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
index 0000000000..116d382768
--- /dev/null
+++ b/src/southbridge/intel/sch/chip.h
@@ -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
index 0000000000..1fa88730bc
--- /dev/null
+++ b/src/southbridge/intel/sch/early_smbus.c
@@ -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
index 0000000000..0ca98e08e2
--- /dev/null
+++ b/src/southbridge/intel/sch/ide.c
@@ -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
index 0000000000..a9750189f7
--- /dev/null
+++ b/src/southbridge/intel/sch/lpc.c
@@ -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
index 0000000000..9d69f0f3e0
--- /dev/null
+++ b/src/southbridge/intel/sch/mmc.c
@@ -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
index 0000000000..a0ed7f9e5a
--- /dev/null
+++ b/src/southbridge/intel/sch/pcie.c
@@ -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
index 0000000000..af3dada2f7
--- /dev/null
+++ b/src/southbridge/intel/sch/reset.c
@@ -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
index 0000000000..dd8be43a82
--- /dev/null
+++ b/src/southbridge/intel/sch/sch.h
@@ -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
index 0000000000..2b32e506b0
--- /dev/null
+++ b/src/southbridge/intel/sch/smbus.c
@@ -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
index 0000000000..c27eadb651
--- /dev/null
+++ b/src/southbridge/intel/sch/smbus.h
@@ -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
index 0000000000..07a7df47a5
--- /dev/null
+++ b/src/southbridge/intel/sch/smi.c
@@ -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
index 0000000000..127f62772a
--- /dev/null
+++ b/src/southbridge/intel/sch/smihandler.c
@@ -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
index 0000000000..e7c283f9a8
--- /dev/null
+++ b/src/southbridge/intel/sch/south.c
@@ -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
index 0000000000..95fc79be93
--- /dev/null
+++ b/src/southbridge/intel/sch/usb.c
@@ -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
index 0000000000..ea20c12bc0
--- /dev/null
+++ b/src/southbridge/intel/sch/usb_client.c
@@ -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
index 0000000000..58e0c330d8
--- /dev/null
+++ b/src/southbridge/intel/sch/usb_debug.c
@@ -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
index 0000000000..561a214825
--- /dev/null
+++ b/src/southbridge/intel/sch/usb_ehci.c
@@ -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,
+};