aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/intel/sch
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/northbridge/intel/sch
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/northbridge/intel/sch')
-rw-r--r--src/northbridge/intel/sch/Kconfig29
-rw-r--r--src/northbridge/intel/sch/Makefile.inc23
-rw-r--r--src/northbridge/intel/sch/acpi.c74
-rw-r--r--src/northbridge/intel/sch/acpi/hostbridge.asl237
-rw-r--r--src/northbridge/intel/sch/acpi/igd.asl324
-rw-r--r--src/northbridge/intel/sch/acpi/peg.asl47
-rw-r--r--src/northbridge/intel/sch/acpi/sch.asl88
-rw-r--r--src/northbridge/intel/sch/chip.h23
-rw-r--r--src/northbridge/intel/sch/early_init.c209
-rw-r--r--src/northbridge/intel/sch/gma.c67
-rw-r--r--src/northbridge/intel/sch/northbridge.c339
-rw-r--r--src/northbridge/intel/sch/nvs.h108
-rw-r--r--src/northbridge/intel/sch/pcie_config.c66
-rw-r--r--src/northbridge/intel/sch/port_access.c75
-rw-r--r--src/northbridge/intel/sch/raminit.c331
-rw-r--r--src/northbridge/intel/sch/raminit.h182
-rw-r--r--src/northbridge/intel/sch/sch.h54
17 files changed, 2276 insertions, 0 deletions
diff --git a/src/northbridge/intel/sch/Kconfig b/src/northbridge/intel/sch/Kconfig
new file mode 100644
index 0000000000..3c9115e99e
--- /dev/null
+++ b/src/northbridge/intel/sch/Kconfig
@@ -0,0 +1,29 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2007-2009 coresystems GmbH
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+config NORTHBRIDGE_INTEL_SCH
+ bool
+ select HAVE_HIGH_TABLES
+
+if NORTHBRIDGE_INTEL_SCH
+
+config FALLBACK_VGA_BIOS_ID
+ string
+ default "8086,8108"
+endif
diff --git a/src/northbridge/intel/sch/Makefile.inc b/src/northbridge/intel/sch/Makefile.inc
new file mode 100644
index 0000000000..ecd2a270b7
--- /dev/null
+++ b/src/northbridge/intel/sch/Makefile.inc
@@ -0,0 +1,23 @@
+#
+# This file is part of the coreboot project.
+#
+# Copyright (C) 2007-2009 coresystems GmbH
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+driver-y += northbridge.c
+driver-y += gma.c
+driver-y += port_access.c
+ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += acpi.c
diff --git a/src/northbridge/intel/sch/acpi.c b/src/northbridge/intel/sch/acpi.c
new file mode 100644
index 0000000000..dbdaf2f7d9
--- /dev/null
+++ b/src/northbridge/intel/sch/acpi.c
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <types.h>
+#include <string.h>
+#include <console/console.h>
+#include <arch/acpi.h>
+#include <arch/acpigen.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+unsigned long acpi_fill_mcfg(unsigned long current)
+{
+ device_t dev;
+ u32 pciexbar = 0;
+ u32 pciexbar_reg;
+ int max_buses;
+
+ dev = dev_find_device(0x8086, 0x27a0, 0);
+ if (!dev)
+ return current;
+
+ pciexbar_reg=pci_read_config32(dev, 0x48);
+
+ // MMCFG not supported or not enabled.
+ if (!(pciexbar_reg & (1 << 0)))
+ return current;
+
+ switch ((pciexbar_reg >> 1) & 3) {
+ case 0: // 256MB
+ pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28));
+ max_buses = 256;
+ break;
+ case 1: // 128M
+ pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27));
+ max_buses = 128;
+ break;
+ case 2: // 64M
+ pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27)|(1 << 26));
+ max_buses = 64;
+ break;
+ default: // RSVD
+ return current;
+ }
+
+ if (!pciexbar)
+ return current;
+#if CONFIG_GENERATE_ACPI_TABLES
+ current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current,
+ pciexbar, 0x0, 0x0, max_buses - 1);
+#endif
+ return current;
+}
+
+
diff --git a/src/northbridge/intel/sch/acpi/hostbridge.asl b/src/northbridge/intel/sch/acpi/hostbridge.asl
new file mode 100644
index 0000000000..a029ef524b
--- /dev/null
+++ b/src/northbridge/intel/sch/acpi/hostbridge.asl
@@ -0,0 +1,237 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+
+Name(_HID,EISAID("PNP0A08")) // PCIe
+Name(_CID,EISAID("PNP0A03")) // PCI
+
+Device (MCHC)
+{
+ Name(_ADR, 0x00000000) // 0:0.0
+
+ OperationRegion(MCHP, PCI_Config, 0x00, 0x100)
+ Field (MCHP, DWordAcc, NoLock, Preserve)
+ {
+ Offset (0x40), // EPBAR
+ EPEN, 1, // Enable
+ , 11, //
+ EPBR, 20, // EPBAR
+
+ Offset (0x44), // MCHBAR
+ MHEN, 1, // Enable
+ , 13, //
+ MHBR, 18, // MCHBAR
+
+ Offset (0x48), // PCIe BAR
+ PXEN, 1, // Enable
+ PXSZ, 2, // BAR size
+ , 23, //
+ PXBR, 6, // PCIe BAR
+
+ Offset (0x4c), // DMIBAR
+ DMEN, 1, // Enable
+ , 11, //
+ DMBR, 20, // DMIBAR
+
+ // ...
+
+ Offset (0x90), // PAM0
+ , 4,
+ PM0H, 2,
+ , 2,
+ Offset (0x91), // PAM1
+ PM1L, 2,
+ , 2,
+ PM1H, 2,
+ , 2,
+ Offset (0x92), // PAM2
+ PM2L, 2,
+ , 2,
+ PM2H, 2,
+ , 2,
+ Offset (0x93), // PAM3
+ PM3L, 2,
+ , 2,
+ PM3H, 2,
+ , 2,
+ Offset (0x94), // PAM4
+ PM4L, 2,
+ , 2,
+ PM4H, 2,
+ , 2,
+ Offset (0x95), // PAM5
+ PM5L, 2,
+ , 2,
+ PM5H, 2,
+ , 2,
+ Offset (0x96), // PAM6
+ PM6L, 2,
+ , 2,
+ PM6H, 2,
+ , 2,
+
+ Offset (0x9c), // Top of Low Used Memory
+ , 3,
+ TLUD, 5,
+
+ Offset (0xa0), // Top of Used Memory
+ TOM, 16,
+ }
+
+}
+
+
+// Current Resource Settings
+
+Method (_CRS, 0, Serialized)
+{
+ Name (MCRS, ResourceTemplate()
+ {
+ // Bus Numbers
+ WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+ 0x0000, 0x0000, 0x00ff, 0x0000, 0x0100,,, PB00)
+
+ // IO Region 0
+ DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, 0x0000, 0x0cf7, 0x0000, 0x0cf8,,, PI00)
+
+ // PCI Config Space
+ Io (Decode16, 0x0cf8, 0x0cf8, 0x0001, 0x0008)
+
+ // IO Region 1
+ DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, 0x0d00, 0xffff, 0x0000, 0xf300,,, PI01)
+
+ // VGA memory (0xa0000-0xbffff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000a0000, 0x000bffff, 0x00000000,
+ 0x00020000,,, ASEG)
+
+ // OPROM reserved (0xc0000-0xc3fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000c0000, 0x000c3fff, 0x00000000,
+ 0x00004000,,, OPR0)
+
+ // OPROM reserved (0xc4000-0xc7fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000c4000, 0x000c7fff, 0x00000000,
+ 0x00004000,,, OPR1)
+
+ // OPROM reserved (0xc8000-0xcbfff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000c8000, 0x000cbfff, 0x00000000,
+ 0x00004000,,, OPR2)
+
+ // OPROM reserved (0xcc000-0xcffff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000cc000, 0x000cffff, 0x00000000,
+ 0x00004000,,, OPR3)
+
+ // OPROM reserved (0xd0000-0xd3fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000d0000, 0x000d3fff, 0x00000000,
+ 0x00004000,,, OPR4)
+
+ // OPROM reserved (0xd4000-0xd7fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000d4000, 0x000d7fff, 0x00000000,
+ 0x00004000,,, OPR5)
+
+ // OPROM reserved (0xd8000-0xdbfff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000d8000, 0x000dbfff, 0x00000000,
+ 0x00004000,,, OPR6)
+
+ // OPROM reserved (0xdc000-0xdffff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000dc000, 0x000dffff, 0x00000000,
+ 0x00004000,,, OPR7)
+
+ // BIOS Extension (0xe0000-0xe3fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000e0000, 0x000e3fff, 0x00000000,
+ 0x00004000,,, ESG0)
+
+ // BIOS Extension (0xe4000-0xe7fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000e4000, 0x000e7fff, 0x00000000,
+ 0x00004000,,, ESG1)
+
+ // BIOS Extension (0xe8000-0xebfff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000e8000, 0x000ebfff, 0x00000000,
+ 0x00004000,,, ESG2)
+
+ // BIOS Extension (0xec000-0xeffff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000ec000, 0x000effff, 0x00000000,
+ 0x00004000,,, ESG3)
+
+ // System BIOS (0xf0000-0xfffff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x000f0000, 0x000fffff, 0x00000000,
+ 0x00010000,,, FSEG)
+
+ // PCI Memory Region (Top of memory-0xfebfffff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0x00000000, 0xfebfffff, 0x00000000,
+ 0x00000000,,, PM01)
+
+ // TPM Area (0xfed40000-0xfed44fff)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, 0xfed40000, 0xfed44fff, 0x00000000,
+ 0x00000000,,, TPMR)
+ })
+
+ // Find PCI resource area in MCRS
+ CreateDwordField(MCRS, PM01._MIN, PMIN)
+ CreateDwordField(MCRS, PM01._MAX, PMAX)
+ CreateDwordField(MCRS, PM01._LEN, PLEN)
+
+ // Fix up PCI memory region:
+ // Enter actual TOLUD. The TOLUD register contains bits 27-31 of
+ // the top of memory address.
+ ShiftLeft (^MCHC.TLUD, 27, PMIN)
+ Add(Subtract(PMAX, PMIN), 1, PLEN)
+
+ Return (MCRS)
+}
+
+/* IRQ assignment is mainboard specific. Get it from mainboard ACPI code */
+#include "acpi/northbridge_pci_irqs.asl"
+
+
diff --git a/src/northbridge/intel/sch/acpi/igd.asl b/src/northbridge/intel/sch/acpi/igd.asl
new file mode 100644
index 0000000000..a6804adb5e
--- /dev/null
+++ b/src/northbridge/intel/sch/acpi/igd.asl
@@ -0,0 +1,324 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Device (GFX0)
+{
+ Name (_ADR, 0x00020000)
+
+ /* Display Output Switching */
+ Method (_DOS, 1)
+ {
+ /* Windows 2000 and Windows XP call _DOS to enable/disable
+ * Display Output Switching during init and while a switch
+ * is already active
+ */
+ Store (And(Arg0, 7), DSEN)
+ }
+
+ /* We try to support as many i945 systems as possible,
+ * so keep the number of DIDs flexible.
+ */
+ Method (_DOD, 0)
+ {
+ If (LEqual(NDID, 1)) {
+ Name(DOD1, Package() {
+ 0xffffffff
+ })
+ Store (Or(0x00010000, DID1), Index(DOD1, 0))
+ Return(DOD1)
+ }
+
+ If (LEqual(NDID, 2)) {
+ Name(DOD2, Package() {
+ 0xffffffff,
+ 0xffffffff
+ })
+ Store (Or(0x00010000, DID2), Index(DOD2, 0))
+ Store (Or(0x00010000, DID2), Index(DOD2, 1))
+ Return(DOD2)
+ }
+
+ If (LEqual(NDID, 3)) {
+ Name(DOD3, Package() {
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff
+ })
+ Store (Or(0x00010000, DID3), Index(DOD3, 0))
+ Store (Or(0x00010000, DID3), Index(DOD3, 1))
+ Store (Or(0x00010000, DID3), Index(DOD3, 2))
+ Return(DOD3)
+ }
+
+ If (LEqual(NDID, 4)) {
+ Name(DOD4, Package() {
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff
+ })
+ Store (Or(0x00010000, DID4), Index(DOD4, 0))
+ Store (Or(0x00010000, DID4), Index(DOD4, 1))
+ Store (Or(0x00010000, DID4), Index(DOD4, 2))
+ Store (Or(0x00010000, DID4), Index(DOD4, 3))
+ Return(DOD4)
+ }
+
+ If (LGreater(NDID, 4)) {
+ Name(DOD5, Package() {
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff,
+ 0xffffffff
+ })
+ Store (Or(0x00010000, DID5), Index(DOD5, 0))
+ Store (Or(0x00010000, DID5), Index(DOD5, 1))
+ Store (Or(0x00010000, DID5), Index(DOD5, 2))
+ Store (Or(0x00010000, DID5), Index(DOD5, 3))
+ Store (Or(0x00010000, DID5), Index(DOD5, 4))
+ Return(DOD5)
+ }
+
+ /* Some error happened, but we have to return something */
+ Return (Package() {0x00000400})
+ }
+
+ Device(DD01)
+ {
+ /* Device Unique ID */
+ Method(_ADR, 0, Serialized)
+ {
+ If(LEqual(DID1, 0)) {
+ Return (1)
+ } Else {
+ Return (And(0xffff, DID1))
+ }
+ }
+
+ /* Device Current Status */
+ Method(_DCS, 0)
+ {
+ TRAP(1)
+ If (And(CSTE, 1)) {
+ Return (0x1f)
+ }
+ Return(0x1d)
+ }
+
+ /* Query Device Graphics State */
+ Method(_DGS, 0)
+ {
+ If (And(NSTE, 1)) {
+ Return(1)
+ }
+ Return(0)
+ }
+
+ /* Device Set State */
+ Method(_DSS, 1)
+ {
+ /* If Parameter Arg0 is (1 << 31) | (1 << 30), the
+ * display switch was completed
+ */
+ If (LEqual(And(Arg0, 0xc0000000), 0xc0000000)) {
+ Store (NSTE, CSTE)
+ }
+ }
+ }
+
+ Device(DD02)
+ {
+ /* Device Unique ID */
+ Method(_ADR, 0, Serialized)
+ {
+ If(LEqual(DID2, 0)) {
+ Return (2)
+ } Else {
+ Return (And(0xffff, DID2))
+ }
+ }
+
+ /* Device Current Status */
+ Method(_DCS, 0)
+ {
+ TRAP(1)
+ If (And(CSTE, 2)) {
+ Return (0x1f)
+ }
+ Return(0x1d)
+ }
+
+ /* Query Device Graphics State */
+ Method(_DGS, 0)
+ {
+ If (And(NSTE, 2)) {
+ Return(1)
+ }
+ Return(0)
+ }
+
+ /* Device Set State */
+ Method(_DSS, 1)
+ {
+ /* If Parameter Arg0 is (1 << 31) | (1 << 30), the
+ * display switch was completed
+ */
+ If (LEqual(And(Arg0, 0xc0000000), 0xc0000000)) {
+ Store (NSTE, CSTE)
+ }
+ }
+ }
+
+
+ Device(DD03)
+ {
+ /* Device Unique ID */
+ Method(_ADR, 0, Serialized)
+ {
+ If(LEqual(DID3, 0)) {
+ Return (3)
+ } Else {
+ Return (And(0xffff, DID3))
+ }
+ }
+
+ /* Device Current Status */
+ Method(_DCS, 0)
+ {
+ TRAP(1)
+ If (And(CSTE, 4)) {
+ Return (0x1f)
+ }
+ Return(0x1d)
+ }
+
+ /* Query Device Graphics State */
+ Method(_DGS, 0)
+ {
+ If (And(NSTE, 4)) {
+ Return(1)
+ }
+ Return(0)
+ }
+
+ /* Device Set State */
+ Method(_DSS, 1)
+ {
+ /* If Parameter Arg0 is (1 << 31) | (1 << 30), the
+ * display switch was completed
+ */
+ If (LEqual(And(Arg0, 0xc0000000), 0xc0000000)) {
+ Store (NSTE, CSTE)
+ }
+ }
+ }
+
+
+ Device(DD04)
+ {
+ /* Device Unique ID */
+ Method(_ADR, 0, Serialized)
+ {
+ If(LEqual(DID4, 0)) {
+ Return (4)
+ } Else {
+ Return (And(0xffff, DID4))
+ }
+ }
+
+ /* Device Current Status */
+ Method(_DCS, 0)
+ {
+ TRAP(1)
+ If (And(CSTE, 8)) {
+ Return (0x1f)
+ }
+ Return(0x1d)
+ }
+
+ /* Query Device Graphics State */
+ Method(_DGS, 0)
+ {
+ If (And(NSTE, 4)) {
+ Return(1)
+ }
+ Return(0)
+ }
+
+ /* Device Set State */
+ Method(_DSS, 1)
+ {
+ /* If Parameter Arg0 is (1 << 31) | (1 << 30), the
+ * display switch was completed
+ */
+ If (LEqual(And(Arg0, 0xc0000000), 0xc0000000)) {
+ Store (NSTE, CSTE)
+ }
+ }
+ }
+
+
+ Device(DD05)
+ {
+ /* Device Unique ID */
+ Method(_ADR, 0, Serialized)
+ {
+ If(LEqual(DID5, 0)) {
+ Return (5)
+ } Else {
+ Return (And(0xffff, DID5))
+ }
+ }
+
+ /* Device Current Status */
+ Method(_DCS, 0)
+ {
+ TRAP(1)
+ If (And(CSTE, 16)) {
+ Return (0x1f)
+ }
+ Return(0x1d)
+ }
+
+ /* Query Device Graphics State */
+ Method(_DGS, 0)
+ {
+ If (And(NSTE, 4)) {
+ Return(1)
+ }
+ Return(0)
+ }
+
+ /* Device Set State */
+ Method(_DSS, 1)
+ {
+ /* If Parameter Arg0 is (1 << 31) | (1 << 30), the
+ * display switch was completed
+ */
+ If (LEqual(And(Arg0, 0xc0000000), 0xc0000000)) {
+ Store (NSTE, CSTE)
+ }
+ }
+ }
+
+}
+
diff --git a/src/northbridge/intel/sch/acpi/peg.asl b/src/northbridge/intel/sch/acpi/peg.asl
new file mode 100644
index 0000000000..bc7f8f7578
--- /dev/null
+++ b/src/northbridge/intel/sch/acpi/peg.asl
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+Device (PEGP)
+{
+ Name (_ADR, 0x00010000)
+
+ // PCI Interrupt Routing.
+ Method (_PRT)
+ {
+ If (PICM) {
+ Return (Package() {
+ Package() { 0x0000ffff, 0, 0, 16 },
+ Package() { 0x0000ffff, 1, 0, 17 },
+ Package() { 0x0000ffff, 2, 0, 18 },
+ Package() { 0x0000ffff, 3, 0, 19 }
+ })
+ } Else {
+ Return (Package() {
+ Package() { 0x0000ffff, 0, \_SB.PCI0.LPCB.LNKA, 0 },
+ Package() { 0x0000ffff, 1, \_SB.PCI0.LPCB.LNKB, 0 },
+ Package() { 0x0000ffff, 2, \_SB.PCI0.LPCB.LNKC, 0 },
+ Package() { 0x0000ffff, 3, \_SB.PCI0.LPCB.LNKD, 0 }
+ })
+ }
+
+ }
+}
+
diff --git a/src/northbridge/intel/sch/acpi/sch.asl b/src/northbridge/intel/sch/acpi/sch.asl
new file mode 100644
index 0000000000..0a11851ea0
--- /dev/null
+++ b/src/northbridge/intel/sch/acpi/sch.asl
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include "../../../northbridge/intel/sch/acpi/hostbridge.asl"
+
+/* PCI Device Resource Consumption */
+Device (PDRC)
+{
+ Name (_HID, EISAID("PNP0C02"))
+ Name (_UID, 1)
+
+ // This does not seem to work correctly yet - set values statically for
+ // now.
+
+ //Name (PDRS, ResourceTemplate() {
+ // Memory32Fixed(ReadWrite, 0x00000000, 0x00004000, RCRB) // RCBA
+ // Memory32Fixed(ReadWrite, 0x00000000, 0x00004000, MCHB) // MCHBAR
+ // Memory32Fixed(ReadWrite, 0x00000000, 0x00001000, DMIB) // DMIBAR
+ // Memory32Fixed(ReadWrite, 0x00000000, 0x00001000, EGPB) // EPBAR
+ // Memory32Fixed(ReadWrite, 0x00000000, 0x00000000, PCIE) // PCIE BAR
+ // Memory32Fixed(ReadWrite, 0xfed20000, 0x00070000, ICHB) // Misc ICH
+ //})
+
+ Name (PDRS, ResourceTemplate() {
+ Memory32Fixed(ReadWrite, 0xfed1c000, 0x00004000) // RCBA
+ Memory32Fixed(ReadWrite, 0xfed14000, 0x00004000) // MCHBAR
+ Memory32Fixed(ReadWrite, 0xfed18000, 0x00001000) // DMIBAR
+ Memory32Fixed(ReadWrite, 0xfed19000, 0x00001000) // EPBAR
+ Memory32Fixed(ReadWrite, 0xf0000000, 0x04000000) // PCIE BAR
+ Memory32Fixed(ReadWrite, 0xfed20000, 0x00020000) // Misc ICH
+ Memory32Fixed(ReadWrite, 0xfed40000, 0x00005000) // Misc ICH
+ Memory32Fixed(ReadWrite, 0xfed45000, 0x0004b000) // Misc ICH
+ })
+
+ // Current Resource Settings
+ Method (_CRS, 0, Serialized)
+ {
+ //CreateDwordField(PDRS, ^RCRB._BAS, RBR0)
+ //ShiftLeft(\_SB.PCI0.LPCB.RCBA, 14, RBR0)
+
+ //CreateDwordField(PDRS, ^MCHB._BAS, MBR0)
+ //ShiftLeft(\_SB.PCI0.MCHC.MHBR, 14, MBR0)
+
+ //CreateDwordField(PDRS, ^DMIB._BAS, DBR0)
+ //ShiftLeft(\_SB.PCI0.MCHC.DMBR, 12, DBR0)
+
+ //CreateDwordField(PDRS, ^EGPB._BAS, EBR0)
+ //ShiftLeft(\_SB.PCI0.MCHC.EPBR, 12, EBR0)
+
+ //CreateDwordField(PDRS, ^PCIE._BAS, PBR0)
+ //ShiftLeft(\_SB.PCI0.MCHC.PXBR, 26, PBR0)
+
+ //CreateDwordField(PDRS, ^PCIE._LEN, PSZ0)
+ //ShiftLeft(0x10000000, \_SB.PCI0.MCHC.PXSZ, PSZ0)
+
+ Return(PDRS)
+ }
+}
+
+// PCIe graphics port 0:1.0
+#include "../../../northbridge/intel/sch/acpi/peg.asl"
+
+// Integrated graphics 0:2.0
+#include "../../../northbridge/intel/sch/acpi/igd.asl"
+
+Scope (\)
+{
+ // backlight control, display switching, lid
+ #include "acpi/video.asl"
+}
diff --git a/src/northbridge/intel/sch/chip.h b/src/northbridge/intel/sch/chip.h
new file mode 100644
index 0000000000..52c2b164c1
--- /dev/null
+++ b/src/northbridge/intel/sch/chip.h
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2010 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+struct northbridge_intel_sch_config {
+};
+
+extern struct chip_operations northbridge_intel_sch_ops;
diff --git a/src/northbridge/intel/sch/early_init.c b/src/northbridge/intel/sch/early_init.c
new file mode 100644
index 0000000000..6ec0169f31
--- /dev/null
+++ b/src/northbridge/intel/sch/early_init.c
@@ -0,0 +1,209 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "sch.h"
+#include "southbridge/intel/sch/sch.h"
+
+#if 0
+static void sch_set_mtrr (void)
+{
+ msr_t msr;
+ printk(BIOS_DEBUG, "1");
+ msr.hi = 0x06060606;
+ msr.lo = 0x06060606;
+ wrmsr (0x250, msr);
+ printk(BIOS_DEBUG, "2");
+ msr.hi = 0x06060606;
+ msr.lo = 0x06060606;
+ wrmsr (0x258, msr);
+ printk(BIOS_DEBUG, "3");
+ msr.hi = 0x0;
+ msr.lo = 0x0;
+ wrmsr (0x259, msr);
+ printk(BIOS_DEBUG, "4");
+ msr.hi = 0x04040404;
+ msr.lo = 0x04040404;
+ wrmsr (0x268, msr);
+ printk(BIOS_DEBUG, "5");
+ msr.hi = 0x04040404;
+ msr.lo = 0x04040404;
+ wrmsr (0x269, msr);
+ printk(BIOS_DEBUG, "6");
+ msr.hi = 0x04040404;
+ msr.lo = 0x04040404;
+ wrmsr (0x26A, msr);
+ printk(BIOS_DEBUG, "7");
+ msr.hi = 0x04040404;
+ msr.lo = 0x04040404;
+ wrmsr (0x26B, msr);
+ printk(BIOS_DEBUG, "8");
+ msr.hi = 0x04040404;
+ msr.lo = 0x04040404;
+ wrmsr (0x26C, msr);
+ printk(BIOS_DEBUG, "9");
+ msr.hi = 0x05050505;
+ msr.lo = 0x05050505;
+ wrmsr (0x26D, msr);
+ printk(BIOS_DEBUG, "10");
+ msr.hi = 0x05050505;
+ msr.lo = 0x05050505;
+ wrmsr (0x26E, msr);
+ printk(BIOS_DEBUG, "11");
+ msr.hi = 0x05050505;
+ msr.lo = 0x05050505;
+ wrmsr (0x26f, msr);
+ printk(BIOS_DEBUG, "12");
+ msr.hi = 0x0;
+ msr.lo = 0x6;
+ wrmsr (0x202, msr);
+ printk(BIOS_DEBUG, "13");
+ msr.hi = 0x0;
+ msr.lo = 0xC0000800;
+ wrmsr (0x203, msr);
+ printk(BIOS_DEBUG, "14");
+ msr.hi = 0x0;
+ msr.lo = 0x3FAF0000;
+ wrmsr (0x204, msr);
+ printk(BIOS_DEBUG, "15");
+ msr.hi = 0x0;
+ msr.lo = 0xFFFF0800;
+ wrmsr (0x205, msr);
+ printk(BIOS_DEBUG, "16");
+ msr.hi = 0x0;
+ msr.lo = 0x3FB00000;
+ wrmsr (0x206, msr);
+ printk(BIOS_DEBUG, "16");
+ msr.hi = 0x0;
+ msr.lo = 0xFFF00800;
+ wrmsr (0x207, msr);
+ printk(BIOS_DEBUG, "17");
+ msr.hi = 0x0;
+ msr.lo = 0x3FC00000;
+ wrmsr (0x208, msr);
+ printk(BIOS_DEBUG, "18");
+ msr.hi = 0x0;
+ msr.lo = 0xFFC00800;
+ wrmsr (0x209, msr);
+ printk(BIOS_DEBUG, "19");
+ msr.hi = 0x0;
+ msr.lo = 0x0;
+ wrmsr (0x20A, msr);
+ printk(BIOS_DEBUG, "20");
+ msr.hi = 0x0;
+ msr.lo = 0x0;
+ wrmsr (0x20B, msr);
+ printk(BIOS_DEBUG, "21");
+ msr.hi = 0x0;
+ msr.lo = 0x0;
+ wrmsr (0x20a, msr);
+ printk(BIOS_DEBUG, "22");
+ msr.hi = 0x0;
+ msr.lo = 0x0;
+ wrmsr (0x20B, msr);
+ printk(BIOS_DEBUG, "23");
+ msr.hi = 0x0;
+ msr.lo = 0x0;
+ wrmsr (0x20c, msr);
+ msr.hi = 0x0;
+ msr.lo = 0x0;
+ wrmsr (0x20d, msr);
+ msr.hi = 0x0;
+ msr.lo = 0x0;
+ wrmsr (0x20E, msr);
+ msr.hi = 0x0;
+ msr.lo = 0x0;
+ wrmsr (0x20F, msr);
+ msr.hi = 0x0;
+ msr.lo = 0XC00;
+ wrmsr (0x2FF, msr);
+ printk(BIOS_DEBUG, "end");
+}
+#endif
+
+static void sch_detect_chipset(void)
+{
+ u16 reg16;
+ u8 reg8;
+ printk(BIOS_INFO, "\n");
+ reg16 = pci_read_config16(PCI_DEV(0, 0x00, 0), 0x2);
+ switch (reg16)
+ {
+ case 0x8101:
+ printk(BIOS_INFO, "UL11L/US15L");
+ break;
+ case 0x8100:
+ printk(BIOS_INFO, "US15W");
+ break;
+ default:
+ printk(BIOS_INFO, "Unknown (%02x)", reg16); /* Others reserved. */
+ }
+ printk(BIOS_INFO, " Chipset\n");
+
+
+ reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0x8);
+ switch (reg8)
+ {
+ case 3:
+ printk(BIOS_INFO, "Qual. Sample ES1, Stepping B1");
+ break;
+ case 4:
+ printk(BIOS_INFO, "Qual. Sample ES2, Stepping C0");
+ break;
+ case 5:
+ printk(BIOS_INFO, "Qual. Sample ES2-Prime, Stepping D0");
+ break;
+ case 6:
+ printk(BIOS_INFO, "Qual. Sample QS, Stepping D1");
+ break;
+
+ default:
+ printk(BIOS_INFO, "Unknown (%02x)", reg8); /* Others reserved. */
+ }
+
+}
+
+static void sch_setup_non_standard_bars(void)
+{
+ printk(BIOS_DEBUG, "Setting up ACPI PM1 block ");
+ pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x48, (0x80000000 |DEFAULT_PMBASE)); /*Address 1000 size 16B*/
+ printk(BIOS_DEBUG, "Setting up ACPI P block ");
+ sch_port_access_write(4,0x70,4,0x80001010);/*Address 1010 size 16B*/
+ pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x40, 0x80001040); /*SM Bus Address 1040 size 64B*/
+ pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x44, 0x80001080); /*GPIO Address 1080 size 64B*/
+ pci_write_config32(PCI_DEV(0, 0x1f, 0), 0x4C, 0x800010C0); /*GPE0 Address 10C0 size 64B*/
+ sch_port_access_write(2,4,4,0x3F703F76); /* FIXME: SMM Control */
+ pci_write_config32(PCI_DEV(0, 0x02, 0), 0x5C, 0x3F800000); /*Base of Stolen memory Address 1080 size 64B*/
+
+ sch_port_access_write(0,0,4, DEFAULT_PCIEXBAR | 1); // pre-b1
+ sch_port_access_write(2,9,4, DEFAULT_PCIEXBAR | 1); // b1+
+
+ /*RCBA*/
+ pci_write_config32(PCI_DEV(0, 0x1f, 0), 0xF0, (DEFAULT_RCBABASE| 1 ));
+ printk(BIOS_DEBUG, " done.\n");
+
+}
+
+static void sch_early_initialization(void)
+{
+ /* Print some chipset specific information */
+ sch_detect_chipset();
+
+ /* Setup all non standard BARs */
+ sch_setup_non_standard_bars();
+}
diff --git a/src/northbridge/intel/sch/gma.c b/src/northbridge/intel/sch/gma.c
new file mode 100644
index 0000000000..28b4624015
--- /dev/null
+++ b/src/northbridge/intel/sch/gma.c
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+static void gma_func0_init(struct device *dev)
+{
+ u32 reg32;
+
+ /* IGD needs to be Bus Master */
+ reg32 = pci_read_config32(dev, PCI_COMMAND);
+ pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER);
+
+ pci_dev_init(dev);
+}
+
+static void gma_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ if (!vendor || !device) {
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ pci_read_config32(dev, PCI_VENDOR_ID));
+ } else {
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+ }
+}
+
+static struct pci_operations gma_pci_ops = {
+ .set_subsystem = gma_set_subsystem,
+};
+
+static struct device_operations gma_func0_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = gma_func0_init,
+ .scan_bus = 0,
+ .enable = 0,
+ .ops_pci = &gma_pci_ops,
+};
+
+
+static const struct pci_driver sch_gma_func0_driver __pci_driver = {
+ .ops = &gma_func0_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x8108,
+};
+
diff --git a/src/northbridge/intel/sch/northbridge.c b/src/northbridge/intel/sch/northbridge.c
new file mode 100644
index 0000000000..bf2870a8aa
--- /dev/null
+++ b/src/northbridge/intel/sch/northbridge.c
@@ -0,0 +1,339 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <arch/io.h>
+#include <stdint.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/hypertransport.h>
+#include <stdlib.h>
+#include <string.h>
+#include <bitops.h>
+#include <cpu/cpu.h>
+#include <boot/tables.h>
+#include "chip.h"
+#include "sch.h"
+
+static int get_pcie_bar(u32 *base, u32 *len)
+{
+ device_t dev;
+ u32 pciexbar_reg;
+
+ dev = dev_find_slot(0, PCI_DEVFN(0, 0));
+ if (!dev)
+ return 0;
+
+ // FIXME: determine at runtime
+#ifdef POULSBO_PRE_B1
+ pciexbar_reg = sch_port_access_read(0,0,4);
+#else
+ pciexbar_reg = sch_port_access_read(2,9,4);
+#endif
+
+ if (!(pciexbar_reg & (1 << 0)))
+ return 0;
+
+ switch ((pciexbar_reg >> 1) & 3) {
+ case 0: // 256MB
+ *base = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28));
+ *len = 256 * 1024 * 1024;
+ return 1;
+ case 1: // 128M
+ *base = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27));
+ *len = 128 * 1024 * 1024;
+ return 1;
+ case 2: // 64M
+ *base = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27)|(1 << 26));
+ *len = 64 * 1024 * 1024;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* IDG memory */
+uint64_t uma_memory_base=0, uma_memory_size=0;
+
+static void add_fixed_resources(struct device *dev, int index)
+{
+ struct resource *resource;
+ u32 pcie_config_base, pcie_config_size;
+
+ printk(BIOS_DEBUG, "Adding UMA memory area\n");
+ resource = new_resource(dev, index);
+ resource->base = (resource_t) uma_memory_base;
+ resource->size = (resource_t) uma_memory_size;
+ resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
+ IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+
+ if (get_pcie_bar(&pcie_config_base, &pcie_config_size)) {
+ printk(BIOS_DEBUG, "Adding PCIe config bar\n");
+ resource = new_resource(dev, index+1);
+ resource->base = (resource_t) pcie_config_base;
+ resource->size = (resource_t) pcie_config_size;
+ resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
+ IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+ }
+
+ printk(BIOS_DEBUG, "Adding CMC shadow area\n");
+ resource = new_resource(dev, index+1);
+ resource->base = (resource_t) CMC_SHADOW;
+ resource->size = (resource_t) (64 * 1024);
+ resource->flags = IORESOURCE_MEM | IORESOURCE_RESERVE |
+ IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+}
+
+
+#if CONFIG_WRITE_HIGH_TABLES==1
+#include <cbmem.h>
+#endif
+
+static void pci_domain_set_resources(device_t dev)
+{
+ uint32_t pci_tolm;
+ uint8_t reg8;
+ uint16_t reg16;
+ unsigned long long tomk, tolud;
+ /* Can we find out how much memory we can use at most
+ * this way?
+ */
+ pci_tolm = find_pci_tolm(dev->link_list);
+ printk(BIOS_DEBUG, "pci_tolm: 0x%x\n", pci_tolm);
+ printk(BIOS_SPEW, "Base of stolen memory: 0x%08x\n",
+ pci_read_config32(dev_find_slot(0, PCI_DEVFN(2, 0)), 0x5c));
+
+ tolud = pci_read_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), 0x9c);
+ printk(BIOS_SPEW, "Top of Low Used DRAM: 0x%08llx\n", tolud << 24);
+
+ tomk = tolud << 14;
+
+ /* Note: subtract IGD device and TSEG */
+ reg8 = pci_read_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), 0x9e);
+ if (reg8 & 1)
+ {
+ int tseg_size = 0;
+ printk(BIOS_DEBUG, "TSEG decoded, subtracting ");
+ reg8 >>= 1;
+ reg8 &= 3;
+ switch (reg8) {
+ case 0:
+ tseg_size = 1024;
+ break; /* TSEG = 1M */
+ case 1:
+ tseg_size = 2048;
+ break; /* TSEG = 2M */
+ case 2:
+ tseg_size = 8192;
+ break; /* TSEG = 8M */
+ }
+
+ printk(BIOS_DEBUG, "%dM\n", tseg_size >> 10);
+ tomk -= tseg_size;
+ }
+
+ reg16 = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0, 0)), GGC);
+ if (!(reg16 & 2))
+ {
+ int uma_size = 0;
+ printk(BIOS_DEBUG, "IGD decoded, subtracting ");
+ reg16 >>= 4;
+ reg16 &= 7;
+ switch (reg16)
+ {
+ case 1:
+ uma_size = 1024;
+ break;
+ case 2:
+ uma_size = 4096;
+ break;
+ case 3:
+ uma_size = 8192;
+ break;
+ }
+ printk(BIOS_DEBUG, "%dM UMA\n", uma_size >> 10);
+ tomk -= uma_size;
+
+ /* For reserving UMA memory in the memory map */
+ uma_memory_base = tomk * 1024ULL;
+ uma_memory_size = uma_size * 1024ULL;
+ }
+
+ /* The following needs to be 2 lines, otherwise the second
+ * number is always 0
+ */
+ printk(BIOS_INFO, "Available memory: %dK", (uint32_t)tomk);
+ printk(BIOS_INFO, " (%dM)\n", (uint32_t)(tomk >> 10));
+
+ /* Report the memory regions */
+ ram_resource(dev, 3, 0, 640);
+ ram_resource(dev, 4, 768, (tomk - 768));
+ if (tomk > 4 * 1024 * 1024) {
+ ram_resource(dev, 5, 4096 * 1024, tomk - 4 * 1024 * 1024);
+ }
+
+ add_fixed_resources(dev, 6);
+
+ assign_resources(dev->link_list);
+
+#if CONFIG_WRITE_HIGH_TABLES==1
+ /* Leave some space for ACPI, PIRQ and MP tables */
+ high_tables_base = (tomk * 1024) - HIGH_MEMORY_SIZE;
+ high_tables_size = HIGH_MEMORY_SIZE;
+#endif
+}
+
+ /* TODO We could determine how many PCIe busses we need in
+ * the bar. For now that number is hardcoded to a max of 64.
+ * See e7525/northbridge.c for an example.
+ */
+static struct device_operations pci_domain_ops = {
+ .read_resources = pci_domain_read_resources,
+ .set_resources = pci_domain_set_resources,
+ .enable_resources = NULL,
+ .init = NULL,
+ .scan_bus = pci_domain_scan_bus,
+#if CONFIG_MMCONF_SUPPORT_DEFAULT
+ .ops_pci_bus = &pci_ops_mmconf,
+#else
+ .ops_pci_bus = &pci_cf8_conf1,
+#endif
+};
+
+static void mc_read_resources(device_t dev)
+{
+ struct resource *resource;
+
+ pci_dev_read_resources(dev);
+
+ /* So, this is one of the big mysteries in the coreboot resource
+ * allocator. This resource should make sure that the address space
+ * of the PCIe memory mapped config space bar. But it does not.
+ */
+
+ /* We use 0xcf as an unused index for our PCIe bar so that we find it again */
+ resource = new_resource(dev, 0xcf);
+ resource->flags =
+ IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
+ IORESOURCE_ASSIGNED;
+ get_pcie_bar((u32*)&resource->base, (u32*)&resource->size);
+ printk(BIOS_DEBUG, "Adding PCIe enhanced config space BAR 0x%08lx-0x%08lx.\n",
+ (unsigned long)(resource->base), (unsigned long)(resource->base + resource->size));
+}
+
+static void mc_set_resources(device_t dev)
+{
+ struct resource *resource;
+
+ /* Report the PCIe BAR */
+ resource = find_resource(dev, 0xcf);
+ if (resource) {
+ report_resource_stored(dev, resource, "<mmconfig>");
+ }
+
+ /* And call the normal set_resources */
+ pci_dev_set_resources(dev);
+}
+
+static void intel_set_subsystem(device_t dev, unsigned vendor, unsigned device)
+{
+ if (!vendor || !device) {
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ pci_read_config32(dev, PCI_VENDOR_ID));
+ } else {
+ pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
+ ((device & 0xffff) << 16) | (vendor & 0xffff));
+ }
+}
+
+#if CONFIG_HAVE_ACPI_RESUME
+extern u8 acpi_slp_type;
+
+static void northbridge_init(struct device *dev)
+{
+ switch (pci_read_config32(dev, SKPAD)) {
+ case 0xcafebabe:
+ printk(BIOS_DEBUG, "Normal boot.\n");
+ acpi_slp_type=0;
+ break;
+ case 0xcafed00d:
+ printk(BIOS_DEBUG, "S3 Resume.\n");
+ acpi_slp_type=3;
+ break;
+ default:
+ printk(BIOS_DEBUG, "Unknown boot method, assuming normal.\n");
+ acpi_slp_type=0;
+ break;
+ }
+}
+#endif
+
+static struct pci_operations intel_pci_ops = {
+ .set_subsystem = intel_set_subsystem,
+};
+
+static struct device_operations mc_ops = {
+ .read_resources = mc_read_resources,
+ .set_resources = mc_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+#if CONFIG_HAVE_ACPI_RESUME
+ .init = northbridge_init,
+#endif
+ .scan_bus = 0,
+ .ops_pci = &intel_pci_ops,
+};
+
+static const struct pci_driver mc_driver __pci_driver = {
+ .ops = &mc_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x8100,
+};
+
+static void cpu_bus_init(device_t dev)
+{
+ initialize_cpus(dev->link_list);
+}
+
+static void cpu_bus_noop(device_t dev)
+{
+}
+
+static struct device_operations cpu_bus_ops = {
+ .read_resources = cpu_bus_noop,
+ .set_resources = cpu_bus_noop,
+ .enable_resources = cpu_bus_noop,
+ .init = cpu_bus_init,
+ .scan_bus = 0,
+};
+
+static void enable_dev(device_t dev)
+{
+ /* Set the operations if it is a special bus type */
+ if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
+ dev->ops = &pci_domain_ops;
+ } else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
+ dev->ops = &cpu_bus_ops;
+ }
+}
+
+struct chip_operations northbridge_intel_sch_ops = {
+ CHIP_NAME("Intel SCH Northbridge")
+ .enable_dev = enable_dev,
+};
diff --git a/src/northbridge/intel/sch/nvs.h b/src/northbridge/intel/sch/nvs.h
new file mode 100644
index 0000000000..3f01f2ace9
--- /dev/null
+++ b/src/northbridge/intel/sch/nvs.h
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+typedef struct {
+ u16 osys;
+ u8 smif;
+ u8 prm0;
+ u8 prm1;
+ u8 scif;
+ u8 prm2;
+ u8 prm3;
+ u8 lckf;
+ u8 prm4;
+ u8 prm5;
+ u32 p80d;
+ u8 lids;
+ u8 pwrs;
+ u8 dbgs;
+ u8 linxs;
+ u8 rsvd;
+ u8 actt;
+ u8 psvt;
+ u8 tc1v;
+ u8 tc2v;
+ u8 tspv;
+ u8 crtt;
+ u8 dtse;
+ u8 dts1;
+ u8 dts2;
+ u8 rsvd2;
+ u8 bnum;
+ u8 b0sc, b1sc, b2sc;
+ u8 b0ss, b1ss, b2ss;
+ u8 rsvd3[3];
+ u8 apic;
+ u8 mpen;
+ u8 bten;
+ u8 ppcm;
+ u8 pcp0;
+ u8 pcp1;
+ u8 rsvd4[4];
+ u8 natp;
+ u8 cmap;
+ u8 cmbp;
+ u8 lptp;
+ u8 fdcp;
+ u8 rfdv;
+ u8 hotk;
+ u8 rtcf;
+ u8 util;
+ u8 acin;
+ u8 igds;
+ u8 tlst;
+ u8 cadl;
+ u8 padl;
+ u16 cste;
+ u16 pste;
+ u16 nste;
+ u16 sste;
+ u8 ndid;
+ u32 did1;
+ u32 did2;
+ u32 did3;
+ u32 did4;
+ u32 did5;
+ u8 rsvd5[0xb];
+ u8 brtl;
+ u8 odds;
+ u8 alse;
+ u8 alaf;
+ u8 llow;
+ u8 lhih;
+ u8 rsvd6;
+ u8 emae;
+ u16 emap;
+ u16 emal;
+ u8 rsvd7;
+ u8 mefe;
+ u8 igps;
+ u8 rsvd8[2];
+ u8 tpmp;
+ u8 tpme;
+ u8 rsvd9[8];
+ u8 gtf0[7];
+ u8 gtf2[7];
+ u8 idem;
+ u8 idet;
+ u8 dock;
+} global_nvs_t;
+
diff --git a/src/northbridge/intel/sch/pcie_config.c b/src/northbridge/intel/sch/pcie_config.c
new file mode 100644
index 0000000000..5cc46a7cbd
--- /dev/null
+++ b/src/northbridge/intel/sch/pcie_config.c
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+static inline __attribute__ ((always_inline))
+u8 pcie_read_config8(device_t dev, unsigned int where)
+{
+ unsigned long addr;
+ addr = DEFAULT_PCIEXBAR | dev | where;
+ return read8(addr);
+}
+
+static inline __attribute__ ((always_inline))
+u16 pcie_read_config16(device_t dev, unsigned int where)
+{
+ unsigned long addr;
+ addr = DEFAULT_PCIEXBAR | dev | where;
+ return read16(addr);
+}
+
+static inline __attribute__ ((always_inline))
+u32 pcie_read_config32(device_t dev, unsigned int where)
+{
+ unsigned long addr;
+ addr = DEFAULT_PCIEXBAR | dev | where;
+ return read32(addr);
+}
+
+static inline __attribute__ ((always_inline))
+void pcie_write_config8(device_t dev, unsigned int where, u8 value)
+{
+ unsigned long addr;
+ addr = DEFAULT_PCIEXBAR | dev | where;
+ write8(addr, value);
+}
+
+static inline __attribute__ ((always_inline))
+void pcie_write_config16(device_t dev, unsigned int where, u16 value)
+{
+ unsigned long addr;
+ addr = DEFAULT_PCIEXBAR | dev | where;
+ write16(addr, value);
+}
+
+static inline __attribute__ ((always_inline))
+void pcie_write_config32(device_t dev, unsigned int where, u32 value)
+{
+ unsigned long addr;
+ addr = DEFAULT_PCIEXBAR | dev | where;
+ write32(addr, value);
+}
diff --git a/src/northbridge/intel/sch/port_access.c b/src/northbridge/intel/sch/port_access.c
new file mode 100644
index 0000000000..73e03c8f81
--- /dev/null
+++ b/src/northbridge/intel/sch/port_access.c
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <device/pci_def.h>
+#include <device/pnp_def.h>
+#include <cpu/x86/lapic.h>
+#include "sch.h"
+
+/*
+ * Restricted Access Regions:
+ *
+ * MCR - Message Control Register
+ * 31 24 16 8 4 0
+ * ----------------------------------------------------------------------------
+ * | | | Target | Write | |
+ * | Opcode | Port | register | byte | Reserved |
+ * | | | Address | Enables | |
+ * ----------------------------------------------------------------------------
+ *
+ * MDR - Message Data Register
+ * 31 0
+ * ----------------------------------------------------------------------------
+ * | |
+ * | Data |
+ * | |
+ * ----------------------------------------------------------------------------
+ *
+ */
+#define MSG_OPCODE_READ 0xD0000000
+#define MSG_OPCODE_WRITE 0xE0000000
+
+#define MCR 0xD0
+#define MDR 0xD4
+
+int sch_port_access_read(int port,int reg, int bytes)
+{
+ pci_write_config32(PCI_DEV(0, 0, 0), MCR, (MSG_OPCODE_READ |(port <<16) | (reg << 8) ));
+ return pci_read_config32(PCI_DEV(0, 0, 0), MDR);
+}
+
+void sch_port_access_write(int port,int reg,int bytes,long data)
+{
+ pci_write_config32(PCI_DEV(0, 0, 0), MDR,data);
+ pci_write_config32(PCI_DEV(0, 0, 0), MCR, (MSG_OPCODE_WRITE |(port <<16) | (reg << 8) ));
+ pci_read_config32(PCI_DEV(0, 0, 0), MDR);
+}
+
+void sch_port_access_write_ram_cmd(int cmd,int port,int reg,int data)
+{
+
+ pci_write_config32(PCI_DEV(0, 0, 0), MDR,data);
+ pci_write_config32(PCI_DEV(0, 0, 0), MCR, ((cmd << 24) |(port <<16) | (reg << 8)));
+ pci_read_config32(PCI_DEV(0, 0, 0), MDR);
+}
+
diff --git a/src/northbridge/intel/sch/raminit.c b/src/northbridge/intel/sch/raminit.c
new file mode 100644
index 0000000000..d2e8af8970
--- /dev/null
+++ b/src/northbridge/intel/sch/raminit.c
@@ -0,0 +1,331 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/cache.h>
+#include <spd.h>
+#include "raminit.h"
+#include "sch.h"
+#define DEBUG_RAM_SETUP
+#define SOFTSTRSP(base, off) *((volatile u8 *)((base) + (off)))
+
+/* Debugging macros. */
+#if defined(DEBUG_RAM_SETUP)
+#define PRINTK_DEBUG(x...) printk(BIOS_DEBUG, x)
+#else
+#define PRINTK_DEBUG(x...)
+#endif
+
+#define BOOT_MODE_RESUME 1
+#define BOOT_MODE_NORMAL 0
+
+#include "port_access.c"
+
+static void detect_fsb(struct sys_info *sysinfo)
+{
+ u32 reg32;
+ reg32 = sch_port_access_read(5, 3, 4);
+ if (reg32 & BIT(3)) {
+ sysinfo->fsb_frequency = 533;
+ } else {
+ sysinfo->fsb_frequency = 400;
+ }
+}
+
+static u32 detect_softstrap_base(void)
+{
+ u32 reg32, base_addr;
+ reg32 = sch_port_access_read(4, 0x71, 2);
+ reg32 &= 0x700;
+ reg32 = reg32 >> 7;
+ switch (reg32) {
+ case 7:
+ base_addr = 0xFFFB0000;
+ break;
+ case 6:
+ base_addr = 0xFFFC0000;
+ break;
+ case 5:
+ base_addr = 0xFFFD0000;
+ break;
+ case 4:
+ base_addr = 0xFFFE0000;
+ break;
+ }
+ return base_addr;
+}
+
+static void detect_softstraps(struct sys_info *sysinfo)
+{
+ u8 reg8, temp;
+ u32 sbase = detect_softstrap_base();
+
+ reg8 = SOFTSTRSP(sbase, 0x87f2);
+ sysinfo->ranks = reg8;
+ if (reg8 == 0) {
+ sysinfo->ram_param_source = RAM_PARAM_SOURCE_SPD;
+ /* FIXME: implement SPD reading */
+ die("no support for reading DIMM config from SPD yet!");
+ return;
+ } else {
+ sysinfo->ram_param_source = RAM_PARAM_SOURCE_SOFTSTRAP;
+ /*Timings from soft strap */
+ reg8 = SOFTSTRSP(sbase, 0x87f0);
+ temp = reg8 & 0x30;
+ temp = temp >> 4;
+ sysinfo->cl = temp;
+ temp = reg8 & 0x0c;
+ temp = temp >> 2;
+ sysinfo->trcd = temp;
+ temp = reg8 & 0x03;
+ sysinfo->trp = temp;
+
+ /*Geometry from Softstrap */
+ reg8 = SOFTSTRSP(sbase, 0x87f1);
+
+ temp = reg8 & 0x06;
+ temp = temp >> 1;
+ sysinfo->device_density = temp;
+
+ temp = reg8 & 0x01;
+ sysinfo->data_width = temp;
+
+ /*Refresh rate default 7.8us */
+ sysinfo->refresh = 3;
+ }
+}
+
+static void program_sch_dram_data(struct sys_info *sysinfo)
+{
+ u32 reg32;
+
+ /* Program DRP DRAM Rank Population and Interface Register
+ * as per data in sysinfo SCH port 1 register 0 .. 0XFF
+ */
+ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+ reg32 &= ~(DRP_FIELDS); /* Clear all DRP fields we'll change */
+ /* Rank0 Device Width, Density, Enable */
+ reg32 |= (sysinfo->data_width) | ((sysinfo->device_density) << 1) | (1 << 3);
+ /* Rank1 Device Width, Density, Enable */
+ reg32 |= (sysinfo->data_width << 4) | ((sysinfo->device_density) << 5) | (1 << 7);
+ sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4, reg32);
+
+ /*
+ Program DTR DRAM Timing Register as per data in sysinfo SCH port 1 register 1
+ tRD_dly = 2 (15:13 = 010b)
+ 0X3F
+ */
+ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DTR, 4);
+ reg32 &= ~(DTR_FIELDS); /* Clear all DTR fields we'll change */
+
+ reg32 = (sysinfo->trp);
+ reg32 |= (sysinfo->trcd) << 2;
+ reg32 |= (sysinfo->cl) << 4;
+ reg32 |= 0X4000; /* tRD_dly = 2 (15:13 = 010b) */
+ sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DTR, 4, reg32);
+
+
+ /* DCO DRAM Controller Operation Register as per data in sysinfo SCH port 1 register 2 0XF */
+ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4);
+ reg32 &= ~(DCO_FIELDS); /*Clear all DTR fields we'll change */
+
+ if (sysinfo->fsb_frequency == 533) {
+ reg32 |= 1;
+ } else {
+ reg32 &= ~(BIT(0));
+ }
+ reg32 = 0x006911c; // FIXME ?
+
+ sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4, reg32);
+}
+
+static void program_dll_config(struct sys_info *sysinfo)
+{
+ if (sysinfo->fsb_frequency == 533) {
+ sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x21, 4, 0x46464646);
+ sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x22, 4, 0x46464646);
+ } else {
+ sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x21, 4, 0x58585858);
+ sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x22, 4, 0x58585858);
+ }
+ sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x23, 4, 0x2222);
+ if (sysinfo->fsb_frequency == 533) {
+ sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x20, 4, 0x993B);
+ } else {
+ sch_port_access_write(SCH_MSG_DUNIT_PORT, 0x20, 4, 0xCC3B);
+ }
+}
+
+static void do_jedec_init(struct sys_info *sysinfo)
+{
+ u32 reg32, rank, cmd, temp, num_ranks;
+ /* Performs JEDEC memory initializattion for all memory rows */
+ /* Set CKE0/1 low */
+ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+ reg32 |= DRP_CKE_DIS;
+ sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4, reg32);
+ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+ rank = 0;
+ num_ranks = sysinfo->ranks;
+ do {
+
+ /* Start clocks */
+ reg32 =
+ sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+ reg32 &= ~(DRP_SCK_DIS); /* Enable all SCK/SCKB by def. */
+ sch_port_access_write(1, SCH_MSG_DUNIT_REG_DRP, 4, reg32);
+ /* Program miscellaneous SCH registers on rank 0 initialization */
+ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+ if (rank == 0) {
+ program_dll_config(sysinfo);
+
+ }
+ printk(BIOS_DEBUG, "Setting up RAM \n");
+ /*
+ Wait 200us
+ reg32 = inb(ACPI_BASE + 8); PM1 Timer
+ reg32 &=0xFFFFFF;
+ reg32 +=0x2EE;
+ do
+ {
+ reg32 = inb(ACPI_BASE + 8);PM1 Timer
+ reg32 &= 0xFFFFFF;
+ }while (reg32 < 0x2EE); */
+ /* Apply NOP */
+ cmd = rank;
+ cmd |= SCH_DRAMINIT_CMD_NOP;
+ sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+ /* Set CKE=high */
+ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+ reg32 &= 0xFFFF9FFF; /* Clear both the CKE static disables */
+ sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4, reg32);
+ /* Wait 400ns (not needed when executing from flash)
+ Precharge all
+ */
+ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DRP, 4);
+ cmd = rank;
+ cmd |= SCH_DRAMINIT_CMD_PALL;
+ sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+
+ /*EMRS(2); High temp self refresh=disabled, partial array self refresh=full */
+ cmd = rank;
+ cmd |= SCH_DRAMINIT_CMD_EMRS2;
+ sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+ /*EMRS(3) (no command) */
+ cmd = rank;
+ cmd |= SCH_DRAMINIT_CMD_EMRS3;
+ sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+ /*EMRS(1); Enable DLL (Leave all bits in the command at 0) */
+ cmd = rank;
+ cmd |= SCH_DRAMINIT_CMD_EMRS1;
+ sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+ /*MRS; Reset DLL (Set memory address bit 8) */
+ cmd = rank;
+ cmd |= SCH_DRAMINIT_CMD_MRS;
+ cmd |= (SCH_JEDEC_DLLRESET << SCH_DRAMINIT_ADDR_OFFSET);
+ sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+ /*Precharge all */
+ cmd = rank;
+ cmd |= SCH_DRAMINIT_CMD_PALL;
+ sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+ /*Issue 2 auto-refresh commands */
+ cmd = rank;
+ cmd |= SCH_DRAMINIT_CMD_AREF;
+ sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+ sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+ /*MRS command including tCL, tWR, burst length (always 4) */
+ cmd = rank;
+ cmd |= (SCH_DRAMINIT_CMD_MRS + JEDEC_STATIC_PARAM); /*Static param */
+ temp = sysinfo->cl;
+ temp += TCL_LOW; /*Adjust for the TCL base */
+ temp = temp << ((SCH_JEDEC_CL_OFFSET + SCH_DRAMINIT_ADDR_OFFSET)); /*Ready the CAS latency */
+ cmd |= temp;
+ sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+ /* Wait 200 clocks (max of 1us, so no need to delay)
+ Issue EMRS(1):OCD default
+ */
+ cmd = rank;
+ cmd |= SCH_DRAMINIT_CMD_EMRS1;
+ cmd |= (SCH_JEDEC_OCD_DEFAULT << SCH_DRAMINIT_ADDR_OFFSET);
+ sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+ /*Issue EMRS(1): OCD cal. mode exit. */
+ cmd = rank;
+ cmd |= SCH_DRAMINIT_CMD_EMRS1;
+ cmd |= (SCH_JEDEC_DQS_DIS << SCH_DRAMINIT_ADDR_OFFSET);
+ sch_port_access_write_ram_cmd(SCH_OPCODE_DRAMINIT, SCH_MSG_DUNIT_PORT, 0, cmd);
+ rank += SCH_DRAMINIT_RANK_MASK;
+ num_ranks--;
+ } while (num_ranks);
+}
+
+/**
+ * @param boot_mode: 0 = normal, 1 = resume
+ */
+
+void sdram_initialize(int boot_mode)
+{
+ struct sys_info sysinfo;
+ u32 reg32;
+
+ printk(BIOS_DEBUG, "Setting up RAM controller.\n");
+
+ memset(&sysinfo, 0, sizeof(sysinfo));
+
+
+ detect_fsb(&sysinfo);
+ detect_softstraps(&sysinfo);
+
+ program_sch_dram_data(&sysinfo);
+
+ /* cold boot */
+ if (boot_mode == BOOT_MODE_NORMAL) {
+ do_jedec_init(&sysinfo);
+ } else {
+ program_dll_config(&sysinfo);
+ }
+
+ /* raminit complete */
+ reg32 = sch_port_access_read(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4);
+ reg32 |= DCO_IC;
+ reg32 |= ((sysinfo.refresh) << 2);
+ reg32 = 0x006919c;
+ sch_port_access_write(SCH_MSG_DUNIT_PORT, SCH_MSG_DUNIT_REG_DCO, 4, reg32);
+
+ /* setting up TOM */
+ reg32 = 0x10000000;
+ reg32 = reg32 >> sysinfo.data_width;
+ reg32 = reg32 << sysinfo.device_density;
+ reg32 = reg32 << sysinfo.ranks;
+ reg32 = 0x40000000;
+ sch_port_access_write(2, 8, 4, reg32);
+
+ /* resume mode */
+ if (boot_mode == BOOT_MODE_RESUME) {
+ sch_port_access_write_ram_cmd(SCH_OPCODE_WAKEFULLON,
+ SCH_MSG_DUNIT_PORT, 0, 0);
+ }
+
+ sch_port_access_write(2, 0, 4, 0x98);
+ sch_port_access_write(2, 3, 4, 0x7);
+ sch_port_access_write(3, 2, 4, 0x408);
+ sch_port_access_write(4, 0x71, 4, 0x600);
+}
+
diff --git a/src/northbridge/intel/sch/raminit.h b/src/northbridge/intel/sch/raminit.h
new file mode 100644
index 0000000000..676667400b
--- /dev/null
+++ b/src/northbridge/intel/sch/raminit.h
@@ -0,0 +1,182 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RAMINIT_H
+#define RAMINIT_H
+
+/**
+ * Bit Equates
+ **/
+#define BIT(x) (1<<x)
+
+#define EBP_TRP_MASK (BIT(1) | BIT(0))
+#define TRP_LOW 3h
+#define TRP_HIGH 5h
+#define EBP_TRP_OFFSET 0 /* Start of TRP field in EBP*/
+#define EBP_TRCD_MASK (BIT(3) | BIT(2))
+#define TRCD_LOW 3h
+#define TRCD_HIGH 5h
+#define EBP_TRCD_OFFSET 2 /* Start of TRCD field in EBP*/
+#define EBP_TCL_MASK (BIT(5) | BIT(4))
+#define TCL_LOW 3 /* Minimum supported CL*/
+#define TCL_HIGH 5 /* Maximum supported CL*/
+#define EBP_TCL_OFFSET 4 /* EBP bit( )for CL mask*/
+#define EBP_DDR2_CL_5_0 BIT(5) /* CL 5.0 = 10b*/
+#define EBP_DDR2_CL_4_0 BIT(4) /* CL 4.0 = 01b*/
+#define EBP_DDR2_CL_3_0 00h /* CL 3.0 = 00b*/
+#define EBP_FREQ_MASK (BIT(10)| BIT(9))
+#define EBP_FREQ_OFFSET 9 /* EBP bit( )for frequency mask*/
+#define EBP_FREQ_400 0 /* 400MHz EBP[10:9] = 00b*/
+#define EBP_FREQ_533 BIT(9) /* 533MHz EBP[10:9] = 01b*/
+#define EBP_REFRESH_MASK (BIT(12)| BIT(11))
+#define EBP_REFRESH_OFFSET 11 /* Bit offset of refresh field*/
+#define EBP_REF_DIS 00h /* Mask for refresh disabled*/
+#define EBP_REF_128CLK BIT(11) /* Mask for 128 clks referesh rate*/
+#define EBP_REF_3_9 BIT(12) /* Mask for 3.9us refresh rate*/
+#define EBP_REF_7_8 (BIT(12)| BIT(11))/* Mask for 7.8us refresh rate*/
+#define EBP_WIDTH_MASK BIT(15)
+#define EBP_WIDTH_OFFSET 15 /* Bit offset of EBP width field*/
+#define EBP_SOCKET_X16 BIT(15) /* Bit mask of x8/x16 bit*/
+#define EBP_DENSITY_MASK (BIT(17)| BIT(16))
+#define EBP_DENSITY_OFFSET 16
+#define EBP_DENSITY_512 BIT(16) /* 512Mbit density*/
+#define EBP_DENSITY_1024 BIT(17) /* 1024Mbit density*/
+#define EBP_DENSITY_2048 (BIT(17)| BIT(16))/* 2048Mbit density*/
+#define EBP_RANKS_MASK BIT(18)
+#define EBP_RANKS_OFFSET 18
+#define EBP_RANKS BIT(18) /* Bit offset of # of ranks bit*/
+#define EBP_PACKAGE_TYPE BIT(19) /* Package type (stacked or not)*/
+#define EBP_2X_MASK BIT(20)
+#define EBP_2X_OFFSET 20 /* Bit offset of ebp 2x refresh field*/
+#define EBP_2X_AUTO_REFRESH BIT(20) /* Bit mask of 2x refresh field*/
+#define EBP_DRAM_PARM_MASK BIT(21)
+#define EBP_DRAM_PARM_OFFSET 21
+#define EBP_DRAM_PARM_SPD 0 /* Use SPD to get DRAM parameters*/
+#define EBP_DRAM_PARM_CMC BIT(21) /* DRAM parameters in CMC binary*/
+#define EBP_BOOT_PATH BIT(31)
+
+
+
+
+#define HB_REG_MCR 0xD0 /* Message Control Register */
+#define HB_REG_MCR_OP_OFFSET 24 /* Offset of the opcode field in MCR */
+#define HB_REG_MCR_PORT_OFFSET 16 /* Offset of the port field in MCR */
+#define HB_REG_MCR_REG_OFFSET 8 /* Offset of the register field in MCR */
+#define HB_REG_MDR 0xD4 /* Message Data Register */
+
+/* SCH Message OpCodes and Attributes*/
+#define SCH_OPCODE_WAKEFULLON 0x2 /* SCH message bus "Wake Full On" opcode*/
+#define SCH_OPCODE_DRAMINIT 0xA0 /* SCH message bus "DRAM Init" opcode */
+#define SCH_DRAMINIT_CMD_MRS 0x4000 /* MRS command */
+#define SCH_DRAMINIT_CMD_EMRS1 0x8 /* EMRS 1 command */
+#define SCH_DRAMINIT_CMD_EMRS2 0x10 /* EMRS 2 command */
+#define SCH_DRAMINIT_CMD_EMRS3 0x18 /* EMRS 3 command */
+#define SCH_DRAMINIT_CMD_CBR 0x1 /* CBR command */
+#define SCH_DRAMINIT_CMD_AREF 0x10001 /* Refresh command, MA10=0->All */
+#define SCH_DRAMINIT_CMD_PALL 0x10002 /* Precharge command, MA10=1->All */
+#define SCH_DRAMINIT_CMD_BACT 0x3 /* Bank activate command */
+#define SCH_DRAMINIT_CMD_NOP 0x7 /* NOP command */
+#define SCH_DRAMINIT_RANK_OFFSET 21 /* Offset of the rank selection bit */
+#define SCH_DRAMINIT_RANK_MASK BIT(21)
+#define SCH_DRAMINIT_ADDR_OFFSET 6 /* Offset of the address field in MDR */
+#define SCH_DRAMINIT_INTLV BIT(3) /* Interleave burst type */
+#define SCH_DRAMINIT_BL4 2 /* Burst Length = 4 */
+#define SCH_DRAMINIT_CL_OFFSET 4 /* CAS Latency bit offset */
+#define SCH_DRAMINIT_OCD_DEFAULT 0xE000 /* OCD Default command */
+#define SCH_DRAMINIT_DQS_DIS BIT(16) /* DQS Disable command */
+#define SCH_OPCODE_READ 0xD0 /* SCH message bus "read" opcode */
+#define SCH_OPCODE_WRITE 0xE0 /* SCH message bus "write" opcode */
+
+/* SCH Message Ports and Registers*/
+
+#define SCH_MSG_DUNIT_PORT 0x1 /* DRAM unit port */
+#define SCH_MSG_DUNIT_REG_DRP 0x0 /* DRAM Rank Population and Interface */
+#define DRP_FIELDS 0xFF /* Pertinent fields in DRP */
+#define DRP_RANK0_OFFSET 3 /* Rank 0 enable offset */
+#define DRP_RANK1_OFFSET 7 /* Rank 1 enable offset */
+#define DRP_DENSITY0_OFFSET 1 /* Density offset - Rank 0 */
+#define DRP_DENSITY1_OFFSET 5 /* Density offset - Rank 1 */
+#define DRP_WIDTH0_OFFSET 0 /* Width offset - Rank 0 */
+#define DRP_WIDTH1_OFFSET 4 /* Width offset - Rank 1 */
+#define DRP_CKE_DIS (BIT(14)| BIT(13)) /* CKE disable bits for both ranks */
+#define DRP_CKE_DIS0 BIT(13) /* CKE disable bit - Rank 0 */
+#define DRP_CKE_DIS1 BIT(14) /* CKE disable bit - Rank 1 */
+#define DRP_SCK_DIS (BIT(11)| BIT(10)) /* SCK/SCKB disable bits */
+#define DRP_SCK_DIS1 BIT(11) /* SCK[1]/SCKB[1] disable */
+#define DRP_SCK_DIS0 BIT(10) /* SCK[0]/SCKB[0] disable */
+#define SCH_MSG_DUNIT_REG_DTR 0x01 /* DRAM Timing Register */
+#define DTR_FIELDS 0x3F /* Pertinent fields in DTR */
+#define DTR_TCL_OFFSET 4 /* CAS latency offset */
+#define DTR_TRCD_OFFSET 2 /* RAS CAS Delay Offset */
+#define DTR_TRP_OFFSET 0 /* RAS Precharge Delay Offset */
+#define SCH_MSG_DUNIT_REG_DCO 0x2 /* DRAM Control Register */
+#define DCO_FIELDS 0xF /* Pertinent fields in DCO */
+#define DCO_REFRESH_OFFSET 2 /* Refresh Rate Field Offset */
+#define DCO_FREQ_OFFSET 0 /* DRAM Frequency Field Offset */
+#define DCO_IC BIT(7) /* Initialization complete bit */
+#define SCH_MSG_PUNIT_PORT 04h /* Punit Port */
+#define SCH_MSG_PUNIT_REG_PCR 71h /* Punit Control Register */
+#define SCH_MSG_TEST_PORT 05h /* Test port */
+#define SCH_MSG_TEST_REG_MSR 03h /* Mode and Status Register */
+
+
+/* Jedec initialization mapping into the MDR address field for DRAM init messages*/
+
+
+#define SCH_JEDEC_DLLRESET BIT(8) /* DLL Reset bit( ) */
+#define SCH_JEDEC_INTLV BIT(3) /* Interleave/NOT(Sequential) bit( ) */
+#define SCH_JEDEC_CL_OFFSET 4 /* Offset of the CAS latency field */
+#define SCH_JEDEC_OCD_DEFAULT (BIT(7)| BIT(8)| BIT(9)) /* OCD default value */
+#define SCH_JEDEC_DQS_DIS BIT(10) /* DQS disable bit */
+#define SCH_JEDEC_BL4 BIT(1) /* Burst length 4 value */
+/*static values used during JEDEC iniatialization. These values are not
+dependent on memory or chipset configuration.*/
+#define JEDEC_STATIC_PARAM ((SCH_JEDEC_INTLV << SCH_DRAMINIT_ADDR_OFFSET) + (SCH_JEDEC_BL4 << SCH_DRAMINIT_ADDR_OFFSET))
+
+#define DIMM_SOCKETS 2
+
+#define DIMM_SPD_BASE 0x50
+#define DIMM_TCO_BASE 0x30
+
+/* Burst length is always 8 */
+#define BURSTLENGTH 8
+#define RAM_PARAM_SOURCE_SOFTSTRAP 1
+#define RAM_PARAM_SOURCE_SPD 0
+struct sys_info {
+
+ u16 memory_frequency; /* 400 or 533*/
+ u16 fsb_frequency; /* 400 or 533*/
+
+ u8 trp; /*3,4,5 DRAM clocks */
+ u8 trcd; /*3,4,5 DRAM clocks */
+ u8 cl; /*CAS Latency 3,4,5*/
+
+ u8 refresh; /*Refresh rate disabled,128 DRAM clocks,3.9us,7.8us */
+
+ u8 data_width; /*x8/x16 data width */
+ u8 device_density; /*SDRAM Device Density 512/1024/2048Mbit */
+ u8 ranks; /*Single/Double */
+ u8 ram_param_source; /*DRAM Parameter Source SPD/SoftStraps(R) Block (down memory) */
+ u8 boot_path;
+
+} __attribute__ ((packed));
+
+void sdram_initialize(int boot_mode);
+
+#endif /* RAMINIT_H */
diff --git a/src/northbridge/intel/sch/sch.h b/src/northbridge/intel/sch/sch.h
new file mode 100644
index 0000000000..f4f334c681
--- /dev/null
+++ b/src/northbridge/intel/sch/sch.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2008 coresystems GmbH
+ * Copyright (C) 2009-2010 iWave Systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __SCH_PULSBO_H__
+#define __SCH_PULSBO_H__ 1
+
+int sch_port_access_read(int port,int reg, int bytes);
+void sch_port_access_write(int port,int reg,int bytes,long data);
+void sch_port_access_write_ram_cmd(int cmd,int port,int reg,int data);
+
+/* Southbridge IO BARs */
+/* TODO Make sure these don't get changed by stage2 */
+#define SCH_ENABLE_BIT (1<<31)
+#define DEFAULT_ACPIPBLKBASE 0x510
+
+#define DEFAULT_SMBUSBASE 0x540
+#define DEFAULT_GPIOBASE 0x588
+#define DEFAULT_GPE0BASE 0x5C0
+#define DEFAULT_SMMCNTRLBASE 0x3F703F76
+
+#define DEFAULT_RCBABASE 0xfed1c000
+
+#define DEFAULT_PCIEXBAR 0xe0000000 /* 4 KB per PCIe device */
+
+/* IGD */
+#define GGC 0x52
+
+/* Root Complex Register Block */
+#define RCBA8(x) *((volatile u8 *)(DEFAULT_RCBABASE + x))
+#define RCBA16(x) *((volatile u16 *)(DEFAULT_RCBABASE + x))
+#define RCBA32(x) *((volatile u32 *)(DEFAULT_RCBABASE + x))
+
+/* FIXME: should probably be in southbridge, but is setup in romstage, too */
+#define CMC_SHADOW 0x3faf0000
+
+#endif