From be61a173512ece32de01562995a91fbbf3f5b335 Mon Sep 17 00:00:00 2001 From: Patrick Georgi Date: Sat, 18 Dec 2010 07:48:43 +0000 Subject: 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 Acked-by: Peter Stuge git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6198 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/northbridge/intel/sch/Kconfig | 29 +++ src/northbridge/intel/sch/Makefile.inc | 23 ++ src/northbridge/intel/sch/acpi.c | 74 ++++++ src/northbridge/intel/sch/acpi/hostbridge.asl | 237 ++++++++++++++++++ src/northbridge/intel/sch/acpi/igd.asl | 324 ++++++++++++++++++++++++ src/northbridge/intel/sch/acpi/peg.asl | 47 ++++ src/northbridge/intel/sch/acpi/sch.asl | 88 +++++++ src/northbridge/intel/sch/chip.h | 23 ++ src/northbridge/intel/sch/early_init.c | 209 ++++++++++++++++ src/northbridge/intel/sch/gma.c | 67 +++++ src/northbridge/intel/sch/northbridge.c | 339 ++++++++++++++++++++++++++ src/northbridge/intel/sch/nvs.h | 108 ++++++++ src/northbridge/intel/sch/pcie_config.c | 66 +++++ src/northbridge/intel/sch/port_access.c | 75 ++++++ src/northbridge/intel/sch/raminit.c | 331 +++++++++++++++++++++++++ src/northbridge/intel/sch/raminit.h | 182 ++++++++++++++ src/northbridge/intel/sch/sch.h | 54 ++++ 17 files changed, 2276 insertions(+) create mode 100644 src/northbridge/intel/sch/Kconfig create mode 100644 src/northbridge/intel/sch/Makefile.inc create mode 100644 src/northbridge/intel/sch/acpi.c create mode 100644 src/northbridge/intel/sch/acpi/hostbridge.asl create mode 100644 src/northbridge/intel/sch/acpi/igd.asl create mode 100644 src/northbridge/intel/sch/acpi/peg.asl create mode 100644 src/northbridge/intel/sch/acpi/sch.asl create mode 100644 src/northbridge/intel/sch/chip.h create mode 100644 src/northbridge/intel/sch/early_init.c create mode 100644 src/northbridge/intel/sch/gma.c create mode 100644 src/northbridge/intel/sch/northbridge.c create mode 100644 src/northbridge/intel/sch/nvs.h create mode 100644 src/northbridge/intel/sch/pcie_config.c create mode 100644 src/northbridge/intel/sch/port_access.c create mode 100644 src/northbridge/intel/sch/raminit.c create mode 100644 src/northbridge/intel/sch/raminit.h create mode 100644 src/northbridge/intel/sch/sch.h (limited to 'src/northbridge/intel/sch') 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 +#include +#include +#include +#include +#include +#include +#include + +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 +#include +#include +#include + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 +#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, ""); + } + + /* 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 +#include +#include +#include +#include +#include +#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 +#include +#include +#include +#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<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 -- cgit v1.2.3