Denis Carikli (GNUtoo@no-log.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3282
-gerrit
commit 55683fb38609a0402ce4f564733188b7779ff414 Author: Denis 'GNUtoo' Carikli GNUtoo@no-log.org Date: Thu May 23 23:36:08 2013 +0200
northbridge/intel/i945: Add TSEG Enabling support.
The resource part of that patch is based on the following commit: e6c3b1d30d3fa88af6da6fcc115aa6cba3c55d1c (haswell: include TSEG region in cacheable memory)
Change-Id: I11fb5cb4083850ab0b1dc7cca86a59760aafbd17 Signed-off-by: Denis 'GNUtoo' Carikli GNUtoo@no-log.org --- src/cpu/x86/smm/smmhandler_tseg.S | 31 ++++++++++++++++- src/cpu/x86/smm/smmrelocate.S | 31 +++++++++++++++-- src/northbridge/intel/i945/Kconfig | 4 +++ src/northbridge/intel/i945/Makefile.inc | 1 + src/northbridge/intel/i945/northbridge.c | 58 +++++++++++++++++++------------- src/northbridge/intel/i945/raminit.c | 34 +++++++++++++++++++ src/northbridge/intel/i945/raminit.h | 9 +++++ src/northbridge/intel/i945/smi.c | 37 ++++++++++++++++++++ 8 files changed, 178 insertions(+), 27 deletions(-)
diff --git a/src/cpu/x86/smm/smmhandler_tseg.S b/src/cpu/x86/smm/smmhandler_tseg.S index eb5d63c..a9cff6c 100644 --- a/src/cpu/x86/smm/smmhandler_tseg.S +++ b/src/cpu/x86/smm/smmhandler_tseg.S @@ -63,6 +63,7 @@ #elif CONFIG_NORTHBRIDGE_INTEL_HASWELL #include <northbridge/intel/haswell/haswell.h> #define TSEG_BAR (DEFAULT_PCIEXBAR | TSEG) +#elif CONFIG_NORTHBRIDGE_INTEL_I945 #else #error "Northbridge must define TSEG_BAR." #endif @@ -82,8 +83,22 @@ * All the bad magic is not all that bad after all. */ smm_handler_start: +#if CONFIG_NORTHBRIDGE_INTEL_I945 + /* tolud_base = pci_read_config8(PCI_DEV(0, 0, 0), TOLUD); */ + movl $0x8000009c, %eax + movw $0xcf8, %dx + outl %eax, %dx + movw $0xcfc, %dx + inl %dx, %eax + + /* tseg_base = tolud - CONFIG_I915_UMA_SIZE - CONFIG_SMM_TSEG_SIZE*/ + subl $CONFIG_I915_UMA_SIZE, %eax + subl $CONFIG_SMM_TSEG_SIZE, %eax + movl %eax, %edx +#else movl $(TSEG_BAR), %eax /* Get TSEG base from PCIE */ addr32 movl (%eax), %edx /* Save TSEG_BAR in %edx */ +#endif andl $~1, %edx /* Remove lock bit */
/* Obtain lock */ @@ -195,8 +210,22 @@ smm_prot_start: call smi_handler
/* Release lock */ +#if CONFIG_NORTHBRIDGE_INTEL_I945 + /* tolud_base = pci_read_config8(PCI_DEV(0, 0, 0), TOLUD); */ + movl $0x8000009c, %eax + movw $0xcf8, %dx + outl %eax, %dx + movw $0xcfc, %dx + inl %dx, %eax + + /* tseg_base = tolud - CONFIG_I915_UMA_SIZE - CONFIG_SMM_TSEG_SIZE*/ + subl $CONFIG_I915_UMA_SIZE, %eax + subl $CONFIG_SMM_TSEG_SIZE, %eax + movl %eax, %ebx +#else movl $(TSEG_BAR), %eax /* Get TSEG base from PCIE */ - movl (%eax), %ebx /* Save TSEG_BAR in %ebx */ + movl (%eax), %ebx /* Save TSEG_BAR in %ebx */ +#endif andl $~1, %ebx /* Remove lock bit */ addl $(smm_lock), %ebx movw $SMI_UNLOCKED, %ax diff --git a/src/cpu/x86/smm/smmrelocate.S b/src/cpu/x86/smm/smmrelocate.S index 16d4b9f..8c20579 100644 --- a/src/cpu/x86/smm/smmrelocate.S +++ b/src/cpu/x86/smm/smmrelocate.S @@ -48,6 +48,7 @@ #if CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE || CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE #include <northbridge/intel/sandybridge/sandybridge.h> #define TSEG_BAR (DEFAULT_PCIEXBAR | TSEG) +#elif CONFIG_NORTHBRIDGE_INTEL_I945 #else #error "Northbridge must define TSEG_BAR." #endif @@ -148,8 +149,21 @@ smm_relocate: shl $10, %edx
#if CONFIG_SMM_TSEG +#if CONFIG_NORTHBRIDGE_INTEL_I945 + /* tolud_base = pci_read_config8(PCI_DEV(0, 0, 0), TOLUD); */ + movl $0x8000009c, %eax + movw $0xcf8, %dx + outl %eax, %dx + movw $0xcfc, %dx + inl %dx, %eax + + /* tseg_base = tolud - CONFIG_I915_UMA_SIZE - CONFIG_SMM_TSEG_SIZE*/ + subl $CONFIG_I915_UMA_SIZE, %eax + subl $CONFIG_SMM_TSEG_SIZE, %eax +#else movl $(TSEG_BAR), %ecx /* Get TSEG base from PCIE */ - addr32 movl (%ecx), %eax /* Save TSEG_BAR in %eax */ + addr32 movl (%ecx), %eax /* Save TSEG_BAR in %eax */ +#endif andl $~1, %eax /* Remove lock bit */ #else movl $0xa0000, %eax @@ -166,8 +180,21 @@ smm_relocate: jnc skip_smrr
/* TSEG base */ +#if CONFIG_NORTHBRIDGE_INTEL_I945 + /* tolud_base = pci_read_config8(PCI_DEV(0, 0, 0), TOLUD); */ + movl $0x8000009c, %eax + movw $0xcf8, %dx + outl %eax, %dx + movw $0xcfc, %dx + inl %dx, %eax + + /* tseg_base = tolud - CONFIG_I915_UMA_SIZE - CONFIG_SMM_TSEG_SIZE*/ + subl $CONFIG_I915_UMA_SIZE, %eax + subl $CONFIG_SMM_TSEG_SIZE, %eax +#else movl $(TSEG_BAR), %ecx /* Get TSEG base from PCIE */ - addr32 movl (%ecx), %eax /* Save TSEG_BAR in %eax */ + addr32 movl (%ecx), %eax /* Save TSEG_BAR in %eax */ +#endif andl $~1, %eax /* Remove lock bit */ movl %eax, %ebx
diff --git a/src/northbridge/intel/i945/Kconfig b/src/northbridge/intel/i945/Kconfig index aec3e33..52cd0f6 100644 --- a/src/northbridge/intel/i945/Kconfig +++ b/src/northbridge/intel/i945/Kconfig @@ -66,4 +66,8 @@ config CHECK_SLFRCS_ON_RESUME On other boards the check always creates a false positive, effectively making it impossible to resume.
+config I915_UMA_SIZE + hex + default 0x800000 + endif diff --git a/src/northbridge/intel/i945/Makefile.inc b/src/northbridge/intel/i945/Makefile.inc index 92a8849..6fea3e0 100644 --- a/src/northbridge/intel/i945/Makefile.inc +++ b/src/northbridge/intel/i945/Makefile.inc @@ -27,3 +27,4 @@ romstage-y += errata.c romstage-y += debug.c
smm-y += udelay.c +smm-y += smi.c diff --git a/src/northbridge/intel/i945/northbridge.c b/src/northbridge/intel/i945/northbridge.c index 9d97f0c..5cd32f6 100644 --- a/src/northbridge/intel/i945/northbridge.c +++ b/src/northbridge/intel/i945/northbridge.c @@ -88,6 +88,9 @@ static void pci_domain_set_resources(device_t dev) uint16_t reg16; unsigned long long tomk, tomk_stolen; uint64_t tseg_memory_base = 0, tseg_memory_size = 0; +#if CONFIG_SMM_TSEG + struct resource *resource; +#endif
/* Can we find out how much memory we can use at most * this way? @@ -105,6 +108,29 @@ static void pci_domain_set_resources(device_t dev) tomk_stolen = tomk;
/* Note: subtract IGD device and TSEG */ + 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 3: + uma_size = 8192; + break; + } + + printk(BIOS_DEBUG, "%dM UMA\n", uma_size >> 10); + tomk_stolen -= uma_size; + + /* For reserving UMA memory in the memory map */ + uma_memory_base = tomk_stolen * 1024ULL; + uma_memory_size = uma_size * 1024ULL; + } + reg8 = pci_read_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), 0x9e); if (reg8 & 1) { int tseg_size = 0; @@ -131,29 +157,6 @@ static void pci_domain_set_resources(device_t dev) tseg_memory_size = tseg_size * 1024ULL; }
- 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 3: - uma_size = 8192; - break; - } - - printk(BIOS_DEBUG, "%dM UMA\n", uma_size >> 10); - tomk_stolen -= uma_size; - - /* For reserving UMA memory in the memory map */ - uma_memory_base = tomk_stolen * 1024ULL; - uma_memory_size = uma_size * 1024ULL; - } - /* The following needs to be 2 lines, otherwise the second * number is always 0 */ @@ -173,8 +176,15 @@ static void pci_domain_set_resources(device_t dev) /* Leave some space for ACPI, PIRQ and MP tables */ high_tables_base = (tomk_stolen * 1024) - HIGH_MEMORY_SIZE; high_tables_size = HIGH_MEMORY_SIZE; +#if CONFIG_SMM_TSEG + resource = new_resource(dev, 8); + resource->base = tseg_memory_base; + resource->size = tseg_memory_size; + resource->flags = IORESOURCE_MEM | IORESOURCE_FIXED | + IORESOURCE_STORED | IORESOURCE_RESERVE | + IORESOURCE_ASSIGNED | IORESOURCE_CACHEABLE; +#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. diff --git a/src/northbridge/intel/i945/raminit.c b/src/northbridge/intel/i945/raminit.c index b1a0684..edd6b6a 100644 --- a/src/northbridge/intel/i945/raminit.c +++ b/src/northbridge/intel/i945/raminit.c @@ -3052,6 +3052,36 @@ static void sdram_setup_processor_side(void) MCHBAR32(SLPCTL) |= (1 << 8); }
+#if CONFIG_SMM_TSEG +static void sdram_enable_tseg(void) +{ + u8 reg8; + + reg8 = pci_read_config8(PCI_DEV(0, 0, 0), ESMRAM); + reg8 |= (1 << 0); /* TSEG Enable */ + + switch(CONFIG_SMM_TSEG_SIZE){ + + case 0x100000: + reg8 &= ~((1<<2)|(1<<1)); + break; + case 0x200000: + reg8 &= ~(1<<1); + reg8 |= (1<<2); + break; + case 0x800000: + reg8 |= (1<<2)|(1<<1); + break; + default: + /* it should not happen because we guard + * ainst that in the raminit.h header + */ + printk(BIOS_ERR, "Invalid TSEG size!\n"); + } + pci_write_config8(PCI_DEV(0, 0, 0), ESMRAM, reg8); +} +#endif + /** * @param boot_path: 0 = normal, 1 = reset, 2 = resume from s3 */ @@ -3180,6 +3210,10 @@ void sdram_initialize(int boot_path, const u8 *spd_addresses) /* Enable Periodic RCOMP */ sdram_enable_rcomp();
+#if CONFIG_SMM_TSEG + sdram_enable_tseg(); +#endif + /* Tell ICH7 that we're done */ reg8 = pci_read_config8(PCI_DEV(0,0x1f,0), 0xa2); reg8 &= ~(1 << 7); diff --git a/src/northbridge/intel/i945/raminit.h b/src/northbridge/intel/i945/raminit.h index 2d8ef9e..7f08af5 100644 --- a/src/northbridge/intel/i945/raminit.h +++ b/src/northbridge/intel/i945/raminit.h @@ -75,5 +75,14 @@ void udelay(u32 us);
#if CONFIG_DEBUG_RAM_SETUP void sdram_dump_mchbar_registers(void); + +#if CONFIG_SMM_TSEG +#if ! (CONFIG_SMM_TSEG_SIZE == 0x100000 || \ + CONFIG_SMM_TSEG_SIZE == 0x200000 || \ + CONFIG_SMM_TSEG_SIZE == 0x800000) +#error Invalid TSEG size +#endif +#endif + #endif #endif /* RAMINIT_H */ diff --git a/src/northbridge/intel/i945/smi.c b/src/northbridge/intel/i945/smi.c new file mode 100644 index 0000000..0993b12 --- /dev/null +++ b/src/northbridge/intel/i945/smi.c @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2013 Denis 'GNUtoo' Carikli + * + * 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 <arch/io.h> +#include <cpu/x86/smm.h> +#include "i945.h" + +#if CONFIG_SMM_TSEG +static u32 tseg_base = 0; +u32 smi_get_tseg_base(void) +{ + if (!tseg_base) + tseg_base = pci_read_config8(PCI_DEV(0, 0, 0), TOLUD) - + CONFIG_I915_UMA_SIZE - CONFIG_SMM_TSEG_SIZE; + return tseg_base; +} +#endif +