diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cpu/amd/family_10h-family_15h/init_cpus.c | 18 | ||||
-rw-r--r-- | src/cpu/amd/family_10h-family_15h/model_10xxx_init.c | 22 | ||||
-rw-r--r-- | src/northbridge/amd/amdfam10/northbridge.c | 144 | ||||
-rw-r--r-- | src/northbridge/amd/amdht/h3ncmn.c | 22 |
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 |