summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/amd/family_10h-family_15h/init_cpus.c18
-rw-r--r--src/cpu/amd/family_10h-family_15h/model_10xxx_init.c22
-rw-r--r--src/northbridge/amd/amdfam10/northbridge.c144
-rw-r--r--src/northbridge/amd/amdht/h3ncmn.c22
4 files changed, 203 insertions, 3 deletions
diff --git a/src/cpu/amd/family_10h-family_15h/init_cpus.c b/src/cpu/amd/family_10h-family_15h/init_cpus.c
index 14d8642083..530ffd2c6f 100644
--- a/src/cpu/amd/family_10h-family_15h/init_cpus.c
+++ b/src/cpu/amd/family_10h-family_15h/init_cpus.c
@@ -347,9 +347,11 @@ static void STOP_CAR_AND_CPU(uint8_t skip_sharedc_config, uint32_t apicid)
static u32 init_cpus(u32 cpu_init_detectedx, struct sys_info *sysinfo)
{
- u32 bsp_apicid = 0;
- u32 apicid;
+ uint32_t bsp_apicid = 0;
+ uint32_t apicid;
+ uint32_t dword;
uint8_t set_mtrrs;
+ uint8_t node_count;
struct node_core_id id;
/* Please refer to the calculations and explaination in cache_as_ram.inc before modifying these values */
@@ -441,6 +443,18 @@ static u32 init_cpus(u32 cpu_init_detectedx, struct sys_info *sysinfo)
cpuSetAMDMSR(id.nodeid);
+ /* Set up HyperTransport probe filter support */
+ if (is_gt_rev_d()) {
+ dword = pci_read_config32(NODE_PCI(id.nodeid, 0), 0x60);
+ node_count = ((dword >> 4) & 0x7) + 1;
+
+ if (node_count > 1) {
+ msr_t msr = rdmsr(BU_CFG2_MSR);
+ msr.hi |= 1 << (42 - 32);
+ wrmsr(BU_CFG2_MSR, msr);
+ }
+ }
+
#if CONFIG_SET_FIDVID
#if CONFIG_LOGICAL_CPUS && CONFIG_SET_FIDVID_CORE0_ONLY
// Run on all AP for proper FID/VID setup.
diff --git a/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c b/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c
index 3bda14c95a..fe9fb9cd0c 100644
--- a/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c
+++ b/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c
@@ -50,6 +50,28 @@ static inline uint8_t is_fam15h(void)
return fam15h;
}
+static inline uint8_t is_gt_rev_d(void)
+{
+ uint8_t fam15h = 0;
+ uint8_t rev_gte_d = 0;
+ uint32_t family;
+ uint32_t model;
+
+ family = model = cpuid_eax(0x80000001);
+ model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
+ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
+
+ if (family >= 0x6f)
+ /* Family 15h or later */
+ fam15h = 1;
+
+ if ((model >= 0x8) || fam15h)
+ /* Revision D or later */
+ rev_gte_d = 1;
+
+ return rev_gte_d;
+}
+
static volatile uint8_t fam15h_startup_flags[MAX_NODES_SUPPORTED][MAX_CORES_SUPPORTED] = {{ 0 }};
static void model_10xxx_init(device_t dev)
diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c
index a922496b10..2684d89449 100644
--- a/src/northbridge/amd/amdfam10/northbridge.c
+++ b/src/northbridge/amd/amdfam10/northbridge.c
@@ -26,10 +26,13 @@
#include <lib.h>
#include <smbios.h>
#include <cpu/cpu.h>
+#include <delay.h>
#include <cpu/x86/lapic.h>
+#include <cpu/x86/cache.h>
#include <cpu/amd/mtrr.h>
#include <cpu/amd/amdfam10_sysconf.h>
+#include <cpu/amd/model_10xxx_msr.h>
#include <cpu/amd/family_10h-family_15h/ram_calc.h>
#if CONFIG_LOGICAL_CPUS
@@ -1523,7 +1526,7 @@ static void cpu_bus_scan(device_t dev)
if(i>=32) {
busn--;
devn-=32;
- pbus = pci_domain->link_list->next);
+ pbus = pci_domain->link_list->next;
}
#endif
@@ -1643,8 +1646,147 @@ static void cpu_bus_scan(device_t dev)
}
}
+static void detect_and_enable_probe_filter(device_t dev)
+{
+ uint32_t dword;
+
+ uint8_t fam15h = 0;
+ uint8_t rev_gte_d = 0;
+ uint8_t dual_node = 0;
+ unsigned nb_cfg_54;
+ uint32_t f3xe8;
+ uint32_t family;
+ uint32_t model;
+
+ family = model = cpuid_eax(0x80000001);
+ model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
+
+ if (is_fam15h()) {
+ /* Family 15h or later */
+ fam15h = 1;
+ nb_cfg_54 = 1;
+ }
+
+ if ((model >= 0x8) || fam15h)
+ /* Revision D or later */
+ rev_gte_d = 1;
+
+ if (rev_gte_d)
+ /* Check for dual node capability */
+ if (f3xe8 & 0x20000000)
+ dual_node = 1;
+
+ if (rev_gte_d && (sysconf.nodes > 1)) {
+ /* Enable the probe filter */
+ uint8_t i;
+ uint8_t pfmode = 0x0;
+
+ uint32_t f3x58[MAX_NODES_SUPPORTED];
+ uint32_t f3x5c[MAX_NODES_SUPPORTED];
+
+ printk(BIOS_DEBUG, "Enabling probe filter\n");
+
+ /* Disable L3 and DRAM scrubbers and configure system for probe filter support */
+ for (i = 0; i < sysconf.nodes; i++) {
+ device_t f2x_dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 2));
+ device_t f3x_dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 3));
+
+ f3x58[i] = pci_read_config32(f3x_dev, 0x58);
+ f3x5c[i] = pci_read_config32(f3x_dev, 0x5c);
+ pci_write_config32(f3x_dev, 0x58, f3x58[i] & ~((0x1f << 24) | 0x1f));
+ pci_write_config32(f3x_dev, 0x5c, f3x5c[i] & ~0x1);
+
+ dword = pci_read_config32(f2x_dev, 0x1b0);
+ dword &= ~(0x7 << 8); /* CohPrefPrbLmt = 0x0 */
+ pci_write_config32(f2x_dev, 0x1b0, dword);
+
+ msr_t msr = rdmsr_amd(BU_CFG2_MSR);
+ msr.hi |= 1 << (42 - 32);
+ wrmsr_amd(BU_CFG2_MSR, msr);
+
+ if (is_fam15h()) {
+ uint8_t subcache_size = 0x0;
+ uint8_t pref_so_repl = 0x0;
+ uint32_t f3x1c4 = pci_read_config32(f3x_dev, 0x1c4);
+ if ((f3x1c4 & 0xffff) == 0xcccc) {
+ subcache_size = 0x1;
+ pref_so_repl = 0x2;
+ pfmode = 0x3;
+ } else {
+ pfmode = 0x2;
+ }
+
+ dword = pci_read_config32(f3x_dev, 0x1d4);
+ dword |= 0x1 << 29; /* PFLoIndexHashEn = 0x1 */
+ dword &= ~(0x3 << 20); /* PFPreferredSORepl = pref_so_repl */
+ dword |= (pref_so_repl & 0x3) << 20;
+ dword |= 0x1 << 17; /* PFWayHashEn = 0x1 */
+ dword |= 0xf << 12; /* PFSubCacheEn = 0xf */
+ dword &= ~(0x3 << 10); /* PFSubCacheSize3 = subcache_size */
+ dword |= (subcache_size & 0x3) << 10;
+ dword &= ~(0x3 << 8); /* PFSubCacheSize2 = subcache_size */
+ dword |= (subcache_size & 0x3) << 8;
+ dword &= ~(0x3 << 6); /* PFSubCacheSize1 = subcache_size */
+ dword |= (subcache_size & 0x3) << 6;
+ dword &= ~(0x3 << 4); /* PFSubCacheSize0 = subcache_size */
+ dword |= (subcache_size & 0x3) << 4;
+ dword &= ~(0x3 << 2); /* PFWayNum = 0x2 */
+ dword |= 0x2 << 2;
+ pci_write_config32(f3x_dev, 0x1d4, dword);
+ } else {
+ pfmode = 0x2;
+
+ dword = pci_read_config32(f3x_dev, 0x1d4);
+ dword |= 0x1 << 29; /* PFLoIndexHashEn = 0x1 */
+ dword &= ~(0x3 << 20); /* PFPreferredSORepl = 0x2 */
+ dword |= 0x2 << 20;
+ dword |= 0xf << 12; /* PFSubCacheEn = 0xf */
+ dword &= ~(0x3 << 10); /* PFSubCacheSize3 = 0x0 */
+ dword &= ~(0x3 << 8); /* PFSubCacheSize2 = 0x0 */
+ dword &= ~(0x3 << 6); /* PFSubCacheSize1 = 0x0 */
+ dword &= ~(0x3 << 4); /* PFSubCacheSize0 = 0x0 */
+ dword &= ~(0x3 << 2); /* PFWayNum = 0x2 */
+ dword |= 0x2 << 2;
+ pci_write_config32(f3x_dev, 0x1d4, dword);
+ }
+ }
+
+ udelay(40);
+
+ disable_cache();
+ wbinvd();
+ for (i = 0; i < sysconf.nodes; i++) {
+ device_t f3x_dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 3));
+
+ dword = pci_read_config32(f3x_dev, 0x1c4);
+ dword |= (0x1 << 31); /* L3TagInit = 1 */
+ pci_write_config32(f3x_dev, 0x1c4, dword);
+ do {
+ } while (pci_read_config32(f3x_dev, 0x1c4) & (0x1 << 31));
+
+ dword = pci_read_config32(f3x_dev, 0x1d4);
+ dword &= ~0x3; /* PFMode = pfmode */
+ dword |= pfmode & 0x3;
+ pci_write_config32(f3x_dev, 0x1d4, dword);
+ do {
+ } while (!(pci_read_config32(f3x_dev, 0x1d4) & (0x1 << 19)));
+ }
+ enable_cache();
+
+ /* Reenable L3 and DRAM scrubbers */
+ for (i = 0; i < sysconf.nodes; i++) {
+ device_t f3x_dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 3));
+
+ pci_write_config32(f3x_dev, 0x58, f3x58[i]);
+ pci_write_config32(f3x_dev, 0x5c, f3x5c[i]);
+ }
+
+ }
+}
+
static void cpu_bus_init(device_t dev)
{
+ detect_and_enable_probe_filter(dev);
initialize_cpus(dev->link_list);
#if CONFIG_AMD_SB_CIMX
sb_After_Pci_Init();
diff --git a/src/northbridge/amd/amdht/h3ncmn.c b/src/northbridge/amd/amdht/h3ncmn.c
index 01c0e48d0c..8ee929d12e 100644
--- a/src/northbridge/amd/amdht/h3ncmn.c
+++ b/src/northbridge/amd/amdht/h3ncmn.c
@@ -103,6 +103,28 @@ static inline uint8_t is_fam15h(void)
return fam15h;
}
+static inline uint8_t is_gt_rev_d(void)
+{
+ uint8_t fam15h = 0;
+ uint8_t rev_gte_d = 0;
+ uint32_t family;
+ uint32_t model;
+
+ family = model = cpuid_eax(0x80000001);
+ model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
+ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
+
+ if (family >= 0x6f)
+ /* Family 15h or later */
+ fam15h = 1;
+
+ if ((model >= 0x8) || fam15h)
+ /* Revision D or later */
+ rev_gte_d = 1;
+
+ return rev_gte_d;
+}
+
/***************************************************************************//**
*
* SBDFO