nb/amd/fam10: Drop support
Relocatable ramstage, postcar stage and C_ENVIRONMENT_BOOTBLOCK are now mandatory features, which this platform lacks. Change-Id: If36ef0749dbb661f731fb04829bd7e2202ebb422 Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/c/coreboot/+/36962 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: HAOUAS Elyes <ehaouas@noos.fr> Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
parent
1ca978ee65
commit
ffcac3eb50
112 changed files with 5 additions and 48884 deletions
|
|
@ -505,7 +505,7 @@ static void config_power_ctrl_misc_reg(pci_devfn_t dev, uint64_t cpuRev,
|
|||
}
|
||||
|
||||
/* TODO: look into C1E state and F3xA0[IdleExitEn]*/
|
||||
#if CONFIG(SVI_HIGH_FREQ)
|
||||
#if 0
|
||||
if (cpuRev & AMD_FAM10_C3) {
|
||||
dword |= SVI_HIGH_FREQ_ON;
|
||||
}
|
||||
|
|
@ -585,7 +585,7 @@ static void config_acpi_pwr_state_ctrl_regs(pci_devfn_t dev, uint64_t cpuRev,
|
|||
if (cpuRev & AMD_DR_Bx ) {
|
||||
smaf001 = 0xA6;
|
||||
} else {
|
||||
#if CONFIG(SVI_HIGH_FREQ)
|
||||
#if 0
|
||||
if (cpuRev & (AMD_RB_C3 | AMD_DA_C3)) {
|
||||
smaf001 = 0xF6;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -576,7 +576,7 @@ static void start_node(u8 node)
|
|||
/* Enable routing table */
|
||||
printk(BIOS_DEBUG, "Start node %02x", node);
|
||||
|
||||
#if CONFIG(NORTHBRIDGE_AMD_AMDFAM10)
|
||||
#if 0
|
||||
/* For FAM10 support, we need to set Dram base/limit for the new node */
|
||||
pci_write_config32(NODE_MP(node), 0x44, 0);
|
||||
pci_write_config32(NODE_MP(node), 0x40, 3);
|
||||
|
|
|
|||
|
|
@ -218,13 +218,6 @@ DEVTREE_CONST struct bus *pci_root_bus(void)
|
|||
|
||||
DEVTREE_CONST struct device *pcidev_path_on_root(pci_devfn_t devfn)
|
||||
{
|
||||
/* Work around pcidev_path_behind() below failing
|
||||
* due tue complicated devicetree with topology
|
||||
* being manipulated on-the-fly.
|
||||
*/
|
||||
if (CONFIG(NORTHBRIDGE_AMD_AMDFAM10))
|
||||
return dev_find_slot(0, devfn);
|
||||
|
||||
return pcidev_path_behind(pci_root_bus(), devfn);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,7 @@ static inline bool offset_unit_id(bool is_sb_ht_chain)
|
|||
{
|
||||
bool need_offset = (CONFIG_HT_CHAIN_UNITID_BASE != 1)
|
||||
|| (CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20);
|
||||
return need_offset && (!CONFIG(SB_HT_CHAIN_UNITID_OFFSET_ONLY)
|
||||
|| is_sb_ht_chain);
|
||||
return need_offset && is_sb_ht_chain;
|
||||
}
|
||||
|
||||
#endif /* DEVICE_HYPERTRANSPORT_DEF_H */
|
||||
|
|
|
|||
|
|
@ -128,5 +128,5 @@ Device(NBF3) {
|
|||
Name(_ADR, 0x00180003)
|
||||
|
||||
/* k10temp thermal zone */
|
||||
#include <northbridge/amd/amdfam10/thermal_mixin.asl>
|
||||
#include "thermal_mixin.asl"
|
||||
} /* end NBF3 */
|
||||
|
|
|
|||
|
|
@ -1,145 +0,0 @@
|
|||
##
|
||||
## This file is part of the coreboot project.
|
||||
##
|
||||
## Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
## 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.
|
||||
##
|
||||
|
||||
config NORTHBRIDGE_AMD_AMDFAM10
|
||||
bool
|
||||
select HAVE_DEBUG_RAM_SETUP
|
||||
select HAVE_DEBUG_SMBUS
|
||||
select HAVE_DEBUG_CAR
|
||||
select HYPERTRANSPORT_PLUGIN_SUPPORT
|
||||
select PCIEXP_ASPM
|
||||
select PCIEXP_COMMON_CLOCK
|
||||
select PCIEXP_CLK_PM
|
||||
select PCIEXP_L1_SUB_STATE
|
||||
select NO_RELOCATABLE_RAMSTAGE
|
||||
|
||||
if NORTHBRIDGE_AMD_AMDFAM10
|
||||
config AGP_APERTURE_SIZE
|
||||
hex
|
||||
default 0x4000000
|
||||
|
||||
config HW_MEM_HOLE_SIZEK
|
||||
hex
|
||||
default 0x100000
|
||||
|
||||
config MMCONF_BASE_ADDRESS
|
||||
hex
|
||||
default 0xc0000000
|
||||
|
||||
config MMCONF_BUS_NUMBER
|
||||
int
|
||||
default 256
|
||||
|
||||
# TODO: Reservation for heap seems excessive
|
||||
config HEAP_SIZE
|
||||
hex
|
||||
default 0xc0000
|
||||
|
||||
config BOOTBLOCK_NORTHBRIDGE_INIT
|
||||
string
|
||||
default "northbridge/amd/amdfam10/bootblock.c"
|
||||
|
||||
config SB_HT_CHAIN_UNITID_OFFSET_ONLY
|
||||
bool
|
||||
default n
|
||||
|
||||
config HT_CHAIN_DISTRIBUTE
|
||||
def_bool n
|
||||
|
||||
config DIMM_DDR2
|
||||
bool
|
||||
default n
|
||||
|
||||
config DIMM_DDR3
|
||||
bool
|
||||
default n
|
||||
|
||||
config DIMM_REGISTERED
|
||||
bool
|
||||
default n
|
||||
|
||||
config DIMM_VOLTAGE_SET_SUPPORT
|
||||
bool
|
||||
default n
|
||||
|
||||
config S3_DATA_SIZE
|
||||
int
|
||||
default 32768
|
||||
depends on (HAVE_ACPI_RESUME)
|
||||
|
||||
config S3_DATA_POS
|
||||
hex
|
||||
default 0x0
|
||||
depends on (HAVE_ACPI_RESUME)
|
||||
|
||||
config SVI_HIGH_FREQ
|
||||
bool
|
||||
default n
|
||||
help
|
||||
Select this for boards with a Voltage Regulator able to operate
|
||||
at 3.4 MHz in SVI mode. Ignored unless the AMD CPU is rev C3.
|
||||
|
||||
menu "HyperTransport setup"
|
||||
#could be implemented for K8 (NORTHBRIDGE_AMD_AMDK8)
|
||||
depends on (NORTHBRIDGE_AMD_AMDFAM10)
|
||||
|
||||
choice
|
||||
prompt "HyperTransport downlink width"
|
||||
default LIMIT_HT_DOWN_WIDTH_16
|
||||
help
|
||||
This option sets the maximum permissible HyperTransport
|
||||
downlink width.
|
||||
|
||||
Use of this option will only limit the autodetected HT width.
|
||||
It will not (and cannot) increase the width beyond the autodetected
|
||||
limits.
|
||||
|
||||
This is primarily used to work around poorly designed or laid out HT
|
||||
traces on certain motherboards.
|
||||
|
||||
config LIMIT_HT_DOWN_WIDTH_8
|
||||
bool "8 bits"
|
||||
config LIMIT_HT_DOWN_WIDTH_16
|
||||
bool "16 bits"
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "HyperTransport uplink width"
|
||||
default LIMIT_HT_UP_WIDTH_16
|
||||
help
|
||||
This option sets the maximum permissible HyperTransport
|
||||
uplink width.
|
||||
|
||||
Use of this option will only limit the autodetected HT width.
|
||||
It will not (and cannot) increase the width beyond the autodetected
|
||||
limits.
|
||||
|
||||
This is primarily used to work around poorly designed or laid out HT
|
||||
traces on certain motherboards.
|
||||
|
||||
config LIMIT_HT_UP_WIDTH_8
|
||||
bool "8 bits"
|
||||
config LIMIT_HT_UP_WIDTH_16
|
||||
bool "16 bits"
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
|
||||
config MAX_REBOOT_CNT
|
||||
int
|
||||
default 6
|
||||
|
||||
endif # NORTHBRIDGE_AMD_AMDFAM10
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
ifeq ($(CONFIG_NORTHBRIDGE_AMD_AMDFAM10),y)
|
||||
|
||||
subdirs-y += ../amdht
|
||||
subdirs-y += ../amdmct/wrappers
|
||||
subdirs-$(CONFIG_DIMM_DDR3) += ../amdmct/mct_ddr3
|
||||
subdirs-$(CONFIG_DIMM_DDR2) += ../amdmct/mct
|
||||
|
||||
# Generic ROMSTAGE stuff
|
||||
romstage-y += reset_test.c debug.c setup_resource_map.c raminit_sysinfo_in_ram.c
|
||||
romstage-y += raminit_amdmct.c pci.c early_ht.c amdfam10_util.c
|
||||
|
||||
# RAMSTAGE
|
||||
ramstage-y += northbridge.c misc_control.c link_control.c nb_control.c
|
||||
ramstage-y += amdfam10_util.c ht_config.c get_pci1234.c
|
||||
ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
|
||||
|
||||
# Enable this if you want to check the values of the PCI routing registers.
|
||||
# Call show_all_routes() anywhere amdfam10.h is included.
|
||||
#ramstage-y += util.c
|
||||
|
||||
# Reserve 2x CONFIG_S3_DATA_SIZE to allow for random file placement
|
||||
# (not respecting erase sector boundaries) within CBFS
|
||||
$(obj)/coreboot_s3nv.rom: $(obj)/config.h
|
||||
echo " S3 NVRAM $(CONFIG_S3_DATA_POS) (S3 storage area)"
|
||||
# force C locale, so cygwin awk doesn't try to interpret the 0xff below as UTF-8 (or worse)
|
||||
printf %d $(CONFIG_S3_DATA_SIZE) | LC_ALL=C awk '{for (i=0; i<$$1*2; i++) {printf "%c", 255}}' > $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
cbfs-files-$(CONFIG_HAVE_ACPI_RESUME) += s3nv
|
||||
s3nv-file := $(obj)/coreboot_s3nv.rom
|
||||
s3nv-align := $(CONFIG_S3_DATA_SIZE)
|
||||
s3nv-type := raw
|
||||
|
||||
endif
|
||||
|
|
@ -1,351 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <console/console.h>
|
||||
#include <string.h>
|
||||
#include <arch/acpi.h>
|
||||
#include <arch/acpigen.h>
|
||||
#include <device/pci.h>
|
||||
#include <cpu/x86/msr.h>
|
||||
#include <cpu/amd/mtrr.h>
|
||||
#include <cpu/amd/amdfam10_sysconf.h>
|
||||
#include "amdfam10.h"
|
||||
|
||||
//it seems some functions can be moved arch/x86/boot/acpi.c
|
||||
|
||||
unsigned long acpi_create_madt_lapic_nmis(unsigned long current, u16 flags, u8 lint)
|
||||
{
|
||||
struct device *cpu;
|
||||
int cpu_index = 0;
|
||||
|
||||
for (cpu = all_devices; cpu; cpu = cpu->next) {
|
||||
if ((cpu->path.type != DEVICE_PATH_APIC) ||
|
||||
(cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
|
||||
continue;
|
||||
}
|
||||
if (!cpu->enabled) {
|
||||
continue;
|
||||
}
|
||||
current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)current, cpu_index, flags, lint);
|
||||
cpu_index++;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
unsigned long acpi_create_srat_lapics(unsigned long current)
|
||||
{
|
||||
struct device *cpu;
|
||||
int cpu_index = 0;
|
||||
|
||||
for (cpu = all_devices; cpu; cpu = cpu->next) {
|
||||
if ((cpu->path.type != DEVICE_PATH_APIC) ||
|
||||
(cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
|
||||
continue;
|
||||
}
|
||||
if (!cpu->enabled) {
|
||||
continue;
|
||||
}
|
||||
printk(BIOS_DEBUG, "SRAT: lapic cpu_index=%02x, node_id=%02x, apic_id=%02x\n", cpu_index, cpu->path.apic.node_id, cpu->path.apic.apic_id);
|
||||
current += acpi_create_srat_lapic((acpi_srat_lapic_t *)current, cpu->path.apic.node_id, cpu->path.apic.apic_id);
|
||||
cpu_index++;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
static unsigned long resk(uint64_t value)
|
||||
{
|
||||
unsigned long resultk;
|
||||
if (value < (1ULL << 42)) {
|
||||
resultk = value >> 10;
|
||||
} else {
|
||||
resultk = 0xffffffff;
|
||||
}
|
||||
return resultk;
|
||||
}
|
||||
|
||||
struct acpi_srat_mem_state {
|
||||
unsigned long current;
|
||||
};
|
||||
|
||||
static void set_srat_mem(void *gp, struct device *dev, struct resource *res)
|
||||
{
|
||||
struct acpi_srat_mem_state *state = gp;
|
||||
unsigned long basek, sizek;
|
||||
basek = resk(res->base);
|
||||
sizek = resk(res->size);
|
||||
|
||||
printk(BIOS_DEBUG, "set_srat_mem: dev %s, res->index=%04lx startk=%08lx, sizek=%08lx\n",
|
||||
dev_path(dev), res->index, basek, sizek);
|
||||
/*
|
||||
* 0-640K must be on node 0
|
||||
* next range is from 1M---
|
||||
* So will cut off before 1M in the mem range
|
||||
*/
|
||||
if ((basek+sizek)<1024) return;
|
||||
|
||||
if (basek < 1024) {
|
||||
sizek -= 1024 - basek;
|
||||
basek = 1024;
|
||||
}
|
||||
|
||||
// need to figure out NV
|
||||
if (res->index > 0xf) /* Exclude MMIO resources, e.g. as set in northbridge.c amdfam10_domain_read_resources() */
|
||||
state->current += acpi_create_srat_mem((acpi_srat_mem_t *)state->current, (res->index & 0xf), basek, sizek, 1);
|
||||
}
|
||||
|
||||
static unsigned long acpi_fill_srat(unsigned long current)
|
||||
{
|
||||
struct acpi_srat_mem_state srat_mem_state;
|
||||
|
||||
/* create all subtables for processors */
|
||||
current = acpi_create_srat_lapics(current);
|
||||
|
||||
/* create all subteble for memory range */
|
||||
|
||||
/* 0-640K must be on node 0 */
|
||||
current += acpi_create_srat_mem((acpi_srat_mem_t *)current, 0, 0, 640, 1);//enable
|
||||
|
||||
srat_mem_state.current = current;
|
||||
search_global_resources(
|
||||
IORESOURCE_MEM | IORESOURCE_CACHEABLE, IORESOURCE_MEM | IORESOURCE_CACHEABLE,
|
||||
set_srat_mem, &srat_mem_state);
|
||||
|
||||
current = srat_mem_state.current;
|
||||
return current;
|
||||
}
|
||||
|
||||
static unsigned long acpi_fill_slit(unsigned long current)
|
||||
{
|
||||
/* Implement SLIT algorithm in BKDG Rev. 3.62 Section 2.3.6.1
|
||||
* Fill the first 8 bytes with the node number,
|
||||
* then fill the next num*num byte with the distance,
|
||||
* Distance entries vary with topology; the local node
|
||||
* is always 10.
|
||||
*
|
||||
* Fully connected:
|
||||
* Set all non-local nodes to 16
|
||||
*
|
||||
* Partially connected; with probe filter:
|
||||
* Set all non-local nodes to 10+(num_hops*6)
|
||||
*
|
||||
* Partially connected; without probe filter:
|
||||
* Set all non-local nodes to 13
|
||||
*
|
||||
* FIXME
|
||||
* The partially connected cases are not implemented;
|
||||
* once a means is found to detect partially connected
|
||||
* topologies, implement the remaining cases.
|
||||
*/
|
||||
|
||||
u8 *p = (u8 *)current;
|
||||
int nodes = sysconf.nodes;
|
||||
int i,j;
|
||||
|
||||
memset(p, 0, 8+nodes*nodes);
|
||||
*p = (u8) nodes;
|
||||
p += 8;
|
||||
|
||||
for (i = 0; i < nodes; i++) {
|
||||
for (j = 0; j < nodes; j++) {
|
||||
if (i == j)
|
||||
p[i*nodes+j] = 10;
|
||||
else
|
||||
p[i*nodes+j] = 16;
|
||||
}
|
||||
}
|
||||
|
||||
current += 8+nodes*nodes;
|
||||
return current;
|
||||
}
|
||||
|
||||
void update_ssdtx(void *ssdtx, int i)
|
||||
{
|
||||
u8 *PCI;
|
||||
u8 *HCIN;
|
||||
u8 *UID;
|
||||
|
||||
PCI = ssdtx + 0x32;
|
||||
HCIN = ssdtx + 0x39;
|
||||
UID = ssdtx + 0x40;
|
||||
|
||||
if (i < 7) {
|
||||
*PCI = (u8) ('4' + i - 1);
|
||||
} else {
|
||||
*PCI = (u8) ('A' + i - 1 - 6);
|
||||
}
|
||||
*HCIN = (u8) i;
|
||||
*UID = (u8) (i + 3);
|
||||
|
||||
/* FIXME: need to update the GSI id in the ssdtx too */
|
||||
|
||||
}
|
||||
|
||||
void northbridge_acpi_write_vars(struct device *device)
|
||||
{
|
||||
/*
|
||||
* If more than one physical CPU is installed, northbridge_acpi_write_vars()
|
||||
* is called more than once and the resultant SSDT table is corrupted
|
||||
* (duplicated entries).
|
||||
* This prevents Linux from booting, with log messages like these:
|
||||
* ACPI Error: [BUSN] Namespace lookup failure, AE_ALREADY_EXISTS (/dswload-353)
|
||||
* ACPI Exception: AE_ALREADY_EXISTS, During name lookup/catalog (/psobject-222)
|
||||
* followed by a slew of ACPI method failures and a hang when the invalid PCI
|
||||
* resource entries are used.
|
||||
* This routine prevents the SSDT table from being corrupted.
|
||||
*/
|
||||
static uint8_t ssdt_generated = 0;
|
||||
if (ssdt_generated)
|
||||
return;
|
||||
ssdt_generated = 1;
|
||||
|
||||
msr_t msr;
|
||||
char pscope[] = "\\_SB.PCI0";
|
||||
int i;
|
||||
|
||||
acpigen_write_scope(pscope);
|
||||
|
||||
acpigen_write_name("BUSN");
|
||||
acpigen_write_package(HC_NUMS);
|
||||
for (i = 0; i < HC_NUMS; i++) {
|
||||
acpigen_write_dword(sysconf.ht_c_conf_bus[i]);
|
||||
}
|
||||
// minus the opcode
|
||||
acpigen_pop_len();
|
||||
|
||||
acpigen_write_name("MMIO");
|
||||
|
||||
acpigen_write_package(HC_NUMS * 4);
|
||||
|
||||
for (i = 0; i<(HC_NUMS*2); i++) { // FIXME: change to more chain
|
||||
acpigen_write_dword(sysconf.conf_mmio_addrx[i]); //base
|
||||
acpigen_write_dword(sysconf.conf_mmio_addr[i]); //mask
|
||||
}
|
||||
// minus the opcode
|
||||
acpigen_pop_len();
|
||||
|
||||
acpigen_write_name("PCIO");
|
||||
|
||||
acpigen_write_package(HC_NUMS * 2);
|
||||
|
||||
for (i = 0; i < HC_NUMS; i++) { // FIXME: change to more chain
|
||||
acpigen_write_dword(sysconf.conf_io_addrx[i]);
|
||||
acpigen_write_dword(sysconf.conf_io_addr[i]);
|
||||
}
|
||||
|
||||
// minus the opcode
|
||||
acpigen_pop_len();
|
||||
|
||||
acpigen_write_name_byte("SBLK", sysconf.sblk);
|
||||
|
||||
msr = rdmsr(TOP_MEM);
|
||||
acpigen_write_name_dword("TOM1", msr.lo);
|
||||
|
||||
msr = rdmsr(TOP_MEM2);
|
||||
/*
|
||||
* Since XP only implements parts of ACPI 2.0, we can't use a qword
|
||||
* here.
|
||||
* See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt
|
||||
* slide 22ff.
|
||||
* Shift value right by 20 bit to make it fit into 32bit,
|
||||
* giving us 1MB granularity and a limit of almost 4Exabyte of memory.
|
||||
*/
|
||||
acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20);
|
||||
|
||||
|
||||
acpigen_write_name_dword("SBDN", sysconf.sbdn);
|
||||
|
||||
acpigen_write_name("HCLK");
|
||||
|
||||
acpigen_write_package(HC_POSSIBLE_NUM);
|
||||
|
||||
for (i = 0; i < sysconf.hc_possible_num; i++) {
|
||||
acpigen_write_dword(sysconf.pci1234[i]);
|
||||
}
|
||||
for (i = sysconf.hc_possible_num; i < HC_POSSIBLE_NUM; i++) { // in case we set array size to other than 8
|
||||
acpigen_write_dword(0x00000000);
|
||||
}
|
||||
// minus the opcode
|
||||
acpigen_pop_len();
|
||||
|
||||
acpigen_write_name("HCDN");
|
||||
|
||||
acpigen_write_package(HC_POSSIBLE_NUM);
|
||||
|
||||
for (i = 0; i < sysconf.hc_possible_num; i++) {
|
||||
acpigen_write_dword(sysconf.hcdn[i]);
|
||||
}
|
||||
for (i = sysconf.hc_possible_num; i < HC_POSSIBLE_NUM; i++) { // in case we set array size to other than 8
|
||||
acpigen_write_dword(0x20202020);
|
||||
}
|
||||
// minus the opcode
|
||||
acpigen_pop_len();
|
||||
|
||||
acpigen_write_name_byte("CBB", CONFIG_CBB);
|
||||
|
||||
u8 CBST, CBB2, CBS2;
|
||||
|
||||
if (CONFIG_CBB == 0xff) {
|
||||
CBST = (u8) (0x0f);
|
||||
} else {
|
||||
if ((sysconf.pci1234[0] >> 12) & 0xff) { //sb chain on other than bus 0
|
||||
CBST = (u8) (0x0f);
|
||||
} else {
|
||||
CBST = (u8) (0x00);
|
||||
}
|
||||
}
|
||||
|
||||
acpigen_write_name_byte("CBST", CBST);
|
||||
|
||||
if ((CONFIG_CBB == 0xff) && (sysconf.nodes > 32)) {
|
||||
CBS2 = 0x0f;
|
||||
CBB2 = (u8)(CONFIG_CBB-1);
|
||||
} else {
|
||||
CBS2 = 0x00;
|
||||
CBB2 = 0x00;
|
||||
}
|
||||
|
||||
acpigen_write_name_byte("CBB2", CBB2);
|
||||
acpigen_write_name_byte("CBS2", CBS2);
|
||||
|
||||
//minus opcode
|
||||
acpigen_pop_len();
|
||||
}
|
||||
|
||||
unsigned long northbridge_write_acpi_tables(struct device *device,
|
||||
unsigned long current,
|
||||
struct acpi_rsdp *rsdp)
|
||||
{
|
||||
acpi_srat_t *srat;
|
||||
acpi_slit_t *slit;
|
||||
|
||||
/* SRAT */
|
||||
current = ALIGN(current, 8);
|
||||
printk(BIOS_DEBUG, "ACPI: * SRAT at %lx\n", current);
|
||||
srat = (acpi_srat_t *) current;
|
||||
acpi_create_srat(srat, acpi_fill_srat);
|
||||
current += srat->header.length;
|
||||
acpi_add_table(rsdp, srat);
|
||||
|
||||
/* SLIT */
|
||||
current = ALIGN(current, 8);
|
||||
printk(BIOS_DEBUG, "ACPI: * SLIT at %lx\n", current);
|
||||
slit = (acpi_slit_t *) current;
|
||||
acpi_create_slit(slit, acpi_fill_slit);
|
||||
current += slit->header.length;
|
||||
acpi_add_table(rsdp, slit);
|
||||
|
||||
return current;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,321 +0,0 @@
|
|||
//
|
||||
// This file is part of the coreboot project.
|
||||
//
|
||||
// Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
// Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
//AMD FAM10 util for BUSB and res range
|
||||
|
||||
Scope (\_SB)
|
||||
{
|
||||
|
||||
Name (OSTB, Ones)
|
||||
Method (OSVR, 0, NotSerialized)
|
||||
{
|
||||
If (LEqual (^OSTB, Ones))
|
||||
{
|
||||
Store (0x00, ^OSTB)
|
||||
}
|
||||
|
||||
Return (^OSTB)
|
||||
}
|
||||
|
||||
Method (SEQL, 2, Serialized)
|
||||
{
|
||||
Store (SizeOf (Arg0), Local0)
|
||||
Store (SizeOf (Arg1), Local1)
|
||||
If (LNot (LEqual (Local0, Local1))) { Return (Zero) }
|
||||
|
||||
Name (BUF0, Buffer (Local0) {})
|
||||
Store (Arg0, BUF0)
|
||||
Name (BUF1, Buffer (Local0) {})
|
||||
Store (Arg1, BUF1)
|
||||
Store (Zero, Local2)
|
||||
While (LLess (Local2, Local0))
|
||||
{
|
||||
Store (DerefOf (Index (BUF0, Local2)), Local3)
|
||||
Store (DerefOf (Index (BUF1, Local2)), Local4)
|
||||
If (LNot (LEqual (Local3, Local4))) { Return (Zero) }
|
||||
|
||||
Increment (Local2)
|
||||
}
|
||||
|
||||
Return (One)
|
||||
}
|
||||
|
||||
|
||||
Method (DADD, 2, NotSerialized)
|
||||
{
|
||||
Store(Arg1, Local0)
|
||||
Store(Arg0, Local1)
|
||||
Add(ShiftLeft(Local1,16), Local0, Local0)
|
||||
Return (Local0)
|
||||
}
|
||||
|
||||
|
||||
Method (GHCE, 1, NotSerialized) // check if the HC enabled
|
||||
{
|
||||
Store (DerefOf (Index (\_SB.PCI0.HCLK, Arg0)), Local1)
|
||||
if (LEqual (And(Local1, 0x01), 0x01)) { Return (0x0F) }
|
||||
Else { Return (0x00) }
|
||||
}
|
||||
|
||||
Method (GHCN, 1, NotSerialized) // get the node num for the HC
|
||||
{
|
||||
Store (0x00, Local0)
|
||||
Store (DerefOf (Index (\_SB.PCI0.HCLK, Arg0)), Local1)
|
||||
Store (ShiftRight(And (Local1, 0xfc), 0x02), Local0)
|
||||
Return (Local0)
|
||||
}
|
||||
|
||||
Method (GHCL, 1, NotSerialized) // get the link num on node for the HC
|
||||
{
|
||||
Store (0x00, Local0)
|
||||
Store (DerefOf (Index (\_SB.PCI0.HCLK, Arg0)), Local1)
|
||||
Store (ShiftRight(And (Local1, 0x700), 0x08), Local0)
|
||||
Return (Local0)
|
||||
}
|
||||
|
||||
Method (GHCD, 2, NotSerialized) // get the unit id base for the HT device in HC
|
||||
{
|
||||
Store (0x00, Local0)
|
||||
Store (DerefOf (Index (\_SB.PCI0.HCDN, Arg0)), Local1)
|
||||
Store (Arg1, Local2) // Arg1 could be 3, 2, 1, 0
|
||||
Multiply (Local2, 0x08, Local2) // change to 24, 16, 8, 0
|
||||
Store (And (ShiftRight(Local1, Local2), 0xff), Local0)
|
||||
Return (Local0)
|
||||
}
|
||||
|
||||
Method (GBUS, 2, NotSerialized)
|
||||
{
|
||||
Store (0x00, Local0)
|
||||
While (LLess (Local0, 0x20)) // 32 ht links
|
||||
{
|
||||
Store (DerefOf (Index (\_SB.PCI0.BUSN, Local0)), Local1)
|
||||
If (LEqual (And (Local1, 0x03), 0x03))
|
||||
{
|
||||
If (LEqual (Arg0, ShiftRight (And (Local1, 0xfc), 0x02)))
|
||||
{
|
||||
If (LOr (LEqual (Arg1, 0xFF), LEqual (Arg1, ShiftRight (And (Local1, 0x0700), 0x08))))
|
||||
{
|
||||
Return (ShiftRight (And (Local1, 0x000FF000), 0x0c))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Increment (Local0)
|
||||
}
|
||||
|
||||
Return (0x00)
|
||||
}
|
||||
|
||||
Method (GWBN, 2, Serialized)
|
||||
{
|
||||
Name (BUF0, ResourceTemplate ()
|
||||
{
|
||||
WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
|
||||
0x0000, // Address Space Granularity
|
||||
0x0000, // Address Range Minimum
|
||||
0x0000, // Address Range Maximum
|
||||
0x0000, // Address Translation Offset
|
||||
0x0001,,,)
|
||||
})
|
||||
CreateWordField (BUF0, 0x08, BMIN)
|
||||
CreateWordField (BUF0, 0x0A, BMAX)
|
||||
CreateWordField (BUF0, 0x0E, BLEN)
|
||||
Store (0x00, Local0)
|
||||
While (LLess (Local0, 0x20))
|
||||
{
|
||||
Store (DerefOf (Index (\_SB.PCI0.BUSN, Local0)), Local1)
|
||||
If (LEqual (And (Local1, 0x03), 0x03))
|
||||
{
|
||||
If (LEqual (Arg0, ShiftRight (And (Local1, 0xfc), 0x02)))
|
||||
{
|
||||
If (LOr (LEqual (Arg1, 0xFF), LEqual (Arg1, ShiftRight (And (Local1, 0x0700), 0x08))))
|
||||
{
|
||||
Store (ShiftRight (And (Local1, 0x000FF000), 0x0c), BMIN)
|
||||
Store (ShiftRight (Local1, 0x14), BMAX)
|
||||
Subtract (BMAX, BMIN, BLEN)
|
||||
Increment (BLEN)
|
||||
Return (RTAG (BUF0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Increment (Local0)
|
||||
}
|
||||
|
||||
Return (RTAG (BUF0))
|
||||
}
|
||||
|
||||
Method (GMEM, 2, Serialized)
|
||||
{
|
||||
Name (BUF0, ResourceTemplate ()
|
||||
{
|
||||
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
|
||||
0x00000000, // Address Space Granularity
|
||||
0x00000000, // Address Range Minimum
|
||||
0x00000000, // Address Range Maximum
|
||||
0x00000000, // Address Translation Offset
|
||||
0x00000001,,,
|
||||
, AddressRangeMemory, TypeStatic)
|
||||
})
|
||||
CreateDWordField (BUF0, 0x0A, MMIN)
|
||||
CreateDWordField (BUF0, 0x0E, MMAX)
|
||||
CreateDWordField (BUF0, 0x16, MLEN)
|
||||
Store (0x00, Local0)
|
||||
Store (0x00, Local4)
|
||||
Store (0x00, Local3)
|
||||
While (LLess (Local0, 0x80)) // 0x20 links * 2(mem, prefmem) *2 (base, limit)
|
||||
{
|
||||
Store (DerefOf (Index (\_SB.PCI0.MMIO, Local0)), Local1)
|
||||
Increment (Local0)
|
||||
Store (DerefOf (Index (\_SB.PCI0.MMIO, Local0)), Local2)
|
||||
If (LEqual (And (Local1, 0x03), 0x03))
|
||||
{
|
||||
If (LEqual (Arg0, And (Local2, 0x3f)))
|
||||
{
|
||||
If (LOr (LEqual (Arg1, 0xFF), LEqual (Arg1, ShiftRight (And (Local1, 0x70), 0x04))))
|
||||
{
|
||||
Store (ShiftLeft (And (Local1, 0xFFFFFF00), 0x08), MMIN)
|
||||
Store (ShiftLeft (And (Local2, 0xFFFFFF00), 0x08), MMAX)
|
||||
Or (MMAX, 0xFFFF, MMAX)
|
||||
Subtract (MMAX, MMIN, MLEN)
|
||||
Increment (MLEN)
|
||||
|
||||
If (Local4)
|
||||
{
|
||||
Concatenate (RTAG (BUF0), Local3, Local5)
|
||||
Store (Local5, Local3)
|
||||
}
|
||||
Else
|
||||
{
|
||||
Store (RTAG (BUF0), Local3)
|
||||
}
|
||||
|
||||
Increment (Local4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Increment (Local0)
|
||||
}
|
||||
|
||||
If (LNot (Local4))
|
||||
{
|
||||
Store (BUF0, Local3)
|
||||
}
|
||||
|
||||
Return (Local3)
|
||||
}
|
||||
|
||||
Method (GIOR, 2, Serialized)
|
||||
{
|
||||
Name (BUF0, ResourceTemplate ()
|
||||
{
|
||||
DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
|
||||
0x00000000, // Address Space Granularity
|
||||
0x00000000, // Address Range Minimum
|
||||
0x00000000, // Address Range Maximum
|
||||
0x00000000, // Address Translation Offset
|
||||
0x00000001,,,
|
||||
, TypeStatic)
|
||||
})
|
||||
CreateDWordField (BUF0, 0x0A, PMIN)
|
||||
CreateDWordField (BUF0, 0x0E, PMAX)
|
||||
CreateDWordField (BUF0, 0x16, PLEN)
|
||||
Store (0x00, Local0)
|
||||
Store (0x00, Local4)
|
||||
Store (0x00, Local3)
|
||||
While (LLess (Local0, 0x40)) // 0x20 ht links * 2 (base, limit)
|
||||
{
|
||||
Store (DerefOf (Index (\_SB.PCI0.PCIO, Local0)), Local1)
|
||||
Increment (Local0)
|
||||
Store (DerefOf (Index (\_SB.PCI0.PCIO, Local0)), Local2)
|
||||
If (LEqual (And (Local1, 0x03), 0x03))
|
||||
{
|
||||
If (LEqual (Arg0, And (Local2, 0x3f)))
|
||||
{
|
||||
If (LOr (LEqual (Arg1, 0xFF), LEqual (Arg1, ShiftRight (And (Local1, 0x70), 0x04))))
|
||||
{
|
||||
Store (And (Local1, 0x01FFF000), PMIN)
|
||||
Store (And (Local2, 0x01FFF000), PMAX)
|
||||
Or (PMAX, 0x0FFF, PMAX)
|
||||
Subtract (PMAX, PMIN, PLEN)
|
||||
Increment (PLEN)
|
||||
|
||||
If (Local4)
|
||||
{
|
||||
Concatenate (RTAG (BUF0), Local3, Local5)
|
||||
Store (Local5, Local3)
|
||||
}
|
||||
Else
|
||||
{
|
||||
If (LGreater (PMAX, PMIN))
|
||||
{
|
||||
If (LOr (LAnd (LEqual (Arg1, 0xFF), LEqual (Arg0, 0x00)), LEqual (Arg1, \_SB.PCI0.SBLK)))
|
||||
{
|
||||
Store (0x0D00, PMIN)
|
||||
Subtract (PMAX, PMIN, PLEN)
|
||||
Increment (PLEN)
|
||||
}
|
||||
|
||||
Store (RTAG (BUF0), Local3)
|
||||
Increment (Local4)
|
||||
}
|
||||
|
||||
If (And (Local1, 0x10))
|
||||
{
|
||||
Store (0x03B0, PMIN)
|
||||
Store (0x03DF, PMAX)
|
||||
Store (0x30, PLEN)
|
||||
|
||||
If (Local4)
|
||||
{
|
||||
Concatenate (RTAG (BUF0), Local3, Local5)
|
||||
Store (Local5, Local3)
|
||||
}
|
||||
Else
|
||||
{
|
||||
Store (RTAG (BUF0), Local3)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Increment (Local4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Increment (Local0)
|
||||
}
|
||||
|
||||
If (LNot (Local4))
|
||||
{
|
||||
Store (RTAG (BUF0), Local3)
|
||||
}
|
||||
|
||||
Return (Local3)
|
||||
}
|
||||
|
||||
Method (RTAG, 1, NotSerialized)
|
||||
{
|
||||
Store (Arg0, Local0)
|
||||
Store (SizeOf (Local0), Local1)
|
||||
Subtract (Local1, 0x02, Local1)
|
||||
Multiply (Local1, 0x08, Local1)
|
||||
CreateField (Local0, 0x00, Local1, RETB)
|
||||
Store (RETB, Local2)
|
||||
Return (Local2)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <console/console.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <device/pci_def.h>
|
||||
#include "raminit.h"
|
||||
#include <northbridge/amd/amdmct/amddefs.h>
|
||||
|
||||
#if !ENV_PCI_SIMPLE_DEVICE
|
||||
u32 Get_NB32(u32 dev, u32 reg)
|
||||
{
|
||||
return pci_read_config32(pcidev_path_on_root(PCI_DEV2DEVFN(dev)), reg);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint64_t mctGetLogicalCPUID(u32 Node)
|
||||
{
|
||||
/* Converts the CPUID to a logical ID MASK that is used to check
|
||||
CPU version support versions */
|
||||
u32 dev;
|
||||
u32 val, valx;
|
||||
u32 family, model, stepping;
|
||||
uint64_t ret;
|
||||
|
||||
if (Node == 0xFF) { /* current node */
|
||||
val = cpuid_eax(0x80000001);
|
||||
} else {
|
||||
dev = PA_NBMISC(Node);
|
||||
val = Get_NB32(dev, 0xfc);
|
||||
}
|
||||
|
||||
family = ((val >> 8) & 0x0f) + ((val >> 20) & 0xff);
|
||||
model = ((val >> 4) & 0x0f) | ((val >> (16-4)) & 0xf0);
|
||||
stepping = val & 0x0f;
|
||||
|
||||
valx = (family << 12) | (model << 4) | (stepping);
|
||||
|
||||
switch (valx) {
|
||||
case 0x10000:
|
||||
ret = AMD_DR_A0A;
|
||||
break;
|
||||
case 0x10001:
|
||||
ret = AMD_DR_A1B;
|
||||
break;
|
||||
case 0x10002:
|
||||
ret = AMD_DR_A2;
|
||||
break;
|
||||
case 0x10020:
|
||||
ret = AMD_DR_B0;
|
||||
break;
|
||||
case 0x10021:
|
||||
ret = AMD_DR_B1;
|
||||
break;
|
||||
case 0x10022:
|
||||
ret = AMD_DR_B2;
|
||||
break;
|
||||
case 0x10023:
|
||||
ret = AMD_DR_B3;
|
||||
break;
|
||||
case 0x10042:
|
||||
ret = AMD_RB_C2;
|
||||
break;
|
||||
case 0x10043:
|
||||
ret = AMD_RB_C3;
|
||||
break;
|
||||
case 0x10062:
|
||||
ret = AMD_DA_C2;
|
||||
break;
|
||||
case 0x10063:
|
||||
ret = AMD_DA_C3;
|
||||
break;
|
||||
case 0x10080:
|
||||
ret = AMD_HY_D0;
|
||||
break;
|
||||
case 0x10081:
|
||||
case 0x10091:
|
||||
ret = AMD_HY_D1;
|
||||
break;
|
||||
case 0x100a0:
|
||||
ret = AMD_PH_E0;
|
||||
break;
|
||||
case 0x15012:
|
||||
case 0x1501f:
|
||||
ret = AMD_OR_B2;
|
||||
break;
|
||||
case 0x15020:
|
||||
case 0x15101:
|
||||
ret = AMD_OR_C0;
|
||||
break;
|
||||
default:
|
||||
/* FIXME: mabe we should die() here. */
|
||||
printk(BIOS_ERR, "FIXME! CPU Version unknown or not supported! %08x\n", valx);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "northbridge/amd/amdfam10/early_ht.c"
|
||||
|
||||
static void bootblock_northbridge_init(void) {
|
||||
/* Nothing special needs to be done to find bus 0 */
|
||||
/* Allow the HT devices to be found */
|
||||
/* mov bsp to bus 0xff when > 8 nodes */
|
||||
set_bsp_node_CHtExtNodeCfgEn();
|
||||
enumerate_ht_chain();
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _AMD_FAM10_CHIP_H_
|
||||
#define _AMD_FAM10_CHIP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct northbridge_amd_amdfam10_config {
|
||||
uint64_t maximum_memory_capacity;
|
||||
};
|
||||
|
||||
#endif /* _AMD_FAM10_CHIP_H_ */
|
||||
|
|
@ -1,324 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
#include <console/console.h>
|
||||
#include <arch/io.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <device/pci_def.h>
|
||||
#include <delay.h>
|
||||
|
||||
void print_debug_addr(const char *str, void *val)
|
||||
{
|
||||
#if CONFIG(DEBUG_CAR)
|
||||
printk(BIOS_DEBUG, "------Address debug: %s%p------\n", str, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_debug_pci_dev(u32 dev)
|
||||
{
|
||||
printk(BIOS_DEBUG, "PCI: %02x:%02x.%02x", (dev>>20) & 0xff, (dev>>15) & 0x1f, (dev>>12) & 0x7);
|
||||
}
|
||||
|
||||
void print_pci_devices(void)
|
||||
{
|
||||
pci_devfn_t dev;
|
||||
for (dev = PCI_DEV(0, 0, 0);
|
||||
dev <= PCI_DEV(0xff, 0x1f, 0x7);
|
||||
dev += PCI_DEV(0,0,1)) {
|
||||
u32 id;
|
||||
id = pci_read_config32(dev, PCI_VENDOR_ID);
|
||||
if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
|
||||
(((id >> 16) & 0xffff) == 0xffff) ||
|
||||
(((id >> 16) & 0xffff) == 0x0000)) {
|
||||
continue;
|
||||
}
|
||||
print_debug_pci_dev(dev);
|
||||
printk(BIOS_DEBUG, " %04x:%04x\n", (id & 0xffff), (id>>16));
|
||||
if (((dev>>12) & 0x07) == 0) {
|
||||
u8 hdr_type;
|
||||
hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
|
||||
if ((hdr_type & 0x80) != 0x80) {
|
||||
dev += PCI_DEV(0,0,7);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print_pci_devices_on_bus(u32 busn)
|
||||
{
|
||||
pci_devfn_t dev;
|
||||
for (dev = PCI_DEV(busn, 0, 0);
|
||||
dev <= PCI_DEV(busn, 0x1f, 0x7);
|
||||
dev += PCI_DEV(0,0,1)) {
|
||||
u32 id;
|
||||
id = pci_read_config32(dev, PCI_VENDOR_ID);
|
||||
if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
|
||||
(((id >> 16) & 0xffff) == 0xffff) ||
|
||||
(((id >> 16) & 0xffff) == 0x0000)) {
|
||||
continue;
|
||||
}
|
||||
print_debug_pci_dev(dev);
|
||||
printk(BIOS_DEBUG, " %04x:%04x\n", (id & 0xffff), (id>>16));
|
||||
if (((dev>>12) & 0x07) == 0) {
|
||||
u8 hdr_type;
|
||||
hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
|
||||
if ((hdr_type & 0x80) != 0x80) {
|
||||
dev += PCI_DEV(0,0,7);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump_pci_device_range(u32 dev, u32 start_reg, u32 size)
|
||||
{
|
||||
int i;
|
||||
print_debug_pci_dev(dev);
|
||||
int j;
|
||||
int end = start_reg + size;
|
||||
|
||||
for (i = start_reg; i < end; i+=4) {
|
||||
u32 val;
|
||||
if ((i & 0x0f) == 0) {
|
||||
printk(BIOS_DEBUG, "\n%04x:",i);
|
||||
}
|
||||
val = pci_read_config32(dev, i);
|
||||
for (j = 0; j < 4; j++) {
|
||||
printk(BIOS_DEBUG, " %02x", val & 0xff);
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
printk(BIOS_DEBUG, "\n");
|
||||
}
|
||||
|
||||
void dump_pci_device(u32 dev)
|
||||
{
|
||||
dump_pci_device_range(dev, 0, 4096);
|
||||
}
|
||||
|
||||
void dump_pci_device_index_wait_range(u32 dev, u32 index_reg, u32 start,
|
||||
u32 size)
|
||||
{
|
||||
int i;
|
||||
int end = start + size;
|
||||
print_debug_pci_dev(dev);
|
||||
printk(BIOS_DEBUG, " -- index_reg=%08x", index_reg);
|
||||
|
||||
for (i = start; i < end; i++) {
|
||||
u32 val;
|
||||
int j;
|
||||
printk(BIOS_DEBUG, "\n%02x:",i);
|
||||
val = pci_read_config32_index_wait(dev, index_reg, i);
|
||||
for (j = 0; j < 4; j++) {
|
||||
printk(BIOS_DEBUG, " %02x", val & 0xff);
|
||||
val >>= 8;
|
||||
}
|
||||
|
||||
}
|
||||
printk(BIOS_DEBUG, "\n");
|
||||
}
|
||||
|
||||
void dump_pci_device_index_wait(u32 dev, u32 index_reg)
|
||||
{
|
||||
dump_pci_device_index_wait_range(dev, index_reg, 0, 0x54);
|
||||
dump_pci_device_index_wait_range(dev, index_reg, 0x100, 0x08); //DIMM1 when memclk > 400Hz
|
||||
}
|
||||
|
||||
void dump_pci_device_index(u32 dev, u32 index_reg, u32 type, u32 length)
|
||||
{
|
||||
int i;
|
||||
print_debug_pci_dev(dev);
|
||||
|
||||
printk(BIOS_DEBUG, " index reg: %04x type: %02x", index_reg, type);
|
||||
|
||||
type<<=28;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
u32 val;
|
||||
if ((i & 0x0f) == 0) {
|
||||
printk(BIOS_DEBUG, "\n%02x:",i);
|
||||
}
|
||||
val = pci_read_config32_index(dev, index_reg, i|type);
|
||||
printk(BIOS_DEBUG, " %08x", val);
|
||||
}
|
||||
printk(BIOS_DEBUG, "\n");
|
||||
}
|
||||
|
||||
void dump_pci_devices(void)
|
||||
{
|
||||
pci_devfn_t dev;
|
||||
for (dev = PCI_DEV(0, 0, 0);
|
||||
dev <= PCI_DEV(0xff, 0x1f, 0x7);
|
||||
dev += PCI_DEV(0,0,1)) {
|
||||
u32 id;
|
||||
id = pci_read_config32(dev, PCI_VENDOR_ID);
|
||||
if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
|
||||
(((id >> 16) & 0xffff) == 0xffff) ||
|
||||
(((id >> 16) & 0xffff) == 0x0000)) {
|
||||
continue;
|
||||
}
|
||||
dump_pci_device(dev);
|
||||
|
||||
if (((dev>>12) & 0x07) == 0) {
|
||||
u8 hdr_type;
|
||||
hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
|
||||
if ((hdr_type & 0x80) != 0x80) {
|
||||
dev += PCI_DEV(0,0,7);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump_pci_devices_on_bus(u32 busn)
|
||||
{
|
||||
pci_devfn_t dev;
|
||||
for (dev = PCI_DEV(busn, 0, 0);
|
||||
dev <= PCI_DEV(busn, 0x1f, 0x7);
|
||||
dev += PCI_DEV(0,0,1)) {
|
||||
u32 id;
|
||||
id = pci_read_config32(dev, PCI_VENDOR_ID);
|
||||
if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
|
||||
(((id >> 16) & 0xffff) == 0xffff) ||
|
||||
(((id >> 16) & 0xffff) == 0x0000)) {
|
||||
continue;
|
||||
}
|
||||
dump_pci_device(dev);
|
||||
|
||||
if (((dev>>12) & 0x07) == 0) {
|
||||
u8 hdr_type;
|
||||
hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
|
||||
if ((hdr_type & 0x80) != 0x80) {
|
||||
dev += PCI_DEV(0,0,7);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG(DEBUG_SMBUS)
|
||||
void dump_spd_registers(const struct mem_controller *ctrl)
|
||||
{
|
||||
int i;
|
||||
printk(BIOS_DEBUG, "\n");
|
||||
for (i = 0; i < DIMM_SOCKETS; i++) {
|
||||
u32 device;
|
||||
device = ctrl->spd_addr[i];
|
||||
if (device) {
|
||||
int j;
|
||||
printk(BIOS_DEBUG, "dimm: %02x.0: %02x", i, device);
|
||||
for (j = 0; j < 128; j++) {
|
||||
int status;
|
||||
u8 byte;
|
||||
if ((j & 0xf) == 0) {
|
||||
printk(BIOS_DEBUG, "\n%02x: ", j);
|
||||
}
|
||||
status = smbus_read_byte(device, j);
|
||||
if (status < 0) {
|
||||
break;
|
||||
}
|
||||
byte = status & 0xff;
|
||||
printk(BIOS_DEBUG, "%02x ", byte);
|
||||
}
|
||||
printk(BIOS_DEBUG, "\n");
|
||||
}
|
||||
device = ctrl->spd_addr[i+DIMM_SOCKETS];
|
||||
if (device) {
|
||||
int j;
|
||||
printk(BIOS_DEBUG, "dimm: %02x.1: %02x", i, device);
|
||||
for (j = 0; j < 128; j++) {
|
||||
int status;
|
||||
u8 byte;
|
||||
if ((j & 0xf) == 0) {
|
||||
printk(BIOS_DEBUG, "\n%02x: ", j);
|
||||
}
|
||||
status = smbus_read_byte(device, j);
|
||||
if (status < 0) {
|
||||
break;
|
||||
}
|
||||
byte = status & 0xff;
|
||||
printk(BIOS_DEBUG, "%02x ", byte);
|
||||
}
|
||||
printk(BIOS_DEBUG, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump_smbus_registers(void)
|
||||
{
|
||||
u32 device;
|
||||
printk(BIOS_DEBUG, "\n");
|
||||
for (device = 1; device < 0x80; device++) {
|
||||
int j;
|
||||
if (smbus_read_byte(device, 0) < 0) continue;
|
||||
printk(BIOS_DEBUG, "smbus: %02x", device);
|
||||
for (j = 0; j < 256; j++) {
|
||||
int status;
|
||||
u8 byte;
|
||||
status = smbus_read_byte(device, j);
|
||||
if (status < 0) {
|
||||
break;
|
||||
}
|
||||
if ((j & 0xf) == 0) {
|
||||
printk(BIOS_DEBUG, "\n%02x: ",j);
|
||||
}
|
||||
byte = status & 0xff;
|
||||
printk(BIOS_DEBUG, "%02x ", byte);
|
||||
}
|
||||
printk(BIOS_DEBUG, "\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void dump_io_resources(u32 port)
|
||||
{
|
||||
|
||||
int i;
|
||||
udelay(2000);
|
||||
printk(BIOS_DEBUG, "%04x:\n", port);
|
||||
for (i = 0; i < 256; i++) {
|
||||
u8 val;
|
||||
if ((i & 0x0f) == 0) {
|
||||
printk(BIOS_DEBUG, "%02x:", i);
|
||||
}
|
||||
val = inb(port);
|
||||
printk(BIOS_DEBUG, " %02x",val);
|
||||
if ((i & 0x0f) == 0x0f) {
|
||||
printk(BIOS_DEBUG, "\n");
|
||||
}
|
||||
port++;
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG(DIMM_DDR2)
|
||||
void print_tx(const char *strval, u32 val)
|
||||
{
|
||||
#if CONFIG(DEBUG_RAM_SETUP)
|
||||
printk(BIOS_DEBUG, "%s%08x\n", strval, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
void print_t(const char *strval)
|
||||
{
|
||||
#if CONFIG(DEBUG_RAM_SETUP)
|
||||
printk(BIOS_DEBUG, "%s", strval);
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_DIMM_DDR2 */
|
||||
|
||||
void print_tf(const char *func, const char *strval)
|
||||
{
|
||||
#if CONFIG(DEBUG_RAM_SETUP)
|
||||
printk(BIOS_DEBUG, "%s: %s", func, strval);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AMDFAM10_DEBUG_H
|
||||
#define AMDFAM10_DEBUG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "pci.h"
|
||||
|
||||
void print_debug_addr(const char *str, void *val);
|
||||
void print_debug_pci_dev(u32 dev);
|
||||
void print_pci_devices(void);
|
||||
void print_pci_devices_on_bus(u32 busn);
|
||||
void dump_pci_device_range(u32 dev, u32 start_reg, u32 size);
|
||||
void dump_pci_device(u32 dev);
|
||||
void dump_pci_device_index_wait_range(u32 dev, u32 index_reg, u32 start,
|
||||
u32 size);
|
||||
void dump_pci_device_index_wait(u32 dev, u32 index_reg);
|
||||
void dump_pci_device_index(u32 dev, u32 index_reg, u32 type, u32 length);
|
||||
void dump_pci_devices(void);
|
||||
void dump_pci_devices_on_bus(u32 busn);
|
||||
|
||||
#if CONFIG(DEBUG_SMBUS)
|
||||
void dump_spd_registers(const struct mem_controller *ctrl);
|
||||
void dump_smbus_registers(void);
|
||||
#endif
|
||||
|
||||
void dump_io_resources(u32 port);
|
||||
|
||||
void print_tx(const char *strval, u32 val);
|
||||
void print_t(const char *strval);
|
||||
void print_tf(const char *func, const char *strval);
|
||||
#endif
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "early_ht.h"
|
||||
#include <stdint.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <device/pci_def.h>
|
||||
|
||||
// For SB HT chain only
|
||||
// mmconf is not ready yet
|
||||
void set_bsp_node_CHtExtNodeCfgEn(void)
|
||||
{
|
||||
#if CONFIG(EXT_RT_TBL_SUPPORT)
|
||||
u32 dword;
|
||||
dword = pci_io_read_config32(PCI_DEV(0, 0x18, 0), 0x68);
|
||||
dword |= (1<<27) | (1<<25);
|
||||
/* CHtExtNodeCfgEn: coherent link extended node configuration enable,
|
||||
Nodes[31:0] will be 0xff:[31:0], Nodes[63:32] will be 0xfe:[31:0]
|
||||
---- 32 nodes now only
|
||||
It can be used even nodes less than 8 nodes.
|
||||
We can have 8 more device on bus 0 in that case
|
||||
*/
|
||||
|
||||
/* CHtExtAddrEn */
|
||||
pci_io_write_config32(PCI_DEV(0, 0x18, 0), 0x68, dword);
|
||||
// CPU on bus 0xff and 0xfe now. For now on we can use CONFIG_CBB and CONFIG_CDB.
|
||||
#endif
|
||||
}
|
||||
|
||||
void enumerate_ht_chain(void)
|
||||
{
|
||||
#if CONFIG_HT_CHAIN_UNITID_BASE != 0
|
||||
/* CONFIG_HT_CHAIN_UNITID_BASE could be 0 (only one ht device in the ht chain),
|
||||
if so, don't need to go through the chain */
|
||||
|
||||
/* Assumption the HT chain that is bus 0 has the HT I/O Hub on it.
|
||||
* On most boards this just happens. If a CPU has multiple
|
||||
* non Coherent links the appropriate bus registers for the
|
||||
* links needs to be programed to point at bus 0.
|
||||
*/
|
||||
unsigned int next_unitid, last_unitid = 0;
|
||||
#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
|
||||
// let't record the device of last ht device, So we can set the
|
||||
// Unitid to CONFIG_HT_CHAIN_END_UNITID_BASE
|
||||
unsigned int real_last_unitid = 0;
|
||||
u8 real_last_pos = 0;
|
||||
int ht_dev_num = 0; // except host_bridge
|
||||
u8 end_used = 0;
|
||||
#endif
|
||||
|
||||
next_unitid = CONFIG_HT_CHAIN_UNITID_BASE;
|
||||
do {
|
||||
u32 id;
|
||||
u8 hdr_type, pos;
|
||||
last_unitid = next_unitid;
|
||||
|
||||
id = pci_io_read_config32(PCI_DEV(0,0,0), PCI_VENDOR_ID);
|
||||
/* If the chain is enumerated quit */
|
||||
if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
|
||||
(((id >> 16) & 0xffff) == 0xffff) ||
|
||||
(((id >> 16) & 0xffff) == 0x0000))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
hdr_type = pci_io_read_config8(PCI_DEV(0,0,0), PCI_HEADER_TYPE);
|
||||
pos = 0;
|
||||
hdr_type &= 0x7f;
|
||||
|
||||
if ((hdr_type == PCI_HEADER_TYPE_NORMAL) ||
|
||||
(hdr_type == PCI_HEADER_TYPE_BRIDGE))
|
||||
{
|
||||
pos = pci_io_read_config8(PCI_DEV(0,0,0), PCI_CAPABILITY_LIST);
|
||||
}
|
||||
while (pos != 0) {
|
||||
u8 cap;
|
||||
cap = pci_io_read_config8(PCI_DEV(0,0,0), pos + PCI_CAP_LIST_ID);
|
||||
if (cap == PCI_CAP_ID_HT) {
|
||||
u16 flags;
|
||||
/* Read and write and reread flags so the link
|
||||
* direction bit is valid.
|
||||
*/
|
||||
flags = pci_io_read_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS);
|
||||
pci_io_write_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS, flags);
|
||||
flags = pci_io_read_config16(PCI_DEV(0,0,0), pos + PCI_CAP_FLAGS);
|
||||
if ((flags >> 13) == 0) {
|
||||
unsigned int count;
|
||||
unsigned int ctrl, ctrl_off;
|
||||
pci_devfn_t devx;
|
||||
|
||||
#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
|
||||
if (next_unitid >= 0x18) {
|
||||
if (!end_used) {
|
||||
next_unitid = CONFIG_HT_CHAIN_END_UNITID_BASE;
|
||||
end_used = 1;
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
real_last_unitid = next_unitid;
|
||||
real_last_pos = pos;
|
||||
ht_dev_num++;
|
||||
#endif
|
||||
#if !CONFIG_HT_CHAIN_END_UNITID_BASE
|
||||
if (!next_unitid)
|
||||
goto out;
|
||||
#endif
|
||||
flags &= ~0x1f;
|
||||
flags |= next_unitid & 0x1f;
|
||||
count = (flags >> 5) & 0x1f;
|
||||
devx = PCI_DEV(0, next_unitid, 0);
|
||||
next_unitid += count;
|
||||
|
||||
pci_io_write_config16(PCI_DEV(0, 0, 0), pos + PCI_CAP_FLAGS, flags);
|
||||
|
||||
/* Test for end of chain */
|
||||
ctrl_off = ((flags >> 10) & 1)?
|
||||
PCI_HT_CAP_SLAVE_CTRL0 : PCI_HT_CAP_SLAVE_CTRL1;
|
||||
|
||||
do {
|
||||
ctrl = pci_io_read_config16(devx, pos + ctrl_off);
|
||||
/* Is this the end of the hypertransport chain? */
|
||||
if (ctrl & (1 << 6)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ctrl & ((1 << 4) | (1 << 8))) {
|
||||
/*
|
||||
* Either the link has failed, or we have
|
||||
* a CRC error.
|
||||
* Sometimes this can happen due to link
|
||||
* retrain, so lets knock it down and see
|
||||
* if its transient
|
||||
*/
|
||||
ctrl |= ((1 << 4) | (1 <<8)); // Link fail + Crc
|
||||
pci_io_write_config16(devx, pos + ctrl_off, ctrl);
|
||||
ctrl = pci_io_read_config16(devx, pos + ctrl_off);
|
||||
if (ctrl & ((1 << 4) | (1 << 8))) {
|
||||
// can not clear the error
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while ((ctrl & (1 << 5)) == 0);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
pos = pci_io_read_config8(PCI_DEV(0, 0, 0), pos + PCI_CAP_LIST_NEXT);
|
||||
}
|
||||
} while (last_unitid != next_unitid);
|
||||
|
||||
out: ;
|
||||
#if CONFIG_HT_CHAIN_END_UNITID_BASE != 0x20
|
||||
if ((ht_dev_num > 1) && (real_last_unitid != CONFIG_HT_CHAIN_END_UNITID_BASE) && !end_used) {
|
||||
u16 flags;
|
||||
flags = pci_io_read_config16(PCI_DEV(0,real_last_unitid,0), real_last_pos + PCI_CAP_FLAGS);
|
||||
flags &= ~0x1f;
|
||||
flags |= CONFIG_HT_CHAIN_END_UNITID_BASE & 0x1f;
|
||||
pci_io_write_config16(PCI_DEV(0, real_last_unitid, 0), real_last_pos + PCI_CAP_FLAGS, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef EARLY_HT_H
|
||||
#define EARLY_HT_H
|
||||
|
||||
void set_bsp_node_CHtExtNodeCfgEn(void);
|
||||
void enumerate_ht_chain(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <bootstate.h>
|
||||
#include <device/pci.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <cpu/amd/amdfam10_sysconf.h>
|
||||
|
||||
|
||||
/* Need pci1234 array
|
||||
* pci1234[0] will record sblink and bus range
|
||||
* pci1234[i] will record ht chain i.
|
||||
* It will keep the sequence when some ht io card is not installed.
|
||||
*
|
||||
* 1n: 8
|
||||
* 2n: 7x2
|
||||
* 3n: 6x3
|
||||
* 4n: 5x4
|
||||
* 5n: 4x5
|
||||
* 6n: 3x6
|
||||
* 7n: 2x7
|
||||
* 8n: 1x8
|
||||
*
|
||||
* 8n(4x2): 8x4
|
||||
* 16n(4x4): 16*2
|
||||
* 20n(4x5): 20x1
|
||||
* 32n(4x4+4x4): 16x1
|
||||
*
|
||||
* Total: xxx: I just want to use 32 instead, If you have more, you may need to
|
||||
* reset HC_POSSIBLE_NUM and update ssdt.dsl (hcdn, hclk)
|
||||
*
|
||||
* Put all the possible ht node/link to the list tp pci1234[] in get_bus_conf.c
|
||||
* on MB dir. How about co-processor on socket 1 on 2 way system.
|
||||
* or socket 2, and socket3 on 4 way system? treat that as one hc too!
|
||||
*
|
||||
*/
|
||||
|
||||
#include "northbridge.h"
|
||||
|
||||
void get_pci1234(void)
|
||||
{
|
||||
|
||||
int i,j;
|
||||
u32 dword;
|
||||
|
||||
dword = sysconf.sblk<<8;
|
||||
dword |= 1;
|
||||
sysconf.pci1234[0] = dword; // sblink
|
||||
sysconf.hcid[0] = 0;
|
||||
|
||||
/* about hardcode numbering for HT_IO support
|
||||
set the node_id and link_id that could have ht chain in the one array,
|
||||
then check if is enabled.... then update final value
|
||||
*/
|
||||
|
||||
//here we need to set hcdn
|
||||
//1. hypertransport.c need to record hcdn_reg together with 0xe0, 0xe4, 0xe8, 0xec when are set
|
||||
//2. so at the same time we need update hsdn with hcdn_reg here
|
||||
|
||||
for (j = 0; j < sysconf.ht_c_num; j++) {
|
||||
u32 dwordx;
|
||||
dwordx = sysconf.ht_c_conf_bus[j];
|
||||
dwordx &=0xfffffffd; //keep bus num, node_id, link_num, enable bits
|
||||
if ((dwordx & 0x7fd) == dword) { //SBLINK
|
||||
sysconf.pci1234[0] = dwordx;
|
||||
sysconf.hcdn[0] = sysconf.hcdn_reg[j];
|
||||
continue;
|
||||
}
|
||||
if ((dwordx & 1)) {
|
||||
// We need to find out the number of HC
|
||||
// for exact match
|
||||
for (i = 1; i < sysconf.hc_possible_num; i++) {
|
||||
if ((dwordx & 0x7fc) == (sysconf.pci1234[i] & 0x7fc)) { // same node and same linkn
|
||||
sysconf.pci1234[i] = dwordx;
|
||||
sysconf.hcdn[i] = sysconf.hcdn_reg[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// for 0xffc match or same node
|
||||
for (i = 1; i < sysconf.hc_possible_num; i++) {
|
||||
if ((dwordx & 0x7fc) == (dwordx & sysconf.pci1234[i] & 0x7fc)) {
|
||||
sysconf.pci1234[i] = dwordx;
|
||||
sysconf.hcdn[i] = sysconf.hcdn_reg[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i < sysconf.hc_possible_num; i++) {
|
||||
if (!(sysconf.pci1234[i] & 1)) {
|
||||
sysconf.pci1234[i] = 0;
|
||||
sysconf.hcdn[i] = 0x20202020;
|
||||
}
|
||||
sysconf.hcid[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void get_default_pci1234(int mb_hc_possible)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mb_hc_possible; i++) {
|
||||
sysconf.pci1234[i] = 0x0000ffc;
|
||||
sysconf.hcdn[i] = 0x20202020;
|
||||
}
|
||||
sysconf.hc_possible_num = mb_hc_possible;
|
||||
get_pci1234();
|
||||
}
|
||||
|
||||
static void amd_bs_sysconf(void *arg)
|
||||
{
|
||||
/* Prepare sysconf structures, which are used to generate IRQ,
|
||||
* MP and ACPI table entries.
|
||||
*/
|
||||
get_bus_conf();
|
||||
}
|
||||
|
||||
BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY, amd_bs_sysconf, NULL);
|
||||
|
|
@ -1,229 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <console/console.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci_ops.h>
|
||||
|
||||
#include <cpu/amd/amdfam10_sysconf.h>
|
||||
#include "northbridge.h"
|
||||
#include "amdfam10.h"
|
||||
#include "ht_config.h"
|
||||
|
||||
struct dram_base_mask_t get_dram_base_mask(u32 nodeid)
|
||||
{
|
||||
struct dram_base_mask_t d;
|
||||
struct device *dev = __f1_dev[0];
|
||||
|
||||
u32 temp;
|
||||
temp = pci_read_config32(dev, 0x44 + (nodeid << 3)); //[39:24] at [31:16]
|
||||
d.mask = ((temp & 0xfff80000)>>(8+3)); // mask out DramMask [26:24] too
|
||||
temp = pci_read_config32(dev, 0x144 + (nodeid <<3)) & 0xff; //[47:40] at [7:0]
|
||||
d.mask |= temp<<21;
|
||||
|
||||
temp = pci_read_config32(dev, 0x40 + (nodeid << 3)); //[39:24] at [31:16]
|
||||
d.mask |= (temp & 1); // enable bit
|
||||
|
||||
d.base = ((temp & 0xfff80000)>>(8+3)); // mask out DramBase [26:24) too
|
||||
temp = pci_read_config32(dev, 0x140 + (nodeid <<3)) & 0xff; //[47:40] at [7:0]
|
||||
d.base |= temp<<21;
|
||||
return d;
|
||||
}
|
||||
|
||||
void set_config_map_reg(struct bus *link)
|
||||
{
|
||||
u32 tempreg;
|
||||
u32 i;
|
||||
u32 ht_c_index = get_ht_c_index(link);
|
||||
u32 linkn = link->link_num & 0x0f;
|
||||
u32 busn_min = (link->secondary >> sysconf.segbit) & 0xff;
|
||||
u32 busn_max = (link->subordinate >> sysconf.segbit) & 0xff;
|
||||
u32 nodeid = amdfam10_nodeid(link->dev);
|
||||
|
||||
tempreg = ((nodeid & 0x30) << (12-4)) | ((nodeid & 0xf) << 4) | 3;
|
||||
tempreg |= (busn_max << 24)|(busn_min << 16)|(linkn << 8);
|
||||
|
||||
for (i = 0; i < sysconf.nodes; i++) {
|
||||
struct device *dev = __f1_dev[i];
|
||||
pci_write_config32(dev, 0xe0 + ht_c_index * 4, tempreg);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_config_map_reg(struct bus *link)
|
||||
{
|
||||
u32 i;
|
||||
u32 ht_c_index = get_ht_c_index(link);
|
||||
|
||||
for (i = 0; i < sysconf.nodes; i++) {
|
||||
struct device *dev = __f1_dev[i];
|
||||
pci_write_config32(dev, 0xe0 + ht_c_index * 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static u32 ht_c_key(struct bus *link)
|
||||
{
|
||||
u32 nodeid = amdfam10_nodeid(link->dev);
|
||||
u32 linkn = link->link_num & 0x0f;
|
||||
u32 val = (linkn << 8) | ((nodeid & 0x3f) << 2) | 3;
|
||||
return val;
|
||||
}
|
||||
|
||||
static u32 get_ht_c_index_by_key(u32 key, sys_info_conf_t *sysinfo)
|
||||
{
|
||||
u32 ht_c_index = 0;
|
||||
|
||||
for (ht_c_index = 0; ht_c_index < 32; ht_c_index++) {
|
||||
if ((sysinfo->ht_c_conf_bus[ht_c_index] & 0xfff) == key) {
|
||||
return ht_c_index;
|
||||
}
|
||||
}
|
||||
|
||||
for (ht_c_index = 0; ht_c_index < 32; ht_c_index++) {
|
||||
if (sysinfo->ht_c_conf_bus[ht_c_index] == 0) {
|
||||
return ht_c_index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
u32 get_ht_c_index(struct bus *link)
|
||||
{
|
||||
u32 val = ht_c_key(link);
|
||||
return get_ht_c_index_by_key(val, &sysconf);
|
||||
}
|
||||
|
||||
void store_ht_c_conf_bus(struct bus *link)
|
||||
{
|
||||
u32 val = ht_c_key(link);
|
||||
u32 ht_c_index = get_ht_c_index_by_key(val, &sysconf);
|
||||
|
||||
u32 segn = (link->subordinate >> 8) & 0x0f;
|
||||
u32 busn_min = link->secondary & 0xff;
|
||||
u32 busn_max = link->subordinate & 0xff;
|
||||
|
||||
val |= (segn << 28) | (busn_max << 20) | (busn_min << 12);
|
||||
|
||||
sysconf.ht_c_conf_bus[ht_c_index] = val;
|
||||
sysconf.hcdn_reg[ht_c_index] = link->hcdn_reg;
|
||||
sysconf.ht_c_num++;
|
||||
}
|
||||
|
||||
u32 get_io_addr_index(u32 nodeid, u32 linkn)
|
||||
{
|
||||
u32 index;
|
||||
|
||||
for (index = 0; index < 256; index++) {
|
||||
|
||||
if (index + 4 >= ARRAY_SIZE(sysconf.conf_io_addrx))
|
||||
die("Error! Out of bounds read in %s:%s\n", __FILE__, __func__);
|
||||
|
||||
if (sysconf.conf_io_addrx[index+4] == 0) {
|
||||
sysconf.conf_io_addr[index+4] = (nodeid & 0x3f);
|
||||
sysconf.conf_io_addrx[index+4] = 1 | ((linkn & 0x7)<<4);
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 get_mmio_addr_index(u32 nodeid, u32 linkn)
|
||||
{
|
||||
u32 index;
|
||||
|
||||
for (index = 0; index < 64; index++) {
|
||||
|
||||
if (index + 8 >= ARRAY_SIZE(sysconf.conf_mmio_addrx))
|
||||
die("Error! Out of bounds read in %s:%s\n", __FILE__, __func__);
|
||||
|
||||
if (sysconf.conf_mmio_addrx[index+8] == 0) {
|
||||
sysconf.conf_mmio_addr[index+8] = (nodeid & 0x3f);
|
||||
sysconf.conf_mmio_addrx[index+8] = 1 | ((linkn & 0x7)<<4);
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void store_conf_io_addr(u32 nodeid, u32 linkn, u32 reg, u32 index,
|
||||
u32 io_min, u32 io_max)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* io range allocation */
|
||||
index = (reg-0xc0)>>3;
|
||||
|
||||
val = (nodeid & 0x3f); // 6 bits used
|
||||
sysconf.conf_io_addr[index] = val | ((io_max<<8) & 0xfffff000); //limit : with nodeid
|
||||
val = 3 | ((linkn & 0x7)<<4); // 8 bits used
|
||||
sysconf.conf_io_addrx[index] = val | ((io_min<<8) & 0xfffff000); // base : with enable bit
|
||||
|
||||
if (sysconf.io_addr_num < (index+1))
|
||||
sysconf.io_addr_num = index+1;
|
||||
}
|
||||
|
||||
|
||||
void store_conf_mmio_addr(u32 nodeid, u32 linkn, u32 reg, u32 index,
|
||||
u32 mmio_min, u32 mmio_max)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* io range allocation */
|
||||
index = (reg-0x80)>>3;
|
||||
|
||||
val = (nodeid & 0x3f); // 6 bits used
|
||||
sysconf.conf_mmio_addr[index] = val | (mmio_max & 0xffffff00); //limit : with nodeid and linkn
|
||||
val = 3 | ((linkn & 0x7)<<4); // 8 bits used
|
||||
sysconf.conf_mmio_addrx[index] = val | (mmio_min & 0xffffff00); // base : with enable bit
|
||||
|
||||
if (sysconf.mmio_addr_num<(index+1))
|
||||
sysconf.mmio_addr_num = index+1;
|
||||
}
|
||||
|
||||
|
||||
void set_io_addr_reg(struct device *dev, u32 nodeid, u32 linkn, u32 reg,
|
||||
u32 io_min, u32 io_max)
|
||||
{
|
||||
u32 i;
|
||||
u32 tempreg;
|
||||
|
||||
/* io range allocation */
|
||||
tempreg = (nodeid&0xf) | ((nodeid & 0x30)<<(8-4)) | (linkn<<4) | ((io_max&0xf0)<<(12-4)); //limit
|
||||
for (i = 0; i < sysconf.nodes; i++)
|
||||
pci_write_config32(__f1_dev[i], reg+4, tempreg);
|
||||
|
||||
tempreg = 3 /*| (3<<4)*/ | ((io_min&0xf0)<<(12-4)); //base :ISA and VGA ?
|
||||
for (i = 0; i < sysconf.nodes; i++)
|
||||
pci_write_config32(__f1_dev[i], reg, tempreg);
|
||||
}
|
||||
|
||||
void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index, u32 mmio_min, u32 mmio_max, u32 nodes)
|
||||
{
|
||||
u32 i;
|
||||
u32 tempreg;
|
||||
|
||||
/* io range allocation */
|
||||
tempreg = (nodeid&0xf) | (linkn<<4) | (mmio_max&0xffffff00); //limit
|
||||
for (i = 0; i < nodes; i++)
|
||||
pci_write_config32(__f1_dev[i], reg+4, tempreg);
|
||||
tempreg = 3 | (nodeid & 0x30) | (mmio_min&0xffffff00);
|
||||
for (i = 0; i < sysconf.nodes; i++)
|
||||
pci_write_config32(__f1_dev[i], reg, tempreg);
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __AMDFAM10_HT_CONFIG_H__
|
||||
#define __AMDFAM10_HT_CONFIG_H__
|
||||
|
||||
typedef struct amdfam10_sysconf_t sys_info_conf_t;
|
||||
|
||||
/* FIXME */
|
||||
u32 amdfam10_nodeid(struct device *dev);
|
||||
extern struct device *__f1_dev[];
|
||||
|
||||
struct dram_base_mask_t {
|
||||
u32 base; //[47:27] at [28:8]
|
||||
u32 mask; //[47:27] at [28:8] and enable at bit 0
|
||||
};
|
||||
|
||||
struct dram_base_mask_t get_dram_base_mask(u32 nodeid);
|
||||
|
||||
u32 get_ht_c_index(struct bus *link);
|
||||
void store_ht_c_conf_bus(struct bus *link);
|
||||
|
||||
void set_config_map_reg(struct bus *link);
|
||||
void clear_config_map_reg(struct bus *link);
|
||||
|
||||
|
||||
void store_conf_io_addr(u32 nodeid, u32 linkn, u32 reg, u32 index,
|
||||
u32 io_min, u32 io_max);
|
||||
|
||||
void store_conf_mmio_addr(u32 nodeid, u32 linkn, u32 reg, u32 index,
|
||||
u32 mmio_min, u32 mmio_max);
|
||||
|
||||
|
||||
u32 get_io_addr_index(u32 nodeid, u32 linkn);
|
||||
u32 get_mmio_addr_index(u32 nodeid, u32 linkn);
|
||||
|
||||
void set_io_addr_reg(struct device *dev, u32 nodeid, u32 linkn, u32 reg,
|
||||
u32 io_min, u32 io_max);
|
||||
|
||||
void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index, u32 mmio_min, u32 mmio_max, u32 nodes);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
static inline uint8_t is_fam15h(void)
|
||||
{
|
||||
uint8_t fam15h = 0;
|
||||
uint32_t family;
|
||||
|
||||
family = cpuid_eax(0x80000001);
|
||||
family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
|
||||
|
||||
if (family >= 0x6f)
|
||||
/* Family 15h or later */
|
||||
fam15h = 1;
|
||||
|
||||
return fam15h;
|
||||
}
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
* Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Configure various power control registers, including processor
|
||||
* boost support.
|
||||
*/
|
||||
|
||||
#include <console/console.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <pc80/mc146818rtc.h>
|
||||
#include <cpu/amd/model_10xxx_rev.h>
|
||||
#include <types.h>
|
||||
|
||||
#include "amdfam10.h"
|
||||
|
||||
static void nb_control_init(struct device *dev)
|
||||
{
|
||||
uint8_t enable_c_states;
|
||||
uint8_t enable_cc6;
|
||||
uint32_t dword;
|
||||
|
||||
printk(BIOS_DEBUG, "NB: Function 4 Link Control.. ");
|
||||
|
||||
/* Configure L3 Power Control */
|
||||
dword = pci_read_config32(dev, 0x1c4);
|
||||
dword |= (0x1 << 8); /* L3PwrSavEn = 1 */
|
||||
pci_write_config32(dev, 0x1c4, dword);
|
||||
|
||||
if (is_fam15h()) {
|
||||
/* Configure L3 Control 2 */
|
||||
dword = pci_read_config32(dev, 0x1cc);
|
||||
dword &= ~(0x7 << 6); /* ImplRdProjDelayThresh = 0x2 */
|
||||
dword |= (0x2 << 6);
|
||||
pci_write_config32(dev, 0x1cc, dword);
|
||||
|
||||
/* Configure TDP Accumulator Divisor Control */
|
||||
dword = pci_read_config32(dev, 0x104);
|
||||
dword &= ~(0xfff << 2); /* TdpAccDivRate = 0xc8 */
|
||||
dword |= (0xc8 << 2);
|
||||
dword &= ~0x3; /* TdpAccDivVal = 0x1 */
|
||||
dword |= 0x1;
|
||||
pci_write_config32(dev, 0x104, dword);
|
||||
|
||||
/* Configure Sample and Residency Timers */
|
||||
dword = pci_read_config32(dev, 0x110);
|
||||
dword &= ~0xfff; /* CSampleTimer = 0x1 */
|
||||
dword |= 0x1;
|
||||
pci_write_config32(dev, 0x110, dword);
|
||||
|
||||
/* Configure APM TDP Control */
|
||||
dword = pci_read_config32(dev, 0x16c);
|
||||
dword |= (0x1 << 4); /* ApmTdpLimitIntEn = 1 */
|
||||
pci_write_config32(dev, 0x16c, dword);
|
||||
|
||||
/* Enable APM */
|
||||
dword = pci_read_config32(dev, 0x15c);
|
||||
dword |= (0x1 << 7); /* ApmMasterEn = 1 */
|
||||
pci_write_config32(dev, 0x15c, dword);
|
||||
|
||||
enable_c_states = 0;
|
||||
enable_cc6 = 0;
|
||||
#if CONFIG(HAVE_ACPI_TABLES)
|
||||
uint8_t nvram;
|
||||
|
||||
if (get_option(&nvram, "cpu_c_states") == CB_SUCCESS)
|
||||
enable_c_states = !!nvram;
|
||||
|
||||
if (get_option(&nvram, "cpu_cc6_state") == CB_SUCCESS)
|
||||
enable_cc6 = !!nvram;
|
||||
#endif
|
||||
|
||||
if (enable_c_states) {
|
||||
/* Configure C-state Control 1 */
|
||||
dword = pci_read_config32(dev, 0x118);
|
||||
dword |= (0x1 << 24); /* PwrGateEnCstAct1 = 1 */
|
||||
dword &= ~(0x7 << 21); /* ClkDivisorCstAct1 = 0x0 */
|
||||
dword &= ~(0x3 << 18); /* CacheFlushTmrSelCstAct1 = 0x1 */
|
||||
dword |= (0x1 << 18);
|
||||
dword |= (0x1 << 17); /* CacheFlushEnCstAct1 = 1 */
|
||||
dword |= (0x1 << 16); /* CpuPrbEnCstAct1 = 1 */
|
||||
dword &= ~(0x1 << 8); /* PwrGateEnCstAct0 = 0 */
|
||||
dword &= ~(0x7 << 5); /* ClkDivisorCstAct0 = 0x0 */
|
||||
dword &= ~(0x3 << 2); /* CacheFlushTmrSelCstAct0 = 0x2 */
|
||||
dword |= (0x2 << 2);
|
||||
dword |= (0x1 << 1); /* CacheFlushEnCstAct0 = 1 */
|
||||
dword |= 0x1; /* CpuPrbEnCstAct0 = 1 */
|
||||
pci_write_config32(dev, 0x118, dword);
|
||||
|
||||
/* Configure C-state Control 2 */
|
||||
dword = pci_read_config32(dev, 0x11c);
|
||||
dword &= ~(0x1 << 8); /* PwrGateEnCstAct2 = 0 */
|
||||
dword &= ~(0x7 << 5); /* ClkDivisorCstAct2 = 0x0 */
|
||||
dword &= ~(0x3 << 2); /* CacheFlushTmrSelCstAct0 = 0x0 */
|
||||
dword &= ~(0x1 << 1); /* CacheFlushEnCstAct0 = 0 */
|
||||
dword &= ~(0x1); /* CpuPrbEnCstAct0 = 0 */
|
||||
pci_write_config32(dev, 0x11c, dword);
|
||||
|
||||
/* Configure C-state Policy Control 1 */
|
||||
dword = pci_read_config32(dev, 0x128);
|
||||
dword &= ~(0x7f << 5); /* CacheFlushTmr = 0x28 */
|
||||
dword |= (0x28 << 5);
|
||||
dword &= ~0x1; /* CoreCstateMode = !enable_cc6 */
|
||||
dword |= ((enable_cc6)?0:1);
|
||||
pci_write_config32(dev, 0x128, dword);
|
||||
}
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "done.\n");
|
||||
}
|
||||
|
||||
|
||||
static struct device_operations mcf4_ops = {
|
||||
.read_resources = pci_dev_read_resources,
|
||||
.set_resources = pci_dev_set_resources,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = nb_control_init,
|
||||
.scan_bus = 0,
|
||||
.ops_pci = 0,
|
||||
};
|
||||
|
||||
static const struct pci_driver mcf4_driver_fam10 __pci_driver = {
|
||||
.ops = &mcf4_ops,
|
||||
.vendor = PCI_VENDOR_ID_AMD,
|
||||
.device = 0x1204,
|
||||
};
|
||||
|
||||
static const struct pci_driver mcf4_driver_fam15_model10 __pci_driver = {
|
||||
.ops = &mcf4_ops,
|
||||
.vendor = PCI_VENDOR_ID_AMD,
|
||||
.device = 0x1404,
|
||||
};
|
||||
|
||||
static const struct pci_driver mcf4_driver_fam15 __pci_driver = {
|
||||
.ops = &mcf4_ops,
|
||||
.vendor = PCI_VENDOR_ID_AMD,
|
||||
.device = 0x1604,
|
||||
};
|
||||
|
|
@ -1,261 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2003 by Eric Biederman
|
||||
* Copyright (C) Stefan Reinauer
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
* Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Turn off machine check triggers when reading
|
||||
* pci space where there are no devices.
|
||||
* This is necessary when scanning the bus for
|
||||
* devices which is done by the kernel
|
||||
*/
|
||||
|
||||
#include <console/console.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <pc80/mc146818rtc.h>
|
||||
#include <lib.h>
|
||||
#include <cbmem.h>
|
||||
#include <cpu/amd/model_10xxx_rev.h>
|
||||
#include <types.h>
|
||||
|
||||
#include "amdfam10.h"
|
||||
|
||||
/**
|
||||
* @brief Read resources for AGP aperture
|
||||
*
|
||||
* @param dev
|
||||
*
|
||||
* There is only one AGP aperture resource needed. The resource is added to
|
||||
* the northbridge of BSP.
|
||||
*
|
||||
* The same trick can be used to augment legacy VGA resources which can
|
||||
* be detect by generic pci reousrce allocator for VGA devices.
|
||||
* BAD: it is more tricky than I think, the resource allocation code is
|
||||
* implemented in a way to NOT DOING legacy VGA resource allocation on
|
||||
* purpose :-(.
|
||||
*/
|
||||
static void mcf3_read_resources(struct device *dev)
|
||||
{
|
||||
struct resource *resource;
|
||||
unsigned char gart;
|
||||
/* Read the generic PCI resources */
|
||||
pci_dev_read_resources(dev);
|
||||
|
||||
/* If we are not the first processor don't allocate the gart apeture */
|
||||
if (dev->path.pci.devfn != PCI_DEVFN(CONFIG_CDB, 3)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gart = 1;
|
||||
get_option(&gart, "gart");
|
||||
|
||||
if (gart) {
|
||||
/* Add a Gart apeture resource */
|
||||
resource = new_resource(dev, 0x94);
|
||||
resource->size = CONFIG_AGP_APERTURE_SIZE;
|
||||
resource->align = log2(resource->size);
|
||||
resource->gran = log2(resource->size);
|
||||
resource->limit = 0xffffffff; /* 4G */
|
||||
resource->flags = IORESOURCE_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_agp_aperture(struct device *dev, uint32_t pci_id)
|
||||
{
|
||||
uint32_t dword;
|
||||
struct resource *resource;
|
||||
|
||||
resource = probe_resource(dev, 0x94);
|
||||
if (resource) {
|
||||
struct device *pdev;
|
||||
u32 gart_base, gart_acr;
|
||||
|
||||
/* Remember this resource has been stored */
|
||||
resource->flags |= IORESOURCE_STORED;
|
||||
|
||||
/* Find the size of the GART aperture */
|
||||
gart_acr = (0<<6)|(0<<5)|(0<<4)|((resource->gran - 25) << 1)|(0<<0);
|
||||
|
||||
/* Get the base address */
|
||||
gart_base = ((resource->base) >> 25) & 0x00007fff;
|
||||
|
||||
/* Update the other northbriges */
|
||||
pdev = 0;
|
||||
while ((pdev = dev_find_device(PCI_VENDOR_ID_AMD, pci_id, pdev))) {
|
||||
/* Store the GART size but don't enable it */
|
||||
pci_write_config32(pdev, 0x90, gart_acr);
|
||||
|
||||
/* Store the GART base address */
|
||||
pci_write_config32(pdev, 0x94, gart_base);
|
||||
|
||||
/* Don't set the GART Table base address */
|
||||
pci_write_config32(pdev, 0x98, 0);
|
||||
|
||||
/* Report the resource has been stored... */
|
||||
report_resource_stored(pdev, resource, " <gart>");
|
||||
|
||||
/* Errata 540 workaround */
|
||||
dword = pci_read_config32(pdev, 0x90);
|
||||
dword |= 0x1 << 6; /* DisGartTblWlkPrb = 0x1 */
|
||||
pci_write_config32(pdev, 0x90, dword);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mcf3_set_resources_fam10h(struct device *dev)
|
||||
{
|
||||
/* Set the gart aperture */
|
||||
set_agp_aperture(dev, 0x1203);
|
||||
|
||||
/* Set the generic PCI resources */
|
||||
pci_dev_set_resources(dev);
|
||||
}
|
||||
|
||||
static void mcf3_set_resources_fam15h_model10(struct device *dev)
|
||||
{
|
||||
/* Set the gart aperture */
|
||||
set_agp_aperture(dev, 0x1403);
|
||||
|
||||
/* Set the generic PCI resources */
|
||||
pci_dev_set_resources(dev);
|
||||
}
|
||||
|
||||
static void mcf3_set_resources_fam15h(struct device *dev)
|
||||
{
|
||||
/* Set the gart aperture */
|
||||
set_agp_aperture(dev, 0x1603);
|
||||
|
||||
/* Set the generic PCI resources */
|
||||
pci_dev_set_resources(dev);
|
||||
}
|
||||
|
||||
static void misc_control_init(struct device *dev)
|
||||
{
|
||||
uint32_t dword;
|
||||
uint8_t nvram;
|
||||
uint8_t boost_limit;
|
||||
uint8_t current_boost;
|
||||
|
||||
printk(BIOS_DEBUG, "NB: Function 3 Misc Control.. ");
|
||||
|
||||
#if CONFIG(DIMM_DDR3) && !CONFIG(NORTHBRIDGE_AMD_AGESA)
|
||||
uint8_t node;
|
||||
uint8_t slot;
|
||||
uint8_t dimm_present;
|
||||
|
||||
/* Restore DRAM MCA registers */
|
||||
struct amdmct_memory_info *mem_info;
|
||||
mem_info = cbmem_find(CBMEM_ID_AMDMCT_MEMINFO);
|
||||
if (mem_info) {
|
||||
node = PCI_SLOT(dev->path.pci.devfn) - 0x18;
|
||||
|
||||
/* Check node for installed DIMMs */
|
||||
dimm_present = 0;
|
||||
|
||||
/* Check all slots for installed DIMMs */
|
||||
for (slot = 0; slot < MAX_DIMMS_SUPPORTED; slot++) {
|
||||
if (mem_info->dct_stat[node].DIMMPresent & (1 << slot)) {
|
||||
dimm_present = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dimm_present) {
|
||||
uint32_t mc4_status_high = pci_read_config32(dev, 0x4c);
|
||||
uint32_t mc4_status_low = pci_read_config32(dev, 0x48);
|
||||
if ((mc4_status_high & (0x1 << 31)) && (mc4_status_high != 0xffffffff)) {
|
||||
printk(BIOS_WARNING, "\nWARNING: MC4 Machine Check Exception detected on node %d!\n"
|
||||
"Signature: %08x%08x\n", node, mc4_status_high, mc4_status_low);
|
||||
}
|
||||
|
||||
/* Clear MC4 error status */
|
||||
pci_write_config32(dev, 0x48, 0x0);
|
||||
pci_write_config32(dev, 0x4c, 0x0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Disable Machine checks from Invalid Locations.
|
||||
* This is needed for PC backwards compatibility.
|
||||
*/
|
||||
dword = pci_read_config32(dev, 0x44);
|
||||
dword |= (1<<6) | (1<<25);
|
||||
pci_write_config32(dev, 0x44, dword);
|
||||
|
||||
boost_limit = 0xf;
|
||||
if (get_option(&nvram, "maximum_p_state_limit") == CB_SUCCESS)
|
||||
boost_limit = nvram & 0xf;
|
||||
|
||||
/* Set P-state maximum value */
|
||||
dword = pci_read_config32(dev, 0xdc);
|
||||
current_boost = (dword >> 8) & 0x7;
|
||||
if (boost_limit > current_boost)
|
||||
boost_limit = current_boost;
|
||||
dword &= ~(0x7 << 8);
|
||||
dword |= (boost_limit & 0x7) << 8;
|
||||
pci_write_config32(dev, 0xdc, dword);
|
||||
|
||||
printk(BIOS_DEBUG, "done.\n");
|
||||
}
|
||||
|
||||
|
||||
static struct device_operations mcf3_ops_fam10h = {
|
||||
.read_resources = mcf3_read_resources,
|
||||
.set_resources = mcf3_set_resources_fam10h,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = misc_control_init,
|
||||
.scan_bus = 0,
|
||||
.ops_pci = 0,
|
||||
};
|
||||
|
||||
static struct device_operations mcf3_ops_fam15h_model10 = {
|
||||
.read_resources = mcf3_read_resources,
|
||||
.set_resources = mcf3_set_resources_fam15h_model10,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = misc_control_init,
|
||||
.scan_bus = 0,
|
||||
.ops_pci = 0,
|
||||
};
|
||||
|
||||
static struct device_operations mcf3_ops_fam15h = {
|
||||
.read_resources = mcf3_read_resources,
|
||||
.set_resources = mcf3_set_resources_fam15h,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = misc_control_init,
|
||||
.scan_bus = 0,
|
||||
.ops_pci = 0,
|
||||
};
|
||||
|
||||
static const struct pci_driver mcf3_driver __pci_driver = {
|
||||
.ops = &mcf3_ops_fam10h,
|
||||
.vendor = PCI_VENDOR_ID_AMD,
|
||||
.device = 0x1203,
|
||||
};
|
||||
|
||||
static const struct pci_driver mcf3_driver_fam15_model10 __pci_driver = {
|
||||
.ops = &mcf3_ops_fam15h_model10,
|
||||
.vendor = PCI_VENDOR_ID_AMD,
|
||||
.device = 0x1403,
|
||||
};
|
||||
|
||||
static const struct pci_driver mcf3_driver_fam15 __pci_driver = {
|
||||
.ops = &mcf3_ops_fam15h,
|
||||
.vendor = PCI_VENDOR_ID_AMD,
|
||||
.device = 0x1603,
|
||||
};
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
* Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Configure various power control registers, including processor boost
|
||||
* and TDP monitoring support.
|
||||
*/
|
||||
|
||||
#include <console/console.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <cpu/amd/model_10xxx_rev.h>
|
||||
|
||||
#include "amdfam10.h"
|
||||
|
||||
static void nb_control_init(struct device *dev)
|
||||
{
|
||||
uint32_t dword;
|
||||
uint32_t f5x80;
|
||||
uint8_t cu_enabled;
|
||||
uint8_t compute_unit_count = 0;
|
||||
|
||||
printk(BIOS_DEBUG, "NB: Function 5 Northbridge Control.. ");
|
||||
|
||||
/* Determine the number of active compute units on this node */
|
||||
f5x80 = pci_read_config32(dev, 0x80);
|
||||
cu_enabled = f5x80 & 0xf;
|
||||
if (cu_enabled == 0x1)
|
||||
compute_unit_count = 1;
|
||||
if (cu_enabled == 0x3)
|
||||
compute_unit_count = 2;
|
||||
if (cu_enabled == 0x7)
|
||||
compute_unit_count = 3;
|
||||
if (cu_enabled == 0xf)
|
||||
compute_unit_count = 4;
|
||||
|
||||
/* Configure Processor TDP Running Average */
|
||||
dword = pci_read_config32(dev, 0xe0);
|
||||
dword &= ~0xf; /* RunAvgRange = 0x9 */
|
||||
dword |= 0x9;
|
||||
pci_write_config32(dev, 0xe0, dword);
|
||||
|
||||
/* Configure northbridge P-states */
|
||||
dword = pci_read_config32(dev, 0x170);
|
||||
dword &= ~(0x7 << 9); /* NbPstateThreshold = compute_unit_count */
|
||||
dword |= (compute_unit_count & 0x7) << 9;
|
||||
pci_write_config32(dev, 0x170, dword);
|
||||
|
||||
printk(BIOS_DEBUG, "done.\n");
|
||||
}
|
||||
|
||||
static struct device_operations mcf5_ops = {
|
||||
.read_resources = pci_dev_read_resources,
|
||||
.set_resources = pci_dev_set_resources,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = nb_control_init,
|
||||
.scan_bus = 0,
|
||||
.ops_pci = 0,
|
||||
};
|
||||
|
||||
static const struct pci_driver mcf5_driver_fam15_model10 __pci_driver = {
|
||||
.ops = &mcf5_ops,
|
||||
.vendor = PCI_VENDOR_ID_AMD,
|
||||
.device = 0x1405,
|
||||
};
|
||||
|
||||
static const struct pci_driver mcf5_driver_fam15 __pci_driver = {
|
||||
.ops = &mcf5_ops,
|
||||
.vendor = PCI_VENDOR_ID_AMD,
|
||||
.device = 0x1605,
|
||||
};
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef NORTHBRIDGE_AMD_AMDFAM10_H
|
||||
#define NORTHBRIDGE_AMD_AMDFAM10_H
|
||||
|
||||
u32 amdfam10_scan_root_bus(struct device *root, u32 max);
|
||||
|
||||
#endif /* NORTHBRIDGE_AMD_AMDFAM10_H */
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AMDFAM10_NUMS_H
|
||||
|
||||
#define AMDFAM10_NUMS_H
|
||||
|
||||
#if CONFIG_MAX_PHYSICAL_CPUS > 8
|
||||
#if CONFIG_MAX_PHYSICAL_CPUS > 32
|
||||
#define NODE_NUMS 64
|
||||
#else
|
||||
#define NODE_NUMS 32
|
||||
#endif
|
||||
#else
|
||||
#define NODE_NUMS 8
|
||||
#endif
|
||||
|
||||
// max HC installed at the same time. ...could be bigger than (48+24) if we have 3x4x4
|
||||
#define HC_NUMS 32
|
||||
|
||||
//it could be more bigger
|
||||
#define HC_POSSIBLE_NUM 32
|
||||
|
||||
#endif
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <device/pci_ops.h>
|
||||
#include "pci.h"
|
||||
|
||||
/* bit [10,8] are dev func, bit[1,0] are dev index */
|
||||
|
||||
u32 pci_read_config32_index(pci_devfn_t dev, u32 index_reg, u32 index)
|
||||
{
|
||||
u32 dword;
|
||||
|
||||
pci_write_config32(dev, index_reg, index);
|
||||
dword = pci_read_config32(dev, index_reg+0x4);
|
||||
return dword;
|
||||
}
|
||||
|
||||
#ifdef UNUSED_CODE
|
||||
void pci_write_config32_index(pci_devfn_t dev, u32 index_reg, u32 index,
|
||||
u32 data)
|
||||
{
|
||||
|
||||
pci_write_config32(dev, index_reg, index);
|
||||
|
||||
pci_write_config32(dev, index_reg + 0x4, data);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
u32 pci_read_config32_index_wait(pci_devfn_t dev, u32 index_reg,
|
||||
u32 index)
|
||||
{
|
||||
|
||||
u32 dword;
|
||||
|
||||
index &= ~(1<<30);
|
||||
pci_write_config32(dev, index_reg, index);
|
||||
do {
|
||||
dword = pci_read_config32(dev, index_reg);
|
||||
} while (!(dword & (1<<31)));
|
||||
dword = pci_read_config32(dev, index_reg+0x4);
|
||||
return dword;
|
||||
}
|
||||
|
||||
#ifdef UNUSED_CODE
|
||||
void pci_write_config32_index_wait(pci_devfn_t dev, u32 index_reg,
|
||||
u32 index, u32 data)
|
||||
{
|
||||
|
||||
u32 dword;
|
||||
|
||||
pci_write_config32(dev, index_reg + 0x4, data);
|
||||
index |= (1<<30);
|
||||
pci_write_config32(dev, index_reg, index);
|
||||
do {
|
||||
dword = pci_read_config32(dev, index_reg);
|
||||
} while (!(dword & (1<<31)));
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AMDFAM10_PCI_H
|
||||
#define AMDFAM10_PCI_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <device/pci_type.h>
|
||||
#include <device/pci_def.h>
|
||||
|
||||
u32 pci_read_config32_index(pci_devfn_t dev, u32 index_reg, u32 index);
|
||||
u32 pci_read_config32_index_wait(pci_devfn_t dev, u32 index_reg, u32 index);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AMDFAM10_RAMINIT_H
|
||||
#define AMDFAM10_RAMINIT_H
|
||||
|
||||
#include <device/pci.h>
|
||||
#include <northbridge/amd/amdmct/amddefs.h>
|
||||
#include <northbridge/amd/amdmct/wrappers/mcti.h>
|
||||
|
||||
struct sys_info;
|
||||
struct DCTStatStruc;
|
||||
struct MCTStatStruc;
|
||||
|
||||
void activate_spd_rom(const struct mem_controller *ctrl);
|
||||
|
||||
int mctRead_SPD(u32 smaddr, u32 reg);
|
||||
void mctSMBhub_Init(u32 node);
|
||||
void mctGet_DIMMAddr(struct DCTStatStruc *pDCTstat, u32 node);
|
||||
void set_sysinfo_in_ram(u32 val);
|
||||
struct sys_info *get_sysinfo(void);
|
||||
void raminit_amdmct(struct sys_info *sysinfo);
|
||||
void amdmct_cbmem_store_info(struct sys_info *sysinfo);
|
||||
void fill_mem_ctrl(u32 controllers, struct mem_controller *ctrl_a, const u8 *spd_addr);
|
||||
uint16_t mct_MaxLoadFreq(uint8_t count, uint8_t highest_rank_count, uint8_t registered, uint8_t voltage, uint16_t freq);
|
||||
u8 mctGetProcessorPackageType(void);
|
||||
void Set_NB32_DCT(uint32_t dev, uint8_t dct, uint32_t reg, uint32_t val);
|
||||
uint32_t Get_NB32_DCT(uint32_t dev, uint8_t dct, uint32_t reg);
|
||||
uint32_t Get_NB32_index_wait_DCT(uint32_t dev, uint8_t dct, uint32_t index_reg, uint32_t index);
|
||||
void Set_NB32_index_wait_DCT(uint32_t dev, uint8_t dct, uint32_t index_reg, uint32_t index, uint32_t data);
|
||||
void fam15h_switch_dct(uint32_t dev, uint8_t dct);
|
||||
uint32_t Get_NB32_DCT_NBPstate(uint32_t dev, uint8_t dct, uint8_t nb_pstate, uint32_t reg);
|
||||
void Set_NB32_DCT_NBPstate(uint32_t dev, uint8_t dct, uint8_t nb_pstate, uint32_t reg, uint32_t val);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,620 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <arch/acpi.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <device/pci.h>
|
||||
#include <string.h>
|
||||
#include <cbmem.h>
|
||||
#include <console/console.h>
|
||||
#include <northbridge/amd/amdfam10/debug.h>
|
||||
#include <northbridge/amd/amdfam10/raminit.h>
|
||||
#include <northbridge/amd/amdfam10/amdfam10.h>
|
||||
#include <timestamp.h>
|
||||
|
||||
/* Global allocation of sysinfo_car */
|
||||
#include <arch/early_variables.h>
|
||||
static struct sys_info sysinfo_car CAR_GLOBAL;
|
||||
|
||||
struct sys_info *get_sysinfo(void)
|
||||
{
|
||||
return car_get_var_ptr(&sysinfo_car);
|
||||
}
|
||||
|
||||
struct mem_controller;
|
||||
extern int spd_read_byte(unsigned int device, unsigned int address);
|
||||
|
||||
void __weak activate_spd_rom(const struct mem_controller *ctrl)
|
||||
{
|
||||
}
|
||||
|
||||
void fam15h_switch_dct(uint32_t dev, uint8_t dct)
|
||||
{
|
||||
uint32_t dword;
|
||||
|
||||
dword = Get_NB32(dev, 0x10c);
|
||||
dword &= ~0x1;
|
||||
dword |= (dct & 0x1);
|
||||
Set_NB32(dev, 0x10c, dword);
|
||||
}
|
||||
|
||||
static inline void fam15h_switch_nb_pstate_config_reg(uint32_t dev, uint8_t nb_pstate)
|
||||
{
|
||||
uint32_t dword;
|
||||
|
||||
dword = Get_NB32(dev, 0x10c);
|
||||
dword &= ~(0x3 << 4);
|
||||
dword |= (nb_pstate & 0x3) << 4;
|
||||
Set_NB32(dev, 0x10c, dword);
|
||||
}
|
||||
|
||||
uint32_t Get_NB32_DCT(uint32_t dev, uint8_t dct, uint32_t reg)
|
||||
{
|
||||
if (is_fam15h()) {
|
||||
/* Obtain address of function 0x1 */
|
||||
uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
|
||||
fam15h_switch_dct(dev_map, dct);
|
||||
return Get_NB32(dev, reg);
|
||||
} else {
|
||||
return Get_NB32(dev, (0x100 * dct) + reg);
|
||||
}
|
||||
}
|
||||
|
||||
void Set_NB32_DCT(uint32_t dev, uint8_t dct, uint32_t reg, uint32_t val)
|
||||
{
|
||||
if (is_fam15h()) {
|
||||
/* Obtain address of function 0x1 */
|
||||
uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
|
||||
fam15h_switch_dct(dev_map, dct);
|
||||
Set_NB32(dev, reg, val);
|
||||
} else {
|
||||
Set_NB32(dev, (0x100 * dct) + reg, val);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Get_NB32_DCT_NBPstate(uint32_t dev, uint8_t dct, uint8_t nb_pstate, uint32_t reg)
|
||||
{
|
||||
if (is_fam15h()) {
|
||||
/* Obtain address of function 0x1 */
|
||||
uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
|
||||
fam15h_switch_dct(dev_map, dct);
|
||||
fam15h_switch_nb_pstate_config_reg(dev_map, nb_pstate);
|
||||
return Get_NB32(dev, reg);
|
||||
} else {
|
||||
return Get_NB32(dev, (0x100 * dct) + reg);
|
||||
}
|
||||
}
|
||||
|
||||
void Set_NB32_DCT_NBPstate(uint32_t dev, uint8_t dct, uint8_t nb_pstate, uint32_t reg, uint32_t val)
|
||||
{
|
||||
if (is_fam15h()) {
|
||||
/* Obtain address of function 0x1 */
|
||||
uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
|
||||
fam15h_switch_dct(dev_map, dct);
|
||||
fam15h_switch_nb_pstate_config_reg(dev_map, nb_pstate);
|
||||
Set_NB32(dev, reg, val);
|
||||
} else {
|
||||
Set_NB32(dev, (0x100 * dct) + reg, val);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Get_NB32_index_wait_DCT(uint32_t dev, uint8_t dct, uint32_t index_reg, uint32_t index)
|
||||
{
|
||||
if (is_fam15h()) {
|
||||
/* Obtain address of function 0x1 */
|
||||
uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
|
||||
fam15h_switch_dct(dev_map, dct);
|
||||
return Get_NB32_index_wait(dev, index_reg, index);
|
||||
} else {
|
||||
return Get_NB32_index_wait(dev, (0x100 * dct) + index_reg, index);
|
||||
}
|
||||
}
|
||||
|
||||
void Set_NB32_index_wait_DCT(uint32_t dev, uint8_t dct, uint32_t index_reg, uint32_t index, uint32_t data)
|
||||
{
|
||||
if (is_fam15h()) {
|
||||
/* Obtain address of function 0x1 */
|
||||
uint32_t dev_map = (dev & (~(0x7 << 12))) | (0x1 << 12);
|
||||
fam15h_switch_dct(dev_map, dct);
|
||||
Set_NB32_index_wait(dev, index_reg, index, data);
|
||||
} else {
|
||||
Set_NB32_index_wait(dev, (0x100 * dct) + index_reg, index, data);
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t voltage_index_to_mv(uint8_t index)
|
||||
{
|
||||
if (index & 0x8)
|
||||
return 1150;
|
||||
if (index & 0x4)
|
||||
return 1250;
|
||||
else if (index & 0x2)
|
||||
return 1350;
|
||||
else
|
||||
return 1500;
|
||||
}
|
||||
|
||||
uint16_t mct_MaxLoadFreq(uint8_t count, uint8_t highest_rank_count, uint8_t registered, uint8_t voltage, uint16_t freq)
|
||||
{
|
||||
/* FIXME
|
||||
* Mainboards need to be able to specify the maximum number of DIMMs installable per channel
|
||||
* For now assume a maximum of 2 DIMMs per channel can be installed
|
||||
*/
|
||||
uint8_t MaxDimmsInstallable = 2;
|
||||
|
||||
/* Return limited maximum RAM frequency */
|
||||
if (CONFIG(DIMM_DDR2)) {
|
||||
if (CONFIG(DIMM_REGISTERED) && registered) {
|
||||
/* K10 BKDG Rev. 3.62 Table 53 */
|
||||
if (count > 2) {
|
||||
/* Limit to DDR2-533 */
|
||||
if (freq > 266) {
|
||||
freq = 266;
|
||||
print_tf(__func__, ": More than 2 registered DIMMs on channel; limiting to DDR2-533\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* K10 BKDG Rev. 3.62 Table 52 */
|
||||
if (count > 1) {
|
||||
/* Limit to DDR2-800 */
|
||||
if (freq > 400) {
|
||||
freq = 400;
|
||||
print_tf(__func__, ": More than 1 unbuffered DIMM on channel; limiting to DDR2-800\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (CONFIG(DIMM_DDR3)) {
|
||||
if (voltage == 0) {
|
||||
printk(BIOS_DEBUG, "%s: WARNING: Mainboard DDR3 voltage unknown, assuming 1.5V!\n", __func__);
|
||||
voltage = 0x1;
|
||||
}
|
||||
|
||||
if (is_fam15h()) {
|
||||
if (CONFIG_CPU_SOCKET_TYPE == 0x15) {
|
||||
/* Socket G34 */
|
||||
if (CONFIG(DIMM_REGISTERED) && registered) {
|
||||
/* Fam15h BKDG Rev. 3.14 Table 27 */
|
||||
if (voltage & 0x4) {
|
||||
/* 1.25V */
|
||||
if (count > 1) {
|
||||
if (highest_rank_count > 1) {
|
||||
/* Limit to DDR3-1066 */
|
||||
if (freq > 533) {
|
||||
freq = 533;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else if (voltage & 0x2) {
|
||||
/* 1.35V */
|
||||
if (count > 1) {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1600 */
|
||||
if (freq > 800) {
|
||||
freq = 800;
|
||||
printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else if (voltage & 0x1) {
|
||||
/* 1.50V */
|
||||
if (count > 1) {
|
||||
/* Limit to DDR3-1600 */
|
||||
if (freq > 800) {
|
||||
freq = 800;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1866 */
|
||||
if (freq > 933) {
|
||||
freq = 933;
|
||||
printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1866\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Fam15h BKDG Rev. 3.14 Table 26 */
|
||||
if (voltage & 0x4) {
|
||||
/* 1.25V */
|
||||
if (count > 1) {
|
||||
if (highest_rank_count > 1) {
|
||||
/* Limit to DDR3-1066 */
|
||||
if (freq > 533) {
|
||||
freq = 533;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else if (voltage & 0x2) {
|
||||
/* 1.35V */
|
||||
if (MaxDimmsInstallable > 1) {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1600 */
|
||||
if (freq > 800) {
|
||||
freq = 800;
|
||||
printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else if (voltage & 0x1) {
|
||||
if (MaxDimmsInstallable == 1) {
|
||||
if (count > 1) {
|
||||
/* Limit to DDR3-1600 */
|
||||
if (freq > 800) {
|
||||
freq = 800;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1866 */
|
||||
if (freq > 933) {
|
||||
freq = 933;
|
||||
printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1866\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (count > 1) {
|
||||
if (highest_rank_count > 1) {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1600 */
|
||||
if (freq > 800) {
|
||||
freq = 800;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1600 */
|
||||
if (freq > 800) {
|
||||
freq = 800;
|
||||
printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (CONFIG_CPU_SOCKET_TYPE == 0x14) {
|
||||
/* Socket C32 */
|
||||
if (CONFIG(DIMM_REGISTERED) && registered) {
|
||||
/* Fam15h BKDG Rev. 3.14 Table 30 */
|
||||
if (voltage & 0x4) {
|
||||
/* 1.25V */
|
||||
if (count > 1) {
|
||||
if (highest_rank_count > 2) {
|
||||
/* Limit to DDR3-800 */
|
||||
if (freq > 400) {
|
||||
freq = 400;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-800\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else if (voltage & 0x2) {
|
||||
/* 1.35V */
|
||||
if (count > 1) {
|
||||
if (highest_rank_count > 2) {
|
||||
/* Limit to DDR3-800 */
|
||||
if (freq > 400) {
|
||||
freq = 400;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-800\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else if (highest_rank_count > 1) {
|
||||
/* Limit to DDR3-1066 */
|
||||
if (freq > 533) {
|
||||
freq = 533;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1600 */
|
||||
if (freq > 800) {
|
||||
freq = 800;
|
||||
printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else if (voltage & 0x1) {
|
||||
/* 1.50V */
|
||||
if (count > 1) {
|
||||
if (highest_rank_count > 2) {
|
||||
/* Limit to DDR3-800 */
|
||||
if (freq > 400) {
|
||||
freq = 400;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-800\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else if (highest_rank_count > 1) {
|
||||
/* Limit to DDR3-1066 */
|
||||
if (freq > 533) {
|
||||
freq = 533;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (highest_rank_count > 2) {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1600 */
|
||||
if (freq > 800) {
|
||||
freq = 800;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 registered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Fam15h BKDG Rev. 3.14 Table 29 */
|
||||
if (voltage & 0x4) {
|
||||
/* 1.25V */
|
||||
if (count > 1) {
|
||||
/* Limit to DDR3-1066 */
|
||||
if (freq > 533) {
|
||||
freq = 533;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else if (voltage & 0x2) {
|
||||
if (count > 1) {
|
||||
if (highest_rank_count > 1) {
|
||||
/* Limit to DDR3-1066 */
|
||||
if (freq > 533) {
|
||||
freq = 533;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else if (voltage & 0x1) {
|
||||
if (MaxDimmsInstallable == 1) {
|
||||
/* Limit to DDR3-1600 */
|
||||
if (freq > 800) {
|
||||
freq = 800;
|
||||
printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
if (count > 1) {
|
||||
if (highest_rank_count > 1) {
|
||||
/* Limit to DDR3-1066 */
|
||||
if (freq > 533) {
|
||||
freq = 533;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: More than 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1600 */
|
||||
if (freq > 800) {
|
||||
freq = 800;
|
||||
printk(BIOS_DEBUG, "%s: 1 unbuffered DIMM on %dmV channel; limiting to DDR3-1600\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* TODO
|
||||
* Other socket support unimplemented
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
if (CONFIG(DIMM_REGISTERED) && registered) {
|
||||
/* K10 BKDG Rev. 3.62 Table 34 */
|
||||
if (count > 2) {
|
||||
/* Limit to DDR3-800 */
|
||||
if (freq > 400) {
|
||||
freq = 400;
|
||||
printk(BIOS_DEBUG, "%s: More than 2 registered DIMMs on %dmV channel; limiting to DDR3-800\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else if (count == 2) {
|
||||
/* Limit to DDR3-1066 */
|
||||
if (freq > 533) {
|
||||
freq = 533;
|
||||
printk(BIOS_DEBUG, "%s: 2 registered DIMMs on %dmV channel; limiting to DDR3-1066\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
} else {
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: 1 registered DIMM on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* K10 BKDG Rev. 3.62 Table 33 */
|
||||
/* Limit to DDR3-1333 */
|
||||
if (freq > 666) {
|
||||
freq = 666;
|
||||
printk(BIOS_DEBUG, "%s: unbuffered DIMMs on %dmV channel; limiting to DDR3-1333\n", __func__, voltage_index_to_mv(voltage));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
int mctRead_SPD(u32 smaddr, u32 reg)
|
||||
{
|
||||
return spd_read_byte(smaddr, reg);
|
||||
}
|
||||
|
||||
|
||||
void mctSMBhub_Init(u32 node)
|
||||
{
|
||||
struct sys_info *sysinfo = &sysinfo_car;
|
||||
struct mem_controller *ctrl = &(sysinfo->ctrl[node]);
|
||||
activate_spd_rom(ctrl);
|
||||
}
|
||||
|
||||
|
||||
void mctGet_DIMMAddr(struct DCTStatStruc *pDCTstat, u32 node)
|
||||
{
|
||||
int j;
|
||||
struct sys_info *sysinfo = &sysinfo_car;
|
||||
struct mem_controller *ctrl = &(sysinfo->ctrl[node]);
|
||||
|
||||
for (j = 0; j < DIMM_SOCKETS; j++) {
|
||||
pDCTstat->DIMMAddr[j*2] = ctrl->spd_addr[j] & 0xff;
|
||||
pDCTstat->DIMMAddr[j*2+1] = ctrl->spd_addr[DIMM_SOCKETS + j] & 0xff;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if CONFIG(SET_FIDVID)
|
||||
u8 mctGetProcessorPackageType(void) {
|
||||
/* FIXME: I guess this belongs wherever mctGetLogicalCPUID ends up ? */
|
||||
u32 BrandId = cpuid_ebx(0x80000001);
|
||||
return (u8)((BrandId >> 28) & 0x0F);
|
||||
}
|
||||
#endif
|
||||
|
||||
void raminit_amdmct(struct sys_info *sysinfo)
|
||||
{
|
||||
struct MCTStatStruc *pMCTstat = &(sysinfo->MCTstat);
|
||||
struct DCTStatStruc *pDCTstatA = sysinfo->DCTstatA;
|
||||
|
||||
printk(BIOS_DEBUG, "raminit_amdmct begin:\n");
|
||||
timestamp_add_now(TS_BEFORE_INITRAM);
|
||||
|
||||
mctAutoInitMCT_D(pMCTstat, pDCTstatA);
|
||||
|
||||
timestamp_add_now(TS_AFTER_INITRAM);
|
||||
printk(BIOS_DEBUG, "raminit_amdmct end:\n");
|
||||
}
|
||||
|
||||
void amdmct_cbmem_store_info(struct sys_info *sysinfo)
|
||||
{
|
||||
if (!sysinfo)
|
||||
return;
|
||||
|
||||
/* Save memory info structures for use in ramstage */
|
||||
size_t i;
|
||||
struct DCTStatStruc *pDCTstatA = NULL;
|
||||
|
||||
if (!acpi_is_wakeup_s3()) {
|
||||
/* Allocate memory */
|
||||
struct amdmct_memory_info *mem_info;
|
||||
mem_info = cbmem_add(CBMEM_ID_AMDMCT_MEMINFO, sizeof(struct amdmct_memory_info));
|
||||
if (!mem_info)
|
||||
return;
|
||||
|
||||
printk(BIOS_DEBUG, "%s: Storing AMDMCT configuration in CBMEM\n", __func__);
|
||||
|
||||
/* Initialize memory */
|
||||
memset(mem_info, 0, sizeof(struct amdmct_memory_info));
|
||||
|
||||
/* Copy data */
|
||||
memcpy(&mem_info->mct_stat, &sysinfo->MCTstat, sizeof(struct MCTStatStruc));
|
||||
for (i = 0; i < MAX_NODES_SUPPORTED; i++) {
|
||||
pDCTstatA = sysinfo->DCTstatA + i;
|
||||
memcpy(&mem_info->dct_stat[i], pDCTstatA, sizeof(struct DCTStatStruc));
|
||||
}
|
||||
mem_info->ecc_enabled = mctGet_NVbits(NV_ECC_CAP);
|
||||
mem_info->ecc_scrub_rate = mctGet_NVbits(NV_DramBKScrub);
|
||||
|
||||
/* Zero out invalid/unused pointers */
|
||||
#if CONFIG(DIMM_DDR3)
|
||||
for (i = 0; i < MAX_NODES_SUPPORTED; i++) {
|
||||
mem_info->dct_stat[i].C_MCTPtr = NULL;
|
||||
mem_info->dct_stat[i].C_DCTPtr[0] = NULL;
|
||||
mem_info->dct_stat[i].C_DCTPtr[1] = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <device/pci_ops.h>
|
||||
#include <northbridge/amd/amdfam10/raminit.h>
|
||||
#include <northbridge/amd/amdfam10/amdfam10.h>
|
||||
#include <delay.h>
|
||||
|
||||
static void set_htic_bit(u8 i, u32 val, u8 bit)
|
||||
{
|
||||
u32 dword;
|
||||
dword = pci_read_config32(NODE_PCI(i, 0), HT_INIT_CONTROL);
|
||||
dword &= ~(1<<bit);
|
||||
dword |= ((val & 1) <<bit);
|
||||
pci_write_config32(NODE_PCI(i, 0), HT_INIT_CONTROL, dword);
|
||||
}
|
||||
|
||||
#ifdef UNUSED_CODE
|
||||
static u32 get_htic_bit(u8 i, u8 bit)
|
||||
{
|
||||
u32 dword;
|
||||
dword = pci_read_config32(NODE_PCI(i, 0), HT_INIT_CONTROL);
|
||||
dword &= (1<<bit);
|
||||
return dword;
|
||||
}
|
||||
|
||||
static void wait_till_sysinfo_in_ram(void)
|
||||
{
|
||||
while (1) {
|
||||
/* give the NB a break, many CPUs spinning on one bit makes a
|
||||
* lot of traffic and time is not too important to APs.
|
||||
*/
|
||||
udelay(1000);
|
||||
if (get_htic_bit(0, 9)) return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void fill_mem_ctrl(u32 controllers, struct mem_controller *ctrl_a, const u8 *spd_addr)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int index = 0;
|
||||
struct mem_controller *ctrl;
|
||||
for (i = 0; i < controllers; i++) {
|
||||
ctrl = &ctrl_a[i];
|
||||
ctrl->node_id = i;
|
||||
ctrl->f0 = NODE_PCI(i, 0);
|
||||
ctrl->f1 = NODE_PCI(i, 1);
|
||||
ctrl->f2 = NODE_PCI(i, 2);
|
||||
ctrl->f3 = NODE_PCI(i, 3);
|
||||
ctrl->f4 = NODE_PCI(i, 4);
|
||||
ctrl->f5 = NODE_PCI(i, 5);
|
||||
|
||||
if (spd_addr == (void *)0) continue;
|
||||
|
||||
ctrl->spd_switch_addr = spd_addr[index++];
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
ctrl->spd_addr[j] = spd_addr[index++];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_sysinfo_in_ram(u32 val)
|
||||
{
|
||||
set_htic_bit(0, val, 9);
|
||||
}
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cpu/x86/lapic.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <northbridge/amd/amdfam10/raminit.h>
|
||||
#include <northbridge/amd/amdfam10/amdfam10.h>
|
||||
|
||||
/* mmconf is not ready */
|
||||
/* io_ext is not ready */
|
||||
u32 cpu_init_detected(u8 nodeid)
|
||||
{
|
||||
u32 htic;
|
||||
pci_devfn_t dev;
|
||||
|
||||
dev = NODE_PCI(nodeid, 0);
|
||||
htic = pci_io_read_config32(dev, HT_INIT_CONTROL);
|
||||
|
||||
return !!(htic & HTIC_INIT_Detect);
|
||||
}
|
||||
|
||||
u32 bios_reset_detected(void)
|
||||
{
|
||||
u32 htic;
|
||||
htic = pci_io_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0), HT_INIT_CONTROL);
|
||||
|
||||
return (htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect);
|
||||
}
|
||||
|
||||
u32 cold_reset_detected(void)
|
||||
{
|
||||
u32 htic;
|
||||
htic = pci_io_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0), HT_INIT_CONTROL);
|
||||
|
||||
return !(htic & HTIC_ColdR_Detect);
|
||||
}
|
||||
|
||||
u32 other_reset_detected(void) // other warm reset not started by BIOS
|
||||
{
|
||||
u32 htic;
|
||||
htic = pci_io_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0), HT_INIT_CONTROL);
|
||||
|
||||
return (htic & HTIC_ColdR_Detect) && (htic & HTIC_BIOSR_Detect);
|
||||
}
|
||||
|
||||
void distinguish_cpu_resets(u8 nodeid)
|
||||
{
|
||||
u32 htic;
|
||||
pci_devfn_t device;
|
||||
device = NODE_PCI(nodeid, 0);
|
||||
htic = pci_io_read_config32(device, HT_INIT_CONTROL);
|
||||
htic |= HTIC_ColdR_Detect | HTIC_BIOSR_Detect | HTIC_INIT_Detect;
|
||||
pci_io_write_config32(device, HT_INIT_CONTROL, htic);
|
||||
}
|
||||
|
||||
u32 warm_reset_detect(u8 nodeid)
|
||||
{
|
||||
u32 htic;
|
||||
pci_devfn_t device;
|
||||
device = NODE_PCI(nodeid, 0);
|
||||
htic = pci_io_read_config32(device, HT_INIT_CONTROL);
|
||||
return (htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect);
|
||||
}
|
||||
|
||||
void set_bios_reset(void)
|
||||
{
|
||||
|
||||
u32 nodes;
|
||||
u32 htic;
|
||||
pci_devfn_t dev;
|
||||
int i;
|
||||
|
||||
nodes = ((pci_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0), 0x60) >> 4) & 7) + 1;
|
||||
|
||||
for (i = 0; i < nodes; i++) {
|
||||
dev = NODE_PCI(i,0);
|
||||
htic = pci_read_config32(dev, HT_INIT_CONTROL);
|
||||
htic &= ~HTIC_BIOSR_Detect;
|
||||
pci_write_config32(dev, HT_INIT_CONTROL, htic);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Look up a which bus a given node/link combination is on.
|
||||
* return 0 when we can't find the answer.
|
||||
*/
|
||||
static u8 node_link_to_bus(u8 node, u8 link) // node are 6 bit, and link three bit
|
||||
{
|
||||
u32 reg;
|
||||
u32 val;
|
||||
|
||||
// put node and link in correct bit
|
||||
val = ((node & 0x0f)<<4) | ((node & 0x30)<< (12-4)) | ((link & 0x07)<<8);
|
||||
|
||||
for (reg = 0xE0; reg < 0xF0; reg += 0x04) {
|
||||
u32 config_map;
|
||||
config_map = pci_io_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 1), reg);
|
||||
if ((config_map & 3) != 3) {
|
||||
continue;
|
||||
}
|
||||
if ((config_map & (((63 & 0x0f)<<4) | ((63 & 0x30)<< (12-4)) | ((7 & 0x07)<<8))
|
||||
) == val)
|
||||
{
|
||||
return (config_map >> 16) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 get_sblk(void)
|
||||
{
|
||||
u32 reg;
|
||||
/* read PCI_DEV(CONFIG_CBB,CONFIG_CDB,0) 0x64 bit [8:9] to find out SbLink m */
|
||||
reg = pci_io_read_config32(PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0), 0x64);
|
||||
return ((reg>>8) & 3);
|
||||
}
|
||||
|
||||
|
||||
u8 get_sbbusn(u8 sblk)
|
||||
{
|
||||
return node_link_to_bus(0, sblk);
|
||||
}
|
||||
|
|
@ -1,282 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
static void setup_default_resource_map(void)
|
||||
{
|
||||
static const u32 register_values[] = {
|
||||
/* Careful set limit registers before base registers which contain
|
||||
the enables */
|
||||
/* DRAM Limit i Registers
|
||||
* F1:0x44 i = 0
|
||||
* F1:0x4C i = 1
|
||||
* F1:0x54 i = 2
|
||||
* F1:0x5C i = 3
|
||||
* F1:0x64 i = 4
|
||||
* F1:0x6C i = 5
|
||||
* F1:0x74 i = 6
|
||||
* F1:0x7C i = 7
|
||||
* [ 2: 0] Destination Node ID
|
||||
* 000 = Node 0
|
||||
* 001 = Node 1
|
||||
* 010 = Node 2
|
||||
* 011 = Node 3
|
||||
* 100 = Node 4
|
||||
* 101 = Node 5
|
||||
* 110 = Node 6
|
||||
* 111 = Node 7
|
||||
* [ 7: 3] Reserved
|
||||
* [10: 8] Interleave select
|
||||
* specifies the values of A[14:12] to use with
|
||||
* interleave enable.
|
||||
* [15:11] Reserved
|
||||
* [31:16] DRAM Limit Address i Bits 39-24
|
||||
* This field defines the upper address bits of a 40 bit
|
||||
* address that define the end of the DRAM region.
|
||||
*/
|
||||
ADDRMAP_REG(0x44), 0x0000f8f8, 0x00000000,
|
||||
ADDRMAP_REG(0x4C), 0x0000f8f8, 0x00000001,
|
||||
ADDRMAP_REG(0x54), 0x0000f8f8, 0x00000002,
|
||||
ADDRMAP_REG(0x5C), 0x0000f8f8, 0x00000003,
|
||||
ADDRMAP_REG(0x64), 0x0000f8f8, 0x00000004,
|
||||
ADDRMAP_REG(0x6C), 0x0000f8f8, 0x00000005,
|
||||
ADDRMAP_REG(0x74), 0x0000f8f8, 0x00000006,
|
||||
ADDRMAP_REG(0x7C), 0x0000f8f8, 0x00000007,
|
||||
/* DRAM Base i Registers
|
||||
* F1:0x40 i = 0
|
||||
* F1:0x48 i = 1
|
||||
* F1:0x50 i = 2
|
||||
* F1:0x58 i = 3
|
||||
* F1:0x60 i = 4
|
||||
* F1:0x68 i = 5
|
||||
* F1:0x70 i = 6
|
||||
* F1:0x78 i = 7
|
||||
* [ 0: 0] Read Enable
|
||||
* 0 = Reads Disabled
|
||||
* 1 = Reads Enabled
|
||||
* [ 1: 1] Write Enable
|
||||
* 0 = Writes Disabled
|
||||
* 1 = Writes Enabled
|
||||
* [ 7: 2] Reserved
|
||||
* [10: 8] Interleave Enable
|
||||
* 000 = No interleave
|
||||
* 001 = Interleave on A[12] (2 nodes)
|
||||
* 010 = reserved
|
||||
* 011 = Interleave on A[12] and A[14] (4 nodes)
|
||||
* 100 = reserved
|
||||
* 101 = reserved
|
||||
* 110 = reserved
|
||||
* 111 = Interleve on A[12] and A[13] and A[14] (8 nodes)
|
||||
* [15:11] Reserved
|
||||
* [13:16] DRAM Base Address i Bits 39-24
|
||||
* This field defines the upper address bits of a 40-bit
|
||||
* address that define the start of the DRAM region.
|
||||
*/
|
||||
ADDRMAP_REG(0x40), 0x0000f8fc, 0x00000000,
|
||||
ADDRMAP_REG(0x48), 0x0000f8fc, 0x00000000,
|
||||
ADDRMAP_REG(0x50), 0x0000f8fc, 0x00000000,
|
||||
ADDRMAP_REG(0x58), 0x0000f8fc, 0x00000000,
|
||||
ADDRMAP_REG(0x60), 0x0000f8fc, 0x00000000,
|
||||
ADDRMAP_REG(0x68), 0x0000f8fc, 0x00000000,
|
||||
ADDRMAP_REG(0x70), 0x0000f8fc, 0x00000000,
|
||||
ADDRMAP_REG(0x78), 0x0000f8fc, 0x00000000,
|
||||
|
||||
/* Memory-Mapped I/O Limit i Registers
|
||||
* F1:0x84 i = 0
|
||||
* F1:0x8C i = 1
|
||||
* F1:0x94 i = 2
|
||||
* F1:0x9C i = 3
|
||||
* F1:0xA4 i = 4
|
||||
* F1:0xAC i = 5
|
||||
* F1:0xB4 i = 6
|
||||
* F1:0xBC i = 7
|
||||
* [ 2: 0] Destination Node ID
|
||||
* 000 = Node 0
|
||||
* 001 = Node 1
|
||||
* 010 = Node 2
|
||||
* 011 = Node 3
|
||||
* 100 = Node 4
|
||||
* 101 = Node 5
|
||||
* 110 = Node 6
|
||||
* 111 = Node 7
|
||||
* [ 3: 3] Reserved
|
||||
* [ 5: 4] Destination Link ID
|
||||
* 00 = Link 0
|
||||
* 01 = Link 1
|
||||
* 10 = Link 2
|
||||
* 11 = Reserved
|
||||
* [ 6: 6] Reserved
|
||||
* [ 7: 7] Non-Posted
|
||||
* 0 = CPU writes may be posted
|
||||
* 1 = CPU writes must be non-posted
|
||||
* [31: 8] Memory-Mapped I/O Limit Address i (39-16)
|
||||
* This field defines the upp address bits of a 40-bit
|
||||
* address that defines the end of a memory-mapped
|
||||
* I/O region n
|
||||
*/
|
||||
ADDRMAP_REG(0x84), 0x00000048, 0x00000000,
|
||||
ADDRMAP_REG(0x8C), 0x00000048, 0x00000000,
|
||||
ADDRMAP_REG(0x94), 0x00000048, 0x00000000,
|
||||
ADDRMAP_REG(0x9C), 0x00000048, 0x00000000,
|
||||
ADDRMAP_REG(0xA4), 0x00000048, 0x00000000,
|
||||
ADDRMAP_REG(0xAC), 0x00000048, 0x00000000,
|
||||
ADDRMAP_REG(0xB4), 0x00000048, 0x00000000,
|
||||
ADDRMAP_REG(0xBC), 0x00000048, 0x00ffff00,
|
||||
|
||||
/* Memory-Mapped I/O Base i Registers
|
||||
* F1:0x80 i = 0
|
||||
* F1:0x88 i = 1
|
||||
* F1:0x90 i = 2
|
||||
* F1:0x98 i = 3
|
||||
* F1:0xA0 i = 4
|
||||
* F1:0xA8 i = 5
|
||||
* F1:0xB0 i = 6
|
||||
* F1:0xB8 i = 7
|
||||
* [ 0: 0] Read Enable
|
||||
* 0 = Reads disabled
|
||||
* 1 = Reads Enabled
|
||||
* [ 1: 1] Write Enable
|
||||
* 0 = Writes disabled
|
||||
* 1 = Writes Enabled
|
||||
* [ 2: 2] Cpu Disable
|
||||
* 0 = Cpu can use this I/O range
|
||||
* 1 = Cpu requests do not use this I/O range
|
||||
* [ 3: 3] Lock
|
||||
* 0 = base/limit registers i are read/write
|
||||
* 1 = base/limit registers i are read-only
|
||||
* [ 7: 4] Reserved
|
||||
* [31: 8] Memory-Mapped I/O Base Address i (39-16)
|
||||
* This field defines the upper address bits of a 40bit
|
||||
* address that defines the start of memory-mapped
|
||||
* I/O region i
|
||||
*/
|
||||
ADDRMAP_REG(0x80), 0x000000f0, 0x00000000,
|
||||
ADDRMAP_REG(0x88), 0x000000f0, 0x00000000,
|
||||
ADDRMAP_REG(0x90), 0x000000f0, 0x00000000,
|
||||
ADDRMAP_REG(0x98), 0x000000f0, 0x00000000,
|
||||
ADDRMAP_REG(0xA0), 0x000000f0, 0x00000000,
|
||||
ADDRMAP_REG(0xA8), 0x000000f0, 0x00000000,
|
||||
ADDRMAP_REG(0xB0), 0x000000f0, 0x00000000,
|
||||
ADDRMAP_REG(0xB8), 0x000000f0, 0x00fc0003,
|
||||
|
||||
/* PCI I/O Limit i Registers
|
||||
* F1:0xC4 i = 0
|
||||
* F1:0xCC i = 1
|
||||
* F1:0xD4 i = 2
|
||||
* F1:0xDC i = 3
|
||||
* [ 2: 0] Destination Node ID
|
||||
* 000 = Node 0
|
||||
* 001 = Node 1
|
||||
* 010 = Node 2
|
||||
* 011 = Node 3
|
||||
* 100 = Node 4
|
||||
* 101 = Node 5
|
||||
* 110 = Node 6
|
||||
* 111 = Node 7
|
||||
* [ 3: 3] Reserved
|
||||
* [ 5: 4] Destination Link ID
|
||||
* 00 = Link 0
|
||||
* 01 = Link 1
|
||||
* 10 = Link 2
|
||||
* 11 = reserved
|
||||
* [11: 6] Reserved
|
||||
* [24:12] PCI I/O Limit Address i
|
||||
* This field defines the end of PCI I/O region n
|
||||
* [31:25] Reserved
|
||||
*/
|
||||
ADDRMAP_REG(0xC4), 0xFE000FC8, 0x01fff000,
|
||||
ADDRMAP_REG(0xCC), 0xFE000FC8, 0x00000000,
|
||||
ADDRMAP_REG(0xD4), 0xFE000FC8, 0x00000000,
|
||||
ADDRMAP_REG(0xDC), 0xFE000FC8, 0x00000000,
|
||||
|
||||
/* PCI I/O Base i Registers
|
||||
* F1:0xC0 i = 0
|
||||
* F1:0xC8 i = 1
|
||||
* F1:0xD0 i = 2
|
||||
* F1:0xD8 i = 3
|
||||
* [ 0: 0] Read Enable
|
||||
* 0 = Reads Disabled
|
||||
* 1 = Reads Enabled
|
||||
* [ 1: 1] Write Enable
|
||||
* 0 = Writes Disabled
|
||||
* 1 = Writes Enabled
|
||||
* [ 3: 2] Reserved
|
||||
* [ 4: 4] VGA Enable
|
||||
* 0 = VGA matches Disabled
|
||||
* 1 = matches all address < 64K and where A[9:0] is in
|
||||
* the range 3B0-3BB or 3C0-3DF independent of the
|
||||
* base & limit registers
|
||||
* [ 5: 5] ISA Enable
|
||||
* 0 = ISA matches Disabled
|
||||
* 1 = Blocks address < 64K and in the last 768 bytes of
|
||||
* eack 1K block from matching agains this base/limit
|
||||
* pair
|
||||
* [11: 6] Reserved
|
||||
* [24:12] PCI I/O Base i
|
||||
* This field defines the start of PCI I/O region n
|
||||
* [31:25] Reserved
|
||||
*/
|
||||
ADDRMAP_REG(0xC0), 0xFE000FCC, 0x00000003,
|
||||
ADDRMAP_REG(0xC8), 0xFE000FCC, 0x00000000,
|
||||
ADDRMAP_REG(0xD0), 0xFE000FCC, 0x00000000,
|
||||
ADDRMAP_REG(0xD8), 0xFE000FCC, 0x00000000,
|
||||
|
||||
/* Config Base and Limit i Registers
|
||||
* F1:0xE0 i = 0
|
||||
* F1:0xE4 i = 1
|
||||
* F1:0xE8 i = 2
|
||||
* F1:0xEC i = 3
|
||||
* [ 0: 0] Read Enable
|
||||
* 0 = Reads Disabled
|
||||
* 1 = Reads Enabled
|
||||
* [ 1: 1] Write Enable
|
||||
* 0 = Writes Disabled
|
||||
* 1 = Writes Enabled
|
||||
* [ 2: 2] Device Number Compare Enable
|
||||
* 0 = The ranges are based on bus number
|
||||
* 1 = The ranges are ranges of devices on bus 0
|
||||
* [ 3: 3] Reserved
|
||||
* [ 6: 4] Destination Node
|
||||
* 000 = Node 0
|
||||
* 001 = Node 1
|
||||
* 010 = Node 2
|
||||
* 011 = Node 3
|
||||
* 100 = Node 4
|
||||
* 101 = Node 5
|
||||
* 110 = Node 6
|
||||
* 111 = Node 7
|
||||
* [ 7: 7] Reserved
|
||||
* [ 9: 8] Destination Link
|
||||
* 00 = Link 0
|
||||
* 01 = Link 1
|
||||
* 10 = Link 2
|
||||
* 11 - Reserved
|
||||
* [15:10] Reserved
|
||||
* [23:16] Bus Number Base i
|
||||
* This field defines the lowest bus number in
|
||||
* configuration region i
|
||||
* [31:24] Bus Number Limit i
|
||||
* This field defines the highest bus number in
|
||||
* configuration regin i
|
||||
*/
|
||||
ADDRMAP_REG(0xE0), 0x0000FC88, 0xff000003,
|
||||
ADDRMAP_REG(0xE4), 0x0000FC88, 0x00000000,
|
||||
ADDRMAP_REG(0xE8), 0x0000FC88, 0x00000000,
|
||||
ADDRMAP_REG(0xEC), 0x0000FC88, 0x00000000,
|
||||
};
|
||||
|
||||
u32 max;
|
||||
max = ARRAY_SIZE(register_values);
|
||||
setup_resource_map(register_values, max);
|
||||
}
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <arch/io.h>
|
||||
#include <stdint.h>
|
||||
#include <console/console.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <northbridge/amd/amdfam10/raminit.h>
|
||||
#include <northbridge/amd/amdfam10/amdfam10.h>
|
||||
|
||||
#define RES_DEBUG 0
|
||||
|
||||
void setup_resource_map(const u32 *register_values, u32 max)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < max; i += 3) {
|
||||
pci_devfn_t dev;
|
||||
u32 where;
|
||||
u32 reg;
|
||||
|
||||
dev = register_values[i] & ~0xfff;
|
||||
where = register_values[i] & 0xfff;
|
||||
reg = pci_read_config32(dev, where);
|
||||
reg &= register_values[i+1];
|
||||
reg |= register_values[i+2];
|
||||
pci_write_config32(dev, where, reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setup_resource_map_offset(const u32 *register_values, u32 max, u32 offset_pci_dev, u32 offset_io_base)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < max; i += 3) {
|
||||
pci_devfn_t dev;
|
||||
u32 where;
|
||||
unsigned long reg;
|
||||
dev = (register_values[i] & ~0xfff) + offset_pci_dev;
|
||||
where = register_values[i] & 0xfff;
|
||||
reg = pci_read_config32(dev, where);
|
||||
reg &= register_values[i+1];
|
||||
reg |= register_values[i+2] + offset_io_base;
|
||||
pci_write_config32(dev, where, reg);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_resource_map_x_offset(const u32 *register_values, u32 max, u32 offset_pci_dev, u32 offset_io_base)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
if (RES_DEBUG)
|
||||
printk(BIOS_DEBUG, "setting up resource map ex offset....\n");
|
||||
|
||||
for (i = 0; i < max; i += 4) {
|
||||
if (RES_DEBUG)
|
||||
printk(BIOS_DEBUG, "%04x: %02x %08x <- & %08x | %08x\n",
|
||||
i/4, register_values[i],
|
||||
register_values[i+1] + ((register_values[i]==RES_PCI_IO) ? offset_pci_dev : 0),
|
||||
register_values[i+2],
|
||||
register_values[i+3] + (((register_values[i] & RES_PORT_IO_32) == RES_PORT_IO_32) ? offset_io_base : 0)
|
||||
);
|
||||
switch (register_values[i]) {
|
||||
case RES_PCI_IO: //PCI
|
||||
{
|
||||
pci_devfn_t dev;
|
||||
u32 where;
|
||||
u32 reg;
|
||||
dev = (register_values[i+1] & ~0xfff) + offset_pci_dev;
|
||||
where = register_values[i+1] & 0xfff;
|
||||
reg = pci_read_config32(dev, where);
|
||||
if (RES_DEBUG)
|
||||
printk(BIOS_SPEW, "WAS: %08x\n", reg);
|
||||
reg &= register_values[i+2];
|
||||
reg |= register_values[i+3];
|
||||
pci_write_config32(dev, where, reg);
|
||||
if (RES_DEBUG)
|
||||
printk(BIOS_SPEW, "NOW: %08x\n", reg);
|
||||
}
|
||||
break;
|
||||
case RES_PORT_IO_8: // io 8
|
||||
{
|
||||
u32 where;
|
||||
u32 reg;
|
||||
where = register_values[i+1] + offset_io_base;
|
||||
reg = inb(where);
|
||||
if (RES_DEBUG)
|
||||
printk(BIOS_SPEW, "WAS: %08x\n", reg);
|
||||
reg &= register_values[i+2];
|
||||
reg |= register_values[i+3];
|
||||
outb(reg, where);
|
||||
if (RES_DEBUG)
|
||||
printk(BIOS_SPEW, "NOW: %08x\n", reg);
|
||||
}
|
||||
break;
|
||||
case RES_PORT_IO_32: //io32
|
||||
{
|
||||
u32 where;
|
||||
u32 reg;
|
||||
where = register_values[i+1] + offset_io_base;
|
||||
reg = inl(where);
|
||||
if (RES_DEBUG)
|
||||
printk(BIOS_SPEW, "WAS: %08x\n", reg);
|
||||
reg &= register_values[i+2];
|
||||
reg |= register_values[i+3];
|
||||
outl(reg, where);
|
||||
if (RES_DEBUG)
|
||||
printk(BIOS_SPEW, "NOW: %08x\n", reg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (RES_DEBUG)
|
||||
printk(BIOS_DEBUG, "done.\n");
|
||||
}
|
||||
|
||||
void setup_resource_map_x(const u32 *register_values, u32 max)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
if (RES_DEBUG)
|
||||
printk(BIOS_DEBUG, "setting up resource map ex offset....\n");
|
||||
|
||||
for (i = 0; i < max; i += 4) {
|
||||
if (RES_DEBUG)
|
||||
printk(BIOS_DEBUG, "%04x: %02x %08x <- & %08x | %08x\n",
|
||||
i/4, register_values[i],register_values[i+1], register_values[i+2], register_values[i+3]);
|
||||
switch (register_values[i]) {
|
||||
case RES_PCI_IO: //PCI
|
||||
{
|
||||
pci_devfn_t dev;
|
||||
u32 where;
|
||||
u32 reg;
|
||||
dev = register_values[i+1] & ~0xfff;
|
||||
where = register_values[i+1] & 0xfff;
|
||||
reg = pci_read_config32(dev, where);
|
||||
reg &= register_values[i+2];
|
||||
reg |= register_values[i+3];
|
||||
pci_write_config32(dev, where, reg);
|
||||
}
|
||||
break;
|
||||
case RES_PORT_IO_8: // io 8
|
||||
{
|
||||
u32 where;
|
||||
u32 reg;
|
||||
where = register_values[i+1];
|
||||
reg = inb(where);
|
||||
reg &= register_values[i+2];
|
||||
reg |= register_values[i+3];
|
||||
outb(reg, where);
|
||||
}
|
||||
break;
|
||||
case RES_PORT_IO_32: //io32
|
||||
{
|
||||
u32 where;
|
||||
u32 reg;
|
||||
where = register_values[i+1];
|
||||
reg = inl(where);
|
||||
reg &= register_values[i+2];
|
||||
reg |= register_values[i+3];
|
||||
outl(reg, where);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (RES_DEBUG)
|
||||
printk(BIOS_DEBUG, "done.\n");
|
||||
}
|
||||
|
|
@ -1,261 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2008 Vincent Legoll <vincent.legoll@gmail.com>
|
||||
* Copyright (C) 2008 Ronald G. Minnich <rminnich@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* fam10 northbridge utilities (dump routing registers).
|
||||
* Designed to be called at any time.
|
||||
* It can be called before RAM is set up by including this file.
|
||||
* It can be called after RAM is set up by including amdfam10.h and enabling the
|
||||
* compilation of this file in src/northbridge/amd/amdfam10/Makefile.inc.
|
||||
*/
|
||||
#include <console/console.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ops.h>
|
||||
|
||||
#include "amdfam10.h"
|
||||
|
||||
/* Function 1 */
|
||||
/* the DRAM, MMIO,and PCIIO routing are 64-bit registers, hence the ending at
|
||||
* 0x78, 0xb8, and 0xd8
|
||||
*/
|
||||
#define DRAM_ROUTE_START 0x40
|
||||
#define DRAM_ROUTE_END 0x78
|
||||
#define MMIO_ROUTE_START 0x80
|
||||
#define MMIO_ROUTE_END 0xb8
|
||||
#define PCIIO_ROUTE_START 0xc0
|
||||
#define PCIIO_ROUTE_END 0xd8
|
||||
#define CONF_ROUTE_START 0xe0
|
||||
#define CONF_ROUTE_END 0xec
|
||||
|
||||
#define BITS(r, shift, mask) (((r>>shift)&mask))
|
||||
|
||||
/**
|
||||
* Return "R" if the register has read-enable bit set.
|
||||
*/
|
||||
static const char *re(u32 i)
|
||||
{
|
||||
return ((i & 1) ? "R" : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return "W" if the register has write-enable bit set.
|
||||
*/
|
||||
static const char *we(u32 i)
|
||||
{
|
||||
return ((i & 1) ? "W" : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string containing the interleave settings.
|
||||
*/
|
||||
static const char *ileave(u32 base)
|
||||
{
|
||||
switch ((base >> 8) & 7) {
|
||||
case 0:
|
||||
return "No interleave";
|
||||
case 1:
|
||||
return "2 nodes";
|
||||
case 3:
|
||||
return "4 nodes";
|
||||
case 7:
|
||||
return "8 nodes";
|
||||
default:
|
||||
return "Reserved";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the node number.
|
||||
* For one case (config registers) these are not the right bit fields.
|
||||
*/
|
||||
static int r_node(u32 reg)
|
||||
{
|
||||
return BITS(reg, 0, 0x7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the link number.
|
||||
* For one case (config registers) these are not the right bit fields.
|
||||
*/
|
||||
static int r_link(u32 reg)
|
||||
{
|
||||
return BITS(reg, 4, 0x3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the DRAM routing info for one base/limit pair.
|
||||
*
|
||||
* Show base, limit, dest node, dest link on that node, read and write
|
||||
* enable, and interleave information.
|
||||
*
|
||||
* @param level Printing level
|
||||
* @param which Register number
|
||||
* @param base Base register
|
||||
* @param lim Limit register
|
||||
*/
|
||||
static void showdram(int level, u8 which, u32 base, u32 lim)
|
||||
{
|
||||
printk(level, "DRAM(%02x)%010llx-%010llx, ->(%d), %s, %s, %s, %d\n",
|
||||
which, (((u64) base & 0xffff0000) << 8),
|
||||
(((u64) lim & 0xffff0000) << 8) + 0xffffff,
|
||||
r_node(lim), re(base), we(base), ileave(base), (lim >> 8) & 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the config routing info for a config register.
|
||||
*
|
||||
* Show base, limit, dest node, dest link on that node, read and write
|
||||
* enable, and device number compare enable
|
||||
*
|
||||
* @param level Printing level
|
||||
* @param which Register number
|
||||
* @param reg Config register
|
||||
*/
|
||||
static void showconfig(int level, u8 which, u32 reg)
|
||||
{
|
||||
/* Don't use r_node() and r_link() here. */
|
||||
printk(level, "Config(%02x)%02x-%02x ->(%d,%d),%s %s (%s numbers)\n",
|
||||
which, BITS(reg, 16, 0xff), BITS(reg, 24, 0xff),
|
||||
BITS(reg, 4, 0x7), BITS(reg, 8, 0x3),
|
||||
re(reg), we(reg),
|
||||
BITS(reg, 2, 0x1)?"dev":"bus");
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the PCIIO routing info for one base/limit pair.
|
||||
*
|
||||
* Show base, limit, dest node, dest link on that node, read and write
|
||||
* enable, and VGA and ISA Enable.
|
||||
*
|
||||
* @param level Printing level
|
||||
* @param which Register number
|
||||
* @param base Base register
|
||||
* @param lim Limit register
|
||||
*/
|
||||
static void showpciio(int level, u8 which, u32 base, u32 lim)
|
||||
{
|
||||
printk(level, "PCIIO(%02x)%07x-%07x, ->(%d,%d), %s, %s,VGA %d ISA %d\n",
|
||||
which, BITS(base, 12, 0x3fff) << 12,
|
||||
(BITS(lim, 12, 0x3fff) << 12) + 0xfff, r_node(lim), r_link(lim),
|
||||
re(base), we(base), BITS(base, 4, 0x1), BITS(base, 5, 0x1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the MMIO routing info for one base/limit pair.
|
||||
*
|
||||
* Show base, limit, dest node, dest link on that node, read and write
|
||||
* enable, and CPU Disable, Lock, and Non-posted.
|
||||
*
|
||||
* @param level Printing level
|
||||
* @param which Register number
|
||||
* @param base Base register
|
||||
* @param lim Limit register
|
||||
*/
|
||||
static void showmmio(int level, u8 which, u32 base, u32 lim)
|
||||
{
|
||||
printk(level, "MMIO(%02x)%010llx-%010llx, ->(%d,%d), %s, %s, "
|
||||
"CPU disable %d, Lock %d, Non posted %d\n",
|
||||
which, ((u64) BITS(base, 0, 0xffffff00)) << 8,
|
||||
(((u64) BITS(lim, 0, 0xffffff00)) << 8) + 0xffff, r_node(lim),
|
||||
r_link(lim), re(base), we(base), BITS(base, 4, 0x1),
|
||||
BITS(base, 7, 0x1), BITS(lim, 7, 0x1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all DRAM routing registers. This function is callable at any time.
|
||||
*
|
||||
* @param level The debug level.
|
||||
* @param dev A 32-bit number in the standard bus/dev/fn format which is used
|
||||
* raw config space.
|
||||
*/
|
||||
static void showalldram(int level, struct device *dev)
|
||||
{
|
||||
u8 reg;
|
||||
for (reg = DRAM_ROUTE_START; reg <= DRAM_ROUTE_END; reg += 8) {
|
||||
u32 base = pci_read_config32(dev, reg);
|
||||
u32 lim = pci_read_config32(dev, reg + 4);
|
||||
if (base || lim!=(reg-DRAM_ROUTE_START)/8)
|
||||
showdram(level, reg, base, lim);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all MMIO routing registers. This function is callable at any time.
|
||||
*
|
||||
* @param level The debug level.
|
||||
* @param dev A 32-bit number in the standard bus/dev/fn format which is used
|
||||
* raw config space.
|
||||
*/
|
||||
static void showallmmio(int level, struct device *dev)
|
||||
{
|
||||
u8 reg;
|
||||
for (reg = MMIO_ROUTE_START; reg <= MMIO_ROUTE_END; reg += 8) {
|
||||
u32 base = pci_read_config32(dev, reg);
|
||||
u32 lim = pci_read_config32(dev, reg + 4);
|
||||
if (base || lim)
|
||||
showmmio(level, reg, base, lim);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all PCIIO routing registers. This function is callable at any time.
|
||||
*
|
||||
* @param level The debug level.
|
||||
* @param dev A 32-bit number in the standard bus/dev/fn format which is used
|
||||
* raw config space.
|
||||
*/
|
||||
static void showallpciio(int level, struct device *dev)
|
||||
{
|
||||
u8 reg;
|
||||
for (reg = PCIIO_ROUTE_START; reg <= PCIIO_ROUTE_END; reg += 8) {
|
||||
u32 base = pci_read_config32(dev, reg);
|
||||
u32 lim = pci_read_config32(dev, reg + 4);
|
||||
if (base || lim)
|
||||
showpciio(level, reg, base, lim);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all config routing registers. This function is callable at any time.
|
||||
*
|
||||
* @param level The debug level.
|
||||
* @param dev A 32-bit number in the standard bus/dev/fn format which is used
|
||||
* raw config space.
|
||||
*/
|
||||
static void showallconfig(int level, struct device *dev)
|
||||
{
|
||||
u8 reg;
|
||||
for (reg = CONF_ROUTE_START; reg <= CONF_ROUTE_END; reg += 4) {
|
||||
u32 val = pci_read_config32(dev, reg);
|
||||
if (val)
|
||||
showconfig(level, reg, val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all routing registers. This function is callable at any time.
|
||||
*
|
||||
* @param level The debug level.
|
||||
* @param dev A 32-bit number in the standard bus/dev/fn format which is used
|
||||
* raw config space.
|
||||
*/
|
||||
void showallroutes(int level, struct device *dev)
|
||||
{
|
||||
showalldram(level, dev);
|
||||
showallmmio(level, dev);
|
||||
showallpciio(level, dev);
|
||||
showallconfig(level, dev);
|
||||
}
|
||||
|
|
@ -1,273 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ASPSDEFS_H
|
||||
#define ASPSDEFS_H
|
||||
|
||||
/* P-state register offset */
|
||||
#define PS_REG0 0 /* offset for P0 */
|
||||
#define PS_REG1 1 /* offset for P1 */
|
||||
#define PS_REG2 2 /* offset for P2 */
|
||||
#define PS_REG3 3 /* offset for P3 */
|
||||
#define PS_REG4 4 /* offset for P4 */
|
||||
|
||||
#define PS_IDD_VALUE_SHFT 0 /* IddValue: current value
|
||||
field offset for msr.hi */
|
||||
#define PS_IDD_VALUE_MASK 0xFF /* IddValue: current value
|
||||
field mask for msr.hi */
|
||||
#define PS_PSDIS_MASK 0x7fffffff /* disable P-state register */
|
||||
#define PS_EN_MASK 0x80000000 /* P-state register enable mask */
|
||||
#define PS_NB_DID_MASK 0x400000 /* P-state Reg[NbDid] Mask */
|
||||
#define PS_NB_VID_M_OFF 0x01ffffff /* P-state Reg[NbVid] Mask OFF */
|
||||
#define PS_CPU_VID_M_ON 0x0fe00 /* P-state Reg[CpuVid] Mask On */
|
||||
#define PS_NB_VID_M_ON 0x0fe000000 /* P-state Reg[NbVid] Mask On */
|
||||
#define PS_CPU_VID_SHFT 9 /* P-state bit shift for CpuVid */
|
||||
#define PS_NB_VID_SHFT 25 /* P-state bit shift for NbVid */
|
||||
#define PS_BOTH_VID_OFF 0x01ff01ff /* Mask NbVid & CpuVid */
|
||||
#define PS_CPU_NB_VID_SHFT 16 /* P-state bit shift from CpuVid to NbVid */
|
||||
#define PS_DIS 0x7fffffff /* disable P-state reg */
|
||||
#define PS_EN 0x80000000 /* enable P-state reg */
|
||||
#define PS_CPU_FID_MASK 0x03f /* MSRC001_00[68:64][CpuFid]
|
||||
Core Frequency Id */
|
||||
#define PS_CURDIV_SHFT 8 /* P-state Current Divisor shift position */
|
||||
#define PS_CPUDID_SHIFT 6 /* P-state CPU DID shift position */
|
||||
|
||||
/* for unfused parts */
|
||||
#define PS_NB_VID_110V 0x48000000
|
||||
#define PS_NB_VID_1175V 0x3c000000
|
||||
/* NB VID 1.100V =0x12[PVI]=0x24[SVI] = 0100100b 7-bit code */
|
||||
|
||||
#define PS_NB_DID0 0 /* NB DID 0 */
|
||||
#define PS_NB_DID1 0x400000 /* NB DID 1 */
|
||||
#define PS_CPU_VID_110V 0x4800 /* CPU VID 1.100V */
|
||||
#define PS_CPU_VID_1175V 0x3c00 /* CPU VID 1.175V */
|
||||
#define PS_CPU_DID 0x40 /* CPU DID 1 = divisor of 2 */
|
||||
#define PS_CPU_DID0 0 /* CPU DID 0 = divisor of 1 */
|
||||
#define PS_CPU_FID_16G 0x00 /* CPU FID of 00 = 1.6GHz */
|
||||
#define PS_CPU_FID_16G1 0x10 /* CPU FId of 16 COF = 16+16/2 = 16 */
|
||||
#define PS_CPU_FID_18G 20 /* CPU FId of 20 COF = 20+16/2 = 18 */
|
||||
#define PS_CPU_FID_19G 22 /* CPU FId of 20 COF = 22+16/2 = 19 */
|
||||
#define PS_CPU_FID_20G 24 /* CPU FId of 20 COF = 24+16/2 = 20 */
|
||||
#define PS_CPU_FID_22G 28 /* CPU FId of 2C COF = 28+16/2 = 22 */
|
||||
#define PS_CPU_FID_30G 44 /* CPU FId of 2C COF = 44+16/2 = 30 */
|
||||
|
||||
|
||||
|
||||
#define PCI_DEV_BASE 24 /* System PCI device ID base */
|
||||
#define LOCAL_APIC_ID_SHIFT 24 /* Local APIC ID shift bit # */
|
||||
#define APIC_CID_SIZE_SHIFT 12 /* ApicCoreIdSize shift bit # */
|
||||
#define FN_0 0 /* Function 0 */
|
||||
#define FN_1 1 /* Function 1 */
|
||||
#define FN_2 2 /* Function 2 */
|
||||
#define FN_3 3 /* Function 3 */
|
||||
#define FN_4 4 /* Function 4 */
|
||||
#define FN_5 5 /* Function 5 */
|
||||
#define FN_80000000 0x80000000 /* Function 8000_0000 */
|
||||
#define FN_80000001 0x80000001 /* Function 8000_0001 */
|
||||
#define FN_80000008 0x80000008 /* Function 8000_0008 */
|
||||
|
||||
#define LNK_INIT_REG 0x6C /* F0x6C link initialization control register */
|
||||
#define WARM_RESET_BIT 0x10 /* bit 4 =1 : warm reset */
|
||||
|
||||
#define HTC_REG 0x64 /* hardware thermal control reg */
|
||||
#define HTC_PS_LMT_MASK 0x8fffffff /* HtcPstateLimit mask off */
|
||||
#define PS_LIMIT_POS 28 /* PstateLimit position for HTC & STC */
|
||||
|
||||
#define STC_REG 0x68 /* software thermal control reg */
|
||||
#define STC_PS_LMT_MASK 0x8fffffff /* StcPstateLimit mask off */
|
||||
|
||||
#define CPTC0 0x0d4 /* Clock Power/Timing Control0 Register*/
|
||||
#define CPTC0_MASK 0x000cffff /* Reset mask for this register */
|
||||
#define CPTC0_NBFID_MASK 0xffffffe0 /* NbFid mask off for this register */
|
||||
#define CPTC0_NBFID_MON 0x1f /* NbFid mask on for this register */
|
||||
#define NB_FID_EN 0x20 /* NbFidEn bit ON */
|
||||
#define NB_CLKDID_ALL 0x80000000 /* NbClkDidApplyAll bit ON */
|
||||
#define NB_CLKDID 0x40000000 /* NbClkDid value set by BIOS */
|
||||
#define NB_CLKDID_SHIFT 28 /* NbClkDid bit shift */
|
||||
#define PW_STP_UP50 0x08000000 /* PowerStepUp 50nS(1000b) */
|
||||
#define PW_STP_DN50 0x00800000 /* PowerStepDown 50nS (1000b)*/
|
||||
#define PW_STP_UP100 0x03000000 /* PowerStepUp 100nS(0011b) */
|
||||
#define PW_STP_DN100 0x00300000 /* PowerStepDown 100nS (0011b)*/
|
||||
#define PW_STP_UP200 0x02000000 /* PowerStepUp 200nS(0010b) */
|
||||
#define PW_STP_DN200 0x00200000 /* PowerStepDown 200nS (0010b)*/
|
||||
#define PW_STP_UP400 0x00000000 /* PowerStepUp 400nS(0000b) */
|
||||
#define PW_STP_DN400 0x00000000 /* PowerStepDown 400nS (0000b)*/
|
||||
#define CLK_RAMP_HYST_SEL_VAL 0x00000f00 /* value mask for clock ramp
|
||||
hysteresis select. BIOS
|
||||
should program
|
||||
F3xC4[ClkRampHystSel] to
|
||||
1111b */
|
||||
|
||||
|
||||
#define LNK_PLL_LOCK 0x00010000 /* LnkPllLock value set (01b) by BIOS */
|
||||
|
||||
|
||||
|
||||
#define PSTATE_CTL 0xC0010070 /* P-state Control Register */
|
||||
#define NB_VID_POS 25 /* NbVid bit shift for position */
|
||||
#define NB_VID_MASK_OFF 0x01ffffff /* NbVid bits mask off */
|
||||
#define NB_VID_MASK_ON 0xfe000000 /* NbVid bits mask on */
|
||||
#define CPU_VID_POS 0x9 /* CpuVid bit shift for position */
|
||||
#define CPU_VID_MASK_OFF 0xffff01ff /* CpuVid bits mask off */
|
||||
#define CPU_VID_MASK_ON 0x0000fe00 /* CpuVid bits mask on */
|
||||
#define CPU_FID_DID_M_ON 0x000001ff /* CpuFid & CpuDid mask on */
|
||||
#define CPU_FID_DID_M_OFF 0xfffffe00 /* CpuFid & CpuDid mask off */
|
||||
#define NB_DID_VID_M_ON 0xfe400000 /* NbDid & NbVid mask on */
|
||||
#define NB_DID_M_ON 0x00400000 /* NbDid mask on */
|
||||
#define NB_DID_M_OFF 0xffbfffff /* NbDid mask off */
|
||||
#define NB_DID_POS 22 /* NbDid bit shift for position */
|
||||
#define PS_M_OFF 0xfff8ffff /* Cur Pstate mask off */
|
||||
#define PS_1 0x00010000 /* P-state 1 */
|
||||
#define PS_2 0x00020000 /* P-state 2 */
|
||||
#define PS_CPU_DID_1 0x40 /* Cpu Did 1 */
|
||||
|
||||
#define NB_VID1_MASK 0x00003f80 /* F3x1F4[NbVid1]*/
|
||||
#define NB_VID1_SHIFT 7 /* F3x1F4[NbVid1] */
|
||||
|
||||
|
||||
|
||||
#define PSTATE_STS 0xC0010071 /* P-state Status Register */
|
||||
#define STARTUP_PS_MASK 0x7 /* StartupPstate Mask */
|
||||
|
||||
/* define for NB VID & CPU VID transition functions */
|
||||
#define IS_NB 1
|
||||
#define IS_CPU 0
|
||||
|
||||
/* F3xD8 Clock Power/Timing Control 1 Register */
|
||||
#define CPTC1 0xd8 /* Clock Power/Timing Control1 Register*/
|
||||
#define VSRAMP_SLAM_MASK 0xffffff88 /* MaskOff [VSRampTime]&[VSSlamTime] */
|
||||
#define VSRAMP_SLAM_VALUE 0x16 /* [VSRampTime]=001b&[VSSlamTime]=110b */
|
||||
#define VSRAMP_MASK 0xffffff8f /* MaskOff [VSRampTime] */
|
||||
#define VSRAMP_VALUE 0x10 /* [VSRampTime]=001b */
|
||||
#define VS_RAMP_T 4 /* VSRampTime bit position */
|
||||
#define VSSLAM_MASK 0xfffffff8 /* MaskOff [VSSlamTime] */
|
||||
#define PWR_PLN_SHIFT 28 /* PwrPlanes bit shift */
|
||||
#define PWR_PLN_ON 0x10000000 /* PwrPlanes bit ON */
|
||||
#define PWR_PLN_OFF 0x0efffffff /* PwrPlanes bit OFF */
|
||||
|
||||
|
||||
|
||||
/* Northbridge Capability Register */
|
||||
#define NB_CAP 0xe8 /* Northbridge Cap Reg */
|
||||
#define CMP_CAP_SHFT 12 /* CMP CAP - number of enabled cores */
|
||||
|
||||
/* F3xDC Clock Power/Timing Control 2 Register */
|
||||
#define CPTC2 0xdc /* Clock Power/Timing Control2 Register*/
|
||||
#define PS_MAX_VAL_POS 8 /* PstateMaxValue bit shift */
|
||||
#define PS_MAX_VAL_MASK 0xfffff8ff /* PstateMaxValue Mask off */
|
||||
#define NB_SYN_PTR_ADJ_POS 12 /* NbsynPtrAdj bit shift */
|
||||
#define NB_SYN_PTR_ADJ_MASK (0x7 << NB_SYN_PTR_ADJ_POS) /* NbsynPtrAdj bit mask */
|
||||
|
||||
#define PRCT_INFO 0x1fc /* Product Info Register */
|
||||
#define DUAL_PLANE_ONLY_MASK 0x80000000 /* F3x1FC[DualPlaneOnly] */
|
||||
#define UNI_NB_FID_BIT 2 /* UniNbFid bit position */
|
||||
#define UNI_NB_VID_BIT 7 /* UniNbVid bit position */
|
||||
#define SPLT_NB_FID_OFFSET 14 /* SpltNbFidOffset value bit position */
|
||||
#define SPLT_NB_VID_OFFSET 17 /* SpltNbVidOffset value bit position */
|
||||
#define NB_CV_UPDATE 0x01 /* F3x1FC[NbCofVidUpdated] bit mask */
|
||||
#define NB_VID_UPDATE_ALL 0x02 /* F3x1FC[NbVidUpdatedAll] bit mask */
|
||||
#define C_FID_DID_M_OFF 0xfffffe00 /* mask off Core FID & DID */
|
||||
|
||||
#define CPB_MASK 0x00000020 /* core performance
|
||||
boost. CPUID Fn8000 0007 edx */
|
||||
#define NC_MASK 0x000000FF /* number of cores - 1. CPUID
|
||||
Fn8000 0008 ecx */
|
||||
#define PW_CTL_MISC 0x0a0 /* Power Control Miscellaneous Register */
|
||||
#define COF_VID_PROG_BIT 0x80000000 /* CofVidProg bit. 0= unfused part */
|
||||
#define DUAL_VDD_BIT 0x40000000 /* DualVdd bit. */
|
||||
#define NB_COFVID_UPDATE_BIT 0x01 /* NbCOFVIDUpdated bit */
|
||||
#define PVI_MODE 0x100 /* PviMode bit mask */
|
||||
#define VID_SLAM_OFF 0x0dfffffff /* set VidSlamMode OFF */
|
||||
#define VID_SLAM_ON 0x020000000 /* set VidSlamMode ON */
|
||||
#define NB_PSTATE_FORCE_ON 0x010000000 /* set Northbridge P-state
|
||||
force on next LDTSTOP
|
||||
assertion on, in F3xA0 */
|
||||
#define BP_INS_TRI_EN_ON 0x00004000 /* breakpoint pins tristate
|
||||
enable in F3xA0 */
|
||||
#define PLLLOCK_OFF 0x0ffffc7ff /* PllLockTime Mask OFF */
|
||||
#define PLLLOCK_DFT 0x00001800 /* PllLockTime default value = 011b */
|
||||
#define PLLLOCK_DFT_L 0x00002800 /* PllLockTime long value = 101b */
|
||||
|
||||
#define SVI_HIGH_FREQ_ON 0x00000200 /* F3xA0[SviHighFreqSel] for
|
||||
3.4 MHz SVI in rev. C3 */
|
||||
|
||||
/* P-state Specification register base in PCI space */
|
||||
#define PS_SPEC_REG 0x1e0 /* PS Spec register base address */
|
||||
#define PCI_REG_LEN 4 /* PCI register length */
|
||||
#define NB_DID_MASK 0x10000 /* NbDid bit mask */
|
||||
#define NB_DID_2 2 /* NbDid = 2 */
|
||||
#define NB_DID_1 1 /* NbDid = 1 */
|
||||
#define SPEC_PWRDIV_M_ON 0x06000000 /* PwrDiv mask on */
|
||||
#define SPEC_PWRVAL_M_ON 0x01e00000 /* PwrValue mask on */
|
||||
#define SPEC_PWRDIV_SHFT 25 /* PwrDiv shift */
|
||||
#define SPEC_PWRVAL_SHFT 17 /* PwrValue shift */
|
||||
|
||||
/* F4x1F4 Northbridge P-state spec register */
|
||||
#define NB_PS_SPEC_REG 0x1f4 /* Nb PS spec reg */
|
||||
|
||||
/* F3x1F0 Product Information Register */
|
||||
#define NB_PSTATE_MASK 0x00070000 /* NbPstate for CPU rev C3 */
|
||||
|
||||
/* F3x1FC Product Information Register */
|
||||
#define NB_COF_VID_UPDATE_MASK 1 /* for CPU rev <= C */
|
||||
#define SINGLE_PLANE_NB_FID_MASK 0x007c/* for CPU rev <= C */
|
||||
#define SINGLE_PLANE_NB_FID_SHIFT 2/* for CPU rev <= C */
|
||||
#define SINGLE_PLANE_NB_VID_MASK 0x3f80/* for CPU rev <= C */
|
||||
#define SINGLE_PLANE_NB_VID_SHIFT 7/* for CPU rev <= C */
|
||||
|
||||
#define DUAL_PLANE_NB_FID_OFF_MASK 0x001c000/* for CPU rev <= C */
|
||||
#define DUAL_PLANE_NB_FID_SHIFT 14/* for CPU rev <= C */
|
||||
#define DUAL_PLANE_NB_VID_OFF_MASK 0x3e0000/* for CPU rev <= C */
|
||||
#define DUAL_PLANE_NB_VID_SHIFT 17/* for CPU rev <= C */
|
||||
|
||||
#define NM_PS_REG (is_fam15h()?8:5) /* number of P-state MSR registers */
|
||||
|
||||
/* sFidVidInit.outFlags defines */
|
||||
#define PWR_CK_OK 0 /* System board check OK */
|
||||
#define PWR_CK_NO_PS 1 /* All P-state registers are over
|
||||
the limit */
|
||||
|
||||
/* bit mask */
|
||||
#define BIT_MASK_1 0x1
|
||||
#define BIT_MASK_2 0x3
|
||||
#define BIT_MASK_3 0x7
|
||||
#define BIT_MASK_4 0x0f
|
||||
#define BIT_MASK_5 0x1f
|
||||
#define BIT_MASK_6 0x3f
|
||||
#define BIT_MASK_7 0x7f
|
||||
#define BIT_MASK_8 0x0ff
|
||||
|
||||
/* VID Code */
|
||||
#define VID_1_100V 0x12 /* 1.100V */
|
||||
#define VID_1_175V 0x1E /* 1.175V */
|
||||
|
||||
/* Nb Fid Code */
|
||||
#define NB_FID_800M 0x00 /* 800MHz */
|
||||
|
||||
/* Nb DID Code */
|
||||
#define NB_DID_0 0
|
||||
#define NB_DID_1 1
|
||||
|
||||
/* GH Logical ID */
|
||||
#define GH_REV_A2 0x4 /* GH Rev A2 logical ID, Upper half */
|
||||
|
||||
#define TSC_FREQ_SEL_SHIFT 24
|
||||
#define TSC_FREQ_SEL_MASK (1 << TSC_FREQ_SEL_SHIFT)
|
||||
|
||||
#define WAIT_PSTATE_TIMEOUT 80000000 /* 0.1 s , unit : 1.25 ns */
|
||||
|
||||
#endif
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "comlib.h"
|
||||
#include "AsPsDefs.h"
|
||||
#include "AsPsNb.h"
|
||||
|
||||
u8 getNumOfNodeNb(void);
|
||||
u8 translateNodeIdToDeviceIdNb(u8 nodeId);
|
||||
|
||||
/**
|
||||
* Return the minimum possible NbCOF (in 100MHz) for the system.
|
||||
*
|
||||
* This function can be run on any core and is used by the HT & Memory init
|
||||
* code in Phase 1.
|
||||
*
|
||||
* @return minNbCOF (in multiple of half of CLKIN, 100MHz).
|
||||
*/
|
||||
u8 getMinNbCOF(void)
|
||||
{
|
||||
u8 numOfNode, i, j, deviceId, nbDid, nbFid, nextNbFid;
|
||||
u32 dtemp;
|
||||
|
||||
nbDid = 0;
|
||||
nbFid = 0;
|
||||
|
||||
/* get number of node in the system */
|
||||
numOfNode = getNumOfNodeNb();
|
||||
|
||||
/* go through each node for the minimum NbCOF (in multiple of CLKIN/2) */
|
||||
for (i = 0; i < numOfNode; i++)
|
||||
{
|
||||
/* stub function for APIC ID virtualization for large MP system later */
|
||||
deviceId = translateNodeIdToDeviceIdNb(i);
|
||||
|
||||
/* read all P-state spec registers for NbDid = 1 */
|
||||
for (j = 0; j < 5; j++)
|
||||
{
|
||||
AmdPCIRead(MAKE_SBDFO(0,0,deviceId,FN_4,PS_SPEC_REG+(j*PCI_REG_LEN)), &dtemp); /*F4x1E0 + j*4 */
|
||||
/* get NbDid */
|
||||
if (dtemp & NB_DID_MASK)
|
||||
nbDid = 1;
|
||||
}
|
||||
/* if F3x1FC[NbCofVidUpdate]=0, NbFid = default value */
|
||||
AmdPCIRead(MAKE_SBDFO(0,0,deviceId,FN_3,PRCT_INFO), &dtemp); /*F3x1FC*/
|
||||
if (!(dtemp & NB_CV_UPDATE)) /* F3x1FC[NbCofVidUpdated]=0, use default VID */
|
||||
{
|
||||
AmdPCIRead(MAKE_SBDFO(0,0,deviceId,FN_3,CPTC0), &dtemp); /*F3xD4*/
|
||||
nextNbFid = (u8) (dtemp & BIT_MASK_5);
|
||||
if (nbDid)
|
||||
nextNbFid = (u8) (nextNbFid >> 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* check PVI/SPI */
|
||||
AmdPCIRead(MAKE_SBDFO(0,0,deviceId,FN_3,PW_CTL_MISC), &dtemp); /*F3xA0*/
|
||||
if (dtemp & PVI_MODE) /* PVI */
|
||||
{
|
||||
AmdPCIRead(MAKE_SBDFO(0,0,deviceId,FN_3,PRCT_INFO), &dtemp); /*F3x1FC*/
|
||||
nextNbFid = (u8) (dtemp >> UNI_NB_FID_BIT);
|
||||
nextNbFid &= BIT_MASK_5;
|
||||
/* if (nbDid)
|
||||
nextNbFid = nextNbFid >> 1; */
|
||||
}
|
||||
else /* SVI */
|
||||
{
|
||||
AmdPCIRead(MAKE_SBDFO(0,0,deviceId,FN_3,PRCT_INFO), &dtemp); /*F3x1FC*/
|
||||
nextNbFid = (u8) ((dtemp >> UNI_NB_FID_BIT) & BIT_MASK_5);
|
||||
nextNbFid = (u8) (nextNbFid + ((dtemp >> SPLT_NB_FID_OFFSET) & BIT_MASK_3));
|
||||
/* if (nbDid)
|
||||
nextNbFid = nextNbFid >> 1; */
|
||||
}
|
||||
}
|
||||
if (i == 0)
|
||||
nbFid = nextNbFid;
|
||||
else if (nbFid > nextNbFid)
|
||||
nbFid = nextNbFid;
|
||||
}
|
||||
|
||||
/* add the base and convert to 100MHz divide by 2 if DID = 1 */
|
||||
if (nbDid)
|
||||
nbFid = (u8) (nbFid + 4);
|
||||
else
|
||||
nbFid = (u8) ((nbFid + 4) << 1);
|
||||
return nbFid;
|
||||
}
|
||||
|
||||
u8 getNumOfNodeNb(void)
|
||||
{
|
||||
u32 dtemp;
|
||||
|
||||
AmdPCIRead(MAKE_SBDFO(0,0,24,0,0x60), &dtemp);
|
||||
dtemp = (dtemp >> 4) & BIT_MASK_3;
|
||||
dtemp++;
|
||||
return (u8)dtemp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PCI device ID for PCI access using node ID.
|
||||
*
|
||||
* This function may need to change node ID to device ID in big MP systems.
|
||||
*
|
||||
* @param nodeId Node ID of the node.
|
||||
* @return PCI device ID of the node.
|
||||
*/
|
||||
u8 translateNodeIdToDeviceIdNb(u8 nodeId)
|
||||
{
|
||||
return (u8) (nodeId+PCI_DEV_BASE);
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ASPSNB_H
|
||||
#define ASPSNB_H
|
||||
|
||||
u8 getMinNbCOF(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
ifeq ($(CONFIG_NORTHBRIDGE_AMD_AMDFAM10),y)
|
||||
|
||||
romstage-y += h3finit.c ht_wrapper.c comlib.c AsPsNb.c h3ncmn.c
|
||||
|
||||
endif
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "comlib.h"
|
||||
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <cpu/amd/msr.h>
|
||||
#include <device/pci_def.h>
|
||||
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
* EXPORTED FUNCTIONS
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void CALLCONV AmdPCIReadBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue)
|
||||
{
|
||||
ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0);
|
||||
|
||||
AmdPCIRead(loc, pValue);
|
||||
*pValue = *pValue >> lowbit; /* Shift */
|
||||
|
||||
/* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */
|
||||
if ((highbit-lowbit) != 31)
|
||||
*pValue &= (((u32)1 << (highbit-lowbit+1))-1);
|
||||
}
|
||||
|
||||
|
||||
void CALLCONV AmdPCIWriteBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue)
|
||||
{
|
||||
u32 temp, mask;
|
||||
|
||||
ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0);
|
||||
|
||||
/* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */
|
||||
if ((highbit-lowbit) != 31)
|
||||
mask = (((u32)1 << (highbit-lowbit+1))-1);
|
||||
else
|
||||
mask = (u32)0xFFFFFFFF;
|
||||
|
||||
AmdPCIRead(loc, &temp);
|
||||
temp &= ~(mask << lowbit);
|
||||
temp |= (*pValue & mask) << lowbit;
|
||||
AmdPCIWrite(loc, &temp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Given a SBDFO this routine will find the next PCI capabilities list entry.
|
||||
* If the end of the list of reached, or if a problem is detected, then
|
||||
* ILLEGAL_SBDFO is returned.
|
||||
*
|
||||
* To start a new search from the beginning of head of the list, specify a
|
||||
* SBDFO with a offset of zero.
|
||||
*/
|
||||
void CALLCONV AmdPCIFindNextCap(SBDFO *pCurrent)
|
||||
{
|
||||
SBDFO base;
|
||||
u32 offset;
|
||||
u32 temp;
|
||||
|
||||
if (*pCurrent == ILLEGAL_SBDFO)
|
||||
return;
|
||||
|
||||
offset = SBDFO_OFF(*pCurrent);
|
||||
base = *pCurrent - offset;
|
||||
*pCurrent = ILLEGAL_SBDFO;
|
||||
|
||||
/* Verify that the SBDFO points to a valid PCI device SANITY CHECK */
|
||||
AmdPCIRead(base, &temp);
|
||||
if (temp == 0xFFFFFFFF)
|
||||
return; /* There is no device at this address */
|
||||
|
||||
/* Verify that the device supports a capability list */
|
||||
AmdPCIReadBits(base + 0x04, 20, 20, &temp);
|
||||
if (temp == 0)
|
||||
return; /* This PCI device does not support capability lists */
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
/* If we are continuing on an existing list */
|
||||
AmdPCIReadBits(base + offset, 15, 8, &temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We are starting on a new list */
|
||||
AmdPCIReadBits(base + 0x34, 7, 0, &temp);
|
||||
}
|
||||
|
||||
if (temp == 0)
|
||||
return; /* We have reached the end of the capabilties list */
|
||||
|
||||
/* Error detection and recovery- The statement below protects against
|
||||
PCI devices with broken PCI capabilities lists. Detect a pointer
|
||||
that is not u32 aligned, points into the first 64 reserved DWORDs
|
||||
or points back to itself.
|
||||
*/
|
||||
if (((temp & 3) != 0) || (temp == offset) || (temp < 0x40))
|
||||
return;
|
||||
|
||||
*pCurrent = base + temp;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void CALLCONV Amdmemcpy(void *pDst, const void *pSrc, u32 length)
|
||||
{
|
||||
ASSERT(length <= 32768);
|
||||
ASSERT(pDst != NULL);
|
||||
ASSERT(pSrc != NULL);
|
||||
|
||||
while (length--) {
|
||||
// *(((u8*)pDst)++) = *(((u8*)pSrc)++);
|
||||
*((u8*)pDst) = *((u8*)pSrc);
|
||||
pDst++;
|
||||
pSrc++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CALLCONV Amdmemset(void *pBuf, u8 val, u32 length)
|
||||
{
|
||||
ASSERT(length <= 32768);
|
||||
ASSERT(pBuf != NULL);
|
||||
|
||||
while (length--) {
|
||||
//*(((u8*)pBuf)++) = val;
|
||||
*(((u8*)pBuf)) = val;
|
||||
pBuf++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
u8 CALLCONV AmdBitScanReverse(u32 value)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 31; i != 0xFF; i--)
|
||||
{
|
||||
if (value & ((u32)1 << i))
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
u32 CALLCONV AmdRotateRight(u32 value, u8 size, u32 count)
|
||||
{
|
||||
u32 msb, mask;
|
||||
ASSERT(size > 0 && size <= 32);
|
||||
|
||||
msb = (u32)1 << (size-1);
|
||||
mask = ((msb-1) << 1) + 1;
|
||||
|
||||
value = value & mask;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
if (value & 1)
|
||||
value = (value >> 1) | msb;
|
||||
else
|
||||
value = value >> 1;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
u32 CALLCONV AmdRotateLeft(u32 value, u8 size, u32 count)
|
||||
{
|
||||
u32 msb, mask;
|
||||
ASSERT(size > 0 && size <= 32);
|
||||
|
||||
msb = (u32)1 << (size-1);
|
||||
mask = ((msb-1) << 1) + 1;
|
||||
|
||||
value = value & mask;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
if (value & msb)
|
||||
value = ((value << 1) & mask) | (u32)1;
|
||||
else
|
||||
value = ((value << 1) & mask);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void CALLCONV AmdPCIRead(SBDFO loc, u32 *Value)
|
||||
{
|
||||
/* Use coreboot PCI functions */
|
||||
*Value = pci_read_config32((loc & 0xFFFFF000), SBDFO_OFF(loc));
|
||||
}
|
||||
|
||||
|
||||
void CALLCONV AmdPCIWrite(SBDFO loc, u32 *Value)
|
||||
{
|
||||
/* Use coreboot PCI functions */
|
||||
pci_write_config32((loc & 0xFFFFF000), SBDFO_OFF(loc), *Value);
|
||||
}
|
||||
|
||||
|
||||
void CALLCONV AmdMSRRead(uint32 Address, uint64 *Value)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
msr = rdmsr(Address);
|
||||
Value->lo = msr.lo;
|
||||
Value->hi = msr.hi;
|
||||
}
|
||||
|
||||
|
||||
void CALLCONV AmdMSRWrite(uint32 Address, uint64 *Value)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
msr.lo = Value->lo;
|
||||
msr.hi = Value->hi;
|
||||
wrmsr(Address, msr);
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef COMLIB_H
|
||||
#define COMLIB_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "porting.h"
|
||||
|
||||
#ifdef AMD_DEBUG_ERROR_STOP
|
||||
/* Macro to aid debugging, causes program to halt and display the line number of the halt */
|
||||
#define STOP_HERE ASSERT(0)
|
||||
#else
|
||||
#define STOP_HERE
|
||||
#endif
|
||||
|
||||
void CALLCONV AmdPCIReadBits(SBDFO loc, uint8 highbit, uint8 lowbit, uint32 *value);
|
||||
void CALLCONV AmdPCIWriteBits(SBDFO loc, uint8 highbit, uint8 lowbit, uint32 *value);
|
||||
void CALLCONV AmdPCIFindNextCap(SBDFO *current);
|
||||
|
||||
void CALLCONV Amdmemcpy(void *dst, const void *src, uint32 length);
|
||||
void CALLCONV Amdmemset(void *buf, uint8 val, uint32 length);
|
||||
|
||||
uint8 CALLCONV AmdBitScanReverse(uint32 value);
|
||||
uint32 CALLCONV AmdRotateRight(uint32 value, uint8 size, uint32 count);
|
||||
uint32 CALLCONV AmdRotateLeft(uint32 value, uint8 size, uint32 count);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,180 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef H3FFEAT_H
|
||||
#define H3FFEAT_H
|
||||
|
||||
#include "h3finit.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* DEFINITIONS AND MACROS
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define MAX_NODES 8
|
||||
#define MAX_LINKS 8
|
||||
#define MAX_PLATFORM_LINKS 64 /* 8x8 fully connected (28) + 4 chains with two HT devices */
|
||||
|
||||
/* These following are internal definitions */
|
||||
#define ROUTETOSELF 0x0F
|
||||
#define INVALID_LINK 0xCC /* Used in port list data structure to mark unused data entries.
|
||||
Can also be used for no link found in a port list search */
|
||||
|
||||
/* definitions for working with the port list structure */
|
||||
#define PORTLIST_TYPE_CPU 0
|
||||
#define PORTLIST_TYPE_IO 1
|
||||
|
||||
/*
|
||||
* Hypertransport Capability definitions and macros
|
||||
*
|
||||
*/
|
||||
|
||||
/* HT Host Capability */
|
||||
/* bool isHTHostCapability(u32 reg) */
|
||||
#define IS_HT_HOST_CAPABILITY(reg) \
|
||||
((reg & (u32)0xE00000FF) == (u32)0x20000008)
|
||||
|
||||
#define HT_HOST_CAP_SIZE 0x20
|
||||
|
||||
/* Host CapabilityRegisters */
|
||||
#define HTHOST_LINK_CAPABILITY_REG 0x00
|
||||
#define HTHOST_LINK_CONTROL_REG 0x04
|
||||
#define HTHOST_FREQ_REV_REG 0x08
|
||||
#define HTHOST_FREQ_REV_REG_2 0x1c
|
||||
#define HT_HOST_REV_REV3 0x60
|
||||
#define HTHOST_FEATURE_CAP_REG 0x0C
|
||||
#define HTHOST_BUFFER_COUNT_REG 0x10
|
||||
#define HTHOST_ISOC_REG 0x14
|
||||
#define HTHOST_LINK_TYPE_REG 0x18
|
||||
#define HTHOST_TYPE_COHERENT 3
|
||||
#define HTHOST_TYPE_NONCOHERENT 7
|
||||
#define HTHOST_TYPE_MASK 0x1F
|
||||
|
||||
/* HT Slave Capability (HT1 compat) */
|
||||
#define IS_HT_SLAVE_CAPABILITY(reg) \
|
||||
((reg & (u32)0xE00000FF) == (u32)0x00000008)
|
||||
#define HTSLAVE_LINK01_OFFSET 4
|
||||
#define HTSLAVE_LINK_CONTROL_0_REG 4
|
||||
#define HTSLAVE_FREQ_REV_0_REG 0xC
|
||||
#define HTSLAVE_FEATURE_CAP_REG 0x10
|
||||
|
||||
/* HT3 gen Capability */
|
||||
#define IS_HT_GEN3_CAPABILITY(reg) \
|
||||
((reg & (u32)0xF80000FF) == (u32)0xD0000008)
|
||||
#define HTGEN3_LINK01_OFFSET 0x10
|
||||
#define HTGEN3_LINK_TRAINING_0_REG 0x10
|
||||
|
||||
/* HT3 Retry Capability */
|
||||
#define IS_HT_RETRY_CAPABILITY(reg) \
|
||||
((reg & (u32)0xF80000FF) == (u32)0xC0000008)
|
||||
|
||||
#define HTRETRY_CONTROL_REG 4
|
||||
|
||||
/* Unit ID Clumping Capability */
|
||||
#define IS_HT_UNITID_CAPABILITY(reg) \
|
||||
((reg & (u32)0xF80000FF) == (u32)0x90000008)
|
||||
|
||||
#define HTUNIT_SUPPORT_REG 4
|
||||
#define HTUNIT_ENABLE_REG 8
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* TYPEDEFS, STRUCTURES, ENUMS
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef struct cNorthBridge cNorthBridge;
|
||||
|
||||
/* A pair consists of a source node, a link to the destination node, the
|
||||
* destination node, and its link back to source node. The even indices are
|
||||
* the source nodes and links, and the odd indices are for the destination
|
||||
* nodes and links.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/* This section is where the link is in the system and how to find it */
|
||||
u8 Type; /* 0 = CPU, 1 = Device, all others reserved */
|
||||
u8 Link; /* 0-1 for devices, 0-7 for CPUs */
|
||||
u8 NodeID; /* The node, or a pointer to the devices parent node */
|
||||
u8 HostLink, HostDepth; /* Link of parent node + depth in chain. Only used by devices */
|
||||
SBDFO Pointer; /* A pointer to the device's slave HT capability, so we don't have to keep searching */
|
||||
|
||||
/* This section is for the final settings, which are written to hardware */
|
||||
BOOL SelRegang; /* Only used for CPU->CPU links */
|
||||
u8 SelWidthIn;
|
||||
u8 SelWidthOut;
|
||||
u8 SelFrequency;
|
||||
uint8_t enable_isochronous_mode;
|
||||
|
||||
/* This section is for keeping track of capabilities and possible configurations */
|
||||
BOOL RegangCap;
|
||||
uint32_t PrvFrequencyCap;
|
||||
uint32_t PrvFeatureCap;
|
||||
u8 PrvWidthInCap;
|
||||
u8 PrvWidthOutCap;
|
||||
uint32_t CompositeFrequencyCap;
|
||||
|
||||
} sPortDescriptor;
|
||||
|
||||
|
||||
/*
|
||||
* Our global state data structure
|
||||
*/
|
||||
typedef struct {
|
||||
AMD_HTBLOCK *HtBlock;
|
||||
|
||||
u8 NodesDiscovered; /* One less than the number of nodes found in the system */
|
||||
u8 TotalLinks;
|
||||
u8 sysMpCap; /* The maximum number of nodes that all processors are capable of */
|
||||
|
||||
/* Two ports for each link
|
||||
* Note: The Port pair 2*N and 2*N+1 are connected together to form a link
|
||||
* (e.g. 0,1 and 8,9 are ports on either end of an HT link) The lower number
|
||||
* port (2*N) is the source port. The device that owns the source port is
|
||||
* always the device closer to the BSP. (i.e. nearer the CPU in a
|
||||
* non-coherent chain, or the CPU with the lower NodeID).
|
||||
*/
|
||||
sPortDescriptor PortList[MAX_PLATFORM_LINKS*2];
|
||||
|
||||
/* The number of coherent links coming off of each node (i.e. the 'Degree' of the node) */
|
||||
u8 sysDegree[MAX_NODES];
|
||||
/* The systems adjency (sysMatrix[i][j] is true if Node_i has a link to Node_j) */
|
||||
BOOL sysMatrix[MAX_NODES][MAX_NODES];
|
||||
|
||||
/* Same as above, but for the currently selected database entry */
|
||||
u8 dbDegree[MAX_NODES];
|
||||
BOOL dbMatrix[MAX_NODES][MAX_NODES];
|
||||
|
||||
u8 Perm[MAX_NODES]; /* The node mapping from the database to the system */
|
||||
u8 ReversePerm[MAX_NODES]; /* The node mapping from the system to the database */
|
||||
|
||||
/* Data for non-coherent initialization */
|
||||
u8 AutoBusCurrent;
|
||||
u8 UsedCfgMapEntires;
|
||||
|
||||
/* 'This' pointer for northbridge */
|
||||
cNorthBridge *nb;
|
||||
} sMainData;
|
||||
|
||||
#endif /* H3FFEAT_H */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,620 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef H3FINIT_H
|
||||
#define H3FINIT_H
|
||||
|
||||
#include "comlib.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* DEFINITIONS AND MACROS
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Width equates for call backs */
|
||||
#define HT_WIDTH_8_BITS 8
|
||||
#define HT_WIDTH_16_BITS 16
|
||||
#define HT_WIDTH_4_BITS 4
|
||||
#define HT_WIDTH_2_BITS 2
|
||||
|
||||
/* Frequency equates for call backs which take an actual frequency setting */
|
||||
#define HT_FREQUENCY_200M 0
|
||||
#define HT_FREQUENCY_400M 2
|
||||
#define HT_FREQUENCY_600M 4
|
||||
#define HT_FREQUENCY_800M 5
|
||||
#define HT_FREQUENCY_1000M 6
|
||||
#define HT_FREQUENCY_1200M 7
|
||||
#define HT_FREQUENCY_1400M 8
|
||||
#define HT_FREQUENCY_1600M 9
|
||||
#define HT_FREQUENCY_1800M 10
|
||||
#define HT_FREQUENCY_2000M 11
|
||||
#define HT_FREQUENCY_2200M 12
|
||||
#define HT_FREQUENCY_2400M 13
|
||||
#define HT_FREQUENCY_2600M 14
|
||||
#define HT_FREQUENCY_2800M 17
|
||||
#define HT_FREQUENCY_3000M 18
|
||||
#define HT_FREQUENCY_3200M 19
|
||||
|
||||
/* Frequency Limit equates for call backs which take a frequency supported mask. */
|
||||
#define HT_FREQUENCY_LIMIT_200M 1
|
||||
#define HT_FREQUENCY_LIMIT_400M 7
|
||||
#define HT_FREQUENCY_LIMIT_600M 0x1F
|
||||
#define HT_FREQUENCY_LIMIT_800M 0x3F
|
||||
#define HT_FREQUENCY_LIMIT_1000M 0x7F
|
||||
#define HT_FREQUENCY_LIMIT_HT1_ONLY 0x7F
|
||||
#define HT_FREQUENCY_LIMIT_1200M 0xFF
|
||||
#define HT_FREQUENCY_LIMIT_1400M 0x1FF
|
||||
#define HT_FREQUENCY_LIMIT_1600M 0x3FF
|
||||
#define HT_FREQUENCY_LIMIT_1800M 0x7FF
|
||||
#define HT_FREQUENCY_LIMIT_2000M 0xFFF
|
||||
#define HT_FREQUENCY_LIMIT_2200M 0x1FFF
|
||||
#define HT_FREQUENCY_LIMIT_2400M 0x3FFF
|
||||
#define HT_FREQUENCY_LIMIT_2600M 0x7FFF
|
||||
#define HT_FREQUENCY_LIMIT_2800M 0x3FFFF
|
||||
#define HT_FREQUENCY_LIMIT_3000M 0x7FFFF
|
||||
#define HT_FREQUENCY_LIMIT_3200M 0xFFFFF
|
||||
|
||||
/*
|
||||
* Event Notify definitions
|
||||
*/
|
||||
|
||||
/* Event Class definitions */
|
||||
#define HT_EVENT_CLASS_CRITICAL 1
|
||||
#define HT_EVENT_CLASS_ERROR 2
|
||||
#define HT_EVENT_CLASS_HW_FAULT 3
|
||||
#define HT_EVENT_CLASS_WARNING 4
|
||||
#define HT_EVENT_CLASS_INFO 5
|
||||
|
||||
/* Event definitions. */
|
||||
|
||||
/* Coherent subfunction events */
|
||||
#define HT_EVENT_COH_EVENTS 0x1000
|
||||
#define HT_EVENT_COH_NO_TOPOLOGY 0x1001
|
||||
#define HT_EVENT_COH_LINK_EXCEED 0x1002
|
||||
#define HT_EVENT_COH_FAMILY_FEUD 0x1003
|
||||
#define HT_EVENT_COH_NODE_DISCOVERED 0x1004
|
||||
#define HT_EVENT_COH_MPCAP_MISMATCH 0x1005
|
||||
|
||||
/* Non-coherent subfunction events */
|
||||
#define HT_EVENT_NCOH_EVENTS 0x2000
|
||||
#define HT_EVENT_NCOH_BUID_EXCEED 0x2001
|
||||
#define HT_EVENT_NCOH_LINK_EXCEED 0x2002
|
||||
#define HT_EVENT_NCOH_BUS_MAX_EXCEED 0x2003
|
||||
#define HT_EVENT_NCOH_CFG_MAP_EXCEED 0x2004
|
||||
#define HT_EVENT_NCOH_DEVICE_FAILED 0x2005
|
||||
#define HT_EVENT_NCOH_AUTO_DEPTH 0x2006
|
||||
|
||||
/* Optimization subfunction events */
|
||||
#define HT_EVENT_OPT_EVENTS 0x3000
|
||||
#define HT_EVENT_OPT_REQUIRED_CAP_RETRY 0x3001
|
||||
#define HT_EVENT_OPT_REQUIRED_CAP_GEN3 0x3002
|
||||
|
||||
/* HW Fault events */
|
||||
#define HT_EVENT_HW_EVENTS 0x4000
|
||||
#define HT_EVENT_HW_SYNCHFLOOD 0x4001
|
||||
#define HT_EVENT_HW_HTCRC 0x4002
|
||||
|
||||
/* The bbHT component (hb*) uses 0x5000 for events.
|
||||
* For consistency, we avoid that range here.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* TYPEDEFS, STRUCTURES, ENUMS
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
u8 **topolist;
|
||||
u8 AutoBusStart;
|
||||
/* Note: This should always be the form AutoBusCurrent+N*AutoBusIncrement, also bus 253-255 are reserved */
|
||||
u8 AutoBusMax;
|
||||
u8 AutoBusIncrement;
|
||||
|
||||
/**----------------------------------------------------------------------------------------
|
||||
*
|
||||
* BOOL
|
||||
* AMD_CB_IgnoreLink(u8 Node, u8 Link)
|
||||
*
|
||||
* Description:
|
||||
* This routine is called every time a coherent link is found and then every
|
||||
* time a non-coherent link from a CPU is found.
|
||||
* Any coherent or non-coherent link from a CPU can be ignored and not used
|
||||
* for discovery or initialization. Useful for connection based systems.
|
||||
* (Note: not called for IO device to IO Device links.)
|
||||
*
|
||||
* Parameters:
|
||||
* @param[in] u8 node = The node on which this link is located
|
||||
* @param[in] u8 link = The link about to be initialized
|
||||
* @param[out] BOOL result = true to ignore this link and skip it
|
||||
* false to initialize the link normally
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*/
|
||||
BOOL (*AMD_CB_IgnoreLink)(u8 Node, u8 Link);
|
||||
|
||||
/**----------------------------------------------------------------------------------------
|
||||
*
|
||||
* BOOL
|
||||
* AMD_CB_OverrideBusNumbers(u8 Node, u8 Link, u8 *SecBus, u8 *SubBus)
|
||||
*
|
||||
* Description:
|
||||
* This routine is called every time a non-coherent chain is processed.
|
||||
* If a system can not use the auto Bus numbering feature for non-coherent chain bus
|
||||
* assignments, this routine can provide explicit control. For each chain, provide
|
||||
* the bus number range to use.
|
||||
*
|
||||
* Parameters:
|
||||
* @param[in] u8 node = The node on which this chain is located
|
||||
* @param[in] u8 link = The link on the host for this chain
|
||||
* @param[out] u8 secBus = Secondary Bus number for this non-coherent chain
|
||||
* @param[out] u8 *subBus = Subordinate Bus number
|
||||
* @param[out] BOOL result = true this routine is supplying the bus numbers
|
||||
* false use auto Bus numbering
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*/
|
||||
BOOL (*AMD_CB_OverrideBusNumbers)(u8 Node, u8 Link, u8 *SecBus, u8 *SubBus);
|
||||
|
||||
/**----------------------------------------------------------------------------------------
|
||||
*
|
||||
* BOOL
|
||||
* AMD_CB_ManualBUIDSwapList(u8 Node, u8 Link, u8 **List)
|
||||
*
|
||||
* Description:
|
||||
* This routine is called every time a non-coherent chain is processed.
|
||||
* BUID assignment may be controlled explicitly on a non-coherent chain. Provide a
|
||||
* swap list. The first part of the list controls the BUID assignment and the
|
||||
* second part of the list provides the device to device linking. Device orientation
|
||||
* can be detected automatically, or explicitly. See documentation for more details.
|
||||
*
|
||||
* Automatic non-coherent init assigns BUIDs starting at 1 and incrementing sequentially
|
||||
* based on each device's unit count.
|
||||
*
|
||||
* Parameters:
|
||||
* @param[in] u8 node = The node on which this chain is located
|
||||
* @param[in] u8 link = The link on the host for this chain
|
||||
* @param[out] u8 **list = supply a pointer to a list
|
||||
* @param[out] BOOL result = true to use a manual list
|
||||
* false to initialize the link automatically
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*/
|
||||
BOOL (*AMD_CB_ManualBUIDSwapList)(u8 Node, u8 Link, const u8 **List);
|
||||
|
||||
/**----------------------------------------------------------------------------------------
|
||||
*
|
||||
* void
|
||||
* AMD_CB_DeviceCapOverride(u8 HostNode, u8 HostLink, u8 Depth, u8 Segment,
|
||||
* u8 Bus, u8 Dev, u32 DevVenID, u8 Link,
|
||||
* u8 *LinkWidthIn, u8 *LinkWidthOut, u16 *FreqCap)
|
||||
*
|
||||
* Description:
|
||||
* This routine is called once for every link on every IO device.
|
||||
* Update the width and frequency capability if needed for this device.
|
||||
* This is used along with device capabilities, the limit call backs, and northbridge
|
||||
* limits to compute the default settings. The components of the device's PCI config
|
||||
* address are provided, so its settings can be consulted if need be. The input width
|
||||
* and frequency are the reported device capabilities.
|
||||
*
|
||||
* Parameters:
|
||||
* @param[in] u8 hostNode = The node on which this chain is located
|
||||
* @param[in] u8 hostLink = The link on the host for this chain
|
||||
* @param[in] u8 Depth = The depth in the I/O chain from the Host
|
||||
* @param[in] u8 Segment = The Device's PCI Bus Segment number
|
||||
* @param[in] u8 Bus = The Device's PCI Bus number
|
||||
* @param[in] u8 Dev = The Device's PCI device Number
|
||||
* @param[in] u32 DevVenID = The Device's PCI Vendor + Device ID (offset 0x00)
|
||||
* @param[in] u8 Link = The Device's link number (0 or 1)
|
||||
* @param[in,out] u8 *LinkWidthIn = modify to change the Link Witdh In
|
||||
* @param[in,out] u8 *LinkWidthOut = modify to change the Link Witdh Out
|
||||
* @param[in,out] u32 *FreqCap = modify to change the link's frequency capability
|
||||
* @param[in,out] u32 *FeatureCap = modify to change the link's feature capability
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*/
|
||||
void (*AMD_CB_DeviceCapOverride)(
|
||||
u8 HostNode,
|
||||
u8 HostLink,
|
||||
u8 Depth,
|
||||
u8 Segment,
|
||||
u8 Bus,
|
||||
u8 Dev,
|
||||
u32 DevVenID,
|
||||
u8 Link,
|
||||
u8 *LinkWidthIn,
|
||||
u8 *LinkWidthOut,
|
||||
u32 *FreqCap,
|
||||
u32 *FeatureCap
|
||||
);
|
||||
|
||||
/**----------------------------------------------------------------------------------------
|
||||
*
|
||||
* void
|
||||
* AMD_CB_Cpu2CpuPCBLimits(u8 NodeA, u8 LinkA, u8 NodeB, u8 LinkB,
|
||||
* u8 *ABLinkWidthLimit, u8 *BALinkWidthLimit, u16 *PCBFreqCap)
|
||||
*
|
||||
* Description:
|
||||
* For each coherent connection this routine is called once.
|
||||
* Update the frequency and width if needed for this link (usually based on board
|
||||
* restriction). This is used with CPU device capabilities and northbridge limits
|
||||
* to compute the default settings. The input width and frequency are valid, but do
|
||||
* not necessarily reflect the minimum setting that will be chosen.
|
||||
*
|
||||
* Parameters:
|
||||
* @param[in] u8 nodeA = One node on which this link is located
|
||||
* @param[in] u8 linkA = The link on this node
|
||||
* @param[in] u8 nodeB = The other node on which this link is located
|
||||
* @param[in] u8 linkB = The link on that node
|
||||
* @param[in,out] u8 *ABLinkWidthLimit = modify to change the Link Witdh In
|
||||
* @param[in,out] u8 *BALinkWidthLimit = modify to change the Link Witdh Out
|
||||
* @param[in,out] u32 *PCBFreqCap = modify to change the link's frequency capability
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*/
|
||||
void (*AMD_CB_Cpu2CpuPCBLimits)(
|
||||
u8 NodeA,
|
||||
u8 LinkA,
|
||||
u8 NodeB,
|
||||
u8 LinkB,
|
||||
u8 *ABLinkWidthLimit,
|
||||
u8 *BALinkWidthLimit,
|
||||
u32 *PCBFreqCap
|
||||
);
|
||||
|
||||
/**----------------------------------------------------------------------------------------
|
||||
*
|
||||
* void
|
||||
* AMD_CB_IOPCBLimits(u8 HostNode, u8 HostLink, u8 Depth, u8 *DownstreamLinkWidthLimit,
|
||||
* u8 *UpstreamLinkWidthLimit, u16 *PCBFreqCap)
|
||||
*
|
||||
* Description:
|
||||
* For each non-coherent connection this routine is called once.
|
||||
* Update the frequency and width if needed for this link (usually based on board
|
||||
* restriction). This is used with device capabilities, device overrides, and northbridge limits
|
||||
* to compute the default settings. The input width and frequency are valid, but do
|
||||
* not necessarily reflect the minimum setting that will be chosen.
|
||||
*
|
||||
* Parameters:
|
||||
* @param[in] u8 hostNode = The node on which this link is located
|
||||
* @param[in] u8 hostLink = The link about to be initialized
|
||||
* @param[in] u8 Depth = The depth in the I/O chain from the Host
|
||||
* @param[in,out] u8 *DownstreamLinkWidthLimit = modify to change the Link Witdh In
|
||||
* @param[in,out] u8 *UpstreamLinkWidthLimit = modify to change the Link Witdh Out
|
||||
* @param[in,out] u32 *PCBFreqCap = modify to change the link's frequency capability
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*/
|
||||
void (*AMD_CB_IOPCBLimits)(
|
||||
u8 HostNode,
|
||||
u8 HostLink,
|
||||
u8 Depth,
|
||||
u8 *DownstreamLinkWidthLimit,
|
||||
u8 *UpstreamLinkWidthLimit,
|
||||
u32 *PCBFreqCap
|
||||
);
|
||||
|
||||
/**----------------------------------------------------------------------------------------
|
||||
*
|
||||
* BOOL
|
||||
* AMD_CB_SkipRegang(u8 NodeA, u8 LinkA, u8 NodeB, u8 LinkB)
|
||||
*
|
||||
* Description:
|
||||
* This routine is called whenever two sublinks are both connected to the same CPUs.
|
||||
* Normally, unganged subsinks between the same two CPUs are reganged.
|
||||
* Return true from this routine to leave the links unganged.
|
||||
*
|
||||
* Parameters:
|
||||
* @param[in] u8 nodeA = One node on which this link is located
|
||||
* @param[in] u8 linkA = The link on this node
|
||||
* @param[in] u8 nodeB = The other node on which this link is located
|
||||
* @param[in] u8 linkB = The link on that node
|
||||
* @param[out] BOOL result = true to leave link unganged
|
||||
* false to regang link automatically
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*/
|
||||
BOOL (*AMD_CB_SkipRegang)(
|
||||
u8 NodeA,
|
||||
u8 LinkA,
|
||||
u8 NodeB,
|
||||
u8 LinkB
|
||||
);
|
||||
|
||||
/**----------------------------------------------------------------------------------------
|
||||
*
|
||||
* BOOL
|
||||
* AMD_CB_CustomizeTrafficDistribution()
|
||||
*
|
||||
* Description:
|
||||
* Near the end of HT initialization, this routine is called once.
|
||||
* If this routine will handle traffic distribution in a proprietary way,
|
||||
* after detecting which links to distribute traffic on and configuring the system,
|
||||
* return true. Return false to let the HT code detect and do traffic distribution
|
||||
* This routine can also be used to simply turn this feature off, or to pre-process
|
||||
* the system before normal traffic distribution.
|
||||
*
|
||||
* Parameters:
|
||||
* @param[out] BOOL result = true skip traffic distribution
|
||||
* false do normal traffic distribution
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*/
|
||||
BOOL (*AMD_CB_CustomizeTrafficDistribution)(void);
|
||||
|
||||
|
||||
/**----------------------------------------------------------------------------------------
|
||||
*
|
||||
* BOOL
|
||||
* AMD_CB_CustomizeBuffers(u8 Node)
|
||||
*
|
||||
* Description:
|
||||
* Near the end of HT initialization, this routine is called once per CPU node.
|
||||
* Implement proprietary buffer tuning and return true, or return false for normal tuning.
|
||||
* This routine can also be used to simply turn this feature off, or to pre-process
|
||||
* the system before normal tuning.
|
||||
*
|
||||
* Parameters:
|
||||
* @param[in] u8 node = buffer allocation may apply to this node
|
||||
* @param[out] BOOL result = true skip buffer allocation on this node
|
||||
* false tune buffers normally
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*/
|
||||
BOOL (*AMD_CB_CustomizeBuffers)(u8 node);
|
||||
|
||||
/**----------------------------------------------------------------------------------------
|
||||
*
|
||||
* void
|
||||
* AMD_CB_OverrideDevicePort(u8 HostNode, u8 HostLink, u8 Depth, u8 *LinkWidthIn,
|
||||
* u8 *LinkWidthOut, u16 *LinkFrequency)
|
||||
*
|
||||
* Description:
|
||||
* Called once for each active link on each IO device.
|
||||
* Provides an opportunity to directly control the frequency and width,
|
||||
* intended for test and debug. The input frequency and width will be used
|
||||
* if not overridden.
|
||||
*
|
||||
* Parameters:
|
||||
* @param[in] u8 hostNode = The node on which this link is located
|
||||
* @param[in] u8 hostLink = The link about to be initialized
|
||||
* @param[in] u8 Depth = The depth in the I/O chain from the Host
|
||||
* @param[in] u8 Link = the link on the device (0 or 1)
|
||||
* @param[in,out] u8 *LinkWidthIn = modify to change the Link Witdh In
|
||||
* @param[in,out] u8 *LinkWidthOut = modify to change the Link Witdh Out
|
||||
* @param[in,out] u16 *LinkFrequency = modify to change the link's frequency capability
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*/
|
||||
void (*AMD_CB_OverrideDevicePort)(
|
||||
u8 HostNode,
|
||||
u8 HostLink,
|
||||
u8 Depth,
|
||||
u8 Link,
|
||||
u8 *LinkWidthIn,
|
||||
u8 *LinkWidthOut,
|
||||
u8 *LinkFrequency
|
||||
);
|
||||
|
||||
/**----------------------------------------------------------------------------------------
|
||||
*
|
||||
* void
|
||||
* AMD_CB_OverrideCpuPort(u8 Node, u8 Link, u8 *LinkWidthIn, u8 *LinkWidthOut,
|
||||
* u16 *LinkFrequency)
|
||||
*
|
||||
* Description:
|
||||
* Called once for each active link on each CPU.
|
||||
* Provides an opportunity to directly control the frequency and width,
|
||||
* intended for test and debug. The input frequency and width will be used
|
||||
* if not overridden.
|
||||
*
|
||||
* Parameters:
|
||||
* @param[in] u8 node = One node on which this link is located
|
||||
* @param[in] u8 link = The link on this node
|
||||
* @param[in,out] u8 *LinkWidthIn = modify to change the Link Witdh In
|
||||
* @param[in,out] u8 *LinkWidthOut = modify to change the Link Witdh Out
|
||||
* @param[in,out] u16 *LinkFrequency = modify to change the link's frequency capability
|
||||
*
|
||||
*---------------------------------------------------------------------------------------
|
||||
*/
|
||||
void (*AMD_CB_OverrideCpuPort)(
|
||||
u8 Node,
|
||||
u8 Link,
|
||||
u8 *LinkWidthIn,
|
||||
u8 *LinkWidthOut,
|
||||
u8 *LinkFrequency
|
||||
);
|
||||
|
||||
/**----------------------------------------------------------------------------------------
|
||||
*
|
||||
* void
|
||||
* AMD_CB_EventNotify(u8 evtClass, u16 event, const u8 *pEventData0)
|
||||
*
|
||||
* Description:
|
||||
* Errors, events, faults, warnings, and useful information are provided by
|
||||
* calling this routine as often as necessary, once for each notification.
|
||||
* See elsewhere in this file for class, event, and event data definitions.
|
||||
* See the documentation for more details.
|
||||
*
|
||||
* Parameters:
|
||||
* @param[in] u8 evtClass = What level event is this
|
||||
* @param[in] u16 event = A unique ID of this event
|
||||
* @param[in] u8 *pEventData0 = useful data associated with the event.
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*/
|
||||
void (*AMD_CB_EventNotify) (
|
||||
u8 evtClass,
|
||||
u16 event,
|
||||
const u8 *pEventData0
|
||||
);
|
||||
|
||||
const struct ht_link_config *ht_link_configuration;
|
||||
|
||||
} AMD_HTBLOCK;
|
||||
|
||||
/*
|
||||
* Event Notification Structures
|
||||
* These structures are passed to AMD_CB_EventNotify as *pEventData0.
|
||||
*/
|
||||
|
||||
/* For event HT_EVENT_HW_SYNCHFLOOD */
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 node;
|
||||
u8 link;
|
||||
} sHtEventHWSynchFlood;
|
||||
|
||||
/* For event HT_EVENT_HW_HTCRC */
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 node;
|
||||
u8 link;
|
||||
u8 laneMask;
|
||||
} sHtEventHWHtCrc;
|
||||
|
||||
/* For event HT_EVENT_NCOH_BUS_MAX_EXCEED */
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 node;
|
||||
u8 link;
|
||||
u8 bus;
|
||||
} sHTEventNcohBusMaxExceed;
|
||||
|
||||
/* For event HT_EVENT_NCOH_LINK_EXCEED */
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 node;
|
||||
u8 link;
|
||||
u8 depth;
|
||||
u8 maxLinks;
|
||||
} sHtEventNcohLinkExceed;
|
||||
|
||||
/* For event HT_EVENT_NCOH_CFG_MAP_EXCEED */
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 node;
|
||||
u8 link;
|
||||
} sHtEventNcohCfgMapExceed;
|
||||
|
||||
/* For event HT_EVENT_NCOH_BUID_EXCEED */
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 node;
|
||||
u8 link;
|
||||
u8 depth;
|
||||
u8 currentBUID;
|
||||
u8 unitCount;
|
||||
} sHtEventNcohBuidExceed;
|
||||
|
||||
/* For event HT_EVENT_NCOH_DEVICE_FAILED */
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 node;
|
||||
u8 link;
|
||||
u8 depth;
|
||||
u8 attemptedBUID;
|
||||
} sHtEventNcohDeviceFailed;
|
||||
|
||||
/* For event HT_EVENT_NCOH_AUTO_DEPTH */
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 node;
|
||||
u8 link;
|
||||
u8 depth;
|
||||
} sHtEventNcohAutoDepth;
|
||||
|
||||
/* For event HT_EVENT_OPT_REQUIRED_CAP_RETRY,
|
||||
* HT_EVENT_OPT_REQUIRED_CAP_GEN3
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 node;
|
||||
u8 link;
|
||||
u8 depth;
|
||||
} sHtEventOptRequiredCap;
|
||||
|
||||
/* For event HT_EVENT_COH_NO_TOPOLOGY */
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 totalNodes;
|
||||
} sHtEventCohNoTopology;
|
||||
|
||||
/* For event HT_EVENT_COH_LINK_EXCEED */
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 node;
|
||||
u8 link;
|
||||
u8 targetNode;
|
||||
u8 totalNodes;
|
||||
u8 maxLinks;
|
||||
} sHtEventCohLinkExceed;
|
||||
|
||||
/* For event HT_EVENT_COH_FAMILY_FEUD */
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 node;
|
||||
u8 link;
|
||||
u8 totalNodes;
|
||||
} sHtEventCohFamilyFeud;
|
||||
|
||||
/* For event HT_EVENT_COH_NODE_DISCOVERED */
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 node;
|
||||
u8 link;
|
||||
u8 newNode;
|
||||
} sHtEventCohNodeDiscovered;
|
||||
|
||||
/* For event HT_EVENT_COH_MPCAP_MISMATCH */
|
||||
typedef struct
|
||||
{
|
||||
u8 eSize;
|
||||
u8 node;
|
||||
u8 link;
|
||||
u8 sysMpCap;
|
||||
u8 totalNodes;
|
||||
} sHtEventCohMpCapMismatch;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* FUNCTIONS PROTOTYPE
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
void amdHtInitialize(AMD_HTBLOCK *pBlock);
|
||||
|
||||
|
||||
#endif /* H3FINIT_H */
|
||||
|
|
@ -1,355 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef HTTOPO_H
|
||||
#define HTTOPO_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* DEFINITIONS AND MACROS
|
||||
*
|
||||
*-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* TYPEDEFS, STRUCTURES, ENUMS
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* 0
|
||||
*/
|
||||
static u8 const amdHtTopologySingleNode[] = {
|
||||
0x01,
|
||||
0x00, 0xFF // Node 0
|
||||
};
|
||||
|
||||
/*
|
||||
* 0---1
|
||||
*/
|
||||
static u8 const amdHtTopologyDualNode[] = {
|
||||
0x02,
|
||||
0x02, 0xFF, 0x00, 0x11, // Node 0
|
||||
0x00, 0x00, 0x01, 0xFF // Node 1
|
||||
};
|
||||
|
||||
/*
|
||||
* 2
|
||||
* |
|
||||
* |
|
||||
* 0---1
|
||||
*/
|
||||
static u8 const amdHtTopologyThreeLine[] = {
|
||||
0x03,
|
||||
0x06, 0xFF, 0x04, 0x11, 0x02, 0x22, // Node 0
|
||||
0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, // Node 1
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0xFF // Node 2
|
||||
};
|
||||
|
||||
/*
|
||||
* 2
|
||||
* |\
|
||||
* | \
|
||||
* 0---1
|
||||
*/
|
||||
static u8 const amdHtTopologyTriangle[] = {
|
||||
0x03,
|
||||
0x06, 0xFF, 0x00, 0x11, 0x00, 0x22, // Node 0
|
||||
0x00, 0x00, 0x05, 0xFF, 0x00, 0x22, // Node 1
|
||||
0x00, 0x00, 0x00, 0x11, 0x03, 0xFF // Node 2
|
||||
};
|
||||
|
||||
/*
|
||||
* 2 3
|
||||
* |\ |
|
||||
* | \|
|
||||
* 0---1
|
||||
*/
|
||||
static u8 const amdHtTopologyFourDegenerate[] = {
|
||||
0x04,
|
||||
0x06, 0xFF, 0x00, 0x11, 0x00, 0x22, 0x00, 0x11, // Node 0
|
||||
0x08, 0x00, 0x0D, 0xFF, 0x08, 0x22, 0x05, 0x33, // Node 1
|
||||
0x00, 0x00, 0x00, 0x11, 0x03, 0xFF, 0x00, 0x11, // Node 2
|
||||
0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x02, 0xFF // Node 3
|
||||
};
|
||||
|
||||
/*
|
||||
* 2---3
|
||||
* |\ /|
|
||||
* |/ \|
|
||||
* 0---1
|
||||
*/
|
||||
static u8 const amdHtTopologyFourFully[] = {
|
||||
0x04,
|
||||
0x0E, 0xFF, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, // Node 0
|
||||
0x00, 0x00, 0x0D, 0xFF, 0x00, 0x22, 0x00, 0x33, // Node 1
|
||||
0x00, 0x00, 0x00, 0x11, 0x0B, 0xFF, 0x00, 0x33, // Node 2
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x07, 0xFF // Node 3
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 2---3
|
||||
* |\ |
|
||||
* | \|
|
||||
* 0---1
|
||||
*/
|
||||
static u8 const amdHtTopologyFourKite[] = {
|
||||
0x04,
|
||||
0x06, 0xFF, 0x00, 0x11, 0x00, 0x22, 0x00, 0x11, // Node 0
|
||||
0x08, 0x00, 0x0D, 0xFF, 0x00, 0x22, 0x00, 0x33, // Node 1
|
||||
0x00, 0x00, 0x00, 0x11, 0x0B, 0xFF, 0x01, 0x33, // Node 2
|
||||
0x00, 0x22, 0x00, 0x11, 0x00, 0x22, 0x06, 0xFF // Node 3
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 2 3
|
||||
* | |
|
||||
* | |
|
||||
* 0---1
|
||||
*/
|
||||
static u8 const amdHtTopologyFourLine[] = {
|
||||
0x04,
|
||||
0x06, 0xFF, 0x04, 0x11, 0x02, 0x22, 0x04, 0x11, // Node 0
|
||||
0x08, 0x00, 0x09, 0xFF, 0x08, 0x00, 0x01, 0x33, // Node 1
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, // Node 2
|
||||
0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x02, 0xFF // Node 3
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 2---3
|
||||
* | |
|
||||
* | |
|
||||
* 0---1
|
||||
*/
|
||||
static u8 const amdHtTopologyFourSquare[] = {
|
||||
0x04,
|
||||
0x06, 0xFF, 0x00, 0x11, 0x02, 0x22, 0x00, 0x22, // Node 0
|
||||
0x00, 0x00, 0x09, 0xFF, 0x00, 0x33, 0x01, 0x33, // Node 1
|
||||
0x08, 0x00, 0x00, 0x00, 0x09, 0xFF, 0x00, 0x33, // Node 2
|
||||
0x00, 0x11, 0x04, 0x11, 0x00, 0x22, 0x06, 0xFF, // Node 3
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 2---3
|
||||
* |\
|
||||
* | \
|
||||
* 0 1
|
||||
*/
|
||||
static u8 const amdHtTopologyFourStar[] = {
|
||||
0x04,
|
||||
0x04, 0xFF, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, // Node 0
|
||||
0x00, 0x22, 0x04, 0xFF, 0x00, 0x22, 0x00, 0x22, // Node 1
|
||||
0x0A, 0x00, 0x09, 0x11, 0x0B, 0xFF, 0x03, 0x33, // Node 2
|
||||
0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x04, 0xFF, // Node 3
|
||||
};
|
||||
|
||||
|
||||
static u8 const amdHtTopologyFiveFully[] = {
|
||||
0x05,
|
||||
0x1E, 0xFF, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, // Node 0
|
||||
0x00, 0x00, 0x1D, 0xFF, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, // Node 1
|
||||
0x00, 0x00, 0x00, 0x11, 0x1B, 0xFF, 0x00, 0x33, 0x00, 0x44, // Node 2
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x17, 0xFF, 0x00, 0x44, // Node 3
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x0F, 0xFF // Node 4
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 4
|
||||
* |\
|
||||
* | \
|
||||
* 2 3
|
||||
* | |
|
||||
* 0---1
|
||||
*/
|
||||
static u8 const amdHtTopologyFiveTwistedLadder[] = {
|
||||
0x05,
|
||||
0x06, 0xFF, 0x04, 0x11, 0x02, 0x22, 0x00, 0x11, 0x00, 0x22, // Node0
|
||||
0x08, 0x00, 0x09, 0xFF, 0x08, 0x00, 0x01, 0x33, 0x00, 0x30, // Node1
|
||||
0x10, 0x00, 0x10, 0x00, 0x11, 0xFF, 0x00, 0x40, 0x01, 0x44, // Node2
|
||||
0x00, 0x11, 0x00, 0x11, 0x00, 0x14, 0x12, 0xFF, 0x02, 0x44, // Node3
|
||||
0x00, 0x22, 0x00, 0x23, 0x00, 0x22, 0x04, 0x33, 0x0C, 0xFF // Node4
|
||||
};
|
||||
|
||||
|
||||
static u8 const amdHtTopologySixFully[] = {
|
||||
0x06,
|
||||
0x3E, 0xFF, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x55, // Node 0
|
||||
0x00, 0x00, 0x3D, 0xFF, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x55, // Node 1
|
||||
0x00, 0x00, 0x00, 0x11, 0x3B, 0xFF, 0x00, 0x33, 0x00, 0x44, 0x00, 0x55, // Node 2
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x37, 0xFF, 0x00, 0x44, 0x00, 0x55, // Node 3
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x2F, 0xFF, 0x00, 0x55, // Node 4
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, 0x1F, 0xFF // Node 5
|
||||
};
|
||||
|
||||
/*
|
||||
*
|
||||
* 4 5
|
||||
* |\ /|
|
||||
* |/ \|
|
||||
* 2 3
|
||||
* | |
|
||||
* 0---1
|
||||
*/
|
||||
static u8 const amdHtTopologySixTwistedLadder[] = {
|
||||
0x06,
|
||||
0x06, 0xFF, 0x04, 0x11, 0x02, 0x22, 0x00, 0x11, 0x02, 0x22, 0x00, 0x12, // Node0
|
||||
0x08, 0x00, 0x09, 0xFF, 0x00, 0x00, 0x01, 0x33, 0x00, 0x03, 0x01, 0x33, // Node1
|
||||
0x30, 0x00, 0x00, 0x00, 0x31, 0xFF, 0x00, 0x54, 0x21, 0x44, 0x00, 0x55, // Node2
|
||||
0x00, 0x11, 0x30, 0x11, 0x00, 0x45, 0x32, 0xFF, 0x00, 0x44, 0x12, 0x55, // Node3
|
||||
0x00, 0x22, 0x00, 0x32, 0x08, 0x22, 0x00, 0x33, 0x0C, 0xFF, 0x00, 0x32, // Node4
|
||||
0x00, 0x23, 0x00, 0x33, 0x00, 0x22, 0x04, 0x33, 0x00, 0x23, 0x0C, 0xFF // Node5
|
||||
};
|
||||
|
||||
|
||||
static u8 const amdHtTopologySevenFully[] = {
|
||||
0x07,
|
||||
0x7E, 0xFF, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x55, 0x00, 0x66, // Node 0
|
||||
0x00, 0x00, 0x7D, 0xFF, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x55, 0x00, 0x66, // Node 1
|
||||
0x00, 0x00, 0x00, 0x11, 0x7B, 0xFF, 0x00, 0x33, 0x00, 0x44, 0x00, 0x55, 0x00, 0x66, // Node 2
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x77, 0xFF, 0x00, 0x44, 0x00, 0x55, 0x00, 0x66, // Node 3
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x6F, 0xFF, 0x00, 0x55, 0x00, 0x66, // Node 4
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, 0x5F, 0xFF, 0x00, 0x66, // Node 5
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x55, 0x3F, 0xFF, // Node 6
|
||||
};
|
||||
|
||||
|
||||
/* 6
|
||||
* |
|
||||
* 4 5
|
||||
* |\ /|
|
||||
* |/ \|
|
||||
* 2 3
|
||||
* | |
|
||||
* 0---1
|
||||
*/
|
||||
static u8 const amdHtTopologySevenTwistedLadder[] = {
|
||||
0x07,
|
||||
0x06, 0xFF, 0x00, 0x11, 0x02, 0x22, 0x00, 0x12, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, // Node0
|
||||
0x00, 0x00, 0x09, 0xFF, 0x00, 0x03, 0x01, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, // Node1
|
||||
0x30, 0x00, 0x00, 0x50, 0x31, 0xFF, 0x00, 0x54, 0x21, 0x44, 0x01, 0x55, 0x21, 0x44, // Node2
|
||||
0x00, 0x41, 0x30, 0x11, 0x00, 0x45, 0x32, 0xFF, 0x02, 0x44, 0x12, 0x55, 0x02, 0x44, // Node3
|
||||
0x48, 0x22, 0x40, 0x33, 0x48, 0x22, 0x40, 0x33, 0x4C, 0xFF, 0x40, 0x32, 0x0C, 0x66, // Node4
|
||||
0x00, 0x22, 0x04, 0x33, 0x00, 0x22, 0x04, 0x33, 0x00, 0x23, 0x0C, 0xFF, 0x00, 0x23, // Node5
|
||||
0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x10, 0xFF // Node6
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 5--4
|
||||
* /####\
|
||||
* 6######3
|
||||
* |######|
|
||||
* 7######2
|
||||
* \####/
|
||||
* 0--1
|
||||
*/
|
||||
static u8 const amdHtTopologyEightFully [] = {
|
||||
0x08,
|
||||
0xFE, 0xFF, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x55, 0x00, 0x66, 0x00, 0x77, // Node 0
|
||||
0x00, 0x00, 0xFD, 0xFF, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x55, 0x00, 0x66, 0x00, 0x77, // Node 1
|
||||
0x00, 0x00, 0x00, 0x11, 0xFB, 0xFF, 0x00, 0x33, 0x00, 0x44, 0x00, 0x55, 0x00, 0x66, 0x00, 0x77, // Node 2
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0xF7, 0xFF, 0x00, 0x44, 0x00, 0x55, 0x00, 0x66, 0x00, 0x77, // Node 3
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0xEF, 0xFF, 0x00, 0x55, 0x00, 0x66, 0x00, 0x77, // Node 4
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, 0xDF, 0xFF, 0x00, 0x66, 0x00, 0x77, // Node 5
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x55, 0xBF, 0xFF, 0x00, 0x77, // Node 6
|
||||
0x00, 0x00, 0x00, 0x11, 0x00, 0x22, 0x00, 0x33, 0x00, 0x44, 0x00, 0x55, 0x00, 0x66, 0x7F, 0xFF // Node 7
|
||||
};
|
||||
|
||||
|
||||
/* 6---7
|
||||
* | |
|
||||
* 4---5
|
||||
* | |
|
||||
* 2---3
|
||||
* | |
|
||||
* 0---1
|
||||
*/
|
||||
static u8 const amdHtTopologyEightStraightLadder[] = {
|
||||
0x08,
|
||||
0x06, 0xFF, 0x00, 0x11, 0x02, 0x22, 0x00, 0x22, 0x02, 0x22, 0x00, 0x22, 0x02, 0x22, 0x00, 0x22, // Node0
|
||||
0x00, 0x00, 0x09, 0xFF, 0x00, 0x33, 0x01, 0x33, 0x00, 0x33, 0x01, 0x33, 0x00, 0x33, 0x01, 0x33, // Node1
|
||||
0x18, 0x00, 0x00, 0x00, 0x19, 0xFF, 0x00, 0x33, 0x09, 0x44, 0x00, 0x44, 0x09, 0x44, 0x00, 0x44, // Node2
|
||||
0x00, 0x11, 0x24, 0x11, 0x00, 0x22, 0x26, 0xFF, 0x00, 0x55, 0x06, 0x55, 0x00, 0x55, 0x06, 0x55, // Node3
|
||||
0x60, 0x22, 0x00, 0x22, 0x60, 0x22, 0x00, 0x22, 0x64, 0xFF, 0x00, 0x55, 0x24, 0x66, 0x00, 0x66, // Node4
|
||||
0x00, 0x33, 0x90, 0x33, 0x00, 0x33, 0x90, 0x33, 0x00, 0x44, 0x98, 0xFF, 0x00, 0x77, 0x18, 0x77, // Node5
|
||||
0x80, 0x44, 0x00, 0x44, 0x80, 0x44, 0x00, 0x44, 0x80, 0x44, 0x00, 0x44, 0x90, 0xFF, 0x00, 0x77, // Node6
|
||||
0x00, 0x55, 0x40, 0x55, 0x00, 0x55, 0x40, 0x55, 0x00, 0x55, 0x40, 0x55, 0x00, 0x66, 0x60, 0xFF // Node7
|
||||
};
|
||||
|
||||
|
||||
/* 6---7
|
||||
* | |
|
||||
* 4 5
|
||||
* |\ /|
|
||||
* |/ \|
|
||||
* 2 3
|
||||
* | |
|
||||
* 0---1
|
||||
*/
|
||||
static u8 const amdHtTopologyEightTwistedLadder[] = {
|
||||
0x08,
|
||||
0x06, 0xFF, 0x00, 0x11, 0x02, 0x22, 0x00, 0x12, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, // Node0
|
||||
0x00, 0x00, 0x09, 0xFF, 0x00, 0x03, 0x01, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, // Node1
|
||||
0x30, 0x00, 0x00, 0x50, 0x31, 0xFF, 0x00, 0x54, 0x21, 0x44, 0x01, 0x55, 0x21, 0x44, 0x01, 0x55, // Node2
|
||||
0x00, 0x41, 0x30, 0x11, 0x00, 0x45, 0x32, 0xFF, 0x02, 0x44, 0x12, 0x55, 0x02, 0x44, 0x12, 0x55, // Node3
|
||||
0x48, 0x22, 0x40, 0x33, 0x48, 0x22, 0x40, 0x33, 0x4C, 0xFF, 0x00, 0x32, 0x0C, 0x66, 0x00, 0x36, // Node4
|
||||
0x80, 0x22, 0x84, 0x33, 0x80, 0x22, 0x84, 0x33, 0x00, 0x23, 0x8C, 0xFF, 0x00, 0x27, 0x0C, 0x77, // Node5
|
||||
0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x80, 0x44, 0x00, 0x74, 0x90, 0xFF, 0x00, 0x77, // Node6
|
||||
0x00, 0x55, 0x00, 0x55, 0x00, 0x55, 0x00, 0x55, 0x00, 0x65, 0x40, 0x55, 0x00, 0x66, 0x60, 0xFF // Node7
|
||||
};
|
||||
|
||||
static const u8 *const amd_topo_list[] = {
|
||||
amdHtTopologySingleNode,
|
||||
amdHtTopologyDualNode,
|
||||
amdHtTopologyThreeLine,
|
||||
amdHtTopologyTriangle,
|
||||
amdHtTopologyFourLine,
|
||||
amdHtTopologyFourStar,
|
||||
amdHtTopologyFourDegenerate,
|
||||
amdHtTopologyFourSquare,
|
||||
amdHtTopologyFourKite,
|
||||
amdHtTopologyFourFully,
|
||||
amdHtTopologyFiveFully,
|
||||
amdHtTopologySixFully,
|
||||
amdHtTopologySevenFully,
|
||||
amdHtTopologyEightFully,
|
||||
amdHtTopologyEightTwistedLadder,
|
||||
amdHtTopologyEightStraightLadder,
|
||||
NULL // NULL to mark end of list
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* FUNCTIONS PROTOTYPE
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
void getAmdTopolist(u8 ***p);
|
||||
|
||||
|
||||
#endif /* HTTOPO_H */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,115 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef H3NCMN_H
|
||||
#define H3NCMN_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <device/pci.h>
|
||||
#include <cpu/amd/msr.h>
|
||||
|
||||
#include "comlib.h"
|
||||
#include "h3finit.h"
|
||||
#include "h3ffeat.h"
|
||||
|
||||
/* Use a macro to convert a node number to a PCI device. If some future port of
|
||||
* this code needs to, this can easily be replaced by a function call:
|
||||
* u8 makePCIDeviceFromNode(u8 node);
|
||||
*/
|
||||
#define makePCIDeviceFromNode(node) \
|
||||
((u8)(24 + node))
|
||||
|
||||
/* Use a macro to convert a node number to a PCI bus. If some future port of
|
||||
* this code needs to, this can easily be replaced by a function call:
|
||||
* u8 makePCIBusFromNode(u8 node);
|
||||
*/
|
||||
#define makePCIBusFromNode(node) \
|
||||
((u8)(0))
|
||||
|
||||
/* Use a macro to convert a node number to a PCI Segment. If some future port of
|
||||
* this code needs to, this can easily be replaced by a function call:
|
||||
* u8 makePCISegmentFromNode(u8 node);
|
||||
*/
|
||||
#define makePCISegmentFromNode(node) \
|
||||
((u8)(0))
|
||||
|
||||
/* Macros to fix support issues that come up with early sample processors, which
|
||||
* sometimes do things like report capabilities that are actually unsupported.
|
||||
* Use the build flag, HT_BUILD_EARLY_SAMPLE_CPU_SUPPORT, to enable this support.
|
||||
*
|
||||
* It's not envisioned this would be replaced by an external function, but the prototype is
|
||||
* u16 fixEarlySampleFreqCapability(u16 fc);
|
||||
*/
|
||||
#ifndef HT_BUILD_EARLY_SAMPLE_CPU_SUPPORT
|
||||
#define fixEarlySampleFreqCapability(fc) \
|
||||
((u16)fc)
|
||||
#else
|
||||
#define fixEarlySampleFreqCapability(fc) \
|
||||
((u16)fc & HT_FREQUENCY_LIMIT_HT1_ONLY)
|
||||
#endif
|
||||
|
||||
struct cNorthBridge
|
||||
{
|
||||
/* Public data, clients of northbridge can access */
|
||||
u8 maxLinks;
|
||||
u8 maxNodes;
|
||||
u8 maxPlatformLinks;
|
||||
|
||||
/* Public Interfaces for northbridge clients, coherent init*/
|
||||
void (*writeRoutingTable)(u8 node, u8 target, u8 link, cNorthBridge *nb);
|
||||
void (*writeNodeID)(u8 node, u8 nodeID, cNorthBridge *nb);
|
||||
u8 (*readDefLnk)(u8 node, cNorthBridge *nb);
|
||||
void (*enableRoutingTables)(u8 node, cNorthBridge *nb);
|
||||
BOOL (*verifyLinkIsCoherent)(u8 node, u8 link, cNorthBridge *nb);
|
||||
BOOL (*readTrueLinkFailStatus)(u8 node, u8 link, sMainData *pDat, cNorthBridge *nb);
|
||||
u8 (*readToken)(u8 node, cNorthBridge *nb);
|
||||
void (*writeToken)(u8 node, u8 value, cNorthBridge *nb);
|
||||
u8 (*getNumCoresOnNode)(u8 node, cNorthBridge *nb);
|
||||
void (*setTotalNodesAndCores)(u8 node, u8 totalNodes, u8 totalCores, cNorthBridge *nb);
|
||||
void (*limitNodes)(u8 node, cNorthBridge *nb);
|
||||
void (*writeFullRoutingTable)(u8 node, u8 target, u8 reqLink, u8 rspLink, u32 bClinks, cNorthBridge *nb);
|
||||
BOOL (*isCompatible)(u8 node, cNorthBridge *nb);
|
||||
BOOL (*isCapable)(u8 node, sMainData *pDat, cNorthBridge *nb);
|
||||
void (*stopLink)(u8 node, u8 link, cNorthBridge *nb);
|
||||
BOOL (*handleSpecialLinkCase)(u8 node, u8 link, sMainData *pDat, cNorthBridge *nb);
|
||||
|
||||
/* Public Interfaces for northbridge clients, noncoherent init */
|
||||
u8 (*readSbLink)(cNorthBridge *nb);
|
||||
BOOL (*verifyLinkIsNonCoherent)(u8 node, u8 link, cNorthBridge *nb);
|
||||
void (*setCFGAddrMap)(u8 cfgMapIndex, u8 secBus, u8 subBus, u8 targetNode, u8 targetLink, sMainData *pDat, cNorthBridge *nb);
|
||||
|
||||
/* Public Interfaces for northbridge clients, Optimization */
|
||||
u8 (*convertBitsToWidth)(u8 value, cNorthBridge *nb);
|
||||
u8 (*convertWidthToBits)(u8 value, cNorthBridge *nb);
|
||||
uint32_t (*northBridgeFreqMask)(u8 node, cNorthBridge *nb);
|
||||
void (*gatherLinkData)(sMainData *pDat, cNorthBridge *nb);
|
||||
void (*setLinkData)(sMainData *pDat, cNorthBridge *nb);
|
||||
|
||||
/* Public Interfaces for northbridge clients, System and performance Tuning. */
|
||||
void (*writeTrafficDistribution)(u32 links01, u32 links10, cNorthBridge *nb);
|
||||
void (*bufferOptimizations)(u8 node, sMainData *pDat, cNorthBridge *nb);
|
||||
|
||||
/* Private Data for northbridge implementation use only */
|
||||
u32 selfRouteRequestMask;
|
||||
u32 selfRouteResponseMask;
|
||||
u8 broadcastSelfBit;
|
||||
u32 compatibleKey;
|
||||
} ;
|
||||
|
||||
void newNorthBridge(u8 node, cNorthBridge *nb);
|
||||
uint8_t is_gt_rev_d(void);
|
||||
|
||||
#endif /* H3NCMN_H */
|
||||
|
|
@ -1,384 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
* Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <cpu/x86/msr.h>
|
||||
#include <console/console.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include "ht_wrapper.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* TYPEDEFS, DEFINITIONS AND MACROS
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Single CPU system? */
|
||||
#if (CONFIG_MAX_PHYSICAL_CPUS == 1)
|
||||
/* FIXME
|
||||
* This #define is used by other #included .c files
|
||||
* When set, multiprocessor support is completely disabled
|
||||
*/
|
||||
#define HT_BUILD_NC_ONLY 1
|
||||
#endif
|
||||
|
||||
/* Debugging Options */
|
||||
//#define AMD_DEBUG_ERROR_STOP 1
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* MODULES USED
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "comlib.h"
|
||||
#include "h3gtopo.h"
|
||||
#include "h3finit.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* LOCAL FUNCTIONS
|
||||
*
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static const char * event_class_string_decodes[] = {
|
||||
[HT_EVENT_CLASS_CRITICAL] = "CRITICAL",
|
||||
[HT_EVENT_CLASS_ERROR] = "ERROR",
|
||||
[HT_EVENT_CLASS_HW_FAULT] = "HARDWARE FAULT",
|
||||
[HT_EVENT_CLASS_WARNING] = "WARNING",
|
||||
[HT_EVENT_CLASS_INFO] = "INFO"
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t code;
|
||||
const char *string;
|
||||
} event_string_decode_t;
|
||||
|
||||
static const event_string_decode_t event_string_decodes[] = {
|
||||
{ HT_EVENT_COH_EVENTS, "HT_EVENT_COH_EVENTS" },
|
||||
{ HT_EVENT_COH_NO_TOPOLOGY, "HT_EVENT_COH_NO_TOPOLOGY" },
|
||||
{ HT_EVENT_COH_LINK_EXCEED, "HT_EVENT_COH_LINK_EXCEED" },
|
||||
{ HT_EVENT_COH_FAMILY_FEUD, "HT_EVENT_COH_FAMILY_FEUD" },
|
||||
{ HT_EVENT_COH_NODE_DISCOVERED, "HT_EVENT_COH_NODE_DISCOVERED" },
|
||||
{ HT_EVENT_COH_MPCAP_MISMATCH, "HT_EVENT_COH_MPCAP_MISMATCH" },
|
||||
{ HT_EVENT_NCOH_EVENTS, "HT_EVENT_NCOH_EVENTS" },
|
||||
{ HT_EVENT_NCOH_BUID_EXCEED, "HT_EVENT_NCOH_BUID_EXCEED" },
|
||||
{ HT_EVENT_NCOH_LINK_EXCEED, "HT_EVENT_NCOH_LINK_EXCEED" },
|
||||
{ HT_EVENT_NCOH_BUS_MAX_EXCEED, "HT_EVENT_NCOH_BUS_MAX_EXCEED" },
|
||||
{ HT_EVENT_NCOH_CFG_MAP_EXCEED, "HT_EVENT_NCOH_CFG_MAP_EXCEED" },
|
||||
{ HT_EVENT_NCOH_DEVICE_FAILED, "HT_EVENT_NCOH_DEVICE_FAILED" },
|
||||
{ HT_EVENT_NCOH_AUTO_DEPTH, "HT_EVENT_NCOH_AUTO_DEPTH" },
|
||||
{ HT_EVENT_OPT_EVENTS, "HT_EVENT_OPT_EVENTS" },
|
||||
{ HT_EVENT_OPT_REQUIRED_CAP_RETRY, "HT_EVENT_OPT_REQUIRED_CAP_RETRY" },
|
||||
{ HT_EVENT_OPT_REQUIRED_CAP_GEN3, "HT_EVENT_OPT_REQUIRED_CAP_GEN3" },
|
||||
{ HT_EVENT_HW_EVENTS, "HT_EVENT_HW_EVENTS" },
|
||||
{ HT_EVENT_HW_SYNCHFLOOD, "HT_EVENT_HW_SYNCHFLOOD" },
|
||||
{ HT_EVENT_HW_HTCRC, "HT_EVENT_HW_HTCRC" }
|
||||
};
|
||||
|
||||
static const char *event_string_decode(uint32_t event)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < ARRAY_SIZE(event_string_decodes); i++)
|
||||
if (event_string_decodes[i].code == event)
|
||||
break;
|
||||
if (i == ARRAY_SIZE(event_string_decodes))
|
||||
return "ERROR: Unmatched event code! "
|
||||
"Did you forget to update event_string_decodes[]?";
|
||||
return event_string_decodes[i].string;
|
||||
}
|
||||
|
||||
/**
|
||||
* void AMD_CB_EventNotify (u8 evtClass, u16 event, const u8 *pEventData0)
|
||||
*/
|
||||
static void AMD_CB_EventNotify (u8 evtClass, u16 event, const u8 *pEventData0)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t log_level;
|
||||
uint8_t dump_event_detail;
|
||||
|
||||
printk(BIOS_DEBUG, "%s: ", __func__);
|
||||
|
||||
/* Decode event */
|
||||
dump_event_detail = 1;
|
||||
switch (evtClass) {
|
||||
case HT_EVENT_CLASS_CRITICAL:
|
||||
case HT_EVENT_CLASS_ERROR:
|
||||
case HT_EVENT_CLASS_HW_FAULT:
|
||||
case HT_EVENT_CLASS_WARNING:
|
||||
case HT_EVENT_CLASS_INFO:
|
||||
log_level = BIOS_DEBUG;
|
||||
printk(log_level, "%s", event_class_string_decodes[evtClass]);
|
||||
break;
|
||||
default:
|
||||
log_level = BIOS_DEBUG;
|
||||
printk(log_level, "UNKNOWN");
|
||||
break;
|
||||
}
|
||||
printk(log_level, ": ");
|
||||
|
||||
switch (event) {
|
||||
case HT_EVENT_COH_EVENTS:
|
||||
case HT_EVENT_COH_NO_TOPOLOGY:
|
||||
case HT_EVENT_COH_LINK_EXCEED:
|
||||
case HT_EVENT_COH_FAMILY_FEUD:
|
||||
printk(log_level, "%s", event_string_decode(event));
|
||||
break;
|
||||
case HT_EVENT_COH_NODE_DISCOVERED:
|
||||
{
|
||||
printk(log_level, "HT_EVENT_COH_NODE_DISCOVERED");
|
||||
sHtEventCohNodeDiscovered *evt = (sHtEventCohNodeDiscovered*)pEventData0;
|
||||
printk(log_level, ": node %d link %d new node: %d",
|
||||
evt->node, evt->link, evt->newNode);
|
||||
dump_event_detail = 0;
|
||||
break;
|
||||
}
|
||||
case HT_EVENT_COH_MPCAP_MISMATCH:
|
||||
case HT_EVENT_NCOH_EVENTS:
|
||||
case HT_EVENT_NCOH_BUID_EXCEED:
|
||||
case HT_EVENT_NCOH_LINK_EXCEED:
|
||||
case HT_EVENT_NCOH_BUS_MAX_EXCEED:
|
||||
case HT_EVENT_NCOH_CFG_MAP_EXCEED:
|
||||
printk(log_level, "%s", event_string_decode(event));
|
||||
break;
|
||||
case HT_EVENT_NCOH_DEVICE_FAILED:
|
||||
{
|
||||
printk(log_level, "%s", event_string_decode(event));
|
||||
sHtEventNcohDeviceFailed *evt = (sHtEventNcohDeviceFailed*)pEventData0;
|
||||
printk(log_level, ": node %d link %d depth: %d attemptedBUID: %d",
|
||||
evt->node, evt->link, evt->depth, evt->attemptedBUID);
|
||||
dump_event_detail = 0;
|
||||
break;
|
||||
}
|
||||
case HT_EVENT_NCOH_AUTO_DEPTH:
|
||||
{
|
||||
printk(log_level, "%s", event_string_decode(event));
|
||||
sHtEventNcohAutoDepth *evt = (sHtEventNcohAutoDepth*)pEventData0;
|
||||
printk(log_level, ": node %d link %d depth: %d",
|
||||
evt->node, evt->link, evt->depth);
|
||||
dump_event_detail = 0;
|
||||
break;
|
||||
}
|
||||
case HT_EVENT_OPT_EVENTS:
|
||||
case HT_EVENT_OPT_REQUIRED_CAP_RETRY:
|
||||
case HT_EVENT_OPT_REQUIRED_CAP_GEN3:
|
||||
case HT_EVENT_HW_EVENTS:
|
||||
case HT_EVENT_HW_SYNCHFLOOD:
|
||||
case HT_EVENT_HW_HTCRC:
|
||||
printk(log_level, "%s", event_string_decode(event));
|
||||
break;
|
||||
default:
|
||||
printk(log_level, "HT_EVENT_UNKNOWN");
|
||||
break;
|
||||
}
|
||||
printk(log_level, "\n");
|
||||
|
||||
if (dump_event_detail) {
|
||||
printk(BIOS_DEBUG, " event class: %02x\n event: %04x\n data: ", evtClass, event);
|
||||
|
||||
for (i = 0; i < *pEventData0; i++) {
|
||||
printk(BIOS_DEBUG, " %02x ", *(pEventData0 + i));
|
||||
}
|
||||
printk(BIOS_DEBUG, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* void getAmdTopolist(u8 ***p)
|
||||
*
|
||||
* point to the stock topo list array
|
||||
*
|
||||
*/
|
||||
void getAmdTopolist(u8 ***p)
|
||||
{
|
||||
*p = (u8 **)amd_topo_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* BOOL AMD_CB_IgnoreLink(u8 Node, u8 Link)
|
||||
* Description:
|
||||
* This routine is used to ignore connected yet faulty HT links,
|
||||
* such as those present in a G34 processor package.
|
||||
*
|
||||
* Parameters:
|
||||
* @param[in] node = The node on which this chain is located
|
||||
* @param[in] link = The link on the host for this chain
|
||||
*/
|
||||
static BOOL AMD_CB_IgnoreLink (u8 node, u8 link)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* void amd_ht_init(struct sys_info *sysinfo)
|
||||
*
|
||||
* AMD HT init coreboot wrapper
|
||||
*
|
||||
*/
|
||||
void amd_ht_init(struct sys_info *sysinfo)
|
||||
{
|
||||
|
||||
if (!sysinfo) {
|
||||
printk(BIOS_DEBUG, "Skipping %s\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
AMD_HTBLOCK ht_wrapper = {
|
||||
NULL, // u8 **topolist;
|
||||
0, // u8 AutoBusStart;
|
||||
32, // u8 AutoBusMax;
|
||||
6, // u8 AutoBusIncrement;
|
||||
AMD_CB_IgnoreLink, // BOOL (*AMD_CB_IgnoreLink)();
|
||||
NULL, // BOOL (*AMD_CB_OverrideBusNumbers)();
|
||||
AMD_CB_ManualBUIDSwapList, // BOOL (*AMD_CB_ManualBUIDSwapList)();
|
||||
NULL, // void (*AMD_CB_DeviceCapOverride)();
|
||||
NULL, // void (*AMD_CB_Cpu2CpuPCBLimits)();
|
||||
NULL, // void (*AMD_CB_IOPCBLimits)();
|
||||
NULL, // BOOL (*AMD_CB_SkipRegang)();
|
||||
NULL, // BOOL (*AMD_CB_CustomizeTrafficDistribution)();
|
||||
NULL, // BOOL (*AMD_CB_CustomizeBuffers)();
|
||||
NULL, // void (*AMD_CB_OverrideDevicePort)();
|
||||
NULL, // void (*AMD_CB_OverrideCpuPort)();
|
||||
AMD_CB_EventNotify, // void (*AMD_CB_EventNotify) ();
|
||||
&sysinfo->ht_link_cfg // struct ht_link_config*
|
||||
};
|
||||
|
||||
printk(BIOS_DEBUG, "Enter %s\n", __func__);
|
||||
amdHtInitialize(&ht_wrapper);
|
||||
printk(BIOS_DEBUG, "Exit %s\n", __func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* void amd_ht_fixup(struct sys_info *sysinfo)
|
||||
*
|
||||
* AMD HT fixup
|
||||
*
|
||||
*/
|
||||
void amd_ht_fixup(struct sys_info *sysinfo) {
|
||||
printk(BIOS_DEBUG, "%s\n", __func__);
|
||||
if (CONFIG(CPU_AMD_MODEL_10XXX)) {
|
||||
uint8_t rev_gte_d = 0;
|
||||
uint8_t fam15h = 0;
|
||||
uint8_t dual_node = 0;
|
||||
uint32_t f3xe8;
|
||||
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)
|
||||
/* Family 10h Revision D or later */
|
||||
rev_gte_d = 1;
|
||||
|
||||
if (rev_gte_d) {
|
||||
f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8);
|
||||
|
||||
/* Check for dual node capability */
|
||||
if (f3xe8 & 0x20000000)
|
||||
dual_node = 1;
|
||||
|
||||
if (dual_node) {
|
||||
/* Each G34 processor contains a defective HT link.
|
||||
* See the Family 10h BKDG Rev 3.62 section 2.7.1.5 for details
|
||||
* For Family 15h see the BKDG Rev. 3.14 section 2.12.1.5 for details.
|
||||
*/
|
||||
uint8_t node;
|
||||
uint8_t node_count = get_nodes();
|
||||
uint32_t dword;
|
||||
for (node = 0; node < node_count; node++) {
|
||||
f3xe8 = pci_read_config32(NODE_PCI(node, 3), 0xe8);
|
||||
uint8_t internal_node_number = ((f3xe8 & 0xc0000000) >> 30);
|
||||
printk(BIOS_DEBUG,
|
||||
"%s: node %d (internal node "
|
||||
"ID %d): disabling defective "
|
||||
"HT link", __func__, node,
|
||||
internal_node_number);
|
||||
if (internal_node_number == 0) {
|
||||
uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x98:0xd8) & 0x1;
|
||||
printk(BIOS_DEBUG, " (L3 connected: %d)\n", package_link_3_connected);
|
||||
if (package_link_3_connected) {
|
||||
/* Set WidthIn and WidthOut to 0 */
|
||||
dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x84:0xc4);
|
||||
dword &= ~0x77000000;
|
||||
pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x84:0xc4, dword);
|
||||
/* Set Ganged to 1 */
|
||||
dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x170:0x178);
|
||||
dword |= 0x00000001;
|
||||
pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x170:0x178, dword);
|
||||
} else {
|
||||
/* Set ConnDly to 1 */
|
||||
dword = pci_read_config32(NODE_PCI(node, 0), 0x16c);
|
||||
dword |= 0x00000100;
|
||||
pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
|
||||
/* Set TransOff and EndOfChain to 1 */
|
||||
dword = pci_read_config32(NODE_PCI(node, 4), (fam15h)?0x84:0xc4);
|
||||
dword |= 0x000000c0;
|
||||
pci_write_config32(NODE_PCI(node, 4), (fam15h)?0x84:0xc4, dword);
|
||||
}
|
||||
} else if (internal_node_number == 1) {
|
||||
uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0xf8:0xb8) & 0x1;
|
||||
printk(BIOS_DEBUG, " (L3 connected: %d)\n", package_link_3_connected);
|
||||
if (package_link_3_connected) {
|
||||
/* Set WidthIn and WidthOut to 0 */
|
||||
dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0xe4:0xa4);
|
||||
dword &= ~0x77000000;
|
||||
pci_write_config32(NODE_PCI(node, 0), (fam15h)?0xe4:0xa4, dword);
|
||||
/* Set Ganged to 1 */
|
||||
/* WARNING
|
||||
* The Family 15h BKDG states that 0x18c should be set,
|
||||
* however this is in error. 0x17c is the correct control
|
||||
* register (sublink 0) for these processors...
|
||||
*/
|
||||
dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x17c:0x174);
|
||||
dword |= 0x00000001;
|
||||
pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x17c:0x174, dword);
|
||||
} else {
|
||||
/* Set ConnDly to 1 */
|
||||
dword = pci_read_config32(NODE_PCI(node, 0), 0x16c);
|
||||
dword |= 0x00000100;
|
||||
pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
|
||||
/* Set TransOff and EndOfChain to 1 */
|
||||
dword = pci_read_config32(NODE_PCI(node, 4), (fam15h)?0xe4:0xa4);
|
||||
dword |= 0x000000c0;
|
||||
pci_write_config32(NODE_PCI(node, 4), (fam15h)?0xe4:0xa4, dword);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 get_nodes(void)
|
||||
{
|
||||
pci_devfn_t dev;
|
||||
u32 nodes;
|
||||
|
||||
dev = PCI_DEV(CONFIG_CBB, CONFIG_CDB, 0);
|
||||
nodes = ((pci_read_config32(dev, 0x60)>>4) & 7);
|
||||
#if CONFIG_MAX_PHYSICAL_CPUS > 8
|
||||
nodes += (((pci_read_config32(dev, 0x160)>>4) & 7)<<3);
|
||||
#endif
|
||||
nodes++;
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AMD_HT_WRAPPER_H
|
||||
#define AMD_HT_WRAPPER_H
|
||||
|
||||
#include <northbridge/amd/amdfam10/raminit.h>
|
||||
#include <northbridge/amd/amdfam10/amdfam10.h>
|
||||
#include <stdint.h>
|
||||
#include "h3finit.h"
|
||||
|
||||
void amd_ht_fixup(struct sys_info *sysinfo);
|
||||
u32 get_nodes(void);
|
||||
void amd_ht_init(struct sys_info *sysinfo);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PORTING_H
|
||||
#define PORTING_H
|
||||
|
||||
|
||||
/* For AMD64 or 32-bit GCC */
|
||||
typedef int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef char int8;
|
||||
typedef unsigned char uint8;
|
||||
|
||||
/* Create the Boolean type */
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
typedef unsigned char BOOL;
|
||||
|
||||
/* Force tight packing of structures */
|
||||
#pragma pack(1)
|
||||
|
||||
#define CALLCONV
|
||||
|
||||
|
||||
typedef struct _uint64
|
||||
{
|
||||
uint32 lo;
|
||||
uint32 hi;
|
||||
}uint64;
|
||||
|
||||
|
||||
/*
|
||||
* SBDFO - Segment Bus Device Function Offset
|
||||
* 31:28 Segment (4-bits)
|
||||
* 27:20 Bus (8-bits)
|
||||
* 19:15 Device (5-bits)
|
||||
* 14:12 Function(3-bits)
|
||||
* 11:00 Offset (12-bits)
|
||||
*/
|
||||
typedef uint32 SBDFO;
|
||||
|
||||
#define MAKE_SBDFO(seg,bus,dev,fun,off) ((((uint32)(seg))<<28) | (((uint32)(bus))<<20) | \
|
||||
(((uint32)(dev))<<15) | (((uint32)(fun))<<12) | ((uint32)(off)))
|
||||
#define SBDFO_SEG(x) (((uint32)(x)>>28) & 0x0F)
|
||||
#define SBDFO_BUS(x) (((uint32)(x)>>20) & 0xFF)
|
||||
#define SBDFO_DEV(x) (((uint32)(x)>>15) & 0x1F)
|
||||
#define SBDFO_FUN(x) (((uint32)(x)>>12) & 0x07)
|
||||
#define SBDFO_OFF(x) (((uint32)(x)) & 0xFFF)
|
||||
#define ILLEGAL_SBDFO 0xFFFFFFFF
|
||||
|
||||
void CALLCONV AmdMSRRead(uint32 Address, uint64 *Value);
|
||||
void CALLCONV AmdMSRWrite(uint32 Address, uint64 *Value);
|
||||
void CALLCONV AmdIORead(uint8 IOSize, uint16 Address, uint32 *Value);
|
||||
void CALLCONV AmdIOWrite(uint8 IOSize, uint16 Address, uint32 *Value);
|
||||
void CALLCONV AmdMemRead(uint8 MemSize, uint64 *Address, uint32 *Value);
|
||||
void CALLCONV AmdMemWrite(uint8 MemSize, uint64 *Address, uint32 *Value);
|
||||
void CALLCONV AmdPCIRead(SBDFO loc, uint32 *Value);
|
||||
void CALLCONV AmdPCIWrite(SBDFO loc, uint32 *Value);
|
||||
void CALLCONV AmdCPUIDRead(uint32 Address, uint32 Regs[4]);
|
||||
|
||||
#define BYTESIZE 1
|
||||
#define WORDSIZE 2
|
||||
#define DWORDSIZE 4
|
||||
|
||||
#endif /* PORTING_H */
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AMDK8_H
|
||||
#define AMDK8_H
|
||||
|
||||
#define HT_INIT_CONTROL 0x6C
|
||||
#define HTIC_ColdR_Detect (1<<4)
|
||||
#define HTIC_BIOSR_Detect (1<<5)
|
||||
#define HTIC_INIT_Detect (1<<6)
|
||||
|
||||
#define NODE_HT(x) PCI_DEV(0,24+x,0)
|
||||
#define NODE_MP(x) PCI_DEV(0,24+x,1)
|
||||
#define NODE_MC(x) PCI_DEV(0,24+x,3)
|
||||
|
||||
void set_bios_reset(void);
|
||||
void distinguish_cpu_resets(unsigned int nodeid);
|
||||
unsigned int get_sblk(void);
|
||||
unsigned int get_sbbusn(unsigned int sblk);
|
||||
|
||||
#endif /* AMDK8_H */
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <device/pci_ops.h>
|
||||
#include <stdint.h>
|
||||
#include <cpu/x86/lapic.h>
|
||||
#include "amdk8.h"
|
||||
|
||||
static inline int cpu_init_detected(unsigned int nodeid)
|
||||
{
|
||||
u32 htic;
|
||||
pci_devfn_t dev;
|
||||
|
||||
dev = PCI_DEV(0, 0x18 + nodeid, 0);
|
||||
htic = pci_io_read_config32(dev, HT_INIT_CONTROL);
|
||||
|
||||
return !!(htic & HTIC_INIT_Detect);
|
||||
}
|
||||
|
||||
static inline int bios_reset_detected(void)
|
||||
{
|
||||
u32 htic;
|
||||
htic = pci_io_read_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL);
|
||||
|
||||
return (htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect);
|
||||
}
|
||||
|
||||
static inline int cold_reset_detected(void)
|
||||
{
|
||||
u32 htic;
|
||||
htic = pci_io_read_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL);
|
||||
|
||||
return !(htic & HTIC_ColdR_Detect);
|
||||
}
|
||||
|
||||
void distinguish_cpu_resets(unsigned int nodeid)
|
||||
{
|
||||
u32 htic;
|
||||
pci_devfn_t device;
|
||||
device = PCI_DEV(0, 0x18 + nodeid, 0);
|
||||
htic = pci_io_read_config32(device, HT_INIT_CONTROL);
|
||||
htic |= HTIC_ColdR_Detect | HTIC_BIOSR_Detect | HTIC_INIT_Detect;
|
||||
pci_io_write_config32(device, HT_INIT_CONTROL, htic);
|
||||
}
|
||||
|
||||
void set_bios_reset(void)
|
||||
{
|
||||
u32 htic;
|
||||
htic = pci_io_read_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL);
|
||||
htic &= ~HTIC_BIOSR_Detect;
|
||||
pci_io_write_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL, htic);
|
||||
}
|
||||
|
||||
static unsigned int node_link_to_bus(unsigned int node, unsigned int link)
|
||||
{
|
||||
u8 reg;
|
||||
|
||||
for (reg = 0xE0; reg < 0xF0; reg += 0x04) {
|
||||
u32 config_map;
|
||||
config_map = pci_io_read_config32(PCI_DEV(0, 0x18, 1), reg);
|
||||
if ((config_map & 3) != 3) {
|
||||
continue;
|
||||
}
|
||||
if ((((config_map >> 4) & 7) == node) &&
|
||||
(((config_map >> 8) & 3) == link))
|
||||
{
|
||||
return (config_map >> 16) & 0xff;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int get_sblk(void)
|
||||
{
|
||||
u32 reg;
|
||||
/* read PCI_DEV(0,0x18,0) 0x64 bit [8:9] to find out SbLink m */
|
||||
reg = pci_io_read_config32(PCI_DEV(0, 0x18, 0), 0x64);
|
||||
return ((reg>>8) & 3);
|
||||
}
|
||||
|
||||
unsigned int get_sbbusn(unsigned int sblk)
|
||||
{
|
||||
return node_link_to_bus(0, sblk);
|
||||
}
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef AMDDEFS_H
|
||||
#define AMDDEFS_H
|
||||
|
||||
/* FIXME: this file should be moved to include/cpu/amd/amddefs.h */
|
||||
|
||||
/* Public Revisions - USE THESE VERSIONS TO MAKE COMPARE WITH CPULOGICALID RETURN VALUE*/
|
||||
#define AMD_SAFEMODE 0x8000000000000000 /* Unknown future revision - SAFE MODE */
|
||||
#define AMD_NPT_F0 0x0000000000000001 /* F0 stepping */
|
||||
#define AMD_NPT_F1 0x0000000000000002 /* F1 stepping */
|
||||
#define AMD_NPT_F2C 0x0000000000000004
|
||||
#define AMD_NPT_F2D 0x0000000000000008
|
||||
#define AMD_NPT_F2E 0x0000000000000010 /* F2 stepping E */
|
||||
#define AMD_NPT_F2G 0x0000000000000020 /* F2 stepping G */
|
||||
#define AMD_NPT_F2J 0x0000000000000040
|
||||
#define AMD_NPT_F2K 0x0000000000000080
|
||||
#define AMD_NPT_F3L 0x0000000000000100 /* F3 Stepping */
|
||||
#define AMD_NPT_G0A 0x0000000000000200 /* G0 stepping */
|
||||
#define AMD_NPT_G1B 0x0000000000000400 /* G1 stepping */
|
||||
#define AMD_DR_A0A 0x0000000000010000 /* Barcelona A0 */
|
||||
#define AMD_DR_A1B 0x0000000000020000 /* Barcelona A1 */
|
||||
#define AMD_DR_A2 0x0000000000040000 /* Barcelona A2 */
|
||||
#define AMD_DR_B0 0x0000000000080000 /* Barcelona B0 */
|
||||
#define AMD_DR_B1 0x0000000000100000 /* Barcelona B1 */
|
||||
#define AMD_DR_B2 0x0000000000200000 /* Barcelona B2 */
|
||||
#define AMD_DR_BA 0x0000000000400000 /* Barcelona BA */
|
||||
#define AMD_DR_B3 0x0000000000800000 /* Barcelona B3 */
|
||||
#define AMD_RB_C2 0x0000000001000000 /* Shanghai C2 */
|
||||
#define AMD_DA_C2 0x0000000002000000 /* XXXX C2 */
|
||||
#define AMD_HY_D0 0x0000000004000000 /* Istanbul D0 */
|
||||
#define AMD_RB_C3 0x0000000008000000 /* ??? C3 */
|
||||
#define AMD_DA_C3 0x0000000010000000 /* XXXX C3 */
|
||||
#define AMD_HY_D1 0x0000000020000000 /* Istanbul D1 */
|
||||
#define AMD_PH_E0 0x0000000040000000 /* Phenom II X4 X6 */
|
||||
#define AMD_OR_B2 0x0000000080000000 /* Interlagos */
|
||||
#define AMD_OR_C0 0x0000000100000000 /* Abu Dhabi */
|
||||
|
||||
/*
|
||||
* Groups - Create as many as you wish, from the above public values
|
||||
*/
|
||||
#define AMD_NPT_F2 (AMD_NPT_F2C | AMD_NPT_F2D | AMD_NPT_F2E | AMD_NPT_F2G | AMD_NPT_F2J | AMD_NPT_F2K)
|
||||
#define AMD_NPT_F3 (AMD_NPT_F3L)
|
||||
#define AMD_NPT_Fx (AMD_NPT_F0 | AMD_NPT_F1 | AMD_NPT_F2 | AMD_NPT_F3)
|
||||
#define AMD_NPT_Gx (AMD_NPT_G0A | AMD_NPT_G1B)
|
||||
#define AMD_NPT_ALL (AMD_NPT_Fx | AMD_NPT_Gx)
|
||||
#define AMD_FINEDELAY (AMD_NPT_F0 | AMD_NPT_F1 | AMD_NPT_F2)
|
||||
#define AMD_GT_F0 (AMD_NPT_ALL AND NOT AMD_NPT_F0)
|
||||
#define AMD_DR_Ax (AMD_DR_A0A + AMD_DR_A1B + AMD_DR_A2)
|
||||
#define AMD_DR_Bx (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_B2 | AMD_DR_B3 | AMD_DR_BA)
|
||||
#define AMD_DR_Cx (AMD_RB_C2 | AMD_RB_C3 | AMD_DA_Cx)
|
||||
#define AMD_DR_Dx (AMD_HY_D0 | AMD_HY_D1)
|
||||
#define AMD_DR_Ex (AMD_PH_E0)
|
||||
#define AMD_DR_LT_B2 (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_BA)
|
||||
#define AMD_DR_LT_B3 (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_B2 | AMD_DR_BA)
|
||||
#define AMD_DR_GT_B0 (AMD_DR_ALL & ~(AMD_DR_B0))
|
||||
#define AMD_DR_GT_Bx (AMD_DR_ALL & ~(AMD_DR_Ax | AMD_DR_Bx))
|
||||
#define AMD_DR_GT_D0 ((AMD_DR_Dx & ~(AMD_HY_D0)) | AMD_DR_Ex)
|
||||
#define AMD_DR_ALL (AMD_DR_Ax | AMD_DR_Bx | AMD_DR_Cx | AMD_DR_Dx | AMD_DR_Ex)
|
||||
#define AMD_FAM10_ALL (AMD_DR_ALL | AMD_RB_C2 | AMD_HY_D0 | AMD_DA_C3 | AMD_DA_C2 | AMD_RB_C3 | AMD_HY_D1 | AMD_PH_E0)
|
||||
#define AMD_FAM10_LT_D (AMD_FAM10_ALL & ~(AMD_HY_D0))
|
||||
#define AMD_FAM10_GT_B0 (AMD_FAM10_ALL & ~(AMD_DR_B0))
|
||||
#define AMD_FAM10_REV_D (AMD_HY_D0 | AMD_HY_D1)
|
||||
#define AMD_DA_Cx (AMD_DA_C2 | AMD_DA_C3)
|
||||
#define AMD_FAM10_C3 (AMD_RB_C3 | AMD_DA_C3)
|
||||
#define AMD_DRBH_Cx (AMD_DR_Cx | AMD_HY_D0)
|
||||
#define AMD_DRBA23_RBC2 (AMD_DR_BA | AMD_DR_B2 | AMD_DR_B3 | AMD_RB_C2)
|
||||
#define AMD_DR_DAC2_OR_C3 (AMD_DA_C2 | AMD_DA_C3 | AMD_RB_C3)
|
||||
#define AMD_FAM15_ALL (AMD_OR_B2 | AMD_OR_C0)
|
||||
|
||||
/*
|
||||
* Public Platforms - USE THESE VERSIONS TO MAKE COMPARE WITH CPUPLATFORMTYPE RETURN VALUE
|
||||
*/
|
||||
#define AMD_PTYPE_DSK 0x001 /* Desktop/DTR/UP */
|
||||
#define AMD_PTYPE_MOB 0x002 /* Mobile/Cool-n-quiet */
|
||||
#define AMD_PTYPE_SVR 0x004 /* Workstation/Server/Multicore DT */
|
||||
#define AMD_PTYPE_UC 0x008 /* Single Core */
|
||||
#define AMD_PTYPE_DC 0x010 /* Dual Core */
|
||||
#define AMD_PTYPE_MC 0x020 /* Multi Core (>2) */
|
||||
#define AMD_PTYPE_UMA 0x040 /* UMA required */
|
||||
|
||||
/*
|
||||
* Groups - Create as many as you wish, from the above public values
|
||||
*/
|
||||
#define AMD_PTYPE_ALL 0xFFFFFFFF /* A mask for all */
|
||||
|
||||
|
||||
/*
|
||||
* CPU PCI HT PHY REGISTER, LINK TYPES - PRIVATE
|
||||
*/
|
||||
#define HTPHY_LINKTYPE_HT3 0x00000001
|
||||
#define HTPHY_LINKTYPE_HT1 0x00000002
|
||||
#define HTPHY_LINKTYPE_COHERENT 0x00000004
|
||||
#define HTPHY_LINKTYPE_NONCOHERENT 0x00000008
|
||||
#define HTPHY_LINKTYPE_CONNECTED (HTPHY_LINKTYPE_COHERENT | HTPHY_LINKTYPE_NONCOHERENT)
|
||||
#define HTPHY_LINKTYPE_GANGED 0x00000010
|
||||
#define HTPHY_LINKTYPE_UNGANGED 0x00000020
|
||||
#define HTPHY_LINKTYPE_ALL 0x7FFFFFFF
|
||||
|
||||
|
||||
/*
|
||||
* CPU HT PHY REGISTERS, FIELDS, AND MASKS
|
||||
*/
|
||||
#define HTPHY_OFFSET_MASK 0xE000FFFF
|
||||
#define HTPHY_WRITE_CMD 0x40000000
|
||||
#define HTPHY_IS_COMPLETE_MASK 0x80000000
|
||||
#define HTPHY_DIRECT_MAP 0x20000000
|
||||
#define HTPHY_DIRECT_OFFSET_MASK 0xE000FFFF
|
||||
|
||||
/*
|
||||
* Processor package types
|
||||
*/
|
||||
#define AMD_PKGTYPE_FrX_1207 0
|
||||
#define AMD_PKGTYPE_AM3_2r2 1
|
||||
#define AMD_PKGTYPE_S1gX 2
|
||||
#define AMD_PKGTYPE_G34 3
|
||||
#define AMD_PKGTYPE_ASB2 4
|
||||
#define AMD_PKGTYPE_C32 5
|
||||
#define AMD_PKGTYPE_FM2 6
|
||||
|
||||
//DDR2 REG and unbuffered : Socket F 1027 and AM3
|
||||
/* every channel have 4 DDR2 DIMM for socket F
|
||||
* 2 for socket M2/M3
|
||||
* 1 for socket s1g1
|
||||
*/
|
||||
#define DIMM_SOCKETS 4
|
||||
struct mem_controller {
|
||||
u32 node_id;
|
||||
pci_devfn_t f0, f1, f2, f3, f4, f5;
|
||||
/* channel0 is DCT0 --- channelA
|
||||
* channel1 is DCT1 --- channelB
|
||||
* can be ganged, a single dual-channel DCT ---> 128 bit
|
||||
* or unganged a two single-channel DCTs ---> 64bit
|
||||
* When the DCTs are ganged, the writes to DCT1 set of registers
|
||||
* (F2x1XX) are ignored and reads return all 0's
|
||||
* The exception is the DCT phy registers, F2x[1,0]98, F2x[1,0]9C,
|
||||
* and all the associated indexed registers, are still
|
||||
* independently accessiable
|
||||
*/
|
||||
/* FIXME: I will only support ganged mode for easy support */
|
||||
u8 spd_switch_addr;
|
||||
u8 spd_addr[DIMM_SOCKETS*2];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
ifeq ($(CONFIG_NORTHBRIDGE_AMD_AMDFAM10),y)
|
||||
|
||||
# DDR2
|
||||
romstage-y += mct_d.c mct_d_gcc.c mctcsi_d.c mctmtr_d.c mctecc_d.c
|
||||
romstage-y += mctpro_d.c mctdqs_d.c mctsrc.c mctsrc1p.c mcttmrl.c
|
||||
romstage-y += mcthdi.c mctndi_d.c mctchi_d.c
|
||||
|
||||
ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x10)
|
||||
romstage-y += mctardk3.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x11)
|
||||
romstage-y += mctardk4.c
|
||||
endif
|
||||
|
||||
endif
|
||||
|
|
@ -1,539 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MCT_H
|
||||
#define MCT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*===========================================================================
|
||||
CPU - K8/FAM10
|
||||
===========================================================================*/
|
||||
#define PT_L1 0 /* CPU Package Type*/
|
||||
#define PT_M2 1
|
||||
#define PT_S1 2
|
||||
|
||||
#define J_MIN 0 /* j loop constraint. 1 = CL 2.0 T*/
|
||||
#define J_MAX 4 /* j loop constraint. 4 = CL 6.0 T*/
|
||||
#define K_MIN 1 /* k loop constraint. 1 = 200 MHz*/
|
||||
#define K_MAX 4 /* k loop constraint. 9 = 400 MHz*/
|
||||
#define CL_DEF 2 /* Default value for failsafe operation. 2 = CL 4.0 T*/
|
||||
#define T_DEF 1 /* Default value for failsafe operation. 1 = 5ns (cycle time)*/
|
||||
|
||||
#define BSCRate 1 /* reg bit field = rate of dram scrubber for ecc*/
|
||||
/* memory initialization (ecc and check-bits).*/
|
||||
/* 1 = 40 ns/64 bytes.*/
|
||||
#define FirstPass 1 /* First pass through RcvEn training*/
|
||||
#define SecondPass 2 /* Second pass through Rcven training*/
|
||||
|
||||
#define RCVREN_MARGIN 6 /* number of DLL taps to delay beyond first passing position*/
|
||||
#define MAXASYNCLATCTL_3 60 /* Max Async Latency Control value (This value will be divided by 20)*/
|
||||
#define DQS_FAIL 1
|
||||
#define DQS_PASS 0
|
||||
#define DQS_WRITEDIR 0
|
||||
#define DQS_READDIR 1
|
||||
#define MIN_DQS_WNDW 3
|
||||
#define secPassOffset 6
|
||||
|
||||
#define PA_HOST (((24 << 3)+0) << 8) /* Node 0 Host Bus function PCI Address bits [15:0] */
|
||||
#define PA_MAP (((24 << 3)+1) << 8) /* Node 0 MAP function PCI Address bits [15:0] */
|
||||
#define PA_DCT (((24 << 3)+2) << 8) /* Node 0 DCT function PCI Address bits [15:0] */
|
||||
#define PA_DCTADDL (((00 << 3)+2) << 8) /* Node x DCT function, Additional Registers PCI Address bits [15:0] */
|
||||
#define PA_NBMISC (((24 << 3)+3) << 8) /* Node 0 Misc PCI Address bits [15:0] */
|
||||
#define PA_NBDEVOP (((00 << 3)+3) << 8) /* Node 0 Misc PCI Address bits [15:0] */
|
||||
|
||||
#define DCC_EN 1 /* X:2:0x94[19]*/
|
||||
#define ILD_Lmt 3 /* X:2:0x94[18:16]*/
|
||||
|
||||
#define EncodedTSPD 0x00191709 /* encodes which SPD byte to get T from*/
|
||||
/* versus CL X, CL X-.5, and CL X-1*/
|
||||
|
||||
#define Bias_TrpT 3 /* bias to convert bus clocks to bit field value*/
|
||||
#define Bias_TrrdT 2
|
||||
#define Bias_TrcdT 3
|
||||
#define Bias_TrasT 3
|
||||
#define Bias_TrcT 11
|
||||
#define Bias_TrtpT 4
|
||||
#define Bias_TwrT 3
|
||||
#define Bias_TwtrT 0
|
||||
|
||||
#define Min_TrpT 3 /* min programmable value in busclocks*/
|
||||
#define Max_TrpT 6 /* max programmable value in busclocks*/
|
||||
#define Min_TrrdT 2
|
||||
#define Max_TrrdT 5
|
||||
#define Min_TrcdT 3
|
||||
#define Max_TrcdT 6
|
||||
#define Min_TrasT 5
|
||||
#define Max_TrasT 18
|
||||
#define Min_TrcT 11
|
||||
#define Max_TrcT 26
|
||||
#define Min_TrtpT 4
|
||||
#define Max_TrtpT 5
|
||||
#define Min_TwrT 3
|
||||
#define Max_TwrT 6
|
||||
#define Min_TwtrT 1
|
||||
#define Max_TwtrT 3
|
||||
|
||||
/* common register bit names */
|
||||
#define DramHoleValid 0 /* func 1, offset F0h, bit 0 */
|
||||
#define CSEnable 0 /* func 2, offset 40h-5C, bit 0 */
|
||||
#define Spare 1 /* func 2, offset 40h-5C, bit 1 */
|
||||
#define TestFail 2 /* func 2, offset 40h-5C, bit 2 */
|
||||
#define DqsRcvEnTrain 18 /* func 2, offset 78h, bit 18 */
|
||||
#define EnDramInit 31 /* func 2, offset 7Ch, bit 31 */
|
||||
#define DisAutoRefresh 18 /* func 2, offset 8Ch, bit 18 */
|
||||
#define InitDram 0 /* func 2, offset 90h, bit 0 */
|
||||
#define BurstLength32 10 /* func 2, offset 90h, bit 10 */
|
||||
#define Width128 11 /* func 2, offset 90h, bit 11 */
|
||||
#define X4Dimm 12 /* func 2, offset 90h, bit 12 */
|
||||
#define UnBuffDimm 16 /* func 2, offset 90h, bit 16 */
|
||||
#define DimmEcEn 19 /* func 2, offset 90h, bit 19 */
|
||||
#define MemClkFreqVal 3 /* func 2, offset 94h, bit 3 */
|
||||
#define RDqsEn 12 /* func 2, offset 94h, bit 12 */
|
||||
#define DisDramInterface 14 /* func 2, offset 94h, bit 14 */
|
||||
#define DctAccessWrite 30 /* func 2, offset 98h, bit 30 */
|
||||
#define DctAccessDone 31 /* func 2, offset 98h, bit 31 */
|
||||
#define PwrSavingsEn 10 /* func 2, offset A0h, bit 10 */
|
||||
#define Mod64BitMux 4 /* func 2, offset A0h, bit 4 */
|
||||
#define DisableJitter 1 /* func 2, offset A0h, bit 1 */
|
||||
#define DramEnabled 9 /* func 2, offset A0h, bit 9 */
|
||||
#define SyncOnUcEccEn 2 /* func 3, offset 44h, bit 2 */
|
||||
|
||||
/*=============================================================================
|
||||
Jedec DDR II
|
||||
=============================================================================*/
|
||||
#define SPD_TYPE 2 /* SPD byte read location*/
|
||||
#define JED_DDRSDRAM 0x07 /* Jedec defined bit field*/
|
||||
#define JED_DDR2SDRAM 0x08 /* Jedec defined bit field*/
|
||||
|
||||
#define SPD_DIMMTYPE 20
|
||||
#define SPD_ATTRIB 21
|
||||
#define JED_DIFCKMSK 0x20 /* Differential Clock Input*/
|
||||
#define JED_REGADCMSK 0x11 /* Registered Address/Control*/
|
||||
#define JED_PROBEMSK 0x40 /* Analysis Probe installed*/
|
||||
#define SPD_DEVATTRIB 22
|
||||
#define SPD_EDCTYPE 11
|
||||
#define JED_ECC 0x02
|
||||
#define JED_ADRCPAR 0x04
|
||||
#define SPD_ROWSZ 3
|
||||
#define SPD_COLSZ 4
|
||||
#define SPD_LBANKS 17 /* number of [logical] banks on each device*/
|
||||
#define SPD_DMBANKS 5 /* number of physical banks on dimm*/
|
||||
#define SPDPLBit 4 /* Dram package bit*/
|
||||
#define SPD_BANKSZ 31 /* capacity of physical bank*/
|
||||
#define SPD_DEVWIDTH 13
|
||||
#define SPD_CASLAT 18
|
||||
#define SPD_TRP 27
|
||||
#define SPD_TRRD 28
|
||||
#define SPD_TRCD 29
|
||||
#define SPD_TRAS 30
|
||||
#define SPD_TWR 36
|
||||
#define SPD_TWTR 37
|
||||
#define SPD_TRTP 38
|
||||
#define SPD_TRCRFC 40
|
||||
#define SPD_TRC 41
|
||||
#define SPD_TRFC 42
|
||||
|
||||
#define SPD_MANDATEYR 93 /* Module Manufacturing Year (BCD) */
|
||||
|
||||
#define SPD_MANDATEWK 94 /* Module Manufacturing Week (BCD) */
|
||||
|
||||
/*--------------------------------------
|
||||
Jedec DDR II related equates
|
||||
--------------------------------------*/
|
||||
#define MYEAR06 6 /* Manufacturing Year BCD encoding of 2006 - 06d*/
|
||||
#define MWEEK24 0x24 /* Manufacturing Week BCD encoding of June - 24d*/
|
||||
|
||||
/*=============================================================================
|
||||
Macros
|
||||
=============================================================================*/
|
||||
|
||||
#define _2GB_RJ8 (2<<(30-8))
|
||||
#define _4GB_RJ8 (4<<(30-8))
|
||||
#define _4GB_RJ4 (4<<(30-4))
|
||||
|
||||
#define BigPagex8_RJ8 (1<<(17+3-8)) /* 128KB * 8 >> 8 */
|
||||
|
||||
/*=============================================================================
|
||||
Global MCT Status Structure
|
||||
=============================================================================*/
|
||||
struct MCTStatStruc {
|
||||
u32 GStatus; /* Global Status bitfield*/
|
||||
u32 HoleBase; /* If not zero, BASE[39:8] (system address)
|
||||
of sub 4GB dram hole for HW remapping.*/
|
||||
u32 Sub4GCacheTop; /* If not zero, the 32-bit top of cacheable memory.*/
|
||||
u32 SysLimit; /* LIMIT[39:8] (system address)*/
|
||||
};
|
||||
/*=============================================================================
|
||||
Global MCT Configuration Status Word (GStatus)
|
||||
=============================================================================*/
|
||||
/*These should begin at bit 0 of GStatus[31:0]*/
|
||||
#define GSB_MTRRshort 0 /* Ran out of MTRRs while mapping memory*/
|
||||
#define GSB_ECCDIMMs 1 /* All banks of all Nodes are ECC capable*/
|
||||
#define GSB_DramECCDis 2 /* Dram ECC requested but not enabled.*/
|
||||
#define GSB_SoftHole 3 /* A Node Base gap was created*/
|
||||
#define GSB_HWHole 4 /* A HW dram remap was created*/
|
||||
#define GSB_NodeIntlv 5 /* Node Memory interleaving was enabled*/
|
||||
#define GSB_SpIntRemapHole 16 /* Special condition for Node Interleave and HW remapping*/
|
||||
|
||||
|
||||
/*===============================================================================
|
||||
Local DCT Status structure (a structure for each DCT)
|
||||
===============================================================================*/
|
||||
|
||||
struct DCTStatStruc { /* A per Node structure*/
|
||||
u8 Node_ID; /* Node ID of current controller*/
|
||||
u8 ErrCode; /* Current error condition of Node
|
||||
0= no error
|
||||
1= Variance Error, DCT is running but not in an optimal configuration.
|
||||
2= Stop Error, DCT is NOT running
|
||||
3= Fatal Error, DCT/MCT initialization has been halted.*/
|
||||
u32 ErrStatus; /* Error Status bit Field */
|
||||
u32 Status; /* Status bit Field*/
|
||||
u8 DIMMAddr[8]; /* SPD address of DIMM controlled by MA0_CS_L[0,1]*/
|
||||
/* SPD address of..MB0_CS_L[0,1]*/
|
||||
/* SPD address of..MA1_CS_L[0,1]*/
|
||||
/* SPD address of..MB1_CS_L[0,1]*/
|
||||
/* SPD address of..MA2_CS_L[0,1]*/
|
||||
/* SPD address of..MB2_CS_L[0,1]*/
|
||||
/* SPD address of..MA3_CS_L[0,1]*/
|
||||
/* SPD address of..MB3_CS_L[0,1]*/
|
||||
u16 DIMMPresent; /* For each bit n 0..7, 1 = DIMM n is present.
|
||||
DIMM# Select Signal
|
||||
0 MA0_CS_L[0,1]
|
||||
1 MB0_CS_L[0,1]
|
||||
2 MA1_CS_L[0,1]
|
||||
3 MB1_CS_L[0,1]
|
||||
4 MA2_CS_L[0,1]
|
||||
5 MB2_CS_L[0,1]
|
||||
6 MA3_CS_L[0,1]
|
||||
7 MB3_CS_L[0,1]*/
|
||||
u16 DIMMValid; /* For each bit n 0..7, 1 = DIMM n is valid and is/will be configured*/
|
||||
u16 DIMMSPDCSE; /* For each bit n 0..7, 1 = DIMM n SPD checksum error*/
|
||||
u16 DimmECCPresent; /* For each bit n 0..7, 1 = DIMM n is ECC capable.*/
|
||||
u16 DimmPARPresent; /* For each bit n 0..7, 1 = DIMM n is ADR/CMD Parity capable.*/
|
||||
u16 Dimmx4Present; /* For each bit n 0..7, 1 = DIMM n contains x4 data devices.*/
|
||||
u16 Dimmx8Present; /* For each bit n 0..7, 1 = DIMM n contains x8 data devices.*/
|
||||
u16 Dimmx16Present; /* For each bit n 0..7, 1 = DIMM n contains x16 data devices.*/
|
||||
u16 DIMM1Kpage; /* For each bit n 0..7, 1 = DIMM n contains 1K page devices.*/
|
||||
u8 MAload[2]; /* Number of devices loading MAA bus*/
|
||||
/* Number of devices loading MAB bus*/
|
||||
u8 MAdimms[2]; /* Number of DIMMs loading CH A*/
|
||||
/* Number of DIMMs loading CH B*/
|
||||
u8 DATAload[2]; /* Number of ranks loading CH A DATA*/
|
||||
/* Number of ranks loading CH B DATA*/
|
||||
u8 DIMMAutoSpeed; /* Max valid Mfg. Speed of DIMMs
|
||||
1 = 200MHz
|
||||
2 = 266MHz
|
||||
3 = 333MHz
|
||||
4 = 400MHz */
|
||||
u8 DIMMCASL; /* Min valid Mfg. CL bitfield
|
||||
0 = 2.0
|
||||
1 = 3.0
|
||||
2 = 4.0
|
||||
3 = 5.0
|
||||
4 = 6.0 */
|
||||
u16 DIMMTrcd; /* Minimax Trcd*40 (ns) of DIMMs*/
|
||||
u16 DIMMTrp; /* Minimax Trp*40 (ns) of DIMMs*/
|
||||
u16 DIMMTrtp; /* Minimax Trtp*40 (ns) of DIMMs*/
|
||||
u16 DIMMTras; /* Minimax Tras*40 (ns) of DIMMs*/
|
||||
u16 DIMMTrc; /* Minimax Trc*40 (ns) of DIMMs*/
|
||||
u16 DIMMTwr; /* Minimax Twr*40 (ns) of DIMMs*/
|
||||
u16 DIMMTrrd; /* Minimax Trrd*40 (ns) of DIMMs*/
|
||||
u16 DIMMTwtr; /* Minimax Twtr*40 (ns) of DIMMs*/
|
||||
u8 Speed; /* Bus Speed (to set Controller)
|
||||
1 = 200MHz
|
||||
2 = 266MHz
|
||||
3 = 333MHz
|
||||
4 = 400MHz */
|
||||
u8 CASL; /* CAS latency DCT setting
|
||||
0 = 2.0
|
||||
1 = 3.0
|
||||
2 = 4.0
|
||||
3 = 5.0
|
||||
4 = 6.0 */
|
||||
u8 Trcd; /* DCT Trcd (busclocks) */
|
||||
u8 Trp; /* DCT Trp (busclocks) */
|
||||
u8 Trtp; /* DCT Trtp (busclocks) */
|
||||
u8 Tras; /* DCT Tras (busclocks) */
|
||||
u8 Trc; /* DCT Trc (busclocks) */
|
||||
u8 Twr; /* DCT Twr (busclocks) */
|
||||
u8 Trrd; /* DCT Trrd (busclocks) */
|
||||
u8 Twtr; /* DCT Twtr (busclocks) */
|
||||
u8 Trfc[4]; /* DCT Logical DIMM0 Trfc
|
||||
0 = 75ns (for 256Mb devs)
|
||||
1 = 105ns (for 512Mb devs)
|
||||
2 = 127.5ns (for 1Gb devs)
|
||||
3 = 195ns (for 2Gb devs)
|
||||
4 = 327.5ns (for 4Gb devs) */
|
||||
/* DCT Logical DIMM1 Trfc (see Trfc0 for format) */
|
||||
/* DCT Logical DIMM2 Trfc (see Trfc0 for format) */
|
||||
/* DCT Logical DIMM3 Trfc (see Trfc0 for format) */
|
||||
u16 CSPresent; /* For each bit n 0..7, 1 = Chip-select n is present */
|
||||
u16 CSTestFail; /* For each bit n 0..7, 1 = Chip-select n is present but disabled */
|
||||
u32 DCTSysBase; /* BASE[39:8] (system address) of this Node's DCTs. */
|
||||
u32 DCTHoleBase; /* If not zero, BASE[39:8] (system address) of dram hole for HW remapping. Dram hole exists on this Node's DCTs. */
|
||||
u32 DCTSysLimit; /* LIMIT[39:8] (system address) of this Node's DCTs */
|
||||
u16 PresetmaxFreq; /* Maximum OEM defined DDR frequency
|
||||
200 = 200MHz (DDR400)
|
||||
266 = 266MHz (DDR533)
|
||||
333 = 333MHz (DDR667)
|
||||
400 = 400MHz (DDR800) */
|
||||
u8 _2Tmode; /* 1T or 2T CMD mode (slow access mode)
|
||||
1 = 1T
|
||||
2 = 2T */
|
||||
u8 TrwtTO; /* DCT TrwtTO (busclocks)*/
|
||||
u8 Twrrd; /* DCT Twrrd (busclocks)*/
|
||||
u8 Twrwr; /* DCT Twrwr (busclocks)*/
|
||||
u8 Trdrd; /* DCT Trdrd (busclocks)*/
|
||||
u32 CH_ODC_CTL[2]; /* Output Driver Strength (see BKDG FN2:Offset 9Ch, index 00h*/
|
||||
u32 CH_ADDR_TMG[2]; /* Address Bus Timing (see BKDG FN2:Offset 9Ch, index 04h*/
|
||||
/* Output Driver Strength (see BKDG FN2:Offset 9Ch, index 20h*/
|
||||
/* Address Bus Timing (see BKDG FN2:Offset 9Ch, index 24h*/
|
||||
u16 CH_EccDQSLike[2]; /* CHA DQS ECC byte like...*/
|
||||
u8 CH_EccDQSScale[2]; /* CHA DQS ECC byte scale*/
|
||||
// u8 reserved_b_1; /* Reserved*/
|
||||
/* CHB DQS ECC byte like...*/
|
||||
/* CHB DQS ECC byte scale*/
|
||||
// u8 reserved_b_2; /*Reserved*/
|
||||
u8 MaxAsyncLat; /* Max Asynchronous Latency (ns)*/
|
||||
u8 CH_B_DQS[2][2][9]; /* CHA Byte 0 - 7 and Check Write DQS Delay*/
|
||||
/* Reserved*/
|
||||
/* CHA Byte 0 - 7 and Check Read DQS Delay*/
|
||||
/* Reserved*/
|
||||
/* CHB Byte 0 - 7 and Check Write DQS Delay*/
|
||||
/* Reserved*/
|
||||
/* CHB Byte 0 - 7 and Check Read DQS Delay*/
|
||||
/* Reserved*/
|
||||
u8 CH_D_RCVRDLY[2][4]; /* CHA DIMM 0 - 3 Receiver Enable Delay*/
|
||||
/* CHB DIMM 0 - 3 Receiver Enable Delay*/
|
||||
u32 PtrPatternBufA; /* Ptr on stack to aligned DQS testing pattern*/
|
||||
u32 PtrPatternBufB; /*Ptr on stack to aligned DQS testing pattern*/
|
||||
u8 Channel; /* Current Channel (0= CH A, 1 = CH B)*/
|
||||
u8 ByteLane; /* Current Byte Lane (0..7)*/
|
||||
u8 Direction; /* Current DQS-DQ training write direction (0 = read, 1 = write)*/
|
||||
u8 Pattern; /* Current pattern*/
|
||||
u8 DQSDelay; /* Current DQS delay value*/
|
||||
u32 TrainErrors; /* Current Training Errors*/
|
||||
// u8 reserved_b_3; /* RSVD */
|
||||
u32 AMC_TSC_DeltaLo; /* Time Stamp Counter measurement of AMC, Low dword*/
|
||||
u32 AMC_TSC_DeltaHi; /* Time Stamp Counter measurement of AMC, High dword*/
|
||||
u8 CH_B_Dly[2][2][2][8]; /* CH A byte lane 0 - 7 minimum filtered window passing DQS delay value*/
|
||||
/* CH A byte lane 0 - 7 maximum filtered window passing DQS delay value*/
|
||||
/* CH B byte lane 0 - 7 minimum filtered window passing DQS delay value*/
|
||||
/* CH B byte lane 0 - 7 maximum filtered window passing DQS delay value*/
|
||||
/* CH A byte lane 0 - 7 minimum filtered window passing DQS delay value*/
|
||||
/* CH A byte lane 0 - 7 maximum filtered window passing DQS delay value*/
|
||||
/* CH B byte lane 0 - 7 minimum filtered window passing DQS delay value*/
|
||||
/* CH B byte lane 0 - 7 maximum filtered window passing DQS delay value*/
|
||||
u32 LogicalCPUID; /* The logical CPUID of the node*/
|
||||
u16 HostBiosSrvc1; /* Word sized general purpose field for use by host BIOS. Scratch space.*/
|
||||
u32 HostBiosSrvc2; /* Dword sized general purpose field for use by host BIOS. Scratch space.*/
|
||||
u16 DimmQRPresent; /* QuadRank DIMM present?*/
|
||||
u16 DimmTrainFail; /* Bitmap showing which dimms failed training*/
|
||||
u16 CSTrainFail; /* Bitmap showing which chipselects failed training*/
|
||||
u16 DimmYr06; /* Bitmap indicating which Dimms have a manufactur's year code <= 2006*/
|
||||
u16 DimmWk2406; /* Bitmap indicating which Dimms have a manufactur's week code <= 24 of 2006 (June)*/
|
||||
u16 DimmDRPresent; /* Bitmap indicating that Dual Rank Dimms are present*/
|
||||
u16 DimmPlPresent; /* Bitmap indicating that Planar (1) or Stacked (0) Dimms are present.*/
|
||||
u16 ChannelTrainFail; /* Bitmap showing the channel information about failed Chip Selects*/
|
||||
/* 0 in any bit field indicates Channel 0*/
|
||||
/* 1 in any bit field indicates Channel 1*/
|
||||
};
|
||||
|
||||
/*===============================================================================
|
||||
Local Error Status Codes (DCTStatStruc.ErrCode)
|
||||
===============================================================================*/
|
||||
#define SC_RunningOK 0
|
||||
#define SC_VarianceErr 1 /* Running non-optimally*/
|
||||
#define SC_StopError 2 /* Not Running*/
|
||||
#define SC_FatalErr 3 /* Fatal Error, MCTB has exited immediately*/
|
||||
|
||||
/*===============================================================================
|
||||
Local Error Status (DCTStatStruc.ErrStatus[31:0])
|
||||
===============================================================================*/
|
||||
#define SB_NoDimms 0
|
||||
#define SB_DIMMChkSum 1
|
||||
#define SB_DimmMismatchM 2 /* dimm module type(buffer) mismatch*/
|
||||
#define SB_DimmMismatchT 3 /* dimm CL/T mismatch*/
|
||||
#define SB_DimmMismatchO 4 /* dimm organization mismatch (128-bit)*/
|
||||
#define SB_NoTrcTrfc 5 /* SPD missing Trc or Trfc info*/
|
||||
#define SB_NoCycTime 6 /* SPD missing byte 23 or 25*/
|
||||
#define SB_BkIntDis 7 /* Bank interleave requested but not enabled*/
|
||||
#define SB_DramECCDis 8 /* Dram ECC requested but not enabled*/
|
||||
#define SB_SpareDis 9 /* Online spare requested but not enabled*/
|
||||
#define SB_MinimumMode 10 /* Running in Minimum Mode*/
|
||||
#define SB_NORCVREN 11 /* No DQS Receiver Enable pass window found*/
|
||||
#define SB_CHA2BRCVREN 12 /* DQS Rcvr En pass window CHA to CH B too large*/
|
||||
#define SB_SmallRCVR 13 /* DQS Rcvr En pass window too small (far right of dynamic range)*/
|
||||
#define SB_NODQSPOS 14 /* No DQS-DQ passing positions*/
|
||||
#define SB_SMALLDQS 15 /* DQS-DQ passing window too small*/
|
||||
|
||||
/*===============================================================================
|
||||
Local Configuration Status (DCTStatStruc.Status[31:0])
|
||||
===============================================================================*/
|
||||
#define SB_Registered 0 /* All DIMMs are Registered*/
|
||||
#define SB_ECCDIMMs 1 /* All banks ECC capable*/
|
||||
#define SB_PARDIMMs 2 /* All banks Addr/CMD Parity capable*/
|
||||
#define SB_DiagClks 3 /* Jedec ALL slots clock enable diag mode*/
|
||||
#define SB_128bitmode 4 /* DCT in 128-bit mode operation*/
|
||||
#define SB_64MuxedMode 5 /* DCT in 64-bit mux'ed mode.*/
|
||||
#define SB_2TMode 6 /* 2T CMD timing mode is enabled.*/
|
||||
#define SB_SWNodeHole 7 /* Remapping of Node Base on this Node to create a gap.*/
|
||||
#define SB_HWHole 8 /* Memory Hole created on this Node using HW remapping.*/
|
||||
|
||||
|
||||
|
||||
/*===============================================================================
|
||||
NVRAM/run-time-configurable Items
|
||||
===============================================================================*/
|
||||
/* Platform Configuration */
|
||||
#define NV_PACK_TYPE 0 /* CPU Package Type (2-bits)
|
||||
0 = NPT L1
|
||||
1 = NPT M2
|
||||
2 = NPT S1*/
|
||||
#define NV_MAX_NODES 1 /* Number of Nodes/Sockets (4-bits)*/
|
||||
#define NV_MAX_DIMMS 2 /* Number of DIMM slots for the specified Node ID (4-bits)*/
|
||||
#define NV_MAX_MEMCLK 3 /* Maximum platform demonstrated Memclock (10-bits)
|
||||
200 = 200MHz (DDR400)
|
||||
266 = 266MHz (DDR533)
|
||||
333 = 333MHz (DDR667)
|
||||
400 = 400MHz (DDR800)*/
|
||||
#define NV_ECC_CAP 4 /* Bus ECC capable (1-bits)
|
||||
0 = Platform not capable
|
||||
1 = Platform is capable*/
|
||||
#define NV_4RANKType 5 /* Quad Rank DIMM slot type (2-bits)
|
||||
0 = Normal
|
||||
1 = R4 (4-Rank Registered DIMMs in AMD server configuration)
|
||||
2 = S4 (Unbuffered SO-DIMMs)*/
|
||||
#define NV_BYPMAX 6 /* Value to set DcqBypassMax field (See Function 2, Offset 94h, [27:24] of BKDG for field definition).
|
||||
4 = 4 times bypass (normal for non-UMA systems)
|
||||
7 = 7 times bypass (normal for UMA systems)*/
|
||||
#define NV_RDWRQBYP 7 /* Value to set RdWrQByp field (See Function 2, Offset A0h, [3:2] of BKDG for field definition).
|
||||
2 = 8 times (normal for non-UMA systems)
|
||||
3 = 16 times (normal for UMA systems)*/
|
||||
|
||||
|
||||
/* Dram Timing */
|
||||
#define NV_MCTUSRTMGMODE 10 /* User Memclock Mode (2-bits)
|
||||
0 = Auto, no user limit
|
||||
1 = Auto, user limit provided in NV_MemCkVal
|
||||
2 = Manual, user value provided in NV_MemCkVal*/
|
||||
#define NV_MemCkVal 11 /* Memory Clock Value (2-bits)
|
||||
0 = 200MHz
|
||||
1 = 266MHz
|
||||
2 = 333MHz
|
||||
3 = 400MHz*/
|
||||
|
||||
/* Dram Configuration */
|
||||
#define NV_BankIntlv 20 /* Dram Bank (chip-select) Interleaving (1-bits)
|
||||
0 = disable
|
||||
1 = enable*/
|
||||
#define NV_AllMemClks 21 /* Turn on All DIMM clocks (1-bits)
|
||||
0 = normal
|
||||
1 = enable all memclocks*/
|
||||
#define NV_SPDCHK_RESTRT 22 /* SPD Check control bitmap (1-bits)
|
||||
0 = Exit current node init if any DIMM has SPD checksum error
|
||||
1 = Ignore faulty SPD checksums (Note: DIMM cannot be enabled)*/
|
||||
#define NV_DQSTrainCTL 23 /* DQS Signal Timing Training Control
|
||||
0 = skip DQS training
|
||||
1 = perform DQS training*/
|
||||
#define NV_NodeIntlv 24 /* Node Memory Interleaving (1-bits)
|
||||
0 = disable
|
||||
1 = enable*/
|
||||
#define NV_BurstLen32 25 /* burstLength32 for 64-bit mode (1-bits)
|
||||
0 = disable (normal)
|
||||
1 = enable (4 beat burst when width is 64-bits)*/
|
||||
|
||||
/* Dram Power */
|
||||
#define NV_CKE_PDEN 30 /* CKE based power down mode (1-bits)
|
||||
0 = disable
|
||||
1 = enable*/
|
||||
#define NV_CKE_CTL 31 /* CKE based power down control (1-bits)
|
||||
0 = per Channel control
|
||||
1 = per Chip select control*/
|
||||
#define NV_CLKHZAltVidC3 32 /* Memclock tri-stating during C3 and Alt VID (1-bits)
|
||||
0 = disable
|
||||
1 = enable*/
|
||||
|
||||
/* Memory Map/Mgt.*/
|
||||
#define NV_BottomIO 40 /* Bottom of 32-bit IO space (8-bits)
|
||||
NV_BottomIO[7:0]=Addr[31:24]*/
|
||||
#define NV_BottomUMA 41 /* Bottom of shared graphics dram (8-bits)
|
||||
NV_BottomUMA[7:0]=Addr[31:24]*/
|
||||
#define NV_MemHole 42 /* Memory Hole Remapping (1-bits)
|
||||
0 = disable
|
||||
1 = enable */
|
||||
|
||||
/* ECC */
|
||||
#define NV_ECC 50 /* Dram ECC enable*/
|
||||
#define NV_NBECC 52 /* ECC MCE enable*/
|
||||
#define NV_ChipKill 53 /* Chip-Kill ECC Mode enable*/
|
||||
#define NV_ECCRedir 54 /* Dram ECC Redirection enable*/
|
||||
#define NV_DramBKScrub 55 /* Dram ECC Background Scrubber CTL*/
|
||||
#define NV_L2BKScrub 56 /* L2 ECC Background Scrubber CTL*/
|
||||
#define NV_DCBKScrub 57 /* DCache ECC Background Scrubber CTL*/
|
||||
#define NV_CS_SpareCTL 58 /* Chip Select Spare Control bit 0:
|
||||
0 = disable Spare
|
||||
1 = enable Spare */
|
||||
/*Chip Select Spare Control bit 1-4:
|
||||
Reserved, must be zero*/
|
||||
#define NV_Parity 60 /* Parity Enable*/
|
||||
#define NV_SyncOnUnEccEn 61 /* SyncOnUnEccEn control
|
||||
0 = disable
|
||||
1 = enable*/
|
||||
|
||||
|
||||
/* global function */
|
||||
u32 NodePresent(u32 Node);
|
||||
u32 Get_NB32n(struct DCTStatStruc *pDCTstat, u32 addrx);
|
||||
u32 Get_NB32(u32 addr); /* NOTE: extend addr to 32 bit for bus > 0 */
|
||||
uint64_t mctGetLogicalCPUID(u32 Node);
|
||||
|
||||
void K8FInterleaveBanks(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
|
||||
|
||||
void mctInitWithWritetoCS(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
|
||||
|
||||
void mctGet_PS_Cfg(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
|
||||
void Get_ChannelPS_Cfg0(unsigned int MAAdimms, unsigned int Speed, unsigned int MAAload, unsigned int DATAAload,
|
||||
unsigned int *AddrTmgCTL, unsigned int *ODC_CTL);
|
||||
void Get_ChannelPS_Cfg1(unsigned int MAAdimms, unsigned int Speed, unsigned int MAAload,
|
||||
unsigned int *AddrTmgCTL, unsigned int *ODC_CTL, unsigned int *val);
|
||||
void Get_ChannelPS_Cfg2(unsigned int MAAdimms, unsigned int Speed, unsigned int MAAload,
|
||||
unsigned int *AddrTmgCTL, unsigned int *ODC_CTL, unsigned int *val);
|
||||
|
||||
u8 MCTDefRet(void);
|
||||
|
||||
u32 Get_RcvrSysAddr(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 channel, u8 receiver, u8 *valid);
|
||||
u32 Get_MCTSysAddr(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 channel, u8 chipsel, u8 *valid);
|
||||
void K8FTrainReceiverEn(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA, u8 pass);
|
||||
void K8FTrainDQSPos(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
u32 SetUpperFSbase(u32 addr_hi);
|
||||
|
||||
|
||||
void K8FECCInit(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
|
||||
void amd_MCTInit(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
|
||||
void K8FCPUMemTyping(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
void K8FCPUMemTyping_clear(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
|
||||
void K8FWaitMemClrDelay(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
|
||||
unsigned int K8FCalcFinalDQSRcvValue(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, unsigned int LeftRcvEn, unsigned int RightRcvEn, unsigned int *valid);
|
||||
|
||||
void K8FGetDeltaTSCPart1(struct DCTStatStruc *pDCTstat);
|
||||
void K8FGetDeltaTSCPart2(struct DCTStatStruc *pDCTstat);
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,804 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
* Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Description: Include file for all generic DDR 2 MCT files.
|
||||
*/
|
||||
#ifndef MCT_D_H
|
||||
#define MCT_D_H
|
||||
|
||||
#define DQS_TRAIN_DEBUG 0
|
||||
|
||||
#include <stdint.h>
|
||||
#include <northbridge/amd/amdfam10/debug.h>
|
||||
#include <northbridge/amd/amdfam10/raminit.h>
|
||||
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
extern const u8 Table_DQSRcvEn_Offset[];
|
||||
extern const u32 TestPattern0_D[];
|
||||
extern const u32 TestPattern1_D[];
|
||||
extern const u32 TestPattern2_D[];
|
||||
|
||||
/*===========================================================================
|
||||
CPU - K8/FAM10
|
||||
===========================================================================*/
|
||||
#define PT_L1 0 /* CPU Package Type */
|
||||
#define PT_M2 1
|
||||
#define PT_S1 2
|
||||
#define PT_GR 3
|
||||
|
||||
#define J_MIN 0 /* j loop constraint. 1 = CL 2.0 T*/
|
||||
#define J_MAX 5 /* j loop constraint. 5 = CL 7.0 T*/
|
||||
#define K_MIN 1 /* k loop constraint. 1 = 200 MHz*/
|
||||
#define K_MAX 5 /* k loop constraint. 5 = 533 MHz*/
|
||||
#define CL_DEF 2 /* Default value for failsafe operation. 2 = CL 4.0 T*/
|
||||
#define T_DEF 1 /* Default value for failsafe operation. 1 = 5ns (cycle time)*/
|
||||
|
||||
#define BSCRate 1 /* reg bit field = rate of dram scrubber for ecc*/
|
||||
/* memory initialization (ecc and check-bits).*/
|
||||
/* 1 = 40 ns/64 bytes.*/
|
||||
#define FirstPass 1 /* First pass through RcvEn training*/
|
||||
#define SecondPass 2 /* Second pass through Rcven training*/
|
||||
|
||||
#define RCVREN_MARGIN 6 /* number of DLL taps to delay beyond first passing position*/
|
||||
#define MAXASYNCLATCTL_2 2 /* Max Async Latency Control value*/
|
||||
#define MAXASYNCLATCTL_3 3 /* Max Async Latency Control value*/
|
||||
|
||||
#define DQS_FAIL 1
|
||||
#define DQS_PASS 0
|
||||
#define DQS_WRITEDIR 1
|
||||
#define DQS_READDIR 0
|
||||
#define MIN_DQS_WNDW 3
|
||||
#define secPassOffset 6
|
||||
#define Pass1MemClkDly 0x20 /* Add 1/2 Memlock delay */
|
||||
#define MAX_RD_LAT 0x3FF
|
||||
#define MIN_FENCE 14
|
||||
#define MAX_FENCE 20
|
||||
#define MIN_DQS_WR_FENCE 14
|
||||
#define MAX_DQS_WR_FENCE 20
|
||||
#define FenceTrnFinDlySeed 19
|
||||
#define EarlyArbEn 19
|
||||
|
||||
#define PA_HOST(Node) ((((0x18+Node) << 3)+0) << 12) /* Node 0 Host Bus function PCI Address bits [15:0]*/
|
||||
#define PA_MAP(Node) ((((0x18+Node) << 3)+1) << 12) /* Node 0 MAP function PCI Address bits [15:0]*/
|
||||
#define PA_DCT(Node) ((((0x18+Node) << 3)+2) << 12) /* Node 0 DCT function PCI Address bits [15:0]*/
|
||||
//#define PA_EXT_DCT (((00 << 3)+4) << 8) /*Node 0 DCT extended configuration registers*/
|
||||
//#define PA_DCTADDL (((00 << 3)+2) << 8) /*Node x DCT function, Additional Registers PCI Address bits [15:0]*/
|
||||
//#define PA_EXT_DCTADDL (((00 << 3)+5) << 8) /*Node x DCT function, Additional Registers PCI Address bits [15:0]*/
|
||||
|
||||
#define PA_NBMISC(Node) ((((0x18+Node) << 3)+3) << 12) /*Node 0 Misc PCI Address bits [15:0]*/
|
||||
//#define PA_NBDEVOP (((00 << 3)+3) << 8) /*Node 0 Misc PCI Address bits [15:0]*/
|
||||
|
||||
#define DCC_EN 1 /* X:2:0x94[19]*/
|
||||
#define ILD_Lmt 3 /* X:2:0x94[18:16]*/
|
||||
|
||||
#define EncodedTSPD 0x00191709 /* encodes which SPD byte to get T from*/
|
||||
/* versus CL X, CL X-.5, and CL X-1*/
|
||||
|
||||
#define Bias_TrpT 3 /* bias to convert bus clocks to bit field value*/
|
||||
#define Bias_TrrdT 2
|
||||
#define Bias_TrcdT 3
|
||||
#define Bias_TrasT 3
|
||||
#define Bias_TrcT 11
|
||||
#define Bias_TrtpT 2
|
||||
#define Bias_TwrT 3
|
||||
#define Bias_TwtrT 0
|
||||
#define Bias_TfawT 7
|
||||
|
||||
#define Min_TrpT 3 /* min programmable value in busclocks*/
|
||||
#define Max_TrpT 6 /* max programmable value in busclocks*/
|
||||
#define Min_TrrdT 2
|
||||
#define Max_TrrdT 5
|
||||
#define Min_TrcdT 3
|
||||
#define Max_TrcdT 6
|
||||
#define Min_TrasT 5
|
||||
#define Max_TrasT 18
|
||||
#define Min_TrcT 11
|
||||
#define Max_TrcT 26
|
||||
#define Min_TrtpT 2
|
||||
#define Max_TrtpT 3
|
||||
#define Min_TwrT 3
|
||||
#define Max_TwrT 6
|
||||
#define Min_TwtrT 1
|
||||
#define Max_TwtrT 3
|
||||
|
||||
/*DDR2-1066 support*/
|
||||
#define Bias_TrcdT_1066 5
|
||||
#define Bias_TrasT_1066 15
|
||||
#define Bias_TrrdT_1066 4
|
||||
#define Bias_TwrT_1066 4
|
||||
#define Bias_TrpT_1066 5
|
||||
#define Bias_TwtrT_1066 4
|
||||
#define Bias_TfawT_1066 15
|
||||
|
||||
#define Min_TrcdT_1066 5
|
||||
#define Max_TrcdT_1066 12
|
||||
#define Min_TrasT_1066 15
|
||||
#define Max_TrasT_1066 30
|
||||
#define Min_TrcT_1066 11
|
||||
#define Max_TrcT_1066 42
|
||||
#define Min_TrrdT_1066 4
|
||||
#define Max_TrrdT_1066 7
|
||||
#define Min_TwrT_1066 5
|
||||
#define Max_TwrT_1066 8
|
||||
#define Min_TrpT_1066 5
|
||||
#define Max_TrpT_1066 12
|
||||
#define Min_TwtrT_1066 4
|
||||
#define Max_TwtrT_1066 7
|
||||
|
||||
/*common register bit names*/
|
||||
#define DramHoleValid 0 /* func 1, offset F0h, bit 0*/
|
||||
#define DramMemHoistValid 1 /* func 1, offset F0h, bit 1*/
|
||||
#define CSEnable 0 /* func 2, offset 40h-5C, bit 0*/
|
||||
#define Spare 1 /* func 2, offset 40h-5C, bit 1*/
|
||||
#define TestFail 2 /* func 2, offset 40h-5C, bit 2*/
|
||||
#define DqsRcvEnTrain 18 /* func 2, offset 78h, bit 18*/
|
||||
#define EnDramInit 31 /* func 2, offset 7Ch, bit 31*/
|
||||
#define DisAutoRefresh 18 /* func 2, offset 8Ch, bit 18*/
|
||||
#define InitDram 0 /* func 2, offset 90h, bit 0*/
|
||||
#define BurstLength32 10 /* func 2, offset 90h, bit 10*/
|
||||
#define Width128 11 /* func 2, offset 90h, bit 11*/
|
||||
#define X4Dimm 12 /* func 2, offset 90h, bit 12*/
|
||||
#define UnBuffDimm 16 /* func 2, offset 90h, bit 16*/
|
||||
#define DimmEcEn 19 /* func 2, offset 90h, bit 19*/
|
||||
#define MemClkFreqVal 3 /* func 2, offset 94h, bit 3*/
|
||||
#define RDqsEn 12 /* func 2, offset 94h, bit 12*/
|
||||
#define DisDramInterface 14 /* func 2, offset 94h, bit 14*/
|
||||
#define DctAccessWrite 30 /* func 2, offset 98h, bit 30*/
|
||||
#define DctAccessDone 31 /* func 2, offset 98h, bit 31*/
|
||||
#define MemClrStatus 0 /* func 2, offset A0h, bit 0*/
|
||||
#define PwrSavingsEn 10 /* func 2, offset A0h, bit 10*/
|
||||
#define Mod64BitMux 4 /* func 2, offset A0h, bit 4*/
|
||||
#define DisableJitter 1 /* func 2, offset A0h, bit 1*/
|
||||
#define MemClrDis 1 /* func 3, offset F8h, FNC 4, bit 1*/
|
||||
#define SyncOnUcEccEn 2 /* func 3, offset 44h, bit 2*/
|
||||
#define Dr_MemClrStatus 10 /* func 3, offset 110h, bit 10*/
|
||||
#define MemClrBusy 9 /* func 3, offset 110h, bit 9*/
|
||||
#define DctGangEn 4 /* func 3, offset 110h, bit 4*/
|
||||
#define MemClrInit 3 /* func 3, offset 110h, bit 3*/
|
||||
#define AssertCke 28 /* func 2, offset 7Ch, bit 28*/
|
||||
#define DeassertMemRstX 27 /* func 2, offset 7Ch, bit 27*/
|
||||
#define SendMrsCmd 26 /* func 2, offset 7Ch, bit 26*/
|
||||
#define SendAutoRefresh 25 /* func 2, offset 7Ch, bit 25*/
|
||||
#define SendPchgAll 24 /* func 2, offset 7Ch, bit 24*/
|
||||
#define DisDqsBar 6 /* func 2, offset 90h, bit 6*/
|
||||
#define DramEnabled 8 /* func 2, offset 110h, bit 8*/
|
||||
#define LegacyBiosMode 9 /* func 2, offset 94h, bit 9*/
|
||||
#define PrefDramTrainMode 28 /* func 2, offset 11Ch, bit 28*/
|
||||
#define FlushWr 30 /* func 2, offset 11Ch, bit 30*/
|
||||
#define DisAutoComp 30 /* func 2, offset 9Ch, Index 8, bit 30*/
|
||||
#define DqsRcvTrEn 13 /* func 2, offset 9Ch, Index 8, bit 13*/
|
||||
#define ForceAutoPchg 23 /* func 2, offset 90h, bit 23*/
|
||||
#define ClLinesToNbDis 15 /* Bu_CFG2, bit 15*/
|
||||
#define WbEnhWsbDis_D (48-32)
|
||||
#define PhyFenceTrEn 3 /* func 2, offset 9Ch, Index 8, bit 3 */
|
||||
#define ParEn 8 /* func 2, offset 90h, bit 8 */
|
||||
#define DcqArbBypassEn 19 /* func 2, offset 94h, bit 19 */
|
||||
#define ActiveCmdAtRst 1 /* func 2, offset A8H, bit 1 */
|
||||
#define FlushWrOnStpGnt 29 /* func 2, offset 11Ch, bit 29 */
|
||||
#define BankSwizzleMode 22 /* func 2, offset 94h, bit 22 */
|
||||
#define ChSetupSync 15 /* func 2, offset 78h, bit 15 */
|
||||
|
||||
|
||||
|
||||
/*=============================================================================
|
||||
SW Initialization
|
||||
============================================================================*/
|
||||
#define DLL_Enable 1
|
||||
#define OCD_Default 2
|
||||
#define OCD_Exit 3
|
||||
|
||||
|
||||
|
||||
/*=============================================================================
|
||||
Jedec DDR II
|
||||
=============================================================================*/
|
||||
#define SPD_TYPE 2 /*SPD byte read location*/
|
||||
#define JED_DDRSDRAM 0x07 /*Jedec defined bit field*/
|
||||
#define JED_DDR2SDRAM 0x08 /*Jedec defined bit field*/
|
||||
|
||||
#define SPD_DIMMTYPE 20
|
||||
#define SPD_ATTRIB 21
|
||||
#define JED_DIFCKMSK 0x20 /*Differential Clock Input*/
|
||||
#define JED_REGADCMSK 0x11 /*Registered Address/Control*/
|
||||
#define JED_PROBEMSK 0x40 /*Analysis Probe installed*/
|
||||
#define SPD_DEVATTRIB 22
|
||||
#define SPD_EDCTYPE 11
|
||||
#define JED_ECC 0x02
|
||||
#define JED_ADRCPAR 0x04
|
||||
#define SPD_ROWSZ 3
|
||||
#define SPD_COLSZ 4
|
||||
#define SPD_LBANKS 17 /*number of [logical] banks on each device*/
|
||||
#define SPD_DMBANKS 5 /*number of physical banks on dimm*/
|
||||
#define SPDPLBit 4 /* Dram package bit*/
|
||||
#define SPD_BANKSZ 31 /*capacity of physical bank*/
|
||||
#define SPD_DEVWIDTH 13
|
||||
#define SPD_CASLAT 18
|
||||
#define SPD_TRP 27
|
||||
#define SPD_TRRD 28
|
||||
#define SPD_TRCD 29
|
||||
#define SPD_TRAS 30
|
||||
#define SPD_TWR 36
|
||||
#define SPD_TWTR 37
|
||||
#define SPD_TRTP 38
|
||||
#define SPD_TRCRFC 40
|
||||
#define SPD_TRC 41
|
||||
#define SPD_TRFC 42
|
||||
|
||||
#define SPD_MANID_START 64
|
||||
#define SPD_PARTN_START 73
|
||||
#define SPD_PARTN_LENGTH 18
|
||||
#define SPD_REVNO_START 91
|
||||
|
||||
#define SPD_MANDATEYR 93 /*Module Manufacturing Year (BCD)*/
|
||||
|
||||
#define SPD_MANDATEWK 94 /*Module Manufacturing Week (BCD)*/
|
||||
|
||||
#define SPD_SERIAL_START 95
|
||||
|
||||
/*-----------------------------
|
||||
Jedec DDR II related equates
|
||||
-----------------------------*/
|
||||
#define MYEAR06 6 /* Manufacturing Year BCD encoding of 2006 - 06d*/
|
||||
#define MWEEK24 0x24 /* Manufacturing Week BCD encoding of June - 24d*/
|
||||
|
||||
/*=============================================================================
|
||||
Macros
|
||||
=============================================================================*/
|
||||
|
||||
#define _2GB_RJ8 (2<<(30-8))
|
||||
#define _4GB_RJ8 (4<<(30-8))
|
||||
#define _4GB_RJ4 (4<<(30-4))
|
||||
|
||||
#define BigPagex8_RJ8 (1<<(17+3-8)) /*128KB * 8 >> 8 */
|
||||
|
||||
/*=============================================================================
|
||||
Global MCT Status Structure
|
||||
=============================================================================*/
|
||||
struct MCTStatStruc {
|
||||
u32 GStatus; /* Global Status bitfield*/
|
||||
u32 HoleBase; /* If not zero, BASE[39:8] (system address)
|
||||
of sub 4GB dram hole for HW remapping.*/
|
||||
u32 Sub4GCacheTop; /* If not zero, the 32-bit top of cacheable memory.*/
|
||||
u32 SysLimit; /* LIMIT[39:8] (system address)*/
|
||||
} __packed;
|
||||
|
||||
/*=============================================================================
|
||||
Global MCT Configuration Status Word (GStatus)
|
||||
=============================================================================*/
|
||||
/*These should begin at bit 0 of GStatus[31:0]*/
|
||||
#define GSB_MTRRshort 0 /* Ran out of MTRRs while mapping memory*/
|
||||
#define GSB_ECCDIMMs 1 /* All banks of all Nodes are ECC capable*/
|
||||
#define GSB_DramECCDis 2 /* Dram ECC requested but not enabled.*/
|
||||
#define GSB_SoftHole 3 /* A Node Base gap was created*/
|
||||
#define GSB_HWHole 4 /* A HW dram remap was created*/
|
||||
#define GSB_NodeIntlv 5 /* Node Memory interleaving was enabled*/
|
||||
#define GSB_SpIntRemapHole 16 /* Special condition for Node Interleave and HW remapping*/
|
||||
#define GSB_EnDIMMSpareNW 17 /* Indicates that DIMM Spare can be used without a warm reset */
|
||||
/* NOTE: This is a local bit used by memory code */
|
||||
|
||||
|
||||
/*===============================================================================
|
||||
Local DCT Status structure (a structure for each DCT)
|
||||
===============================================================================*/
|
||||
|
||||
struct DCTPersistentStatStruc {
|
||||
u8 CH_D_DIR_B_DQS[2][4][2][9]; /* [A/B] [DIMM1-4] [R/W] [DQS] */
|
||||
/* CHA DIMM0 Byte 0 - 7 and Check Write DQS Delay*/
|
||||
/* CHA DIMM0 Byte 0 - 7 and Check Read DQS Delay*/
|
||||
/* CHA DIMM1 Byte 0 - 7 and Check Write DQS Delay*/
|
||||
/* CHA DIMM1 Byte 0 - 7 and Check Read DQS Delay*/
|
||||
/* CHB DIMM0 Byte 0 - 7 and Check Write DQS Delay*/
|
||||
/* CHB DIMM0 Byte 0 - 7 and Check Read DQS Delay*/
|
||||
/* CHB DIMM1 Byte 0 - 7 and Check Write DQS Delay*/
|
||||
/* CHB DIMM1 Byte 0 - 7 and Check Read DQS Delay*/
|
||||
u8 CH_D_B_RCVRDLY[2][4][8]; /* [A/B] [DIMM0-3] [DQS] */
|
||||
/* CHA DIMM 0 Receiver Enable Delay*/
|
||||
/* CHA DIMM 1 Receiver Enable Delay*/
|
||||
/* CHA DIMM 2 Receiver Enable Delay*/
|
||||
/* CHA DIMM 3 Receiver Enable Delay*/
|
||||
|
||||
/* CHB DIMM 0 Receiver Enable Delay*/
|
||||
/* CHB DIMM 1 Receiver Enable Delay*/
|
||||
/* CHB DIMM 2 Receiver Enable Delay*/
|
||||
/* CHB DIMM 3 Receiver Enable Delay*/
|
||||
u8 CH_D_BC_RCVRDLY[2][4];
|
||||
/* CHA DIMM 0 - 4 Check Byte Receiver Enable Delay*/
|
||||
/* CHB DIMM 0 - 4 Check Byte Receiver Enable Delay*/
|
||||
u16 HostBiosSrvc1; /* Word sized general purpose field for use by host BIOS. Scratch space.*/
|
||||
u32 HostBiosSrvc2; /* Dword sized general purpose field for use by host BIOS. Scratch space.*/
|
||||
} __packed;
|
||||
|
||||
|
||||
struct DCTStatStruc { /* A per Node structure*/
|
||||
/* DCTStatStruct_F - start */
|
||||
u8 Node_ID; /* Node ID of current controller*/
|
||||
uint8_t Internal_Node_ID; /* Internal Node ID of the current controller */
|
||||
uint8_t Dual_Node_Package; /* 1 = Dual node package (G34) */
|
||||
uint8_t stopDCT; /* Set if the DCT will be stopped */
|
||||
u8 ErrCode; /* Current error condition of Node
|
||||
0= no error
|
||||
1= Variance Error, DCT is running but not in an optimal configuration.
|
||||
2= Stop Error, DCT is NOT running
|
||||
3= Fatal Error, DCT/MCT initialization has been halted.*/
|
||||
u32 ErrStatus; /* Error Status bit Field */
|
||||
u32 Status; /* Status bit Field*/
|
||||
u8 DIMMAddr[8]; /* SPD address of DIMM controlled by MA0_CS_L[0,1]*/
|
||||
/* SPD address of..MB0_CS_L[0,1]*/
|
||||
/* SPD address of..MA1_CS_L[0,1]*/
|
||||
/* SPD address of..MB1_CS_L[0,1]*/
|
||||
/* SPD address of..MA2_CS_L[0,1]*/
|
||||
/* SPD address of..MB2_CS_L[0,1]*/
|
||||
/* SPD address of..MA3_CS_L[0,1]*/
|
||||
/* SPD address of..MB3_CS_L[0,1]*/
|
||||
u16 DIMMPresent; /*For each bit n 0..7, 1 = DIMM n is present.
|
||||
DIMM# Select Signal
|
||||
0 MA0_CS_L[0,1]
|
||||
1 MB0_CS_L[0,1]
|
||||
2 MA1_CS_L[0,1]
|
||||
3 MB1_CS_L[0,1]
|
||||
4 MA2_CS_L[0,1]
|
||||
5 MB2_CS_L[0,1]
|
||||
6 MA3_CS_L[0,1]
|
||||
7 MB3_CS_L[0,1]*/
|
||||
u16 DIMMValid; /* For each bit n 0..7, 1 = DIMM n is valid and is/will be configured*/
|
||||
u16 DIMMMismatch; /* For each bit n 0..7, 1 = DIMM n is mismatched, channel B is always considered the mismatch */
|
||||
u16 DIMMSPDCSE; /* For each bit n 0..7, 1 = DIMM n SPD checksum error*/
|
||||
u16 DimmECCPresent; /* For each bit n 0..7, 1 = DIMM n is ECC capable.*/
|
||||
u16 DimmPARPresent; /* For each bit n 0..7, 1 = DIMM n is ADR/CMD Parity capable.*/
|
||||
u16 Dimmx4Present; /* For each bit n 0..7, 1 = DIMM n contains x4 data devices.*/
|
||||
u16 Dimmx8Present; /* For each bit n 0..7, 1 = DIMM n contains x8 data devices.*/
|
||||
u16 Dimmx16Present; /* For each bit n 0..7, 1 = DIMM n contains x16 data devices.*/
|
||||
u16 DIMM2Kpage; /* For each bit n 0..7, 1 = DIMM n contains 1K page devices.*/
|
||||
u8 MAload[2]; /* Number of devices loading MAA bus*/
|
||||
/* Number of devices loading MAB bus*/
|
||||
u8 MAdimms[2]; /*Number of DIMMs loading CH A*/
|
||||
/* Number of DIMMs loading CH B*/
|
||||
u8 DATAload[2]; /*Number of ranks loading CH A DATA*/
|
||||
/* Number of ranks loading CH B DATA*/
|
||||
u8 DIMMAutoSpeed; /*Max valid Mfg. Speed of DIMMs
|
||||
1 = 200MHz
|
||||
2 = 266MHz
|
||||
3 = 333MHz
|
||||
4 = 400MHz
|
||||
5 = 533MHz*/
|
||||
u8 DIMMCASL; /* Min valid Mfg. CL bitfield
|
||||
0 = 2.0
|
||||
1 = 3.0
|
||||
2 = 4.0
|
||||
3 = 5.0
|
||||
4 = 6.0 */
|
||||
u16 DIMMTrcd; /* Minimax Trcd*40 (ns) of DIMMs*/
|
||||
u16 DIMMTrp; /* Minimax Trp*40 (ns) of DIMMs*/
|
||||
u16 DIMMTrtp; /* Minimax Trtp*40 (ns) of DIMMs*/
|
||||
u16 DIMMTras; /* Minimax Tras*40 (ns) of DIMMs*/
|
||||
u16 DIMMTrc; /* Minimax Trc*40 (ns) of DIMMs*/
|
||||
u16 DIMMTwr; /* Minimax Twr*40 (ns) of DIMMs*/
|
||||
u16 DIMMTrrd; /* Minimax Trrd*40 (ns) of DIMMs*/
|
||||
u16 DIMMTwtr; /* Minimax Twtr*40 (ns) of DIMMs*/
|
||||
u8 Speed; /* Bus Speed (to set Controller)
|
||||
1 = 200MHz
|
||||
2 = 266MHz
|
||||
3 = 333MHz
|
||||
4 = 400MHz */
|
||||
u8 CASL; /* CAS latency DCT setting
|
||||
0 = 2.0
|
||||
1 = 3.0
|
||||
2 = 4.0
|
||||
3 = 5.0
|
||||
4 = 6.0 */
|
||||
u8 Trcd; /* DCT Trcd (busclocks) */
|
||||
u8 Trp; /* DCT Trp (busclocks) */
|
||||
u8 Trtp; /* DCT Trtp (busclocks) */
|
||||
u8 Tras; /* DCT Tras (busclocks) */
|
||||
u8 Trc; /* DCT Trc (busclocks) */
|
||||
u8 Twr; /* DCT Twr (busclocks) */
|
||||
u8 Trrd; /* DCT Trrd (busclocks) */
|
||||
u8 Twtr; /* DCT Twtr (busclocks) */
|
||||
u8 Trfc[4]; /* DCT Logical DIMM0 Trfc
|
||||
0 = 75ns (for 256Mb devs)
|
||||
1 = 105ns (for 512Mb devs)
|
||||
2 = 127.5ns (for 1Gb devs)
|
||||
3 = 195ns (for 2Gb devs)
|
||||
4 = 327.5ns (for 4Gb devs) */
|
||||
/* DCT Logical DIMM1 Trfc (see Trfc0 for format) */
|
||||
/* DCT Logical DIMM2 Trfc (see Trfc0 for format) */
|
||||
/* DCT Logical DIMM3 Trfc (see Trfc0 for format) */
|
||||
u16 CSPresent; /* For each bit n 0..7, 1 = Chip-select n is present */
|
||||
u16 CSTestFail; /* For each bit n 0..7, 1 = Chip-select n is present but disabled */
|
||||
u32 DCTSysBase; /* BASE[39:8] (system address) of this Node's DCTs. */
|
||||
u32 DCTHoleBase; /* If not zero, BASE[39:8] (system address) of dram hole for HW remapping. Dram hole exists on this Node's DCTs. */
|
||||
u32 DCTSysLimit; /* LIMIT[39:8] (system address) of this Node's DCTs */
|
||||
u16 PresetmaxFreq; /* Maximum OEM defined DDR frequency
|
||||
200 = 200MHz (DDR400)
|
||||
266 = 266MHz (DDR533)
|
||||
333 = 333MHz (DDR667)
|
||||
400 = 400MHz (DDR800) */
|
||||
u8 _2Tmode; /* 1T or 2T CMD mode (slow access mode)
|
||||
1 = 1T
|
||||
2 = 2T */
|
||||
u8 TrwtTO; /* DCT TrwtTO (busclocks)*/
|
||||
u8 Twrrd; /* DCT Twrrd (busclocks)*/
|
||||
u8 Twrwr; /* DCT Twrwr (busclocks)*/
|
||||
u8 Trdrd; /* DCT Trdrd (busclocks)*/
|
||||
u32 CH_ODC_CTL[2]; /* Output Driver Strength (see BKDG FN2:Offset 9Ch, index 00h*/
|
||||
u32 CH_ADDR_TMG[2]; /* Address Bus Timing (see BKDG FN2:Offset 9Ch, index 04h*/
|
||||
/* Output Driver Strength (see BKDG FN2:Offset 9Ch, index 20h*/
|
||||
/* Address Bus Timing (see BKDG FN2:Offset 9Ch, index 24h*/
|
||||
u16 CH_EccDQSLike[2]; /* CHA DQS ECC byte like...*/
|
||||
u8 CH_EccDQSScale[2]; /* CHA DQS ECC byte scale*/
|
||||
/* CHA DQS ECC byte like...*/
|
||||
/* CHA DQS ECC byte scale*/
|
||||
u8 MaxAsyncLat; /* Max Asynchronous Latency (ns)*/
|
||||
// NOTE: Not used in Barcelona - u8 CH_D_RCVRDLY[2][4];
|
||||
/* CHA DIMM 0 - 4 Receiver Enable Delay*/
|
||||
/* CHB DIMM 0 - 4 Receiver Enable Delay */
|
||||
// NOTE: Not used in Barcelona - u8 CH_D_B_DQS[2][2][8];
|
||||
/* CHA Byte 0-7 Write DQS Delay */
|
||||
/* CHA Byte 0-7 Read DQS Delay */
|
||||
/* CHB Byte 0-7 Write DQS Delay */
|
||||
/* CHB Byte 0-7 Read DQS Delay */
|
||||
u32 PtrPatternBufA; /* Ptr on stack to aligned DQS testing pattern*/
|
||||
u32 PtrPatternBufB; /* Ptr on stack to aligned DQS testing pattern*/
|
||||
u8 Channel; /* Current Channel (0= CH A, 1 = CH B)*/
|
||||
u8 ByteLane; /* Current Byte Lane (0..7)*/
|
||||
u8 Direction; /* Current DQS-DQ training write direction (0 = read, 1 = write)*/
|
||||
u8 Pattern; /* Current pattern*/
|
||||
u8 DQSDelay; /* Current DQS delay value*/
|
||||
u32 TrainErrors; /* Current Training Errors*/
|
||||
|
||||
u32 AMC_TSC_DeltaLo; /* Time Stamp Counter measurement of AMC, Low dword*/
|
||||
u32 AMC_TSC_DeltaHi; /* Time Stamp Counter measurement of AMC, High dword*/
|
||||
// NOTE: Not used in Barcelona - u8 CH_D_DIR_MaxMin_B_Dly[2][4][2][2][8];
|
||||
/* CH A byte lane 0 - 7 minimum filtered window passing DQS delay value*/
|
||||
/* CH A byte lane 0 - 7 maximum filtered window passing DQS delay value*/
|
||||
/* CH B byte lane 0 - 7 minimum filtered window passing DQS delay value*/
|
||||
/* CH B byte lane 0 - 7 maximum filtered window passing DQS delay value*/
|
||||
/* CH A byte lane 0 - 7 minimum filtered window passing DQS delay value*/
|
||||
/* CH A byte lane 0 - 7 maximum filtered window passing DQS delay value*/
|
||||
/* CH B byte lane 0 - 7 minimum filtered window passing DQS delay value*/
|
||||
/* CH B byte lane 0 - 7 maximum filtered window passing DQS delay value*/
|
||||
uint64_t LogicalCPUID; /* The logical CPUID of the node*/
|
||||
u16 DimmQRPresent; /* QuadRank DIMM present?*/
|
||||
u16 DimmTrainFail; /* Bitmap showing which dimms failed training*/
|
||||
u16 CSTrainFail; /* Bitmap showing which chipselects failed training*/
|
||||
u16 DimmYr06; /* Bitmap indicating which Dimms have a manufactur's year code <= 2006*/
|
||||
u16 DimmWk2406; /* Bitmap indicating which Dimms have a manufactur's week code <= 24 of 2006 (June)*/
|
||||
u16 DimmDRPresent; /* Bitmap indicating that Dual Rank Dimms are present*/
|
||||
u16 DimmPlPresent; /* Bitmap indicating that Planar (1) or Stacked (0) Dimms are present.*/
|
||||
u16 ChannelTrainFai; /* Bitmap showing the channel information about failed Chip Selects
|
||||
0 in any bit field indicates Channel 0
|
||||
1 in any bit field indicates Channel 1 */
|
||||
u16 CSUsrTestFail; /* Chip selects excluded by user */
|
||||
/* DCTStatStruct_F - end */
|
||||
|
||||
u16 CH_MaxRdLat[2]; /* Max Read Latency (ns) for DCT 0*/
|
||||
/* Max Read Latency (ns) for DCT 1*/
|
||||
u8 DIMMValidDCT[2]; /* DIMM# in DCT0*/
|
||||
/* DIMM# in DCT1*/
|
||||
u8 MaxDCTs; /* Max number of DCTs in system*/
|
||||
// NOTE: removed u8 DCT. Use ->dev_ for pci R/W; /*DCT pointer*/
|
||||
u8 GangedMode; /* Ganged mode enabled, 0 = disabled, 1 = enabled*/
|
||||
u8 DRPresent; /* Family 10 present flag, 0 = not Fam10, 1 = Fam10*/
|
||||
u32 NodeSysLimit; /* BASE[39:8],for DCT0+DCT1 system address*/
|
||||
u8 WrDatGrossH;
|
||||
u8 DqsRcvEnGrossL;
|
||||
// NOTE: Not used - u8 NodeSpeed /* Bus Speed (to set Controller)
|
||||
/* 1 = 200MHz */
|
||||
/* 2 = 266MHz */
|
||||
/* 3 = 333MHz */
|
||||
// NOTE: Not used - u8 NodeCASL /* CAS latency DCT setting
|
||||
/* 0 = 2.0 */
|
||||
/* 1 = 3.0 */
|
||||
/* 2 = 4.0 */
|
||||
/* 3 = 5.0 */
|
||||
/* 4 = 6.0 */
|
||||
u8 TrwtWB;
|
||||
u8 CurrRcvrCHADelay; /* for keep current RcvrEnDly of chA*/
|
||||
u16 T1000; /* get the T1000 figure (cycle time (ns)*1K)*/
|
||||
u8 DqsRcvEn_Pass; /* for TrainRcvrEn byte lane pass flag*/
|
||||
u8 DqsRcvEn_Saved; /* for TrainRcvrEn byte lane saved flag*/
|
||||
u8 SeedPass1Remainder; /* for Phy assisted DQS receiver enable training*/
|
||||
|
||||
/* for second pass - Second pass should never run for Fam10*/
|
||||
// NOTE: Not used for Barcelona - u8 CH_D_B_RCVRDLY_1[2][4][8]; /* CHA DIMM 0 Receiver Enable Delay*/
|
||||
/* CHA DIMM 1 Receiver Enable Delay*/
|
||||
/* CHA DIMM 2 Receiver Enable Delay*/
|
||||
/* CHA DIMM 3 Receiver Enable Delay*/
|
||||
|
||||
/* CHB DIMM 0 Receiver Enable Delay*/
|
||||
/* CHB DIMM 1 Receiver Enable Delay*/
|
||||
/* CHB DIMM 2 Receiver Enable Delay*/
|
||||
/* CHB DIMM 3 Receiver Enable Delay*/
|
||||
|
||||
u8 ClToNB_flag; /* is used to restore ClLinesToNbDis bit after memory */
|
||||
u32 NodeSysBase; /* for channel interleave usage */
|
||||
|
||||
/* New for LB Support */
|
||||
u8 NodePresent;
|
||||
u32 dev_host;
|
||||
u32 dev_map;
|
||||
u32 dev_dct;
|
||||
u32 dev_nbmisc;
|
||||
|
||||
uint8_t DimmRows[MAX_DIMMS_SUPPORTED];
|
||||
uint8_t DimmCols[MAX_DIMMS_SUPPORTED];
|
||||
uint8_t DimmRanks[MAX_DIMMS_SUPPORTED];
|
||||
uint8_t DimmBanks[MAX_DIMMS_SUPPORTED];
|
||||
uint8_t DimmWidth[MAX_DIMMS_SUPPORTED];
|
||||
uint8_t DimmRegistered[MAX_DIMMS_SUPPORTED];
|
||||
|
||||
uint64_t DimmManufacturerID[MAX_DIMMS_SUPPORTED];
|
||||
char DimmPartNumber[MAX_DIMMS_SUPPORTED][SPD_PARTN_LENGTH+1];
|
||||
uint16_t DimmRevisionNumber[MAX_DIMMS_SUPPORTED];
|
||||
uint32_t DimmSerialNumber[MAX_DIMMS_SUPPORTED];
|
||||
|
||||
/* NOTE: This must remain the last entry in this structure */
|
||||
struct DCTPersistentStatStruc persistentData;
|
||||
} __packed;
|
||||
|
||||
/*===============================================================================
|
||||
Local Error Status Codes (DCTStatStruc.ErrCode)
|
||||
===============================================================================*/
|
||||
#define SC_RunningOK 0
|
||||
#define SC_VarianceErr 1 /* Running non-optimally*/
|
||||
#define SC_StopError 2 /* Not Running*/
|
||||
#define SC_FatalErr 3 /* Fatal Error, MCTB has exited immediately*/
|
||||
|
||||
/*===============================================================================
|
||||
Local Error Status (DCTStatStruc.ErrStatus[31:0])
|
||||
===============================================================================*/
|
||||
#define SB_NoDimms 0
|
||||
#define SB_DIMMChkSum 1
|
||||
#define SB_DimmMismatchM 2 /* dimm module type(buffer) mismatch*/
|
||||
#define SB_DimmMismatchT 3 /* dimm CL/T mismatch*/
|
||||
#define SB_DimmMismatchO 4 /* dimm organization mismatch (128-bit)*/
|
||||
#define SB_NoTrcTrfc 5 /* SPD missing Trc or Trfc info*/
|
||||
#define SB_NoCycTime 6 /* SPD missing byte 23 or 25*/
|
||||
#define SB_BkIntDis 7 /* Bank interleave requested but not enabled*/
|
||||
#define SB_DramECCDis 8 /* Dram ECC requested but not enabled*/
|
||||
#define SB_SpareDis 9 /* Online spare requested but not enabled*/
|
||||
#define SB_MinimumMode 10 /* Running in Minimum Mode*/
|
||||
#define SB_NORCVREN 11 /* No DQS Receiver Enable pass window found*/
|
||||
#define SB_CHA2BRCVREN 12 /* DQS Rcvr En pass window CHA to CH B too large*/
|
||||
#define SB_SmallRCVR 13 /* DQS Rcvr En pass window too small (far right of dynamic range)*/
|
||||
#define SB_NODQSPOS 14 /* No DQS-DQ passing positions*/
|
||||
#define SB_SMALLDQS 15 /* DQS-DQ passing window too small*/
|
||||
#define SB_DCBKScrubDis 16 /* DCache scrub requested but not enabled */
|
||||
|
||||
/*===============================================================================
|
||||
Local Configuration Status (DCTStatStruc.Status[31:0])
|
||||
===============================================================================*/
|
||||
#define SB_Registered 0 /* All DIMMs are Registered*/
|
||||
#define SB_ECCDIMMs 1 /* All banks ECC capable*/
|
||||
#define SB_PARDIMMs 2 /* All banks Addr/CMD Parity capable*/
|
||||
#define SB_DiagClks 3 /* Jedec ALL slots clock enable diag mode*/
|
||||
#define SB_128bitmode 4 /* DCT in 128-bit mode operation*/
|
||||
#define SB_64MuxedMode 5 /* DCT in 64-bit mux'ed mode.*/
|
||||
#define SB_2TMode 6 /* 2T CMD timing mode is enabled.*/
|
||||
#define SB_SWNodeHole 7 /* Remapping of Node Base on this Node to create a gap.*/
|
||||
#define SB_HWHole 8 /* Memory Hole created on this Node using HW remapping.*/
|
||||
#define SB_Over400MHz 9 /* DCT freq >= 400MHz flag*/
|
||||
#define SB_DQSPos_Pass2 10 /* Using for TrainDQSPos DIMM0/1, when freq >= 400MHz*/
|
||||
#define SB_DQSRcvLimit 11 /* Using for DQSRcvEnTrain to know we have reached to upper bound.*/
|
||||
#define SB_ExtConfig 12 /* Indicator the default setting for extend PCI configuration support*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*===============================================================================
|
||||
NVRAM/run-time-configurable Items
|
||||
===============================================================================*/
|
||||
/*Platform Configuration*/
|
||||
#define NV_PACK_TYPE 0 /* CPU Package Type (2-bits)
|
||||
0 = NPT L1
|
||||
1 = NPT M2
|
||||
2 = NPT S1*/
|
||||
#define NV_MAX_NODES 1 /* Number of Nodes/Sockets (4-bits)*/
|
||||
#define NV_MAX_DIMMS 2 /* Number of DIMM slots for the specified Node ID (4-bits)*/
|
||||
#define NV_MAX_MEMCLK 3 /* Maximum platform demonstrated Memclock (10-bits)
|
||||
200 = 200MHz (DDR400)
|
||||
266 = 266MHz (DDR533)
|
||||
333 = 333MHz (DDR667)
|
||||
400 = 400MHz (DDR800)*/
|
||||
#define NV_MIN_MEMCLK 4 /* Minimum platform demonstrated Memclock (10-bits) */
|
||||
#define NV_ECC_CAP 5 /* Bus ECC capable (1-bits)
|
||||
0 = Platform not capable
|
||||
1 = Platform is capable*/
|
||||
#define NV_4RANKType 6 /* Quad Rank DIMM slot type (2-bits)
|
||||
0 = Normal
|
||||
1 = R4 (4-Rank Registered DIMMs in AMD server configuration)
|
||||
2 = S4 (Unbuffered SO-DIMMs)*/
|
||||
#define NV_BYPMAX 7 /* Value to set DcqBypassMax field (See Function 2, Offset 94h, [27:24] of BKDG for field definition).
|
||||
4 = 4 times bypass (normal for non-UMA systems)
|
||||
7 = 7 times bypass (normal for UMA systems)*/
|
||||
#define NV_RDWRQBYP 8 /* Value to set RdWrQByp field (See Function 2, Offset A0h, [3:2] of BKDG for field definition).
|
||||
2 = 8 times (normal for non-UMA systems)
|
||||
3 = 16 times (normal for UMA systems)*/
|
||||
|
||||
|
||||
/*Dram Timing*/
|
||||
#define NV_MCTUSRTMGMODE 10 /* User Memclock Mode (2-bits)
|
||||
0 = Auto, no user limit
|
||||
1 = Auto, user limit provided in NV_MemCkVal
|
||||
2 = Manual, user value provided in NV_MemCkVal*/
|
||||
#define NV_MemCkVal 11 /* Memory Clock Value (2-bits)
|
||||
0 = 200MHz
|
||||
1 = 266MHz
|
||||
2 = 333MHz
|
||||
3 = 400MHz*/
|
||||
|
||||
/*Dram Configuration*/
|
||||
#define NV_BankIntlv 20 /* Dram Bank (chip-select) Interleaving (1-bits)
|
||||
0 = disable
|
||||
1 = enable*/
|
||||
#define NV_AllMemClks 21 /* Turn on All DIMM clocks (1-bits)
|
||||
0 = normal
|
||||
1 = enable all memclocks*/
|
||||
#define NV_SPDCHK_RESTRT 22 /* SPD Check control bitmap (1-bits)
|
||||
0 = Exit current node init if any DIMM has SPD checksum error
|
||||
1 = Ignore faulty SPD checksums (Note: DIMM cannot be enabled)*/
|
||||
#define NV_DQSTrainCTL 23 /* DQS Signal Timing Training Control
|
||||
0 = skip DQS training
|
||||
1 = perform DQS training*/
|
||||
#define NV_NodeIntlv 24 /* Node Memory Interleaving (1-bits)
|
||||
0 = disable
|
||||
1 = enable*/
|
||||
#define NV_BurstLen32 25 /* BurstLength32 for 64-bit mode (1-bits)
|
||||
0 = disable (normal)
|
||||
1 = enable (4 beat burst when width is 64-bits)*/
|
||||
|
||||
/*Dram Power*/
|
||||
#define NV_CKE_PDEN 30 /* CKE based power down mode (1-bits)
|
||||
0 = disable
|
||||
1 = enable*/
|
||||
#define NV_CKE_CTL 31 /* CKE based power down control (1-bits)
|
||||
0 = per Channel control
|
||||
1 = per Chip select control*/
|
||||
#define NV_CLKHZAltVidC3 32 /* Memclock tri-stating during C3 and Alt VID (1-bits)
|
||||
0 = disable
|
||||
1 = enable*/
|
||||
|
||||
/*Memory Map/Mgt.*/
|
||||
#define NV_BottomIO 40 /* Bottom of 32-bit IO space (8-bits)
|
||||
NV_BottomIO[7:0]=Addr[31:24]*/
|
||||
#define NV_BottomUMA 41 /* Bottom of shared graphics dram (8-bits)
|
||||
NV_BottomUMA[7:0]=Addr[31:24]*/
|
||||
#define NV_MemHole 42 /* Memory Hole Remapping (1-bits)
|
||||
0 = disable
|
||||
1 = enable */
|
||||
|
||||
/*ECC*/
|
||||
#define NV_ECC 50 /* Dram ECC enable*/
|
||||
#define NV_NBECC 52 /* ECC MCE enable*/
|
||||
#define NV_ChipKill 53 /* Chip-Kill ECC Mode enable*/
|
||||
#define NV_ECCRedir 54 /* Dram ECC Redirection enable*/
|
||||
#define NV_DramBKScrub 55 /* Dram ECC Background Scrubber CTL*/
|
||||
#define NV_L2BKScrub 56 /* L2 ECC Background Scrubber CTL*/
|
||||
#define NV_L3BKScrub 57 /* L3 ECC Background Scrubber CTL*/
|
||||
#define NV_DCBKScrub 58 /* DCache ECC Background Scrubber CTL*/
|
||||
#define NV_CS_SpareCTL 59 /* Chip Select Spare Control bit 0:
|
||||
0 = disable Spare
|
||||
1 = enable Spare */
|
||||
/* Chip Select Spare Control bit 1-4:
|
||||
Reserved, must be zero*/
|
||||
#define NV_SyncOnUnEccEn 61 /* SyncOnUnEccEn control
|
||||
0 = disable
|
||||
1 = enable*/
|
||||
#define NV_Unganged 62
|
||||
|
||||
#define NV_ChannelIntlv 63 /* Channel Interleaving (3-bits)
|
||||
xx0b = disable
|
||||
yy1b = enable with DctSelIntLvAddr set to yyb */
|
||||
|
||||
#define NV_MAX_DIMMS_PER_CH 64 /* Maximum number of DIMMs per channel */
|
||||
|
||||
#include <northbridge/amd/amdfam10/amdfam10.h>
|
||||
|
||||
/*===============================================================================
|
||||
CBMEM storage
|
||||
===============================================================================*/
|
||||
struct amdmct_memory_info {
|
||||
struct MCTStatStruc mct_stat;
|
||||
struct DCTStatStruc dct_stat[MAX_NODES_SUPPORTED];
|
||||
uint16_t ecc_enabled;
|
||||
uint16_t ecc_scrub_rate;
|
||||
} __packed;
|
||||
|
||||
u32 Get_NB32(u32 dev, u32 reg);
|
||||
void Set_NB32(u32 dev, u32 reg, u32 val);
|
||||
u32 Get_NB32_index(u32 dev, u32 index_reg, u32 index);
|
||||
void Set_NB32_index(u32 dev, u32 index_reg, u32 index, u32 data);
|
||||
u32 Get_NB32_index_wait(u32 dev, u32 index_reg, u32 index);
|
||||
void Set_NB32_index_wait(u32 dev, u32 index_reg, u32 index, u32 data);
|
||||
u32 OtherTiming_A_D(struct DCTStatStruc *pDCTstat, u32 val);
|
||||
void mct_ForceAutoPrecharge_D(struct DCTStatStruc *pDCTstat, u32 dct);
|
||||
u32 Modify_D3CMP(struct DCTStatStruc *pDCTstat, u32 dct, u32 value);
|
||||
u8 mct_checkNumberOfDqsRcvEn_1Pass(u8 pass);
|
||||
u32 SetupDqsPattern_1PassA(u8 Pass);
|
||||
u32 SetupDqsPattern_1PassB(u8 Pass);
|
||||
u8 mct_Get_Start_RcvrEnDly_1Pass(u8 Pass);
|
||||
u8 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat, u8 RcvrEnDly, u8 RcvrEnDlyLimit, u8 Channel, u8 Receiver, u8 Pass);
|
||||
void CPUMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
uint64_t mctGetLogicalCPUID(u32 Node);
|
||||
u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
void TrainReceiverEn_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA, u8 Pass);
|
||||
void mct_TrainDQSPos_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
void mctSetEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
void TrainMaxReadLatency_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
void mct_EndDQSTraining_D(struct MCTStatStruc *pMCTstat,struct DCTStatStruc *pDCTstatA);
|
||||
void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u8 RcvrEnDly, u8 FinalValue, u8 Channel, u8 Receiver, u32 dev, u32 index_reg, u8 Addl_Index, u8 Pass);
|
||||
void SetEccDQSRcvrEn_D(struct DCTStatStruc *pDCTstat, u8 Channel);
|
||||
void mctGet_PS_Cfg_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u32 dct);
|
||||
void InterleaveBanks_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct);
|
||||
void mct_SetDramConfigHi_D(struct DCTStatStruc *pDCTstat, u32 dct, u32 DramConfigHi);
|
||||
void mct_DramInit_Hw_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct);
|
||||
void SyncSetting(struct DCTStatStruc *pDCTstat);
|
||||
void mct_SetClToNB_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
|
||||
void mct_SetWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
|
||||
void mct_TrainRcvrEn_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 Pass);
|
||||
void mct_EnableDimmEccEn_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 _DisableDramECC);
|
||||
u32 procOdtWorkaround(struct DCTStatStruc *pDCTstat, u32 dct, u32 val);
|
||||
void mct_BeforeDramInit_D(struct DCTStatStruc *pDCTstat, u32 dct);
|
||||
void InterleaveNodes_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
void InterleaveChannels_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
void mct_BeforeDQSTrain_Samp_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat);
|
||||
void StoreDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 ChipSel);
|
||||
void phyAssistedMemFnceTraining(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
u8 mct_SaveRcvEnDly_D_1Pass(struct DCTStatStruc *pDCTstat, u8 pass);
|
||||
u32 CheckNBCOFAutoPrechg(struct DCTStatStruc *pDCTstat, u32 dct);
|
||||
u8 mct_AdjustDQSPosDelay_D(struct DCTStatStruc *pDCTstat, u8 dly);
|
||||
void mct_AdjustScrub_D(struct DCTStatStruc *pDCTstat, u16 *scrub_request);
|
||||
u8 mct_InitReceiver_D(struct DCTStatStruc *pDCTstat, u8 dct);
|
||||
void mct_Wait(u32 cycles);
|
||||
u8 mct_RcvrRankEnabled_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 Channel, u8 ChipSel);
|
||||
u32 mct_GetRcvrSysAddr_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 channel, u8 receiver, u8 *valid);
|
||||
void mct_Read1LTestPattern_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u32 addr);
|
||||
void EarlySampleSupport_D(void);
|
||||
|
||||
void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA);
|
||||
void mct_AdjustDelayRange_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u8 *dqs_pos);
|
||||
void mct_EnableDatIntlv_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat);
|
||||
void MCTMemClrSync_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA);
|
||||
void beforeInterleaveChannels_D(struct DCTStatStruc *pDCTstatA, u8 *enabled);
|
||||
u8 mct_checkFenceHoleAdjust_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u8 DQSDelay,
|
||||
u8 ChipSel, u8 *result);
|
||||
void proc_IOCLFLUSH_D(u32 addr_hi);
|
||||
void mct_Write1LTestPattern_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat,
|
||||
u32 TestAddr, u8 pattern);
|
||||
u8 NodePresent_D(u8 Node);
|
||||
void DCTMemClr_Init_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat);
|
||||
void MCTMemClr_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA);
|
||||
void print_debug_dqs(const char *str, u32 val, u8 level);
|
||||
void print_debug_dqs_pair(const char *str, u32 val, const char *str2, u32 val2, u8 level);
|
||||
u8 mct_DisableDimmEccEn_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat);
|
||||
void ResetDCTWrPtr_D(u32 dev, u32 index_reg, u32 index);
|
||||
void SetTargetWTIO_D(u32 TestAddr);
|
||||
void ResetTargetWTIO_D(void);
|
||||
u32 mct_GetMCTSysAddr_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u8 Channel,
|
||||
u8 receiver, u8 *valid);
|
||||
#endif
|
||||
|
|
@ -1,351 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
inline void _WRMSR(u32 addr, u32 lo, u32 hi)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"wrmsr"
|
||||
:
|
||||
:"c"(addr),"a"(lo), "d" (hi)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
inline void _RDMSR(u32 addr, u32 *lo, u32 *hi)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"rdmsr"
|
||||
:"=a"(*lo), "=d" (*hi)
|
||||
:"c"(addr)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
inline void _RDTSC(u32 *lo, u32 *hi)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"rdtsc"
|
||||
: "=a" (*lo), "=d"(*hi)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
inline void _cpu_id(u32 addr, u32 *val)
|
||||
{
|
||||
__asm__ volatile(
|
||||
"cpuid"
|
||||
: "=a" (val[0]),
|
||||
"=b" (val[1]),
|
||||
"=c" (val[2]),
|
||||
"=d" (val[3])
|
||||
: "0" (addr));
|
||||
|
||||
}
|
||||
|
||||
|
||||
u32 bsr(u32 x)
|
||||
{
|
||||
u8 i;
|
||||
u32 ret = 0;
|
||||
|
||||
for (i = 31; i > 0; i--) {
|
||||
if (x & (1<<i)) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
u32 bsf(u32 x)
|
||||
{
|
||||
u8 i;
|
||||
u32 ret = 32;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (x & (1<<i)) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define _MFENCE asm volatile ("mfence")
|
||||
|
||||
#define _SFENCE asm volatile ("sfence")
|
||||
|
||||
/* prevent speculative execution of following instructions */
|
||||
#define _EXECFENCE asm volatile ("outb %al, $0xed")
|
||||
|
||||
#include <cpu/x86/cr.h>
|
||||
|
||||
void proc_CLFLUSH(u32 addr_hi)
|
||||
{
|
||||
SetUpperFSbase(addr_hi);
|
||||
|
||||
__asm__ volatile (
|
||||
/* clflush fs:[eax] */
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"clflush %%fs:(%0)\n\t"
|
||||
"mfence\n\t"
|
||||
::"a" (addr_hi<<8)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void WriteLNTestPattern(u32 addr_lo, u8 *buf_a, u32 line_num)
|
||||
{
|
||||
__asm__ volatile (
|
||||
/*prevent speculative execution of following instructions*/
|
||||
/* FIXME: needed ? */
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"1:\n\t"
|
||||
"movdqa (%3), %%xmm0\n\t"
|
||||
"movntdq %%xmm0, %%fs:(%0)\n\t" /* xmm0 is 128 bit */
|
||||
"addl %1, %0\n\t"
|
||||
"addl %1, %3\n\t"
|
||||
"loop 1b\n\t"
|
||||
"mfence\n\t"
|
||||
|
||||
:: "a" (addr_lo), "d" (16), "c" (line_num * 4), "b"(buf_a)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
u32 read32_fs(u32 addr_lo)
|
||||
{
|
||||
u32 value;
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"movl %%fs:(%1), %0\n\t"
|
||||
:"=b"(value): "a" (addr_lo)
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
#ifdef UNUSED_CODE
|
||||
static u8 read8_fs(u32 addr_lo)
|
||||
{
|
||||
u8 byte;
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"movb %%fs:(%1), %b0\n\t"
|
||||
"mfence\n\t"
|
||||
:"=b"(byte): "a" (addr_lo)
|
||||
);
|
||||
return byte;
|
||||
}
|
||||
#endif
|
||||
|
||||
void FlushDQSTestPattern_L9(u32 addr_lo)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"clflush %%fs:-128(%%ecx)\n\t"
|
||||
"clflush %%fs:-64(%%ecx)\n\t"
|
||||
"clflush %%fs:(%%ecx)\n\t"
|
||||
"clflush %%fs:64(%%ecx)\n\t"
|
||||
|
||||
"clflush %%fs:-128(%%eax)\n\t"
|
||||
"clflush %%fs:-64(%%eax)\n\t"
|
||||
"clflush %%fs:(%%eax)\n\t"
|
||||
"clflush %%fs:64(%%eax)\n\t"
|
||||
|
||||
"clflush %%fs:-128(%%ebx)\n\t"
|
||||
|
||||
:: "b" (addr_lo+128+8*64), "c"(addr_lo+128),
|
||||
"a"(addr_lo+128+4*64)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
__attribute__((noinline)) void FlushDQSTestPattern_L18(u32 addr_lo)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"clflush %%fs:-128(%%eax)\n\t"
|
||||
"clflush %%fs:-64(%%eax)\n\t"
|
||||
"clflush %%fs:(%%eax)\n\t"
|
||||
"clflush %%fs:64(%%eax)\n\t"
|
||||
|
||||
"clflush %%fs:-128(%%edi)\n\t"
|
||||
"clflush %%fs:-64(%%edi)\n\t"
|
||||
"clflush %%fs:(%%edi)\n\t"
|
||||
"clflush %%fs:64(%%edi)\n\t"
|
||||
|
||||
"clflush %%fs:-128(%%ebx)\n\t"
|
||||
"clflush %%fs:-64(%%ebx)\n\t"
|
||||
"clflush %%fs:(%%ebx)\n\t"
|
||||
"clflush %%fs:64(%%ebx)\n\t"
|
||||
|
||||
"clflush %%fs:-128(%%ecx)\n\t"
|
||||
"clflush %%fs:-64(%%ecx)\n\t"
|
||||
"clflush %%fs:(%%ecx)\n\t"
|
||||
"clflush %%fs:64(%%ecx)\n\t"
|
||||
|
||||
"clflush %%fs:-128(%%edx)\n\t"
|
||||
"clflush %%fs:-64(%%edx)\n\t"
|
||||
|
||||
:: "b" (addr_lo+128+8*64), "c" (addr_lo+128+12*64),
|
||||
"d" (addr_lo +128+16*64), "a"(addr_lo+128),
|
||||
"D"(addr_lo+128+4*64)
|
||||
);
|
||||
}
|
||||
|
||||
void ReadL18TestPattern(u32 addr_lo)
|
||||
{
|
||||
// set fs and use fs prefix to access the mem
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"movl %%fs:-128(%%esi), %%eax\n\t" //TestAddr cache line
|
||||
"movl %%fs:-64(%%esi), %%eax\n\t" //+1
|
||||
"movl %%fs:(%%esi), %%eax\n\t" //+2
|
||||
"movl %%fs:64(%%esi), %%eax\n\t" //+3
|
||||
|
||||
"movl %%fs:-128(%%edi), %%eax\n\t" //+4
|
||||
"movl %%fs:-64(%%edi), %%eax\n\t" //+5
|
||||
"movl %%fs:(%%edi), %%eax\n\t" //+6
|
||||
"movl %%fs:64(%%edi), %%eax\n\t" //+7
|
||||
|
||||
"movl %%fs:-128(%%ebx), %%eax\n\t" //+8
|
||||
"movl %%fs:-64(%%ebx), %%eax\n\t" //+9
|
||||
"movl %%fs:(%%ebx), %%eax\n\t" //+10
|
||||
"movl %%fs:64(%%ebx), %%eax\n\t" //+11
|
||||
|
||||
"movl %%fs:-128(%%ecx), %%eax\n\t" //+12
|
||||
"movl %%fs:-64(%%ecx), %%eax\n\t" //+13
|
||||
"movl %%fs:(%%ecx), %%eax\n\t" //+14
|
||||
"movl %%fs:64(%%ecx), %%eax\n\t" //+15
|
||||
|
||||
"movl %%fs:-128(%%edx), %%eax\n\t" //+16
|
||||
"movl %%fs:-64(%%edx), %%eax\n\t" //+17
|
||||
"mfence\n\t"
|
||||
|
||||
:: "a"(0), "b" (addr_lo+128+8*64), "c" (addr_lo+128+12*64),
|
||||
"d" (addr_lo +128+16*64), "S"(addr_lo+128),
|
||||
"D"(addr_lo+128+4*64)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
void ReadL9TestPattern(u32 addr_lo)
|
||||
{
|
||||
|
||||
// set fs and use fs prefix to access the mem
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
|
||||
"movl %%fs:-128(%%ecx), %%eax\n\t" //TestAddr cache line
|
||||
"movl %%fs:-64(%%ecx), %%eax\n\t" //+1
|
||||
"movl %%fs:(%%ecx), %%eax\n\t" //+2
|
||||
"movl %%fs:64(%%ecx), %%eax\n\t" //+3
|
||||
|
||||
"movl %%fs:-128(%%edx), %%eax\n\t" //+4
|
||||
"movl %%fs:-64(%%edx), %%eax\n\t" //+5
|
||||
"movl %%fs:(%%edx), %%eax\n\t" //+6
|
||||
"movl %%fs:64(%%edx), %%eax\n\t" //+7
|
||||
|
||||
"movl %%fs:-128(%%ebx), %%eax\n\t" //+8
|
||||
"mfence\n\t"
|
||||
|
||||
:: "a"(0), "b" (addr_lo+128+8*64), "c"(addr_lo+128),
|
||||
"d"(addr_lo+128+4*64)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
void ReadMaxRdLat1CLTestPattern_D(u32 addr)
|
||||
{
|
||||
SetUpperFSbase(addr);
|
||||
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"movl %%fs:-128(%%esi), %%eax\n\t" //TestAddr cache line
|
||||
"movl %%fs:-64(%%esi), %%eax\n\t" //+1
|
||||
"movl %%fs:(%%esi), %%eax\n\t" //+2
|
||||
"mfence\n\t"
|
||||
:: "a"(0), "S"((addr<<8)+128)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
void WriteMaxRdLat1CLTestPattern_D(u32 buf, u32 addr)
|
||||
{
|
||||
SetUpperFSbase(addr);
|
||||
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"1:\n\t"
|
||||
"movdqa (%3), %%xmm0\n\t"
|
||||
"movntdq %%xmm0, %%fs:(%0)\n\t" /* xmm0 is 128 bit */
|
||||
"addl %1, %0\n\t"
|
||||
"addl %1, %3\n\t"
|
||||
"loop 1b\n\t"
|
||||
"mfence\n\t"
|
||||
|
||||
:: "a" (addr<<8), "d" (16), "c" (3 * 4), "b"(buf)
|
||||
);
|
||||
}
|
||||
|
||||
void FlushMaxRdLatTestPattern_D(u32 addr)
|
||||
{
|
||||
/* Flush a pattern of 72 bit times (per DQ) from cache.
|
||||
* This procedure is used to ensure cache miss on the next read training.
|
||||
*/
|
||||
|
||||
SetUpperFSbase(addr);
|
||||
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"clflush %%fs:-128(%%esi)\n\t" //TestAddr cache line
|
||||
"clflush %%fs:-64(%%esi)\n\t" //+1
|
||||
"clflush %%fs:(%%esi)\n\t" //+2
|
||||
"mfence\n\t"
|
||||
|
||||
:: "S"((addr<<8)+128)
|
||||
);
|
||||
}
|
||||
|
||||
u32 stream_to_int(u8 const *p)
|
||||
{
|
||||
int i;
|
||||
u32 val;
|
||||
u32 valx;
|
||||
|
||||
val = 0;
|
||||
|
||||
for (i = 3; i >= 0; i--) {
|
||||
val <<= 8;
|
||||
valx = *(p+i);
|
||||
val |= valx;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
u8 oemNodePresent_D(u8 Node, u8 *ret)
|
||||
{
|
||||
*ret = 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MCT_D_GCC_H
|
||||
#define MCT_D_GCC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void _WRMSR(u32 addr, u32 lo, u32 hi);
|
||||
void _RDMSR(u32 addr, u32 *lo, u32 *hi);
|
||||
void _RDTSC(u32 *lo, u32 *hi);
|
||||
void _cpu_id(u32 addr, u32 *val);
|
||||
u32 bsr(u32 x);
|
||||
u32 bsf(u32 x);
|
||||
|
||||
#define _MFENCE asm volatile ("mfence")
|
||||
#define _SFENCE asm volatile ("sfence")
|
||||
|
||||
/* prevent speculative execution of following instructions */
|
||||
#define _EXECFENCE asm volatile ("outb %al, $0xed")
|
||||
|
||||
u32 SetUpperFSbase(u32 addr_hi);
|
||||
void proc_CLFLUSH(u32 addr_hi);
|
||||
void WriteLNTestPattern(u32 addr_lo, u8 *buf_a, u32 line_num);
|
||||
u32 read32_fs(u32 addr_lo);
|
||||
void FlushDQSTestPattern_L9(u32 addr_lo);
|
||||
__attribute__((noinline)) void FlushDQSTestPattern_L18(u32 addr_lo);
|
||||
void ReadL18TestPattern(u32 addr_lo);
|
||||
void ReadL9TestPattern(u32 addr_lo);
|
||||
void ReadMaxRdLat1CLTestPattern_D(u32 addr);
|
||||
void WriteMaxRdLat1CLTestPattern_D(u32 buf, u32 addr);
|
||||
void FlushMaxRdLatTestPattern_D(u32 addr);
|
||||
u32 stream_to_int(u8 const *p);
|
||||
u8 oemNodePresent_D(u8 Node, u8 *ret);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,179 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mct_d.h"
|
||||
|
||||
static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload,
|
||||
u8 DATAAload, u32 *AddrTmgCTL, u32 *ODC_CTL);
|
||||
|
||||
|
||||
void mctGet_PS_Cfg_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u32 dct)
|
||||
{
|
||||
u16 val, valx;
|
||||
|
||||
print_tx("dct: ", dct);
|
||||
print_tx("Speed: ", pDCTstat->Speed);
|
||||
|
||||
Get_ChannelPS_Cfg0_D(pDCTstat->MAdimms[dct], pDCTstat->Speed,
|
||||
pDCTstat->MAload[dct], pDCTstat->DATAload[dct],
|
||||
&(pDCTstat->CH_ADDR_TMG[dct]), &(pDCTstat->CH_ODC_CTL[dct]));
|
||||
|
||||
|
||||
if (pDCTstat->MAdimms[dct] == 1)
|
||||
pDCTstat->CH_ODC_CTL[dct] |= 0x20000000; /* 75ohms */
|
||||
else
|
||||
pDCTstat->CH_ODC_CTL[dct] |= 0x10000000; /* 150ohms */
|
||||
|
||||
pDCTstat->_2Tmode = 1;
|
||||
|
||||
/* use byte lane 4 delay for ECC lane */
|
||||
pDCTstat->CH_EccDQSLike[0] = 0x0504;
|
||||
pDCTstat->CH_EccDQSScale[0] = 0; /* 100% byte lane 4 */
|
||||
pDCTstat->CH_EccDQSLike[1] = 0x0504;
|
||||
pDCTstat->CH_EccDQSScale[1] = 0; /* 100% byte lane 4 */
|
||||
|
||||
|
||||
/*
|
||||
Overrides and/or exceptions
|
||||
*/
|
||||
|
||||
/* 1) QRx4 needs to adjust CS/ODT setup time */
|
||||
// FIXME: Add Ax support?
|
||||
if (mctGet_NVbits(NV_MAX_DIMMS) == 4) {
|
||||
if (pDCTstat->DimmQRPresent != 0) {
|
||||
pDCTstat->CH_ADDR_TMG[dct] &= 0xFF00FFFF;
|
||||
pDCTstat->CH_ADDR_TMG[dct] |= 0x00000000;
|
||||
if (pDCTstat->MAdimms[dct] == 4) {
|
||||
pDCTstat->CH_ADDR_TMG[dct] &= 0xFF00FFFF;
|
||||
pDCTstat->CH_ADDR_TMG[dct] |= 0x002F0000;
|
||||
if (pDCTstat->Speed == 3 || pDCTstat->Speed == 4) {
|
||||
pDCTstat->CH_ADDR_TMG[dct] &= 0xFF00FFFF;
|
||||
pDCTstat->CH_ADDR_TMG[dct] |= 0x00002F00;
|
||||
if (pDCTstat->MAdimms[dct] == 4)
|
||||
pDCTstat->CH_ODC_CTL[dct] = 0x00331222;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 2) DRx4 (R/C-J) @ DDR667 needs to adjust CS/ODT setup time */
|
||||
if (pDCTstat->Speed == 3 || pDCTstat->Speed == 4) {
|
||||
val = pDCTstat->Dimmx4Present;
|
||||
if (dct == 0) {
|
||||
val &= 0x55;
|
||||
} else {
|
||||
val &= 0xAA;
|
||||
val >>= 1;
|
||||
}
|
||||
val &= pDCTstat->DIMMValid;
|
||||
if (val) {
|
||||
//FIXME: skip for Ax
|
||||
valx = pDCTstat->DimmDRPresent;
|
||||
if (dct == 0) {
|
||||
valx &= 0x55;
|
||||
} else {
|
||||
valx &= 0xAA;
|
||||
valx >>= 1;
|
||||
}
|
||||
val &= valx;
|
||||
if (val != 0) {
|
||||
if (mctGet_NVbits(NV_MAX_DIMMS) == 8 ||
|
||||
pDCTstat->Speed == 3) {
|
||||
pDCTstat->CH_ADDR_TMG[dct] &= 0xFFFF00FF;
|
||||
pDCTstat->CH_ADDR_TMG[dct] |= 0x00002F00;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pDCTstat->CH_ODC_CTL[dct] = procOdtWorkaround(pDCTstat, dct, pDCTstat->CH_ODC_CTL[dct]);
|
||||
|
||||
print_tx("CH_ODC_CTL: ", pDCTstat->CH_ODC_CTL[dct]);
|
||||
print_tx("CH_ADDR_TMG: ", pDCTstat->CH_ADDR_TMG[dct]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*===============================================================================
|
||||
* Vendor is responsible for correct settings.
|
||||
* M2/Unbuffered 4 Slot - AMD Design Guideline.
|
||||
*===============================================================================
|
||||
* #1, BYTE, Speed (DCTStatstruc.Speed) (Secondary Key)
|
||||
* #2, BYTE, number of Address bus loads on the Channel. (Tershery Key)
|
||||
* These must be listed in ascending order.
|
||||
* FFh (0xFE) has special meaning of 'any', and must be listed first for each speed grade.
|
||||
* #3, DWORD, Address Timing Control Register Value
|
||||
* #4, DWORD, Output Driver Compensation Control Register Value
|
||||
* #5, BYTE, Number of DIMMs (Primary Key)
|
||||
*/
|
||||
static const u8 Table_ATC_ODC_8D_D[] = {
|
||||
0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x22, 0x12, 0x11, 0x00, 1,
|
||||
0xFE, 0xFF, 0x00, 0x00, 0x37, 0x00, 0x22, 0x12, 0x11, 0x00, 2,
|
||||
1, 0xFF, 0x00, 0x00, 0x2F, 0x00, 0x22, 0x12, 0x11, 0x00, 3,
|
||||
2, 0xFF, 0x00, 0x00, 0x2F, 0x00, 0x22, 0x12, 0x11, 0x00, 3,
|
||||
3, 0xFF, 0x2F, 0x00, 0x2F, 0x00, 0x22, 0x12, 0x11, 0x00, 3,
|
||||
4, 0xFF, 0x2F, 0x00, 0x2F, 0x00, 0x22, 0x12, 0x33, 0x00, 3,
|
||||
1, 0xFF, 0x00, 0x00, 0x2F, 0x00, 0x22, 0x12, 0x11, 0x00, 4,
|
||||
2, 0xFF, 0x00, 0x00, 0x2F, 0x00, 0x22, 0x12, 0x11, 0x00, 4,
|
||||
3, 0xFF, 0x2F, 0x00, 0x2F, 0x00, 0x22, 0x12, 0x33, 0x00, 4,
|
||||
4, 0xFF, 0x2F, 0x00, 0x2F, 0x00, 0x22, 0x12, 0x33, 0x00, 4,
|
||||
0xFF
|
||||
};
|
||||
|
||||
static const u8 Table_ATC_ODC_4D_D[] = {
|
||||
0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x22, 0x12, 0x11, 0x00, 1,
|
||||
0xFE, 0xFF, 0x00, 0x00, 0x37, 0x00, 0x22, 0x12, 0x11, 0x00, 2,
|
||||
0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x22, 0x12, 0x11, 0x00, 3,
|
||||
0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x22, 0x12, 0x11, 0x00, 4,
|
||||
0xFF
|
||||
};
|
||||
|
||||
|
||||
static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload,
|
||||
u8 DATAAload, u32 *AddrTmgCTL, u32 *ODC_CTL)
|
||||
{
|
||||
const u8 *p;
|
||||
|
||||
*AddrTmgCTL = 0;
|
||||
*ODC_CTL = 0;
|
||||
|
||||
if (mctGet_NVbits(NV_MAX_DIMMS) == 8) {
|
||||
/* 8 DIMM Table */
|
||||
p = Table_ATC_ODC_8D_D;
|
||||
//FIXME Add Ax support
|
||||
} else {
|
||||
/* 4 DIMM Table*/
|
||||
p = Table_ATC_ODC_4D_D;
|
||||
//FIXME Add Ax support
|
||||
}
|
||||
|
||||
while (*p != 0xFF) {
|
||||
if ((MAAdimms == *(p+10)) || (*(p+10) == 0xFE)) {
|
||||
if ((*p == Speed) || (*p == 0xFE)) {
|
||||
if (MAAload <= *(p+1)) {
|
||||
*AddrTmgCTL = stream_to_int((u8*)(p+2));
|
||||
*ODC_CTL = stream_to_int((u8*)(p+6));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
p+=11;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mct_d.h"
|
||||
|
||||
static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload,
|
||||
u8 DATAAload, u32 *AddrTmgCTL, u32 *ODC_CTL,
|
||||
u8 *CMDmode);
|
||||
|
||||
|
||||
void mctGet_PS_Cfg_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u32 dct)
|
||||
{
|
||||
print_tx("dct: ", dct);
|
||||
print_tx("Speed: ", pDCTstat->Speed);
|
||||
|
||||
Get_ChannelPS_Cfg0_D(pDCTstat->MAdimms[dct], pDCTstat->Speed,
|
||||
pDCTstat->MAload[dct], pDCTstat->DATAload[dct],
|
||||
&(pDCTstat->CH_ADDR_TMG[dct]), &(pDCTstat->CH_ODC_CTL[dct]),
|
||||
&pDCTstat->_2Tmode);
|
||||
|
||||
if (pDCTstat->MAdimms[dct] == 1)
|
||||
pDCTstat->CH_ODC_CTL[dct] |= 0x20000000; /* 75ohms */
|
||||
else
|
||||
pDCTstat->CH_ODC_CTL[dct] |= 0x10000000; /* 150ohms */
|
||||
|
||||
|
||||
/*
|
||||
* Overrides and/or workarounds
|
||||
*/
|
||||
pDCTstat->CH_ODC_CTL[dct] = procOdtWorkaround(pDCTstat, dct, pDCTstat->CH_ODC_CTL[dct]);
|
||||
|
||||
print_tx("4 CH_ODC_CTL: ", pDCTstat->CH_ODC_CTL[dct]);
|
||||
print_tx("4 CH_ADDR_TMG: ", pDCTstat->CH_ADDR_TMG[dct]);
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
* Vendor is responsible for correct settings.
|
||||
* M2/Unbuffered 4 Slot - AMD Design Guideline.
|
||||
*=============================================================================
|
||||
* #1, BYTE, Speed (DCTStatstruc.Speed)
|
||||
* #2, BYTE, number of Address bus loads on the Channel.
|
||||
* These must be listed in ascending order.
|
||||
* FFh (-1) has special meaning of 'any', and must be listed first for
|
||||
* each speed grade.
|
||||
* #3, DWORD, Address Timing Control Register Value
|
||||
* #4, DWORD, Output Driver Compensation Control Register Value
|
||||
*/
|
||||
|
||||
static const u8 Table_ATC_ODC_D_Bx[] = {
|
||||
1, 0xFF, 0x00, 0x2F, 0x2F, 0x0, 0x22, 0x13, 0x11, 0x0,
|
||||
2, 12, 0x00, 0x2F, 0x2F, 0x0, 0x22, 0x13, 0x11, 0x0,
|
||||
2, 16, 0x00, 0x2F, 0x00, 0x0, 0x22, 0x13, 0x11, 0x0,
|
||||
2, 20, 0x00, 0x2F, 0x38, 0x0, 0x22, 0x13, 0x11, 0x0,
|
||||
2, 24, 0x00, 0x2F, 0x37, 0x0, 0x22, 0x13, 0x11, 0x0,
|
||||
2, 32, 0x00, 0x2F, 0x34, 0x0, 0x22, 0x13, 0x11, 0x0,
|
||||
3, 12, 0x20, 0x22, 0x20, 0x0, 0x22, 0x13, 0x11, 0x0,
|
||||
3, 16, 0x20, 0x22, 0x30, 0x0, 0x22, 0x13, 0x11, 0x0,
|
||||
3, 20, 0x20, 0x22, 0x2C, 0x0, 0x22, 0x13, 0x11, 0x0,
|
||||
3, 24, 0x20, 0x22, 0x2A, 0x0, 0x22, 0x13, 0x11, 0x0,
|
||||
3, 32, 0x20, 0x22, 0x2B, 0x0, 0x22, 0x13, 0x11, 0x0,
|
||||
4, 0xFF, 0x20, 0x25, 0x20, 0x0, 0x22, 0x33, 0x11, 0x0,
|
||||
5, 0xFF, 0x20, 0x20, 0x2F, 0x0, 0x22, 0x32, 0x11, 0x0,
|
||||
0xFF
|
||||
};
|
||||
|
||||
|
||||
static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload,
|
||||
u8 DATAAload, u32 *AddrTmgCTL, u32 *ODC_CTL,
|
||||
u8 *CMDmode)
|
||||
{
|
||||
u8 const *p;
|
||||
|
||||
*AddrTmgCTL = 0;
|
||||
*ODC_CTL = 0;
|
||||
*CMDmode = 1;
|
||||
|
||||
// FIXME: add Ax support
|
||||
if (MAAdimms == 0) {
|
||||
*ODC_CTL = 0x00111222;
|
||||
if (Speed == 3)
|
||||
*AddrTmgCTL = 0x00202220;
|
||||
else if (Speed == 2)
|
||||
*AddrTmgCTL = 0x002F2F00;
|
||||
else if (Speed == 1)
|
||||
*AddrTmgCTL = 0x002F2F00;
|
||||
else if (Speed == 4)
|
||||
*AddrTmgCTL = 0x00202520;
|
||||
else if (Speed == 5)
|
||||
*AddrTmgCTL = 0x002F2020;
|
||||
else
|
||||
*AddrTmgCTL = 0x002F2F2F;
|
||||
} else if (MAAdimms == 1) {
|
||||
if (Speed == 4) {
|
||||
*CMDmode = 2;
|
||||
*AddrTmgCTL = 0x00202520;
|
||||
*ODC_CTL = 0x00113222;
|
||||
} else if (Speed == 5) {
|
||||
*CMDmode = 2;
|
||||
*AddrTmgCTL = 0x002F2020;
|
||||
*ODC_CTL = 0x00113222;
|
||||
} else {
|
||||
*CMDmode = 1;
|
||||
*ODC_CTL = 0x00111222;
|
||||
if (Speed == 3) {
|
||||
*AddrTmgCTL = 0x00202220;
|
||||
} else if (Speed == 2) {
|
||||
if (MAAload == 4)
|
||||
*AddrTmgCTL = 0x002B2F00;
|
||||
else if (MAAload == 16)
|
||||
*AddrTmgCTL = 0x002B2F00;
|
||||
else if (MAAload == 8)
|
||||
*AddrTmgCTL = 0x002F2F00;
|
||||
else
|
||||
*AddrTmgCTL = 0x002F2F00;
|
||||
} else if (Speed == 1) {
|
||||
*AddrTmgCTL = 0x002F2F00;
|
||||
} else {
|
||||
*AddrTmgCTL = 0x002F2F2F;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*CMDmode = 2;
|
||||
p = Table_ATC_ODC_D_Bx;
|
||||
do {
|
||||
if (Speed == *p) {
|
||||
if (MAAload <= *(p+1)) {
|
||||
*AddrTmgCTL = stream_to_int(p+2);
|
||||
*ODC_CTL = stream_to_int(p+6);
|
||||
break;
|
||||
}
|
||||
}
|
||||
p+=10;
|
||||
} while (*p == 0xff);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mct_d.h"
|
||||
|
||||
void InterleaveChannels_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
|
||||
u8 Node;
|
||||
u32 DramBase, DctSelBase;
|
||||
u8 DctSelIntLvAddr, DctSelHi;
|
||||
u8 HoleValid = 0;
|
||||
u32 HoleSize, HoleBase = 0;
|
||||
u32 val, tmp;
|
||||
u32 dct0_size, dct1_size;
|
||||
u8 enabled;
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
|
||||
/* HoleValid - indicates whether the current Node contains hole.
|
||||
* HoleSize - indicates whether there is IO hole in the whole system
|
||||
* memory.
|
||||
*/
|
||||
|
||||
/* call back to wrapper not needed ManualChannelInterleave_D(); */
|
||||
/* call back - DctSelIntLvAddr = mctGet_NVbits(NV_ChannelIntlv);*/ /* override interleave */
|
||||
// FIXME: Check for Cx
|
||||
DctSelIntLvAddr = mctGet_NVbits(NV_ChannelIntlv); /* typ = 5: Hash*: exclusive OR of address bits[20:16, 6]. */
|
||||
beforeInterleaveChannels_D(pDCTstatA, &enabled);
|
||||
|
||||
if (DctSelIntLvAddr & 1) {
|
||||
DctSelIntLvAddr >>= 1;
|
||||
HoleSize = 0;
|
||||
if ((pMCTstat->GStatus & (1 << GSB_SoftHole)) ||
|
||||
(pMCTstat->GStatus & (1 << GSB_HWHole))) {
|
||||
if (pMCTstat->HoleBase) {
|
||||
HoleBase = pMCTstat->HoleBase >> 8;
|
||||
HoleSize = HoleBase & 0xFFFF0000;
|
||||
HoleSize |= ((~HoleBase) + 1) & 0xFFFF;
|
||||
}
|
||||
}
|
||||
Node = 0;
|
||||
while (Node < MAX_NODES_SUPPORTED) {
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
val = Get_NB32(pDCTstat->dev_map, 0xF0);
|
||||
if (val & (1 << DramHoleValid))
|
||||
HoleValid = 1;
|
||||
if (!pDCTstat->GangedMode && pDCTstat->DIMMValidDCT[0] && pDCTstat->DIMMValidDCT[1]) {
|
||||
DramBase = pDCTstat->NodeSysBase >> 8;
|
||||
dct1_size = ((pDCTstat->NodeSysLimit) + 2) >> 8;
|
||||
dct0_size = Get_NB32(pDCTstat->dev_dct, 0x114);
|
||||
if (dct0_size >= 0x10000) {
|
||||
dct0_size -= HoleSize;
|
||||
}
|
||||
|
||||
dct0_size -= DramBase;
|
||||
dct1_size -= dct0_size;
|
||||
DctSelHi = 0x05; /* DctSelHiRngEn = 1, DctSelHi = 0 */
|
||||
if (dct1_size == dct0_size) {
|
||||
dct1_size = 0;
|
||||
DctSelHi = 0x04; /* DctSelHiRngEn = 0 */
|
||||
} else if (dct1_size > dct0_size) {
|
||||
dct1_size = dct0_size;
|
||||
DctSelHi = 0x07; /* DctSelHiRngEn = 1, DctSelHi = 1 */
|
||||
}
|
||||
dct0_size = dct1_size;
|
||||
dct0_size += DramBase;
|
||||
dct0_size += dct1_size;
|
||||
if (dct0_size >= HoleBase) /* if DctSelBaseAddr > HoleBase */
|
||||
dct0_size += HoleSize;
|
||||
DctSelBase = dct0_size;
|
||||
|
||||
if (dct1_size == 0)
|
||||
dct0_size = 0;
|
||||
dct0_size -= dct1_size; /* DctSelBaseOffset = DctSelBaseAddr - Interleaved region */
|
||||
Set_NB32(pDCTstat->dev_dct, 0x114, dct0_size);
|
||||
|
||||
if (dct1_size == 0)
|
||||
dct1_size = DctSelBase;
|
||||
val = Get_NB32(pDCTstat->dev_dct, 0x110);
|
||||
val &= 0x7F8;
|
||||
val |= dct1_size;
|
||||
val |= DctSelHi;
|
||||
val |= (DctSelIntLvAddr << 6) & 0xFF;
|
||||
Set_NB32(pDCTstat->dev_dct, 0x110, val);
|
||||
print_tx("InterleaveChannels: F2x110 DRAM Controller Select Low Register = ", val);
|
||||
|
||||
if (HoleValid) {
|
||||
tmp = DramBase;
|
||||
val = DctSelBase;
|
||||
if (val < HoleBase) { /* DctSelBaseAddr < DramHoleBase */
|
||||
val -= DramBase;
|
||||
val >>= 1;
|
||||
tmp += val;
|
||||
}
|
||||
tmp += HoleSize;
|
||||
val = Get_NB32(pDCTstat->dev_map, 0xF0); /* DramHoleOffset */
|
||||
val &= 0xFFFF007F;
|
||||
val |= (tmp & ~0xFFFF007F);
|
||||
Set_NB32(pDCTstat->dev_map, 0xF0, val);
|
||||
print_tx("InterleaveChannels: F1xF0 DRAM Hole Address Register = ", val);
|
||||
|
||||
}
|
||||
}
|
||||
print_tx("InterleaveChannels_D: Node ", Node);
|
||||
print_tx("InterleaveChannels_D: Status ", pDCTstat->Status);
|
||||
print_tx("InterleaveChannels_D: ErrStatus ", pDCTstat->ErrStatus);
|
||||
print_tx("InterleaveChannels_D: ErrCode ", pDCTstat->ErrCode);
|
||||
Node++;
|
||||
}
|
||||
}
|
||||
print_t("InterleaveChannels_D: Done\n");
|
||||
}
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mct_d.h"
|
||||
|
||||
/* Low swap bit vs bank size encoding (physical, not logical address bit)
|
||||
* ;To calculate the number by hand, add the number of Bank address bits
|
||||
* ;(2 or 3) to the number of column address bits, plus 3 (the logical
|
||||
* ;page size), and subtract 8.
|
||||
*/
|
||||
static const u8 Tab_int_D[] = { 6,7,7,8,8,8,8,8,9,9,8,9 };
|
||||
|
||||
void InterleaveBanks_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u8 dct)
|
||||
{
|
||||
u8 ChipSel, EnChipSels;
|
||||
u32 AddrLoMask, AddrHiMask;
|
||||
u32 AddrLoMaskN, AddrHiMaskN, MemSize = 0;
|
||||
u8 DoIntlv, _CsIntCap;
|
||||
u32 BitDelta, BankEncd = 0;
|
||||
|
||||
u32 dev;
|
||||
u32 reg;
|
||||
u32 reg_off;
|
||||
u32 val;
|
||||
u32 val_lo, val_hi;
|
||||
|
||||
DoIntlv = mctGet_NVbits(NV_BankIntlv);
|
||||
_CsIntCap = 0;
|
||||
EnChipSels = 0;
|
||||
|
||||
dev = pDCTstat->dev_dct;
|
||||
reg_off = 0x100 * dct;
|
||||
|
||||
ChipSel = 0; /* Find out if current configuration is capable */
|
||||
while (DoIntlv && (ChipSel < MAX_CS_SUPPORTED)) {
|
||||
reg = 0x40+(ChipSel << 2) + reg_off; /* Dram CS Base 0 */
|
||||
val = Get_NB32(dev, reg);
|
||||
if (val & (1 << CSEnable)) {
|
||||
EnChipSels++;
|
||||
reg = 0x60+((ChipSel >> 1) << 2)+reg_off; /*Dram CS Mask 0 */
|
||||
val = Get_NB32(dev, reg);
|
||||
val >>= 19;
|
||||
val &= 0x3ff;
|
||||
val++;
|
||||
if (EnChipSels == 1)
|
||||
MemSize = val;
|
||||
else
|
||||
/*If mask sizes not same then skip */
|
||||
if (val != MemSize)
|
||||
break;
|
||||
reg = 0x80 + reg_off; /*Dram Bank Addressing */
|
||||
val = Get_NB32(dev, reg);
|
||||
val >>= (ChipSel >> 1) << 2;
|
||||
val &= 0x0f;
|
||||
if (EnChipSels == 1)
|
||||
BankEncd = val;
|
||||
else
|
||||
/*If number of Rows/Columns not equal, skip */
|
||||
if (val != BankEncd)
|
||||
break;
|
||||
}
|
||||
ChipSel++;
|
||||
}
|
||||
if (ChipSel == MAX_CS_SUPPORTED) {
|
||||
if ((EnChipSels == 2) || (EnChipSels == 4) || (EnChipSels == 8))
|
||||
_CsIntCap = 1;
|
||||
}
|
||||
|
||||
if (DoIntlv) {
|
||||
if (!_CsIntCap) {
|
||||
pDCTstat->ErrStatus |= 1 << SB_BkIntDis;
|
||||
DoIntlv = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (DoIntlv) {
|
||||
val = Tab_int_D[BankEncd];
|
||||
if (pDCTstat->Status & (1 << SB_128bitmode))
|
||||
val++;
|
||||
|
||||
AddrLoMask = (EnChipSels - 1) << val;
|
||||
AddrLoMaskN = ~AddrLoMask;
|
||||
|
||||
val = bsf(MemSize) + 19;
|
||||
AddrHiMask = (EnChipSels -1) << val;
|
||||
AddrHiMaskN = ~AddrHiMask;
|
||||
|
||||
BitDelta = bsf(AddrHiMask) - bsf(AddrLoMask);
|
||||
|
||||
for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel++) {
|
||||
reg = 0x40+(ChipSel << 2) + reg_off; /*Dram CS Base 0 */
|
||||
val = Get_NB32(dev, reg);
|
||||
if (val & 3) {
|
||||
val_lo = val & AddrLoMask;
|
||||
val_hi = val & AddrHiMask;
|
||||
val &= AddrLoMaskN;
|
||||
val &= AddrHiMaskN;
|
||||
val_lo <<= BitDelta;
|
||||
val_hi >>= BitDelta;
|
||||
val |= val_lo;
|
||||
val |= val_hi;
|
||||
Set_NB32(dev, reg, val);
|
||||
|
||||
if (ChipSel & 1)
|
||||
continue;
|
||||
|
||||
reg = 0x60 + ((ChipSel >> 1) << 2) + reg_off; /*Dram CS Mask 0 */
|
||||
val = Get_NB32(dev, reg);
|
||||
val_lo = val & AddrLoMask;
|
||||
val_hi = val & AddrHiMask;
|
||||
val &= AddrLoMaskN;
|
||||
val &= AddrHiMaskN;
|
||||
val_lo <<= BitDelta;
|
||||
val_hi >>= BitDelta;
|
||||
val |= val_lo;
|
||||
val |= val_hi;
|
||||
Set_NB32(dev, reg, val);
|
||||
}
|
||||
}
|
||||
print_t("InterleaveBanks_D: Banks Interleaved ");
|
||||
} /* DoIntlv */
|
||||
|
||||
print_tx("InterleaveBanks_D: Status ", pDCTstat->Status);
|
||||
print_tx("InterleaveBanks_D: ErrStatus ", pDCTstat->ErrStatus);
|
||||
print_tx("InterleaveBanks_D: ErrCode ", pDCTstat->ErrCode);
|
||||
print_t("InterleaveBanks_D: Done\n");
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,314 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include "mct_d.h"
|
||||
|
||||
static void setSyncOnUnEccEn_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA);
|
||||
#ifdef UNUSED_CODE
|
||||
static u32 GetScrubAddr_D(u32 Node);
|
||||
#endif
|
||||
static u8 isDramECCEn_D(struct DCTStatStruc *pDCTstat);
|
||||
|
||||
|
||||
/* Initialize ECC modes of Integrated Dram+Memory Controllers of a network of
|
||||
* Hammer processors. Use Dram background scrubber to fast initialize ECC bits
|
||||
* of all dram.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Order that items are set:
|
||||
* 1. eccen bit in NB
|
||||
* 2. Scrub Base
|
||||
* 3. Temp Node Base
|
||||
* 4. Temp Node Limit
|
||||
* 5. Redir bit in NB
|
||||
* 6. Scrub CTL
|
||||
*
|
||||
* Conditions for setting background scrubber.
|
||||
* 1. node is present
|
||||
* 2. node has dram functioning (WE = RE = 1)
|
||||
* 3. all eccdimms (or bit 17 of offset 90,fn 2)
|
||||
* 4. no chip-select gap exists
|
||||
*
|
||||
* The dram background scrubber is used under very controlled circumstances to
|
||||
* initialize all the ECC bits on the DIMMs of the entire dram address map
|
||||
* (including hidden or lost dram and dram above 4GB). We will turn the scrub
|
||||
* rate up to maximum, which should clear 4GB of dram in about 2.7 seconds.
|
||||
* We will activate the scrubbers of all nodes with ecc dram and let them run in
|
||||
* parallel, thereby reducing even further the time required to condition dram.
|
||||
* Finally, we will go through each node and either disable background scrubber,
|
||||
* or set the scrub rate to the user setup specified rate.
|
||||
*
|
||||
* To allow the NB to scrub, we need to wait a time period long enough to
|
||||
* guarantee that the NB scrubs the entire dram on its node. Do do this, we
|
||||
* simply sample the scrub ADDR once, for an initial value, then we sample and poll until the polled value of scrub ADDR
|
||||
* has wrapped around at least once: Scrub ADDRi+1 < Scrub ADDRi. Since we let all
|
||||
* Nodes run in parallel, we need to guarantee that all nodes have wrapped. To do
|
||||
* this efficiently, we need only to sample one of the nodes, the node with the
|
||||
* largest ammount of dram populated is the one which will take the longest amount
|
||||
* of time (the scrub rate is set to max, the same rate, on all nodes). So,
|
||||
* during setup of scrub Base, we determine how much memory and which node has
|
||||
* the largest memory installed.
|
||||
*
|
||||
* Scrubbing should not ordinarily be enabled on a Node with a chip-select gap
|
||||
* (aka SW memhole, cs hoisting, etc..).To init ECC memory on this node, the
|
||||
* scrubber is used in two steps. First, the Dram Limit for the node is adjusted
|
||||
* down to the bottom of the gap, and that ECC dram is initialized. Second, the
|
||||
* original Limit is restored, the Scrub base is set to 4GB, and scrubber is
|
||||
* allowed to run until the Scrub Addr wraps around to zero.
|
||||
*/
|
||||
u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
u8 Node;
|
||||
u8 AllECC;
|
||||
u16 OB_NBECC;
|
||||
u32 curBase;
|
||||
u16 OB_ECCRedir;
|
||||
u32 LDramECC;
|
||||
u32 OF_ScrubCTL;
|
||||
u8 MemClrECC;
|
||||
|
||||
u32 dev;
|
||||
u32 reg;
|
||||
u32 val;
|
||||
u16 nvbits;
|
||||
|
||||
mctHookBeforeECC();
|
||||
|
||||
/* Construct these booleans, based on setup options, for easy handling
|
||||
later in this procedure */
|
||||
OB_NBECC = mctGet_NVbits(NV_NBECC); /* MCA ECC (MCE) enable bit */
|
||||
|
||||
OB_ECCRedir = mctGet_NVbits(NV_ECCRedir); /* ECC Redirection */
|
||||
|
||||
mctGet_NVbits(NV_ChipKill); /* ECC Chip-kill mode */
|
||||
|
||||
OF_ScrubCTL = 0; /* Scrub CTL for Dcache, L2, and dram */
|
||||
nvbits = mctGet_NVbits(NV_DCBKScrub);
|
||||
mct_AdjustScrub_D(pDCTstatA, &nvbits);
|
||||
OF_ScrubCTL |= (u32) nvbits << 16;
|
||||
|
||||
nvbits = mctGet_NVbits(NV_L2BKScrub);
|
||||
OF_ScrubCTL |= (u32) nvbits << 8;
|
||||
|
||||
nvbits = mctGet_NVbits(NV_DramBKScrub);
|
||||
OF_ScrubCTL |= nvbits;
|
||||
|
||||
AllECC = 1;
|
||||
MemClrECC = 0;
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
LDramECC = 0;
|
||||
if (NodePresent_D(Node)) { /*If Node is present */
|
||||
dev = pDCTstat->dev_map;
|
||||
reg = 0x40+(Node << 3); /* Dram Base Node 0 + index */
|
||||
val = Get_NB32(dev, reg);
|
||||
|
||||
/* WE/RE is checked */
|
||||
if ((val & 3) == 3) { /* Node has dram populated */
|
||||
/* Negate 'all nodes/dimms ECC' flag if non ecc
|
||||
memory populated */
|
||||
if (pDCTstat->Status & (1 << SB_ECCDIMMs)) {
|
||||
LDramECC = isDramECCEn_D(pDCTstat);
|
||||
if (pDCTstat->ErrCode != SC_RunningOK) {
|
||||
pDCTstat->Status &= ~(1 << SB_ECCDIMMs);
|
||||
if (!OB_NBECC) {
|
||||
pDCTstat->ErrStatus |= (1 << SB_DramECCDis);
|
||||
}
|
||||
AllECC = 0;
|
||||
LDramECC =0;
|
||||
}
|
||||
} else {
|
||||
AllECC = 0;
|
||||
}
|
||||
if (LDramECC) { /* if ECC is enabled on this dram */
|
||||
if (OB_NBECC) {
|
||||
mct_EnableDatIntlv_D(pMCTstat, pDCTstat);
|
||||
dev = pDCTstat->dev_nbmisc;
|
||||
reg =0x44; /* MCA NB Configuration */
|
||||
val = Get_NB32(dev, reg);
|
||||
val |= 1 << 22; /* EccEn */
|
||||
Set_NB32(dev, reg, val);
|
||||
DCTMemClr_Init_D(pMCTstat, pDCTstat);
|
||||
MemClrECC = 1;
|
||||
print_tx(" ECC enabled on node: ", Node);
|
||||
}
|
||||
} /* this node has ECC enabled dram */
|
||||
} else {
|
||||
LDramECC = 0;
|
||||
} /* Node has Dram */
|
||||
|
||||
if (MemClrECC) {
|
||||
MCTMemClrSync_D(pMCTstat, pDCTstatA);
|
||||
}
|
||||
} /* if Node present */
|
||||
}
|
||||
|
||||
if (AllECC)
|
||||
pMCTstat->GStatus |= 1 << GSB_ECCDIMMs;
|
||||
else
|
||||
pMCTstat->GStatus &= ~(1 << GSB_ECCDIMMs);
|
||||
|
||||
/* Program the Dram BKScrub CTL to the proper (user selected) value.*/
|
||||
/* Reset MC4_STS. */
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
LDramECC = 0;
|
||||
if (NodePresent_D(Node)) { /* If Node is present */
|
||||
reg = 0x40+(Node << 3); /* Dram Base Node 0 + index */
|
||||
val = Get_NB32(pDCTstat->dev_map, reg);
|
||||
curBase = val & 0xffff0000;
|
||||
/*WE/RE is checked because memory config may have been */
|
||||
if ((val & 3) == 3) { /* Node has dram populated */
|
||||
if (isDramECCEn_D(pDCTstat)) { /* if ECC is enabled on this dram */
|
||||
dev = pDCTstat->dev_nbmisc;
|
||||
val = curBase << 8;
|
||||
if (OB_ECCRedir) {
|
||||
val |= (1<<0); /* enable redirection */
|
||||
}
|
||||
Set_NB32(dev, 0x5C, val); /* Dram Scrub Addr Low */
|
||||
val = curBase >> 24;
|
||||
Set_NB32(dev, 0x60, val); /* Dram Scrub Addr High */
|
||||
Set_NB32(dev, 0x58, OF_ScrubCTL); /*Scrub Control */
|
||||
|
||||
/* Divisor should not be set deeper than
|
||||
* divide by 16 when Dcache scrubber or
|
||||
* L2 scrubber is enabled.
|
||||
*/
|
||||
if ((OF_ScrubCTL & (0x1F << 16)) || (OF_ScrubCTL & (0x1F << 8))) {
|
||||
val = Get_NB32(dev, 0x84);
|
||||
if ((val & 0xE0000000) > 0x80000000) { /* Get F3x84h[31:29]ClkDivisor for C1 */
|
||||
val &= 0x1FFFFFFF; /* If ClkDivisor is deeper than divide-by-16 */
|
||||
val |= 0x80000000; /* set it to divide-by-16 */
|
||||
Set_NB32(dev, 0x84, val);
|
||||
}
|
||||
}
|
||||
} /* this node has ECC enabled dram */
|
||||
} /*Node has Dram */
|
||||
} /*if Node present */
|
||||
}
|
||||
|
||||
if (mctGet_NVbits(NV_SyncOnUnEccEn))
|
||||
setSyncOnUnEccEn_D(pMCTstat, pDCTstatA);
|
||||
|
||||
mctHookAfterECC();
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
if (NodePresent_D(Node)) {
|
||||
print_tx("ECCInit: Node ", Node);
|
||||
print_tx("ECCInit: Status ", pDCTstat->Status);
|
||||
print_tx("ECCInit: ErrStatus ", pDCTstat->ErrStatus);
|
||||
print_tx("ECCInit: ErrCode ", pDCTstat->ErrCode);
|
||||
print_t("ECCInit: Done\n");
|
||||
}
|
||||
}
|
||||
return MemClrECC;
|
||||
}
|
||||
|
||||
|
||||
static void setSyncOnUnEccEn_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
u32 Node;
|
||||
u32 reg;
|
||||
u32 dev;
|
||||
u32 val;
|
||||
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
if (NodePresent_D(Node)) { /* If Node is present*/
|
||||
reg = 0x40+(Node << 3); /* Dram Base Node 0 + index*/
|
||||
val = Get_NB32(pDCTstat->dev_map, reg);
|
||||
/*WE/RE is checked because memory config may have been*/
|
||||
if ((val & 3) == 3) { /* Node has dram populated*/
|
||||
if (isDramECCEn_D(pDCTstat)) {
|
||||
/*if ECC is enabled on this dram*/
|
||||
dev = pDCTstat->dev_nbmisc;
|
||||
reg = 0x44; /* MCA NB Configuration*/
|
||||
val = Get_NB32(dev, reg);
|
||||
val |= (1 << SyncOnUcEccEn);
|
||||
Set_NB32(dev, reg, val);
|
||||
}
|
||||
} /* Node has Dram*/
|
||||
} /* if Node present*/
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UNUSED_CODE
|
||||
static u32 GetScrubAddr_D(u32 Node)
|
||||
{
|
||||
/* Get the current 40-bit Scrub ADDR address, scaled to 32-bits,
|
||||
* of the specified Node.
|
||||
*/
|
||||
|
||||
u32 reg;
|
||||
u32 regx;
|
||||
u32 lo, hi;
|
||||
u32 val;
|
||||
u32 dev = PA_NBMISC(Node);
|
||||
|
||||
|
||||
reg = 0x60; /* Scrub Addr High */
|
||||
hi = Get_NB32(dev, reg);
|
||||
|
||||
regx = 0x5C; /* Scrub Addr Low */
|
||||
lo = Get_NB32(dev, regx);
|
||||
/* Scrub Addr High again, detect 32-bit wrap */
|
||||
val = Get_NB32(dev, reg);
|
||||
if (val != hi) {
|
||||
hi = val; /* Scrub Addr Low again, if wrap occurred */
|
||||
lo = Get_NB32(dev, regx);
|
||||
}
|
||||
|
||||
val = hi << 24;
|
||||
val |= lo >> 8;
|
||||
|
||||
return val; /* ScrubAddr[39:8] */
|
||||
}
|
||||
#endif
|
||||
|
||||
static u8 isDramECCEn_D(struct DCTStatStruc *pDCTstat)
|
||||
{
|
||||
u32 reg;
|
||||
u32 val;
|
||||
u8 i;
|
||||
u32 dev = pDCTstat->dev_dct;
|
||||
u8 ch_end;
|
||||
u8 isDimmECCEn = 0;
|
||||
|
||||
if (pDCTstat->GangedMode) {
|
||||
ch_end = 1;
|
||||
} else {
|
||||
ch_end = 2;
|
||||
}
|
||||
for (i = 0; i < ch_end; i++) {
|
||||
if (pDCTstat->DIMMValidDCT[i] > 0) {
|
||||
reg = 0x90 + i * 0x100; /* Dram Config Low */
|
||||
val = Get_NB32(dev, reg);
|
||||
if (val & (1 << DimmEcEn)) {
|
||||
/* set local flag 'dram ecc capable' */
|
||||
isDimmECCEn = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isDimmECCEn;
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
static const u8 Tab_GRCLKDis[] = { 8,0,8,8,0,0,8,0 };
|
||||
|
||||
|
||||
u32 mct_AdjustMemClkDis_GR(struct DCTStatStruc *pDCTstat, u32 dct,
|
||||
u32 DramTimingLo)
|
||||
{
|
||||
/* Greayhound format -> Griffin format */
|
||||
u32 NewDramTimingLo;
|
||||
u32 dev = pDCTstat->dev_dct;
|
||||
u32 reg;
|
||||
u32 reg_off = 0x100 * dct;
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
DramTimingLo = val;
|
||||
/* Dram Timing Low (owns Clock Enable bits) */
|
||||
NewDramTimingLo = Get_NB32(dev, 0x88 + reg_off);
|
||||
if (mctGet_NVbits(NV_AllMemClks) == 0) {
|
||||
/*Special Jedec SPD diagnostic bit - "enable all clocks"*/
|
||||
if (!(pDCTstat->Status & (1<<SB_DiagClks))) {
|
||||
for (i = 0; i < MAX_DIMMS_SUPPORTED; i++) {
|
||||
val = Tab_GRCLKDis[i];
|
||||
if (val < 8) {
|
||||
if (!(pDCTstat->DIMMValidDCT[dct] & (1<<val))) {
|
||||
/* disable memclk */
|
||||
NewDramTimingLo |= (1<<(i+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DramTimingLo &= ~(0xff<<24);
|
||||
DramTimingLo |= NewDramTimingLo & (0xff<<24);
|
||||
DramTimingLo &= (0x4d<<24); /* FIXME - enable all MemClks for now */
|
||||
|
||||
return DramTimingLo;
|
||||
}
|
||||
|
||||
|
||||
u32 mct_AdjustDramConfigLo_GR(struct DCTStatStruc *pDCTstat, u32 dct, u32 val)
|
||||
{
|
||||
/* Greayhound format -> Griffin format */
|
||||
/*FIXME - BurstLength32 must be 0 when F3x44[DramEccEn]=1. */
|
||||
/*
|
||||
; mov cx,PA_NBMISC+44h ;MCA NB Configuration
|
||||
; call Get_NB32n_D
|
||||
; bt eax,22 ;EccEn
|
||||
; .if (CARRY?)
|
||||
; btr eax,BurstLength32
|
||||
; .endif
|
||||
*/
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
void mct_AdjustMemHoist_GR(struct DCTStatStruc *pDCTstat, u32 base, u32 HoleSize)
|
||||
{
|
||||
u32 val;
|
||||
if (base >= pDCTstat->DCTHoleBase) {
|
||||
u32 dev = pDCTstat->dev_dct;
|
||||
base += HoleSize;
|
||||
base >>= 27 - 8;
|
||||
val = Get_NB32(dev, 0x110);
|
||||
val &= ~(0xfff<<11);
|
||||
val |= (base & 0xfff)<<11;
|
||||
Set_NB32(dev, 0x110, val);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mct_d.h"
|
||||
|
||||
void mct_DramInit_Hw_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u8 dct)
|
||||
{
|
||||
u32 val;
|
||||
u32 reg;
|
||||
u32 dev = pDCTstat->dev_dct;
|
||||
|
||||
/*flag for selecting HW/SW DRAM Init HW DRAM Init */
|
||||
reg = 0x90 + 0x100 * dct; /*DRAM Configuration Low */
|
||||
val = Get_NB32(dev, reg);
|
||||
val |= (1<<InitDram);
|
||||
Set_NB32(dev, reg, val);
|
||||
}
|
||||
|
|
@ -1,254 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mct_d.h"
|
||||
#include <cpu/amd/mtrr.h>
|
||||
#include <cpu/x86/mtrr.h>
|
||||
|
||||
static void SetMTRRrangeWB_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr);
|
||||
static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr, u16 MtrrType);
|
||||
|
||||
void CPUMemTyping_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
/* BSP only. Set the fixed MTRRs for common legacy ranges.
|
||||
* Set TOP_MEM and TOM2.
|
||||
* Set some variable MTRRs with WB Uncacheable type.
|
||||
*/
|
||||
|
||||
u32 Bottom32bIO, Bottom40bIO, Cache32bTOP;
|
||||
u32 val;
|
||||
u32 addr;
|
||||
u32 lo, hi;
|
||||
|
||||
/* Set temporary top of memory from Node structure data.
|
||||
* Adjust temp top of memory down to accommodate 32-bit IO space.
|
||||
* Bottom40bIO = top of memory, right justified 8 bits
|
||||
* (defines dram versus IO space type)
|
||||
* Bottom32bIO = sub 4GB top of memory, right justified 8 bits
|
||||
* (defines dram versus IO space type)
|
||||
* Cache32bTOP = sub 4GB top of WB cacheable memory,
|
||||
* right justified 8 bits
|
||||
*/
|
||||
|
||||
val = mctGet_NVbits(NV_BottomIO);
|
||||
if (val == 0)
|
||||
val++;
|
||||
|
||||
Bottom32bIO = val << (24-8);
|
||||
|
||||
val = pMCTstat->SysLimit + 1;
|
||||
if (val <= _4GB_RJ8) {
|
||||
Bottom40bIO = 0;
|
||||
if (Bottom32bIO >= val)
|
||||
Bottom32bIO = val;
|
||||
} else {
|
||||
Bottom40bIO = val;
|
||||
}
|
||||
|
||||
Cache32bTOP = Bottom32bIO;
|
||||
|
||||
/*======================================================================
|
||||
Set default values for CPU registers
|
||||
======================================================================*/
|
||||
|
||||
/* NOTE : For coreboot, we don't need to set mtrr enables here because
|
||||
they are still enable from cache_as_ram.inc */
|
||||
|
||||
addr = MTRR_FIX_64K_00000;
|
||||
lo = 0x1E1E1E1E;
|
||||
hi = lo;
|
||||
_WRMSR(addr, lo, hi); /* 0 - 512K = WB Mem */
|
||||
addr = MTRR_FIX_16K_80000;
|
||||
_WRMSR(addr, lo, hi); /* 512K - 640K = WB Mem */
|
||||
|
||||
/*======================================================================
|
||||
Set variable MTRR values
|
||||
======================================================================*/
|
||||
/* NOTE: for coreboot change from 0x200 to 0x204: coreboot is using
|
||||
0x200, 0x201 for [1M, CONFIG_TOP_MEM)
|
||||
0x202, 0x203 for ROM Caching
|
||||
*/
|
||||
addr = MTRR_PHYS_BASE(2); /* MTRR phys base 2*/
|
||||
/* use TOP_MEM as limit*/
|
||||
/* Limit = TOP_MEM|TOM2*/
|
||||
/* Base = 0*/
|
||||
print_tx("\t CPUMemTyping: Cache32bTOP:", Cache32bTOP);
|
||||
SetMTRRrangeWB_D(0, &Cache32bTOP, &addr);
|
||||
/* Base */
|
||||
/* Limit */
|
||||
/* MtrrAddr */
|
||||
if (addr == -1) /* ran out of MTRRs?*/
|
||||
pMCTstat->GStatus |= 1<<GSB_MTRRshort;
|
||||
|
||||
pMCTstat->Sub4GCacheTop = Cache32bTOP<<8;
|
||||
|
||||
/*======================================================================
|
||||
Set TOP_MEM and TOM2 CPU registers
|
||||
======================================================================*/
|
||||
addr = TOP_MEM;
|
||||
lo = Bottom32bIO<<8;
|
||||
hi = Bottom32bIO>>24;
|
||||
_WRMSR(addr, lo, hi);
|
||||
print_tx("\t CPUMemTyping: Bottom32bIO:", Bottom32bIO);
|
||||
print_tx("\t CPUMemTyping: Bottom40bIO:", Bottom40bIO);
|
||||
if (Bottom40bIO) {
|
||||
hi = Bottom40bIO >> 24;
|
||||
lo = Bottom40bIO << 8;
|
||||
if (mctSetNodeBoundary_D())
|
||||
lo &= 0xC0000000;
|
||||
addr += 3; /* TOM2 */
|
||||
_WRMSR(addr, lo, hi);
|
||||
}
|
||||
addr = SYSCFG_MSR; /* SYS_CFG */
|
||||
_RDMSR(addr, &lo, &hi);
|
||||
if (Bottom40bIO) {
|
||||
lo |= SYSCFG_MSR_TOM2En; /* MtrrTom2En = 1 */
|
||||
lo |= SYSCFG_MSR_TOM2WB; /* Tom2ForceMemTypeWB */
|
||||
} else {
|
||||
lo &= ~SYSCFG_MSR_TOM2En; /* MtrrTom2En = 0 */
|
||||
lo &= ~SYSCFG_MSR_TOM2WB; /* Tom2ForceMemTypeWB */
|
||||
}
|
||||
_WRMSR(addr, lo, hi);
|
||||
}
|
||||
|
||||
|
||||
static void SetMTRRrangeWB_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr)
|
||||
{
|
||||
/*set WB type*/
|
||||
SetMTRRrange_D(Base, pLimit, pMtrrAddr, 6);
|
||||
}
|
||||
|
||||
|
||||
static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr, u16 MtrrType)
|
||||
{
|
||||
/* Program MTRRs to describe given range as given cache type.
|
||||
* Use MTRR pairs starting with the given MTRRphys Base address,
|
||||
* and use as many as is required up to (excluding) MSR 020C, which
|
||||
* is reserved for OS.
|
||||
*
|
||||
* "Limit" in the context of this procedure is not the numerically
|
||||
* correct limit, but rather the Last address+1, for purposes of coding
|
||||
* efficiency and readability. Size of a region is then Limit-Base.
|
||||
*
|
||||
* 1. Size of each range must be a power of two
|
||||
* 2. Each range must be naturally aligned (Base is same as size)
|
||||
*
|
||||
* There are two code paths: the ascending path and descending path
|
||||
* (analogous to bsf and bsr), where the next limit is a function of the
|
||||
* next set bit in a forward or backward sequence of bits (as a function
|
||||
* of the Limit). We start with the ascending path, to ensure that
|
||||
* regions are naturally aligned, then we switch to the descending path
|
||||
* to maximize MTRR usage efficiency. Base = 0 is a special case where we
|
||||
* start with the descending path. Correct Mask for region is
|
||||
* 2comp(Size-1)-1, which is 2comp(Limit-Base-1)-1
|
||||
*/
|
||||
|
||||
u32 curBase, curLimit, curSize;
|
||||
u32 val, valx;
|
||||
u32 addr;
|
||||
|
||||
val = curBase = Base;
|
||||
curLimit = *pLimit;
|
||||
addr = *pMtrrAddr;
|
||||
while ((addr >= 0x200) && (addr < 0x20C) && (val < *pLimit)) {
|
||||
/* start with "ascending" code path */
|
||||
/* alignment (largest block size)*/
|
||||
valx = 1 << bsf(curBase);
|
||||
curSize = valx;
|
||||
|
||||
/* largest legal limit, given current non-zero range Base*/
|
||||
valx += curBase;
|
||||
if ((curBase == 0) || (*pLimit < valx)) {
|
||||
/* flop direction to "descending" code path*/
|
||||
valx = 1<<bsr(*pLimit - curBase);
|
||||
curSize = valx;
|
||||
valx += curBase;
|
||||
}
|
||||
curLimit = valx; /*eax = curBase, edx = curLimit*/
|
||||
valx = val>>24;
|
||||
val <<= 8;
|
||||
|
||||
/* now program the MTRR */
|
||||
val |= MtrrType; /* set cache type (UC or WB)*/
|
||||
_WRMSR(addr, val, valx); /* prog. MTRR with current region Base*/
|
||||
val = ((~(curSize - 1))+1) - 1; /* Size-1*/ /*Mask = 2comp(Size-1)-1*/
|
||||
valx = (val >> 24) | (0xff00); /* GH have 48 bits addr */
|
||||
val <<= 8;
|
||||
val |= (1 << 11); /* set MTRR valid*/
|
||||
addr++;
|
||||
_WRMSR(addr, val, valx); /* prog. MTRR with current region Mask*/
|
||||
val = curLimit;
|
||||
curBase = val; /* next Base = current Limit (loop exit)*/
|
||||
addr++; /* next MTRR pair addr */
|
||||
}
|
||||
if (val < *pLimit) {
|
||||
*pLimit = val;
|
||||
addr = -1;
|
||||
}
|
||||
*pMtrrAddr = addr;
|
||||
}
|
||||
|
||||
void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
/* UMA memory size may need splitting the MTRR configuration into two
|
||||
Before training use NB_BottomIO or the physical memory size to set the MTRRs.
|
||||
After training, add UMAMemTyping function to reconfigure the MTRRs based on
|
||||
NV_BottomUMA (for UMA systems only).
|
||||
This two-step process allows all memory to be cached for training
|
||||
*/
|
||||
u32 Bottom32bIO, Cache32bTOP;
|
||||
u32 val;
|
||||
u32 addr;
|
||||
u32 lo, hi;
|
||||
|
||||
/*======================================================================
|
||||
* Adjust temp top of memory down to accommodate UMA memory start
|
||||
*======================================================================*/
|
||||
/* Bottom32bIO = sub 4GB top of memory, right justified 8 bits
|
||||
* (defines dram versus IO space type)
|
||||
* Cache32bTOP = sub 4GB top of WB cacheable memory, right justified 8 bits */
|
||||
|
||||
Bottom32bIO = pMCTstat->Sub4GCacheTop >> 8;
|
||||
|
||||
val = mctGet_NVbits(NV_BottomUMA);
|
||||
if (val == 0)
|
||||
val++;
|
||||
|
||||
val <<= (24-8);
|
||||
if (val < Bottom32bIO) {
|
||||
Cache32bTOP = val;
|
||||
pMCTstat->Sub4GCacheTop = val;
|
||||
|
||||
/*======================================================================
|
||||
* Clear variable MTRR values
|
||||
*======================================================================*/
|
||||
addr = MTRR_PHYS_BASE(0);
|
||||
lo = 0;
|
||||
hi = lo;
|
||||
while (addr < MTRR_PHYS_BASE(6)) {
|
||||
_WRMSR(addr, lo, hi); /* prog. MTRR with current region Mask */
|
||||
addr++; /* next MTRR pair addr */
|
||||
}
|
||||
|
||||
/*======================================================================
|
||||
* Set variable MTRR values
|
||||
*======================================================================*/
|
||||
print_tx("\t UMAMemTyping_D: Cache32bTOP:", Cache32bTOP);
|
||||
SetMTRRrangeWB_D(0, &Cache32bTOP, &addr);
|
||||
if (addr == -1) /* ran out of MTRRs?*/
|
||||
pMCTstat->GStatus |= 1<<GSB_MTRRshort;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,234 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mct_d.h"
|
||||
|
||||
void InterleaveNodes_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
|
||||
/* Applies Node memory interleaving if enabled and if all criteria are met. */
|
||||
u8 Node;
|
||||
u32 Base;
|
||||
u32 MemSize, MemSize0 = 0;
|
||||
u32 Dct0MemSize = 0, DctSelBase, DctSelBaseOffset = 0;
|
||||
u8 Nodes;
|
||||
u8 NodesWmem;
|
||||
u8 DoIntlv;
|
||||
u8 _NdIntCap;
|
||||
u8 _SWHole;
|
||||
u32 HWHoleSz;
|
||||
u32 DramHoleAddrReg;
|
||||
u32 HoleBase;
|
||||
u32 dev0;
|
||||
u32 reg0;
|
||||
u32 val;
|
||||
u8 i;
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
|
||||
DoIntlv = mctGet_NVbits(NV_NodeIntlv);
|
||||
|
||||
_NdIntCap = 0;
|
||||
HWHoleSz = 0; /*For HW remapping, NOT Node hoisting. */
|
||||
|
||||
pDCTstat = pDCTstatA + 0;
|
||||
dev0 = pDCTstat->dev_host;
|
||||
Nodes = ((Get_NB32(dev0, 0x60) >> 4) & 0x7) + 1;
|
||||
|
||||
|
||||
dev0 = pDCTstat->dev_map;
|
||||
reg0 = 0x40;
|
||||
|
||||
NodesWmem = 0;
|
||||
Node = 0;
|
||||
|
||||
while (DoIntlv && (Node < Nodes)) {
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
if (pMCTstat->GStatus & (1 << GSB_SpIntRemapHole)) {
|
||||
pMCTstat->GStatus |= 1 << GSB_HWHole;
|
||||
_SWHole = 0;
|
||||
} else if (pDCTstat->Status & (1 << SB_SWNodeHole)) {
|
||||
_SWHole = 1;
|
||||
} else {
|
||||
_SWHole = 0;
|
||||
}
|
||||
|
||||
if (!_SWHole) {
|
||||
Base = Get_NB32(dev0, reg0);
|
||||
if (Base & 1) {
|
||||
NodesWmem++;
|
||||
Base &= 0xFFFF0000; /* Base[39:8] */
|
||||
|
||||
if (pDCTstat->Status & (1 << SB_HWHole)) {
|
||||
|
||||
/* to get true amount of dram,
|
||||
* subtract out memory hole if HW dram remapping */
|
||||
DramHoleAddrReg = Get_NB32(pDCTstat->dev_map, 0xF0);
|
||||
HWHoleSz = DramHoleAddrReg >> 16;
|
||||
HWHoleSz = (((~HWHoleSz) + 1) & 0xFF);
|
||||
HWHoleSz <<= 24-8;
|
||||
}
|
||||
/* check to see if the amount of memory on each channel
|
||||
* are the same on all nodes */
|
||||
|
||||
DctSelBase = Get_NB32(pDCTstat->dev_dct, 0x114);
|
||||
if (DctSelBase) {
|
||||
DctSelBase <<= 8;
|
||||
if (pDCTstat->Status & (1 << SB_HWHole)) {
|
||||
if (DctSelBase >= 0x1000000) {
|
||||
DctSelBase -= HWHoleSz;
|
||||
}
|
||||
}
|
||||
DctSelBaseOffset -= Base;
|
||||
if (Node == 0) {
|
||||
Dct0MemSize = DctSelBase;
|
||||
} else if (DctSelBase != Dct0MemSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MemSize = Get_NB32(dev0, reg0 + 4);
|
||||
MemSize &= 0xFFFF0000;
|
||||
MemSize += 0x00010000;
|
||||
MemSize -= Base;
|
||||
if (pDCTstat->Status & (1 << SB_HWHole)) {
|
||||
MemSize -= HWHoleSz;
|
||||
}
|
||||
if (Node == 0) {
|
||||
MemSize0 = MemSize;
|
||||
} else if (MemSize0 != MemSize) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
Node++;
|
||||
reg0 += 8;
|
||||
}
|
||||
|
||||
if (Node == Nodes) {
|
||||
/* if all nodes have memory and no Node had SW memhole */
|
||||
if (Nodes == 2 || Nodes == 4 || Nodes == 8)
|
||||
_NdIntCap = 1;
|
||||
}
|
||||
|
||||
if (!_NdIntCap)
|
||||
DoIntlv = 0;
|
||||
|
||||
|
||||
if (pMCTstat->GStatus & 1 << (GSB_SpIntRemapHole)) {
|
||||
HWHoleSz = pMCTstat->HoleBase;
|
||||
if (HWHoleSz == 0) {
|
||||
HWHoleSz = mctGet_NVbits(NV_BottomIO) & 0xFF;
|
||||
HWHoleSz <<= 24-8;
|
||||
}
|
||||
HWHoleSz = ((~HWHoleSz) + 1) & 0x00FF0000;
|
||||
}
|
||||
|
||||
if (DoIntlv) {
|
||||
MCTMemClr_D(pMCTstat,pDCTstatA);
|
||||
/* Program Interleaving enabled on Node 0 map only.*/
|
||||
MemSize0 <<= bsf(Nodes); /* MemSize = MemSize*2 (or 4, or 8) */
|
||||
Dct0MemSize <<= bsf(Nodes);
|
||||
MemSize0 += HWHoleSz;
|
||||
Base = ((Nodes - 1) << 8) | 3;
|
||||
reg0 = 0x40;
|
||||
Node = 0;
|
||||
while (Node < Nodes) {
|
||||
Set_NB32(dev0, reg0, Base);
|
||||
MemSize = MemSize0;
|
||||
MemSize--;
|
||||
MemSize &= 0xFFFF0000;
|
||||
MemSize |= Node << 8; /* set IntlvSel[2:0] field */
|
||||
MemSize |= Node; /* set DstNode[2:0] field */
|
||||
Set_NB32(dev0, reg0 + 4, MemSize0);
|
||||
reg0 += 8;
|
||||
Node++;
|
||||
}
|
||||
|
||||
/* set base/limit to F1x120/124 per Node */
|
||||
Node = 0;
|
||||
while (Node < Nodes) {
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
pDCTstat->NodeSysBase = 0;
|
||||
MemSize = MemSize0;
|
||||
MemSize -= HWHoleSz;
|
||||
MemSize--;
|
||||
pDCTstat->NodeSysLimit = MemSize;
|
||||
Set_NB32(pDCTstat->dev_map, 0x120, Node << 21);
|
||||
MemSize = MemSize0;
|
||||
MemSize--;
|
||||
MemSize >>= 19;
|
||||
val = Base;
|
||||
val &= 0x700;
|
||||
val <<= 13;
|
||||
val |= MemSize;
|
||||
Set_NB32(pDCTstat->dev_map, 0x124, val);
|
||||
|
||||
if (pMCTstat->GStatus & (1 << GSB_HWHole)) {
|
||||
HoleBase = pMCTstat->HoleBase;
|
||||
if (Dct0MemSize >= HoleBase) {
|
||||
val = HWHoleSz;
|
||||
if (Node == 0) {
|
||||
val += Dct0MemSize;
|
||||
}
|
||||
} else {
|
||||
val = HWHoleSz + Dct0MemSize;
|
||||
}
|
||||
|
||||
val >>= 8; /* DramHoleOffset */
|
||||
HoleBase <<= 8; /* DramHoleBase */
|
||||
val |= HoleBase;
|
||||
val |= 1 << DramMemHoistValid;
|
||||
val |= 1 << DramHoleValid;
|
||||
Set_NB32(pDCTstat->dev_map, 0xF0, val);
|
||||
}
|
||||
|
||||
|
||||
Set_NB32(pDCTstat->dev_dct, 0x114, Dct0MemSize >> 8); /* DctSelBaseOffset */
|
||||
val = Get_NB32(pDCTstat->dev_dct, 0x110);
|
||||
val &= 0x7FF;
|
||||
val |= Dct0MemSize >> 8;
|
||||
Set_NB32(pDCTstat->dev_dct, 0x110, val); /* DctSelBaseAddr */
|
||||
print_tx("InterleaveNodes: DRAM Controller Select Low Register = ", val);
|
||||
Node++;
|
||||
}
|
||||
|
||||
|
||||
/* Copy Node 0 into other Nodes' CSRs */
|
||||
Node = 1;
|
||||
while (Node < Nodes) {
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
|
||||
for (i = 0x40; i <= 0x80; i++) {
|
||||
val = Get_NB32(dev0, i);
|
||||
Set_NB32(pDCTstat->dev_map, i, val);
|
||||
}
|
||||
|
||||
val = Get_NB32(dev0, 0xF0);
|
||||
Set_NB32(pDCTstat->dev_map, 0xF0, val);
|
||||
Node++;
|
||||
}
|
||||
pMCTstat->GStatus = (1 << GSB_NodeIntlv);
|
||||
}
|
||||
print_tx("InterleaveNodes_D: Status ", pDCTstat->Status);
|
||||
print_tx("InterleaveNodes_D: ErrStatus ", pDCTstat->ErrStatus);
|
||||
print_tx("InterleaveNodes_D: ErrCode ", pDCTstat->ErrCode);
|
||||
print_t("InterleaveNodes_D: Done\n");
|
||||
}
|
||||
|
|
@ -1,396 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mct_d.h"
|
||||
|
||||
void EarlySampleSupport_D(void)
|
||||
{
|
||||
}
|
||||
|
||||
u32 procOdtWorkaround(struct DCTStatStruc *pDCTstat, u32 dct, u32 val)
|
||||
{
|
||||
uint64_t tmp;
|
||||
tmp = pDCTstat->LogicalCPUID;
|
||||
if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
|
||||
val &= 0x0FFFFFFF;
|
||||
if (pDCTstat->MAdimms[dct] > 1)
|
||||
val |= 0x10000000;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
u32 OtherTiming_A_D(struct DCTStatStruc *pDCTstat, u32 val)
|
||||
{
|
||||
/* Bug#10695:One MEMCLK Bubble Writes Don't Do X4 X8 Switching Correctly
|
||||
* Solution: BIOS should set DRAM Timing High[Twrwr] > 00b
|
||||
* (F2x[1, 0]8C[1:0] > 00b). Silicon Status: Fixed in Rev B
|
||||
* FIXME: check if this is still required.
|
||||
*/
|
||||
uint64_t tmp;
|
||||
tmp = pDCTstat->LogicalCPUID;
|
||||
if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
|
||||
if (!(val & (3<<12)))
|
||||
val |= 1<<12;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
void mct_ForceAutoPrecharge_D(struct DCTStatStruc *pDCTstat, u32 dct)
|
||||
{
|
||||
uint64_t tmp;
|
||||
u32 reg;
|
||||
u32 reg_off;
|
||||
u32 dev;
|
||||
u32 val;
|
||||
|
||||
tmp = pDCTstat->LogicalCPUID;
|
||||
if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
|
||||
if (CheckNBCOFAutoPrechg(pDCTstat, dct)) {
|
||||
dev = pDCTstat->dev_dct;
|
||||
reg_off = 0x100 * dct;
|
||||
reg = 0x90 + reg_off; /* Dram Configuration Lo */
|
||||
val = Get_NB32(dev, reg);
|
||||
val |= 1<<ForceAutoPchg;
|
||||
if (!pDCTstat->GangedMode)
|
||||
val |= 1<<BurstLength32;
|
||||
Set_NB32(dev, reg, val);
|
||||
|
||||
reg = 0x88 + reg_off; /* cx = Dram Timing Lo */
|
||||
val = Get_NB32(dev, reg);
|
||||
val |= 0x000F0000; /* Trc = 0Fh */
|
||||
Set_NB32(dev, reg, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mct_EndDQSTraining_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
/* Bug#13341: Prefetch is getting killed when the limit is reached in
|
||||
* PrefDramTrainMode
|
||||
* Solution: Explicitly clear the PrefDramTrainMode bit after training
|
||||
* sequence in order to ensure resumption of normal HW prefetch
|
||||
* behavior.
|
||||
* NOTE -- this has been documented with a note at the end of this
|
||||
* section in the BKDG (although, admittedly, the note does not really
|
||||
* stand out).
|
||||
* Silicon Status: Fixed in Rev B (confirm)
|
||||
* FIXME: check this.
|
||||
*/
|
||||
|
||||
uint64_t tmp;
|
||||
u32 dev;
|
||||
u32 reg;
|
||||
u32 val;
|
||||
u32 Node;
|
||||
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
|
||||
if (!pDCTstat->NodePresent) break;
|
||||
|
||||
tmp = pDCTstat->LogicalCPUID;
|
||||
if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
|
||||
dev = pDCTstat->dev_dct;
|
||||
reg = 0x11c;
|
||||
val = Get_NB32(dev, reg);
|
||||
val &= ~(1<<PrefDramTrainMode);
|
||||
Set_NB32(dev, reg, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void mct_BeforeDQSTrain_Samp_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat)
|
||||
{
|
||||
/* Bug#15115: Uncertainty In The Sync Chain Leads To Setup Violations
|
||||
* In TX FIFO
|
||||
* Solution: BIOS should program DRAM Control Register[RdPtrInit] = 5h,
|
||||
* (F2x[1, 0]78[3:0] = 5h).
|
||||
* Silicon Status: Fixed In Rev B0
|
||||
*/
|
||||
|
||||
/* Bug#15880: Determine validity of reset settings for DDR PHY timing
|
||||
* regi..
|
||||
* Solution: At least, set WrDqs fine delay to be 0 for DDR2 training.
|
||||
*/
|
||||
|
||||
u32 dev;
|
||||
u32 reg_off;
|
||||
u32 index_reg;
|
||||
u32 index;
|
||||
u32 reg;
|
||||
u32 val;
|
||||
uint64_t tmp;
|
||||
u32 Channel;
|
||||
|
||||
tmp = pDCTstat->LogicalCPUID;
|
||||
if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
|
||||
|
||||
dev = pDCTstat->dev_dct;
|
||||
index = 0;
|
||||
|
||||
for (Channel = 0; Channel < 2; Channel++) {
|
||||
index_reg = 0x98 + 0x100 * Channel;
|
||||
val = Get_NB32_index_wait(dev, index_reg, 0x0d004007);
|
||||
val |= 0x3ff;
|
||||
Set_NB32_index_wait(dev, index_reg, 0x0d0f4f07, val);
|
||||
}
|
||||
|
||||
for (Channel = 0; Channel < 2; Channel++) {
|
||||
if (pDCTstat->GangedMode && Channel)
|
||||
break;
|
||||
reg_off = 0x100 * Channel;
|
||||
reg = 0x78 + reg_off;
|
||||
val = Get_NB32(dev, reg);
|
||||
val &= ~(0x07);
|
||||
val |= 5;
|
||||
Set_NB32(dev, reg, val);
|
||||
}
|
||||
|
||||
for (Channel = 0; Channel < 2; Channel++) {
|
||||
reg_off = 0x100 * Channel;
|
||||
val = 0;
|
||||
index_reg = 0x98 + reg_off;
|
||||
for (index = 0x30; index < (0x45 + 1); index++) {
|
||||
Set_NB32_index_wait(dev, index_reg, index, val);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
u32 Modify_D3CMP(struct DCTStatStruc *pDCTstat, u32 dct, u32 value)
|
||||
{
|
||||
/* Errata#189: Reads To Phy Driver Calibration Register and Phy
|
||||
* Predriver Calibration Register Do Not Return Bit 27.
|
||||
* Solution: See #41322 for details.
|
||||
* BIOS can modify bit 27 of the Phy Driver Calibration register
|
||||
* as follows:
|
||||
* 1. Read F2x[1, 0]9C_x09
|
||||
* 2. Read F2x[1, 0]9C_x0D004201
|
||||
* 3. Set F2x[1, 0]9C_x09[27] = F2x[1, 0]9C_x0D004201[10]
|
||||
* BIOS can modify bit 27 of the Phy Predriver Calibration register
|
||||
* as follows:
|
||||
* 1. Read F2x[1, 0]9C_x0A
|
||||
* 2. Read F2x[1, 0]9C_x0D004209
|
||||
* 3. Set F2x[1, 0]9C_x0A[27] = F2x[1, 0]9C_x0D004209[10]
|
||||
* Silicon Status: Fixed planned for DR-B0
|
||||
*/
|
||||
|
||||
u32 dev;
|
||||
u32 index_reg;
|
||||
u32 index;
|
||||
u32 val;
|
||||
uint64_t tmp;
|
||||
|
||||
tmp = pDCTstat->LogicalCPUID;
|
||||
if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
|
||||
dev = pDCTstat->dev_dct;
|
||||
index_reg = 0x98 + 0x100 * dct;
|
||||
index = 0x0D004201;
|
||||
val = Get_NB32_index_wait(dev, index_reg, index);
|
||||
value &= ~(1<<27);
|
||||
value |= ((val >> 10) & 1) << 27;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void SyncSetting(struct DCTStatStruc *pDCTstat)
|
||||
{
|
||||
/* Errata#198: AddrCmdSetup, CsOdtSetup, and CkeSetup Require Identical
|
||||
* Programming For Both Channels in Ganged Mode
|
||||
* Solution: The BIOS must program the following DRAM timing parameters
|
||||
* the same for both channels:
|
||||
* 1. F2x[1, 0]9C_x04[21] (AddrCmdSetup)
|
||||
* 2. F2x[1, 0]9C_x04[15] (CsOdtSetup)
|
||||
* 3. F2x[1, 0]9C_x04[5]) (CkeSetup)
|
||||
* That is, if the AddrCmdSetup, CsOdtSetup, or CkeSetup is
|
||||
* set to 1'b1 for one of the controllers, then the corresponding
|
||||
* AddrCmdSetup, CsOdtSetup, or CkeSetup must be set to 1'b1 for the
|
||||
* other controller.
|
||||
* Silicon Status: Fix TBD
|
||||
*/
|
||||
|
||||
uint64_t tmp;
|
||||
tmp = pDCTstat->LogicalCPUID;
|
||||
if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
|
||||
pDCTstat->CH_ODC_CTL[1] = pDCTstat->CH_ODC_CTL[0];
|
||||
pDCTstat->CH_ADDR_TMG[1] = pDCTstat->CH_ADDR_TMG[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
u32 CheckNBCOFAutoPrechg(struct DCTStatStruc *pDCTstat, u32 dct)
|
||||
{
|
||||
u32 ret = 0;
|
||||
u32 lo, hi;
|
||||
u32 msr;
|
||||
u32 val;
|
||||
u32 valx, valy;
|
||||
u32 NbDid;
|
||||
|
||||
/* 3 * (Fn2xD4[NBFid]+4)/(2^NbDid)/(3+Fn2x94[MemClkFreq]) */
|
||||
msr = 0xC0010071;
|
||||
_RDMSR(msr, &lo, &hi);
|
||||
NbDid = (lo >> 22) & 1;
|
||||
|
||||
val = Get_NB32(pDCTstat->dev_dct, 0x94 + 0x100 * dct);
|
||||
valx = ((val & 0x07) + 3) << NbDid;
|
||||
print_tx("MemClk:", valx >> NbDid);
|
||||
|
||||
val = Get_NB32(pDCTstat->dev_nbmisc, 0xd4);
|
||||
valy = ((val & 0x1f) + 4) * 3;
|
||||
print_tx("NB COF:", valy >> NbDid);
|
||||
|
||||
val = valy/valx;
|
||||
if ((val == 3) && (valy % valx)) /* 3 < NClk/MemClk < 4 */
|
||||
ret = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void mct_BeforeDramInit_D(struct DCTStatStruc *pDCTstat, u32 dct)
|
||||
{
|
||||
uint64_t tmp;
|
||||
u32 Speed;
|
||||
u32 ch, ch_start, ch_end;
|
||||
u32 index_reg;
|
||||
u32 dev;
|
||||
u32 val;
|
||||
|
||||
tmp = pDCTstat->LogicalCPUID;
|
||||
if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
|
||||
Speed = pDCTstat->Speed;
|
||||
/* MemClkFreq = 333MHz or 533MHz */
|
||||
if ((Speed == 3) || (Speed == 2)) {
|
||||
if (pDCTstat->GangedMode) {
|
||||
ch_start = 0;
|
||||
ch_end = 2;
|
||||
} else {
|
||||
ch_start = dct;
|
||||
ch_end = dct+1;
|
||||
}
|
||||
dev = pDCTstat->dev_dct;
|
||||
|
||||
for (ch = ch_start; ch < ch_end; ch++) {
|
||||
index_reg = 0x98 + 0x100 * ch;
|
||||
val = Get_NB32_index(dev, index_reg, 0x0D00E001);
|
||||
val &= ~(0xf0);
|
||||
val |= 0x80;
|
||||
Set_NB32_index(dev, index_reg, 0x0D01E001, val);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UNUSED_CODE
|
||||
/* Callback not required */
|
||||
static u8 mct_AdjustDelay_D(struct DCTStatStruc *pDCTstat, u8 dly)
|
||||
{
|
||||
u8 skip = 0;
|
||||
dly &= 0x1f;
|
||||
if ((dly >= MIN_FENCE) && (dly <= MAX_FENCE))
|
||||
skip = 1;
|
||||
|
||||
return skip;
|
||||
}
|
||||
#endif
|
||||
|
||||
u8 mct_checkFenceHoleAdjust_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u8 DQSDelay,
|
||||
u8 ChipSel, u8 *result)
|
||||
{
|
||||
u8 ByteLane;
|
||||
uint64_t tmp;
|
||||
|
||||
tmp = pDCTstat->LogicalCPUID;
|
||||
if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
|
||||
if (pDCTstat->Direction == DQS_WRITEDIR) {
|
||||
if ((pDCTstat->Speed == 2) || (pDCTstat->Speed == 3)) {
|
||||
if (DQSDelay == 13) {
|
||||
if (*result == 0xFF) {
|
||||
for (ByteLane = 0; ByteLane < 8; ByteLane++) {
|
||||
pDCTstat->DQSDelay = 13;
|
||||
pDCTstat->ByteLane = ByteLane;
|
||||
/* store the value into the data structure */
|
||||
StoreDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mct_AdjustDQSPosDelay_D(pDCTstat, DQSDelay)) {
|
||||
*result = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
u8 mct_AdjustDQSPosDelay_D(struct DCTStatStruc *pDCTstat, u8 dly)
|
||||
{
|
||||
u8 skip = 0;
|
||||
|
||||
dly &= 0x1f;
|
||||
if ((dly >= MIN_DQS_WR_FENCE) && (dly <= MAX_DQS_WR_FENCE))
|
||||
skip = 1;
|
||||
|
||||
return skip;
|
||||
|
||||
}
|
||||
|
||||
#ifdef UNUSED_CODE
|
||||
static u8 mctDoAxRdPtrInit_D(struct DCTStatStruc *pDCTstat, u8 *Rdtr)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
tmp = pDCTstat->LogicalCPUID;
|
||||
if ((tmp == AMD_DR_A0A) || (tmp == AMD_DR_A1B) || (tmp == AMD_DR_A2)) {
|
||||
*Rdtr = 5;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void mct_AdjustScrub_D(struct DCTStatStruc *pDCTstat, u16 *scrub_request) {
|
||||
|
||||
/* Erratum #202: disable DCache scrubber for Ax parts */
|
||||
|
||||
if (pDCTstat->LogicalCPUID & (AMD_DR_Ax)) {
|
||||
*scrub_request = 0;
|
||||
pDCTstat->ErrStatus |= 1 << SB_DCBKScrubDis;
|
||||
}
|
||||
}
|
||||
|
||||
void beforeInterleaveChannels_D(struct DCTStatStruc *pDCTstatA, u8 *enabled) {
|
||||
if (pDCTstatA->LogicalCPUID & (AMD_DR_Ax))
|
||||
*enabled = 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mct_d.h"
|
||||
|
||||
u8 mct_checkNumberOfDqsRcvEn_1Pass(u8 pass)
|
||||
{
|
||||
u8 ret = 1;
|
||||
if (pass == SecondPass)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
u32 SetupDqsPattern_1PassA(u8 pass)
|
||||
{
|
||||
return (u32) TestPattern1_D;
|
||||
}
|
||||
|
||||
|
||||
u32 SetupDqsPattern_1PassB(u8 pass)
|
||||
{
|
||||
return (u32) TestPattern0_D;
|
||||
}
|
||||
|
||||
u8 mct_Get_Start_RcvrEnDly_1Pass(u8 pass)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 mct_Average_RcvrEnDly_1Pass(struct DCTStatStruc *pDCTstat, u8 Channel, u8 Receiver,
|
||||
u8 Pass)
|
||||
{
|
||||
u8 i, MaxValue;
|
||||
u8 *p;
|
||||
u8 val;
|
||||
|
||||
MaxValue = 0;
|
||||
p = pDCTstat->persistentData.CH_D_B_RCVRDLY[Channel][Receiver >> 1];
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
/* get left value from DCTStatStruc.CHA_D0_B0_RCVRDLY*/
|
||||
val = p[i];
|
||||
/* get right value from DCTStatStruc.CHA_D0_B0_RCVRDLY_1*/
|
||||
val += Pass1MemClkDly;
|
||||
/* write back the value to stack */
|
||||
if (val > MaxValue)
|
||||
MaxValue = val;
|
||||
|
||||
p[i] = val;
|
||||
}
|
||||
|
||||
return MaxValue;
|
||||
}
|
||||
|
||||
#ifdef UNUSED_CODE
|
||||
static u8 mct_AdjustFinalDQSRcvValue_1Pass(u8 val_1p, u8 val_2p)
|
||||
{
|
||||
return (val_1p & 0xff) + ((val_2p & 0xff)<<8);
|
||||
}
|
||||
#endif
|
||||
|
||||
u8 mct_SaveRcvEnDly_D_1Pass(struct DCTStatStruc *pDCTstat, u8 pass)
|
||||
{
|
||||
u8 ret;
|
||||
ret = 0;
|
||||
if ((pDCTstat->DqsRcvEn_Pass == 0xff) && (pass== FirstPass))
|
||||
ret = 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
u8 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
|
||||
u8 RcvrEnDly, u8 RcvrEnDlyLimit,
|
||||
u8 Channel, u8 Receiver, u8 Pass)
|
||||
|
||||
{
|
||||
return mct_Average_RcvrEnDly_1Pass(pDCTstat, Channel, Receiver, Pass);
|
||||
}
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
u8 mct_checkNumberOfDqsRcvEn_Pass(u8 pass)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
u32 SetupDqsPattern_PassA(u8 Pass)
|
||||
{
|
||||
u32 ret;
|
||||
if (Pass == FirstPass)
|
||||
ret = (u32) TestPattern1_D;
|
||||
else
|
||||
ret = (u32) TestPattern2_D;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
u32 SetupDqsPattern_PassB(u8 Pass)
|
||||
{
|
||||
u32 ret;
|
||||
if (Pass == FirstPass)
|
||||
ret = (u32) TestPattern0_D;
|
||||
else
|
||||
ret = (u32) TestPattern2_D;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
u8 mct_Get_Start_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
|
||||
u8 Channel, u8 Receiver,
|
||||
u8 Pass)
|
||||
{
|
||||
u8 RcvrEnDly;
|
||||
|
||||
if (Pass == FirstPass)
|
||||
RcvrEnDly = 0;
|
||||
else {
|
||||
u8 max = 0;
|
||||
u8 val;
|
||||
u8 i;
|
||||
u8 *p = pDCTstat->persistentData.CH_D_B_RCVRDLY[Channel][Receiver>>1];
|
||||
u8 bn;
|
||||
bn = 8;
|
||||
|
||||
for (i = 0; i < bn; i++) {
|
||||
val = p[i];
|
||||
if (val > max) {
|
||||
max = val;
|
||||
}
|
||||
}
|
||||
RcvrEnDly = max;
|
||||
// while (1) {; }
|
||||
// RcvrEnDly += secPassOffset; //FIXME Why
|
||||
}
|
||||
|
||||
return RcvrEnDly;
|
||||
}
|
||||
|
||||
|
||||
|
||||
u8 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
|
||||
u8 RcvrEnDly, u8 RcvrEnDlyLimit,
|
||||
u8 Channel, u8 Receiver, u8 Pass)
|
||||
{
|
||||
u8 i;
|
||||
u8 *p;
|
||||
u8 *p_1;
|
||||
u8 val;
|
||||
u8 val_1;
|
||||
u8 valid = 1;
|
||||
u8 bn;
|
||||
|
||||
bn = 8;
|
||||
|
||||
p = pDCTstat->persistentData.CH_D_B_RCVRDLY[Channel][Receiver>>1];
|
||||
|
||||
if (Pass == SecondPass) { /* second pass must average values */
|
||||
//FIXME: which byte?
|
||||
p_1 = pDCTstat->B_RCVRDLY_1;
|
||||
// p_1 = pDCTstat->persistentData.CH_D_B_RCVRDLY_1[Channel][Receiver>>1];
|
||||
for (i = 0; i < bn; i++) {
|
||||
val = p[i];
|
||||
/* left edge */
|
||||
if (val != (RcvrEnDlyLimit - 1)) {
|
||||
val -= Pass1MemClkDly;
|
||||
val_1 = p_1[i];
|
||||
val += val_1;
|
||||
val >>= 1;
|
||||
p[i] = val;
|
||||
} else {
|
||||
valid = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!valid) {
|
||||
pDCTstat->ErrStatus |= 1<<SB_NORCVREN;
|
||||
} else {
|
||||
pDCTstat->DimmTrainFail &= ~(1<<(Receiver + Channel));
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < bn; i++) {
|
||||
val = p[i];
|
||||
/* Add 1/2 Memlock delay */
|
||||
val += 0x5; // NOTE: middle value with DQSRCVEN_SAVED_GOOD_TIMES
|
||||
p[i] = val;
|
||||
pDCTstat->DimmTrainFail &= ~(1<<(Receiver + Channel));
|
||||
}
|
||||
}
|
||||
|
||||
return RcvrEnDly;
|
||||
}
|
||||
|
|
@ -1,409 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <console/console.h>
|
||||
#include <cpu/x86/cr.h>
|
||||
#include <cpu/amd/msr.h>
|
||||
|
||||
#include "mct_d.h"
|
||||
|
||||
/*
|
||||
* Description: Max Read Latency Training feature for DDR 2 MCT
|
||||
*/
|
||||
|
||||
static u8 CompareMaxRdLatTestPattern_D(u32 pattern_buf, u32 addr);
|
||||
static u32 GetMaxRdLatTestAddr_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u8 Channel,
|
||||
u8 *MaxRcvrEnDly, u8 *valid);
|
||||
u8 mct_GetStartMaxRdLat_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u8 Channel,
|
||||
u8 DQSRcvEnDly, u32 *Margin);
|
||||
static void maxRdLatencyTrain_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat);
|
||||
static void mct_setMaxRdLatTrnVal_D(struct DCTStatStruc *pDCTstat, u8 Channel,
|
||||
u16 MaxRdLatVal);
|
||||
|
||||
/*Warning: These must be located so they do not cross a logical 16-bit
|
||||
segment boundary!*/
|
||||
static const u32 TestMaxRdLAtPattern_D[] = {
|
||||
0x6E0E3FAC, 0x0C3CFF52,
|
||||
0x4A688181, 0x49C5B613,
|
||||
0x7C780BA6, 0x5C1650E3,
|
||||
0x0C4F9D76, 0x0C6753E6,
|
||||
0x205535A5, 0xBABFB6CA,
|
||||
0x610E6E5F, 0x0C5F1C87,
|
||||
0x488493CE, 0x14C9C383,
|
||||
0xF5B9A5CD, 0x9CE8F615,
|
||||
|
||||
0xAAD714B5, 0xC38F1B4C,
|
||||
0x72ED647C, 0x669F7562,
|
||||
0x5233F802, 0x4A898B30,
|
||||
0x10A40617, 0x3326B465,
|
||||
0x55386E04, 0xC807E3D3,
|
||||
0xAB49E193, 0x14B4E63A,
|
||||
0x67DF2495, 0xEA517C45,
|
||||
0x7624CE51, 0xF8140C51,
|
||||
|
||||
0x4824BD23, 0xB61DD0C9,
|
||||
0x072BCFBE, 0xE8F3807D,
|
||||
0x919EA373, 0x25E30C47,
|
||||
0xFEB12958, 0x4DA80A5A,
|
||||
0xE9A0DDF8, 0x792B0076,
|
||||
0xE81C73DC, 0xF025B496,
|
||||
0x1DB7E627, 0x808594FE,
|
||||
0x82668268, 0x655C7783,
|
||||
};
|
||||
|
||||
|
||||
static u32 SetupMaxRdPattern(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat,
|
||||
u32 *buffer)
|
||||
{
|
||||
/* 1. Copy the alpha and Beta patterns from ROM to Cache,
|
||||
* aligning on 16 byte boundary
|
||||
* 2. Set the ptr to Cacheable copy in DCTStatstruc.PtrPatternBufA
|
||||
* for Alpha
|
||||
* 3. Set the ptr to Cacheable copy in DCTStatstruc.PtrPatternBufB
|
||||
* for Beta
|
||||
*/
|
||||
|
||||
u32 *buf;
|
||||
u8 i;
|
||||
|
||||
buf = (u32 *)(((u32)buffer + 0x10) & (0xfffffff0));
|
||||
|
||||
for (i = 0; i < (16 * 3); i++) {
|
||||
buf[i] = TestMaxRdLAtPattern_D[i];
|
||||
}
|
||||
|
||||
return (u32)buf;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void TrainMaxReadLatency_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
u8 Node;
|
||||
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
|
||||
if (!pDCTstat->NodePresent)
|
||||
break;
|
||||
|
||||
if (pDCTstat->DCTSysLimit)
|
||||
maxRdLatencyTrain_D(pMCTstat, pDCTstat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void maxRdLatencyTrain_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat)
|
||||
{
|
||||
u8 Channel;
|
||||
u32 TestAddr0;
|
||||
u8 _DisableDramECC = 0, _Wrap32Dis = 0, _SSE2 = 0;
|
||||
u16 MaxRdLatDly;
|
||||
u8 RcvrEnDly = 0;
|
||||
u32 PatternBuffer[60]; // FIXME: why not 48 + 4
|
||||
u32 Margin;
|
||||
u32 addr;
|
||||
CRx_TYPE cr4;
|
||||
u32 lo, hi;
|
||||
|
||||
u8 valid;
|
||||
u32 pattern_buf;
|
||||
|
||||
cr4 = read_cr4();
|
||||
if (cr4 & (1<<9)) { /* save the old value */
|
||||
_SSE2 = 1;
|
||||
}
|
||||
cr4 |= (1<<9); /* OSFXSR enable SSE2 */
|
||||
write_cr4(cr4);
|
||||
|
||||
addr = HWCR_MSR;
|
||||
_RDMSR(addr, &lo, &hi);
|
||||
if (lo & (1<<17)) { /* save the old value */
|
||||
_Wrap32Dis = 1;
|
||||
}
|
||||
lo |= (1<<17); /* HWCR.wrap32dis */
|
||||
lo &= ~(1<<15); /* SSEDIS */
|
||||
/* Setting wrap32dis allows 64-bit memory references in
|
||||
real mode */
|
||||
_WRMSR(addr, lo, hi);
|
||||
|
||||
_DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat);
|
||||
|
||||
pattern_buf = SetupMaxRdPattern(pMCTstat, pDCTstat, PatternBuffer);
|
||||
|
||||
for (Channel = 0; Channel < 2; Channel++) {
|
||||
print_debug_dqs("\tMaxRdLatencyTrain51: Channel ",Channel, 1);
|
||||
pDCTstat->Channel = Channel;
|
||||
|
||||
if ((pDCTstat->Status & (1 << SB_128bitmode)) && Channel)
|
||||
break; /*if ganged mode, skip DCT 1 */
|
||||
|
||||
TestAddr0 = GetMaxRdLatTestAddr_D(pMCTstat, pDCTstat, Channel, &RcvrEnDly, &valid);
|
||||
if (!valid) /* Address not supported on current CS */
|
||||
continue;
|
||||
/* rank 1 of DIMM, testpattern 0 */
|
||||
WriteMaxRdLat1CLTestPattern_D(pattern_buf, TestAddr0);
|
||||
|
||||
MaxRdLatDly = mct_GetStartMaxRdLat_D(pMCTstat, pDCTstat, Channel, RcvrEnDly, &Margin);
|
||||
print_debug_dqs("\tMaxRdLatencyTrain52: MaxRdLatDly start ", MaxRdLatDly, 2);
|
||||
print_debug_dqs("\tMaxRdLatencyTrain52: MaxRdLatDly Margin ", Margin, 2);
|
||||
while (MaxRdLatDly < MAX_RD_LAT) { /* sweep Delay value here */
|
||||
mct_setMaxRdLatTrnVal_D(pDCTstat, Channel, MaxRdLatDly);
|
||||
ReadMaxRdLat1CLTestPattern_D(TestAddr0);
|
||||
if (CompareMaxRdLatTestPattern_D(pattern_buf, TestAddr0) == DQS_PASS)
|
||||
break;
|
||||
SetTargetWTIO_D(TestAddr0);
|
||||
FlushMaxRdLatTestPattern_D(TestAddr0);
|
||||
ResetTargetWTIO_D();
|
||||
MaxRdLatDly++;
|
||||
}
|
||||
print_debug_dqs("\tMaxRdLatencyTrain53: MaxRdLatDly end ", MaxRdLatDly, 2);
|
||||
mct_setMaxRdLatTrnVal_D(pDCTstat, Channel, MaxRdLatDly + Margin);
|
||||
}
|
||||
|
||||
if (_DisableDramECC) {
|
||||
mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC);
|
||||
}
|
||||
|
||||
if (!_Wrap32Dis) {
|
||||
addr = HWCR_MSR;
|
||||
_RDMSR(addr, &lo, &hi);
|
||||
lo &= ~(1<<17); /* restore HWCR.wrap32dis */
|
||||
_WRMSR(addr, lo, hi);
|
||||
}
|
||||
if (!_SSE2) {
|
||||
cr4 = read_cr4();
|
||||
cr4 &= ~(1<<9); /* restore cr4.OSFXSR */
|
||||
write_cr4(cr4);
|
||||
}
|
||||
|
||||
#if DQS_TRAIN_DEBUG > 0
|
||||
{
|
||||
u8 Channel;
|
||||
printk(BIOS_DEBUG, "maxRdLatencyTrain: CH_MaxRdLat:\n");
|
||||
for (Channel = 0; Channel < 2; Channel++) {
|
||||
printk(BIOS_DEBUG, "Channel: %02x: %02x\n", Channel, pDCTstat->CH_MaxRdLat[Channel]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void mct_setMaxRdLatTrnVal_D(struct DCTStatStruc *pDCTstat,
|
||||
u8 Channel, u16 MaxRdLatVal)
|
||||
{
|
||||
u8 i;
|
||||
u32 reg;
|
||||
u32 dev;
|
||||
u32 val;
|
||||
|
||||
if (pDCTstat->GangedMode) {
|
||||
Channel = 0; // for safe
|
||||
for (i = 0; i < 2; i++)
|
||||
pDCTstat->CH_MaxRdLat[i] = MaxRdLatVal;
|
||||
} else {
|
||||
pDCTstat->CH_MaxRdLat[Channel] = MaxRdLatVal;
|
||||
}
|
||||
|
||||
dev = pDCTstat->dev_dct;
|
||||
reg = 0x78 + Channel * 0x100;
|
||||
val = Get_NB32(dev, reg);
|
||||
val &= ~(0x3ff<<22);
|
||||
val |= MaxRdLatVal << 22;
|
||||
/* program MaxRdLatency to correspond with current delay */
|
||||
Set_NB32(dev, reg, val);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static u8 CompareMaxRdLatTestPattern_D(u32 pattern_buf, u32 addr)
|
||||
{
|
||||
/* Compare only the first beat of data. Since target addrs are cache
|
||||
* line aligned, the Channel parameter is used to determine which cache
|
||||
* QW to compare.
|
||||
*/
|
||||
|
||||
u32 *test_buf = (u32 *)pattern_buf;
|
||||
u32 addr_lo;
|
||||
u32 val, val_test;
|
||||
int i;
|
||||
u8 ret = DQS_PASS;
|
||||
|
||||
SetUpperFSbase(addr);
|
||||
addr_lo = addr << 8;
|
||||
|
||||
_EXECFENCE;
|
||||
for (i = 0; i < (16*3); i++) {
|
||||
val = read32_fs(addr_lo);
|
||||
val_test = test_buf[i];
|
||||
|
||||
print_debug_dqs_pair("\t\t\t\t\t\ttest_buf = ", (u32)test_buf, " value = ", val_test, 5);
|
||||
print_debug_dqs_pair("\t\t\t\t\t\ttaddr_lo = ", addr_lo, " value = ", val, 5);
|
||||
if (val != val_test) {
|
||||
ret = DQS_FAIL;
|
||||
break;
|
||||
}
|
||||
addr_lo += 4;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 GetMaxRdLatTestAddr_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat,
|
||||
u8 Channel, u8 *MaxRcvrEnDly,
|
||||
u8 *valid)
|
||||
{
|
||||
u8 Max = 0;
|
||||
|
||||
u8 Channel_Max = 0;
|
||||
u8 d;
|
||||
u8 d_Max = 0;
|
||||
|
||||
u8 Byte;
|
||||
u32 TestAddr0 = 0;
|
||||
u8 ch, ch_start, ch_end;
|
||||
u8 bn;
|
||||
|
||||
bn = 8;
|
||||
|
||||
if (pDCTstat->Status & (1 << SB_128bitmode)) {
|
||||
ch_start = 0;
|
||||
ch_end = 2;
|
||||
} else {
|
||||
ch_start = Channel;
|
||||
ch_end = Channel + 1;
|
||||
}
|
||||
|
||||
*valid = 0;
|
||||
|
||||
for (ch = ch_start; ch < ch_end; ch++) {
|
||||
for (d = 0; d < 4; d++) {
|
||||
for (Byte = 0; Byte < bn; Byte++) {
|
||||
u8 tmp;
|
||||
tmp = pDCTstat->persistentData.CH_D_B_RCVRDLY[ch][d][Byte];
|
||||
if (tmp > Max) {
|
||||
Max = tmp;
|
||||
Channel_Max = Channel;
|
||||
d_Max = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel_Max, d_Max << 1)) {
|
||||
TestAddr0 = mct_GetMCTSysAddr_D(pMCTstat, pDCTstat, Channel_Max, d_Max << 1, valid);
|
||||
}
|
||||
|
||||
if (*valid)
|
||||
*MaxRcvrEnDly = Max;
|
||||
|
||||
return TestAddr0;
|
||||
|
||||
}
|
||||
|
||||
u8 mct_GetStartMaxRdLat_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat,
|
||||
u8 Channel, u8 DQSRcvEnDly, u32 *Margin)
|
||||
{
|
||||
u32 SubTotal;
|
||||
u32 val;
|
||||
u32 valx;
|
||||
u32 valxx;
|
||||
u32 index_reg;
|
||||
u32 reg_off;
|
||||
u32 dev;
|
||||
|
||||
if (pDCTstat->GangedMode)
|
||||
Channel = 0;
|
||||
|
||||
index_reg = 0x98 + 0x100 * Channel;
|
||||
|
||||
reg_off = 0x100 * Channel;
|
||||
dev = pDCTstat->dev_dct;
|
||||
|
||||
/* Multiply the CAS Latency by two to get a number of 1/2 MEMCLKs units.*/
|
||||
val = Get_NB32(dev, 0x88 + reg_off);
|
||||
SubTotal = ((val & 0x0f) + 1) << 1; /* SubTotal is 1/2 Memclk unit */
|
||||
|
||||
/* If registered DIMMs are being used then add 1 MEMCLK to the sub-total*/
|
||||
val = Get_NB32(dev, 0x90 + reg_off);
|
||||
if (!(val & (1 << UnBuffDimm)))
|
||||
SubTotal += 2;
|
||||
|
||||
/*If the address prelaunch is setup for 1/2 MEMCLKs then add 1,
|
||||
* else add 2 to the sub-total. if (AddrCmdSetup || CsOdtSetup
|
||||
* || CkeSetup) then K := K + 2; */
|
||||
val = Get_NB32_index_wait(dev, index_reg, 0x04);
|
||||
if (!(val & 0x00202020))
|
||||
SubTotal += 1;
|
||||
else
|
||||
SubTotal += 2;
|
||||
|
||||
/* If the F2x[1, 0]78[RdPtrInit] field is 4, 5, 6 or 7 MEMCLKs,
|
||||
* then add 4, 3, 2, or 1 MEMCLKs, respectively to the sub-total. */
|
||||
val = Get_NB32(dev, 0x78 + reg_off);
|
||||
SubTotal += 8 - (val & 0x0f);
|
||||
|
||||
/* Convert bits 7-5 (also referred to as the course delay) of the current
|
||||
* (or worst case) DQS receiver enable delay to 1/2 MEMCLKs units,
|
||||
* rounding up, and add this to the sub-total. */
|
||||
SubTotal += DQSRcvEnDly >> 5; /*BOZO-no rounding up */
|
||||
|
||||
SubTotal <<= 1; /*scale 1/2 MemClk to 1/4 MemClk */
|
||||
|
||||
/* Convert the sub-total (in 1/2 MEMCLKs) to northbridge clocks (NCLKs)
|
||||
* as follows (assuming DDR400 and assuming that no P-state or link speed
|
||||
* changes have occurred). */
|
||||
|
||||
/*New formula:
|
||||
SubTotal *= 3*(Fn2xD4[NBFid]+4)/(3+Fn2x94[MemClkFreq])/2 */
|
||||
val = Get_NB32(dev, 0x94 + reg_off);
|
||||
/* SubTotal div 4 to scale 1/4 MemClk back to MemClk */
|
||||
val &= 7;
|
||||
if (val == 4) {
|
||||
val++; /* adjust for DDR2-1066 */
|
||||
}
|
||||
valx = (val + 3) << 2; /* SubTotal div 4 to scale 1/4 MemClk back to MemClk */
|
||||
|
||||
|
||||
val = Get_NB32(pDCTstat->dev_nbmisc, 0xD4);
|
||||
val = ((val & 0x1f) + 4) * 3;
|
||||
|
||||
/* Calculate 1 MemClk + 1 NCLK delay in NCLKs for margin */
|
||||
valxx = val << 2;
|
||||
valxx /= valx;
|
||||
if (valxx % valx)
|
||||
valxx++; /* round up */
|
||||
valxx++; /* add 1NCLK */
|
||||
*Margin = valxx; /* one MemClk delay in NCLKs and one additional NCLK */
|
||||
|
||||
val *= SubTotal;
|
||||
|
||||
val /= valx;
|
||||
if (val % valx)
|
||||
val++; /* round up */
|
||||
|
||||
|
||||
|
||||
return val;
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
ifeq ($(CONFIG_NORTHBRIDGE_AMD_AMDFAM10),y)
|
||||
|
||||
# DDR3
|
||||
romstage-$(CONFIG_HAVE_ACPI_RESUME) += s3utils.c
|
||||
romstage-y += mct_d.c mctmtr_d.c mctcsi_d.c mctecc_d.c mctdqs_d.c mctsrc.c
|
||||
romstage-y += mctsdi.c mctprod.c mctproc.c mctprob.c mcthwl.c mctwl.c
|
||||
romstage-y += mport_d.c mutilc_d.c modtrdim.c mhwlc_d.c mctrci.c mctsrc1p.c
|
||||
romstage-y += mcttmrl.c mcthdi.c mctndi_d.c mctchi_d.c modtrd.c mct_d_gcc.c
|
||||
|
||||
ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x11)
|
||||
romstage-y += mctardk5.c
|
||||
endif
|
||||
ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x13)
|
||||
romstage-y += mctardk5.c
|
||||
endif
|
||||
ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x14)
|
||||
romstage-y += mctardk5.c
|
||||
endif
|
||||
ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x15)
|
||||
romstage-y += mctardk5.c
|
||||
endif
|
||||
ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x16)
|
||||
romstage-y += mctardk5.c
|
||||
endif
|
||||
ifeq ($(CONFIG_CPU_SOCKET_TYPE), 0x12)
|
||||
romstage-y += mctardk6.c
|
||||
endif
|
||||
|
||||
ramstage-$(CONFIG_HAVE_ACPI_RESUME) += s3utils.c
|
||||
|
||||
endif
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,296 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mct_d_gcc.h"
|
||||
#include <stdint.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
void _WRMSR(u32 addr, u32 lo, u32 hi)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"wrmsr"
|
||||
:
|
||||
:"c"(addr),"a"(lo), "d" (hi)
|
||||
);
|
||||
}
|
||||
|
||||
void _RDMSR(u32 addr, u32 *lo, u32 *hi)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"rdmsr"
|
||||
:"=a"(*lo), "=d" (*hi)
|
||||
:"c"(addr)
|
||||
);
|
||||
}
|
||||
|
||||
void _RDTSC(u32 *lo, u32 *hi)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"rdtsc"
|
||||
: "=a" (*lo), "=d"(*hi)
|
||||
);
|
||||
}
|
||||
|
||||
void _cpu_id(u32 addr, u32 *val)
|
||||
{
|
||||
__asm__ volatile(
|
||||
"cpuid"
|
||||
: "=a" (val[0]),
|
||||
"=b" (val[1]),
|
||||
"=c" (val[2]),
|
||||
"=d" (val[3])
|
||||
: "0" (addr));
|
||||
|
||||
}
|
||||
|
||||
u32 bsr(u32 x)
|
||||
{
|
||||
u8 i;
|
||||
u32 ret = 0;
|
||||
|
||||
for (i = 31; i > 0; i--) {
|
||||
if (x & (1<<i)) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
u32 bsf(u32 x)
|
||||
{
|
||||
u8 i;
|
||||
u32 ret = 32;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (x & (1<<i)) {
|
||||
ret = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void proc_MFENCE(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"mfence\n\t"
|
||||
:::"memory"
|
||||
);
|
||||
}
|
||||
|
||||
void proc_CLFLUSH(u32 addr_hi)
|
||||
{
|
||||
SetUpperFSbase(addr_hi);
|
||||
|
||||
__asm__ volatile (
|
||||
/* clflush fs:[eax] */
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"clflush %%fs:(%0)\n\t"
|
||||
"mfence\n\t"
|
||||
::"a" (addr_hi<<8)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void WriteLNTestPattern(u32 addr_lo, u8 *buf_a, u32 line_num)
|
||||
{
|
||||
uint32_t step = 16;
|
||||
uint32_t count = line_num * 4;
|
||||
|
||||
__asm__ volatile (
|
||||
/*prevent speculative execution of following instructions*/
|
||||
/* FIXME: needed ? */
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"1:\n\t"
|
||||
"movdqa (%3), %%xmm0\n\t"
|
||||
"movntdq %%xmm0, %%fs:(%0)\n\t" /* xmm0 is 128 bit */
|
||||
"addl %1, %0\n\t"
|
||||
"addl %1, %3\n\t"
|
||||
"loop 1b\n\t"
|
||||
"mfence\n\t"
|
||||
|
||||
: "+a" (addr_lo), "+d" (step), "+c" (count), "+b" (buf_a) : :
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
u32 read32_fs(u32 addr_lo)
|
||||
{
|
||||
u32 value;
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"movl %%fs:(%1), %0\n\t"
|
||||
:"=b"(value): "a" (addr_lo)
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
uint64_t read64_fs(uint32_t addr_lo)
|
||||
{
|
||||
uint64_t value = 0;
|
||||
uint32_t value_lo;
|
||||
uint32_t value_hi;
|
||||
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"mfence\n\t"
|
||||
"movl %%fs:(%2), %0\n\t"
|
||||
"movl %%fs:(%3), %1\n\t"
|
||||
:"=c"(value_lo), "=d"(value_hi): "a" (addr_lo), "b" (addr_lo + 4) : "memory"
|
||||
);
|
||||
value |= value_lo;
|
||||
value |= ((uint64_t)value_hi) << 32;
|
||||
return value;
|
||||
}
|
||||
|
||||
void FlushDQSTestPattern_L9(u32 addr_lo)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"clflush %%fs:-128(%%ecx)\n\t"
|
||||
"clflush %%fs:-64(%%ecx)\n\t"
|
||||
"clflush %%fs:(%%ecx)\n\t"
|
||||
"clflush %%fs:64(%%ecx)\n\t"
|
||||
|
||||
"clflush %%fs:-128(%%eax)\n\t"
|
||||
"clflush %%fs:-64(%%eax)\n\t"
|
||||
"clflush %%fs:(%%eax)\n\t"
|
||||
"clflush %%fs:64(%%eax)\n\t"
|
||||
|
||||
"clflush %%fs:-128(%%ebx)\n\t"
|
||||
|
||||
:: "b" (addr_lo+128+8*64), "c"(addr_lo+128),
|
||||
"a"(addr_lo+128+4*64)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
__attribute__((noinline)) void FlushDQSTestPattern_L18(u32 addr_lo)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"clflush %%fs:-128(%%eax)\n\t"
|
||||
"clflush %%fs:-64(%%eax)\n\t"
|
||||
"clflush %%fs:(%%eax)\n\t"
|
||||
"clflush %%fs:64(%%eax)\n\t"
|
||||
|
||||
"clflush %%fs:-128(%%edi)\n\t"
|
||||
"clflush %%fs:-64(%%edi)\n\t"
|
||||
"clflush %%fs:(%%edi)\n\t"
|
||||
"clflush %%fs:64(%%edi)\n\t"
|
||||
|
||||
"clflush %%fs:-128(%%ebx)\n\t"
|
||||
"clflush %%fs:-64(%%ebx)\n\t"
|
||||
"clflush %%fs:(%%ebx)\n\t"
|
||||
"clflush %%fs:64(%%ebx)\n\t"
|
||||
|
||||
"clflush %%fs:-128(%%ecx)\n\t"
|
||||
"clflush %%fs:-64(%%ecx)\n\t"
|
||||
"clflush %%fs:(%%ecx)\n\t"
|
||||
"clflush %%fs:64(%%ecx)\n\t"
|
||||
|
||||
"clflush %%fs:-128(%%edx)\n\t"
|
||||
"clflush %%fs:-64(%%edx)\n\t"
|
||||
|
||||
:: "b" (addr_lo+128+8*64), "c" (addr_lo+128+12*64),
|
||||
"d" (addr_lo +128+16*64), "a"(addr_lo+128),
|
||||
"D"(addr_lo+128+4*64)
|
||||
);
|
||||
}
|
||||
|
||||
void ReadMaxRdLat1CLTestPattern_D(u32 addr)
|
||||
{
|
||||
SetUpperFSbase(addr);
|
||||
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"movl %%fs:-128(%%esi), %%eax\n\t" /* TestAddr cache line */
|
||||
"movl %%fs:-64(%%esi), %%eax\n\t" /* +1 */
|
||||
"movl %%fs:(%%esi), %%eax\n\t" /* +2 */
|
||||
"mfence\n\t"
|
||||
:: "a"(0), "S"((addr<<8)+128)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
void WriteMaxRdLat1CLTestPattern_D(u32 buf, u32 addr)
|
||||
{
|
||||
uint32_t addr_phys = addr << 8;
|
||||
uint32_t step = 16;
|
||||
uint32_t count = 3 * 4;
|
||||
|
||||
SetUpperFSbase(addr);
|
||||
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"1:\n\t"
|
||||
"movdqa (%3), %%xmm0\n\t"
|
||||
"movntdq %%xmm0, %%fs:(%0)\n\t" /* xmm0 is 128 bit */
|
||||
"addl %1, %0\n\t"
|
||||
"addl %1, %3\n\t"
|
||||
"loop 1b\n\t"
|
||||
"mfence\n\t"
|
||||
|
||||
: "+a" (addr_phys), "+d" (step), "+c" (count), "+b" (buf) : :
|
||||
);
|
||||
}
|
||||
|
||||
void FlushMaxRdLatTestPattern_D(u32 addr)
|
||||
{
|
||||
/* Flush a pattern of 72 bit times (per DQ) from cache.
|
||||
* This procedure is used to ensure cache miss on the next read training.
|
||||
*/
|
||||
|
||||
SetUpperFSbase(addr);
|
||||
|
||||
__asm__ volatile (
|
||||
"outb %%al, $0xed\n\t" /* _EXECFENCE */
|
||||
"clflush %%fs:-128(%%esi)\n\t" /* TestAddr cache line */
|
||||
"clflush %%fs:-64(%%esi)\n\t" /* +1 */
|
||||
"clflush %%fs:(%%esi)\n\t" /* +2 */
|
||||
"mfence\n\t"
|
||||
|
||||
:: "S"((addr<<8)+128)
|
||||
);
|
||||
}
|
||||
|
||||
u32 stream_to_int(u8 *p)
|
||||
{
|
||||
int i;
|
||||
u32 val;
|
||||
u32 valx;
|
||||
|
||||
val = 0;
|
||||
|
||||
for (i = 3; i >= 0; i--) {
|
||||
val <<= 8;
|
||||
valx = *(p+i);
|
||||
val |= valx;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
u8 oemNodePresent_D(u8 Node, u8 *ret)
|
||||
{
|
||||
*ret = 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
* Copyright (C) 2016 Damien Zammit <damien@zamaudio.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef MCT_D_GCC_H
|
||||
#define MCT_D_GCC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cpu/x86/cr.h>
|
||||
|
||||
void _WRMSR(u32 addr, u32 lo, u32 hi);
|
||||
void _RDMSR(u32 addr, u32 *lo, u32 *hi);
|
||||
void _RDTSC(u32 *lo, u32 *hi);
|
||||
void _cpu_id(u32 addr, u32 *val);
|
||||
u32 bsr(u32 x);
|
||||
u32 bsf(u32 x);
|
||||
#define _MFENCE asm volatile ("mfence")
|
||||
#define _SFENCE asm volatile ("sfence")
|
||||
|
||||
/* prevent speculative execution of following instructions */
|
||||
#define _EXECFENCE asm volatile ("outb %al, $0xed")
|
||||
|
||||
u32 SetUpperFSbase(u32 addr_hi);
|
||||
|
||||
void proc_MFENCE(void);
|
||||
void proc_CLFLUSH(u32 addr_hi);
|
||||
void WriteLNTestPattern(u32 addr_lo, u8 *buf_a, u32 line_num);
|
||||
u32 read32_fs(u32 addr_lo);
|
||||
uint64_t read64_fs(uint32_t addr_lo);
|
||||
void FlushDQSTestPattern_L9(u32 addr_lo);
|
||||
__attribute__((noinline)) void FlushDQSTestPattern_L18(u32 addr_lo);
|
||||
void ReadMaxRdLat1CLTestPattern_D(u32 addr);
|
||||
void WriteMaxRdLat1CLTestPattern_D(u32 buf, u32 addr);
|
||||
void FlushMaxRdLatTestPattern_D(u32 addr);
|
||||
u32 stream_to_int(u8 *p);
|
||||
u8 oemNodePresent_D(u8 Node, u8 *ret);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* AM3/ASB2/C32/G34 DDR3 */
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <stdint.h>
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
static uint8_t is_fam15h(void)
|
||||
{
|
||||
uint8_t fam15h = 0;
|
||||
uint32_t family;
|
||||
|
||||
family = cpuid_eax(0x80000001);
|
||||
family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
|
||||
|
||||
if (family >= 0x6f)
|
||||
/* Family 15h or later */
|
||||
fam15h = 1;
|
||||
|
||||
return fam15h;
|
||||
}
|
||||
|
||||
static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload,
|
||||
u32 *ODC_CTL,
|
||||
u8 *CMDmode);
|
||||
|
||||
void mctGet_PS_Cfg_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u32 dct)
|
||||
{
|
||||
if (is_fam15h()) {
|
||||
pDCTstat->CH_ADDR_TMG[dct] = fam15h_address_timing_compensation_code(pDCTstat, dct);
|
||||
pDCTstat->CH_ODC_CTL[dct] = fam15h_output_driver_compensation_code(pDCTstat, dct);
|
||||
pDCTstat->_2Tmode = fam15h_slow_access_mode(pDCTstat, dct);
|
||||
} else {
|
||||
Get_ChannelPS_Cfg0_D(pDCTstat->MAdimms[dct], pDCTstat->Speed,
|
||||
pDCTstat->MAload[dct],
|
||||
&(pDCTstat->CH_ODC_CTL[dct]),
|
||||
&pDCTstat->_2Tmode);
|
||||
|
||||
if (pDCTstat->Status & (1 << SB_Registered)) {
|
||||
pDCTstat->_2Tmode = 1; /* Disable slow access mode */
|
||||
}
|
||||
pDCTstat->CH_ADDR_TMG[dct] = fam10h_address_timing_compensation_code(pDCTstat, dct);
|
||||
|
||||
pDCTstat->CH_ODC_CTL[dct] |= 0x20000000; /* 60ohms */
|
||||
}
|
||||
|
||||
pDCTstat->CH_EccDQSLike[0] = 0x0403;
|
||||
pDCTstat->CH_EccDQSScale[0] = 0x70;
|
||||
pDCTstat->CH_EccDQSLike[1] = 0x0403;
|
||||
pDCTstat->CH_EccDQSScale[1] = 0x70;
|
||||
}
|
||||
|
||||
/*
|
||||
* In: MAAdimms - number of DIMMs on the channel
|
||||
* : Speed - Speed (see DCTStatstruc.Speed for definition)
|
||||
* : MAAload - number of address bus loads on the channel
|
||||
* Out: AddrTmgCTL - Address Timing Control Register Value
|
||||
* : ODC_CTL - Output Driver Compensation Control Register Value
|
||||
* : CMDmode - CMD mode
|
||||
*/
|
||||
static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload,
|
||||
u32 *ODC_CTL,
|
||||
u8 *CMDmode)
|
||||
{
|
||||
*ODC_CTL = 0;
|
||||
*CMDmode = 1;
|
||||
|
||||
if (MAAdimms == 1) {
|
||||
*ODC_CTL = 0x00113222;
|
||||
*CMDmode = 1;
|
||||
} else /* if (MAAdimms == 0) */ {
|
||||
if (Speed == 4) {
|
||||
*CMDmode = 1;
|
||||
} else if (Speed == 5) {
|
||||
*CMDmode = 1;
|
||||
} else if (Speed == 6) {
|
||||
*CMDmode = 2;
|
||||
} else {
|
||||
*CMDmode = 2;
|
||||
}
|
||||
*ODC_CTL = 0x00223323;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* The socket type Fr2, G (1207) are not tested.
|
||||
*/
|
||||
|
||||
static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload,
|
||||
u8 DATAAload, u32 *AddrTmgCTL, u32 *ODC_CTL,
|
||||
u8 *CMDmode);
|
||||
|
||||
|
||||
void mctGet_PS_Cfg_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u32 dct)
|
||||
{
|
||||
Get_ChannelPS_Cfg0_D(pDCTstat->MAdimms[dct], pDCTstat->Speed,
|
||||
pDCTstat->MAload[dct], pDCTstat->DATAload[dct],
|
||||
&(pDCTstat->CH_ADDR_TMG[dct]), &(pDCTstat->CH_ODC_CTL[dct]),
|
||||
&pDCTstat->_2Tmode);
|
||||
|
||||
if (pDCTstat->GangedMode == 1 && dct == 0)
|
||||
Get_ChannelPS_Cfg0_D(pDCTstat->MAdimms[1], pDCTstat->Speed,
|
||||
pDCTstat->MAload[1], pDCTstat->DATAload[1],
|
||||
&(pDCTstat->CH_ADDR_TMG[1]), &(pDCTstat->CH_ODC_CTL[1]),
|
||||
&pDCTstat->_2Tmode);
|
||||
|
||||
pDCTstat->CH_EccDQSLike[0] = 0x0302;
|
||||
pDCTstat->CH_EccDQSLike[1] = 0x0302;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* In: MAAdimms - number of DIMMs on the channel
|
||||
* : Speed - Speed (see DCTStatstruc.Speed for definition)
|
||||
* : MAAload - number of address bus loads on the channel
|
||||
* : DATAAload - number of ranks on the channel
|
||||
* Out: AddrTmgCTL - Address Timing Control Register Value
|
||||
* : ODC_CTL - Output Driver Compensation Control Register Value
|
||||
* : CMDmode - CMD mode
|
||||
*/
|
||||
static void Get_ChannelPS_Cfg0_D(u8 MAAdimms, u8 Speed, u8 MAAload,
|
||||
u8 DATAAload, u32 *AddrTmgCTL, u32 *ODC_CTL,
|
||||
u8 *CMDmode)
|
||||
{
|
||||
*AddrTmgCTL = 0;
|
||||
*ODC_CTL = 0;
|
||||
*CMDmode = 1;
|
||||
|
||||
if (mctGet_NVbits(NV_MAX_DIMMS) == 4) {
|
||||
if (Speed == 4) {
|
||||
*AddrTmgCTL = 0x00000000;
|
||||
} else if (Speed == 5) {
|
||||
*AddrTmgCTL = 0x003C3C3C;
|
||||
if (MAAdimms > 1)
|
||||
*AddrTmgCTL = 0x003A3C3A;
|
||||
} else if (Speed == 6) {
|
||||
if (MAAdimms == 1)
|
||||
*AddrTmgCTL = 0x003A3A3A;
|
||||
else
|
||||
*AddrTmgCTL = 0x00383A38;
|
||||
} else {
|
||||
if (MAAdimms == 1)
|
||||
*AddrTmgCTL = 0x00373937;
|
||||
else
|
||||
*AddrTmgCTL = 0x00353935;
|
||||
}
|
||||
} else {
|
||||
if (Speed == 4) {
|
||||
*AddrTmgCTL = 0x00000000;
|
||||
if (MAAdimms == 3)
|
||||
*AddrTmgCTL = 0x00380038;
|
||||
} else if (Speed == 5) {
|
||||
if (MAAdimms == 1)
|
||||
*AddrTmgCTL = 0x003C3C3C;
|
||||
else if (MAAdimms == 2)
|
||||
*AddrTmgCTL = 0x003A3C3A;
|
||||
else
|
||||
*AddrTmgCTL = 0x00373C37;
|
||||
} else if (Speed == 6) {
|
||||
if (MAAdimms == 1)
|
||||
*AddrTmgCTL = 0x003A3A3A;
|
||||
else if (MAAdimms == 2)
|
||||
*AddrTmgCTL = 0x00383A38;
|
||||
else
|
||||
*AddrTmgCTL = 0x00343A34;
|
||||
} else {
|
||||
if (MAAdimms == 1)
|
||||
*AddrTmgCTL = 0x00393939;
|
||||
else if (MAAdimms == 2)
|
||||
*AddrTmgCTL = 0x00363936;
|
||||
else
|
||||
*AddrTmgCTL = 0x00303930;
|
||||
}
|
||||
}
|
||||
|
||||
if ((MAAdimms == 1) && (MAAload < 4))
|
||||
*ODC_CTL = 0x20113222;
|
||||
else
|
||||
*ODC_CTL = 0x20223222;
|
||||
|
||||
*CMDmode = 1;
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
#include <console/console.h>
|
||||
|
||||
void InterleaveChannels_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
|
||||
u8 Node;
|
||||
u32 DramBase, DctSelBase;
|
||||
u8 DctSelIntLvAddr, DctSelHi;
|
||||
u8 HoleValid = 0;
|
||||
u32 HoleSize, HoleBase = 0;
|
||||
u32 val, tmp;
|
||||
u32 dct0_size, dct1_size;
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
|
||||
/* HoleValid - indicates whether the current Node contains hole.
|
||||
* HoleSize - indicates whether there is IO hole in the whole system
|
||||
* memory.
|
||||
*/
|
||||
|
||||
/* call back to wrapper not needed ManualChannelInterleave_D(); */
|
||||
/* call back - DctSelIntLvAddr = mctGet_NVbits(NV_ChannelIntlv);*/ /* override interleave */
|
||||
/* Manually set: typ = 5, otherwise typ = 7. */
|
||||
DctSelIntLvAddr = mctGet_NVbits(NV_ChannelIntlv); /* typ = 5: Hash*: exclusive OR of address bits[20:16, 6]. */
|
||||
|
||||
if (DctSelIntLvAddr & 1) {
|
||||
DctSelIntLvAddr >>= 1;
|
||||
HoleSize = 0;
|
||||
if ((pMCTstat->GStatus & (1 << GSB_SoftHole)) ||
|
||||
(pMCTstat->GStatus & (1 << GSB_HWHole))) {
|
||||
if (pMCTstat->HoleBase) {
|
||||
HoleBase = pMCTstat->HoleBase >> 8;
|
||||
HoleSize = HoleBase & 0xFFFF0000;
|
||||
HoleSize |= ((~HoleBase) + 1) & 0xFFFF;
|
||||
}
|
||||
}
|
||||
Node = 0;
|
||||
while (Node < MAX_NODES_SUPPORTED) {
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
val = Get_NB32(pDCTstat->dev_map, 0xF0);
|
||||
if (val & (1 << DramHoleValid))
|
||||
HoleValid = 1;
|
||||
if (!pDCTstat->GangedMode && pDCTstat->DIMMValidDCT[0] && pDCTstat->DIMMValidDCT[1]) {
|
||||
DramBase = pDCTstat->NodeSysBase >> 8;
|
||||
dct1_size = ((pDCTstat->NodeSysLimit) + 2) >> 8;
|
||||
dct0_size = Get_NB32(pDCTstat->dev_dct, 0x114);
|
||||
if (dct0_size >= 0x10000) {
|
||||
dct0_size -= HoleSize;
|
||||
}
|
||||
|
||||
dct0_size -= DramBase;
|
||||
dct1_size -= dct0_size;
|
||||
DctSelHi = 0x05; /* DctSelHiRngEn = 1, DctSelHi = 0 */
|
||||
if (dct1_size == dct0_size) {
|
||||
dct1_size = 0;
|
||||
DctSelHi = 0x04; /* DctSelHiRngEn = 0 */
|
||||
} else if (dct1_size > dct0_size) {
|
||||
dct1_size = dct0_size;
|
||||
DctSelHi = 0x07; /* DctSelHiRngEn = 1, DctSelHi = 1 */
|
||||
}
|
||||
dct0_size = dct1_size;
|
||||
dct0_size += DramBase;
|
||||
dct0_size += dct1_size;
|
||||
if (dct0_size >= HoleBase) /* if DctSelBaseAddr > HoleBase */
|
||||
dct0_size += HoleSize;
|
||||
DctSelBase = dct0_size;
|
||||
|
||||
if (dct1_size == 0)
|
||||
dct0_size = 0;
|
||||
dct0_size -= dct1_size; /* DctSelBaseOffset = DctSelBaseAddr - Interleaved region */
|
||||
Set_NB32(pDCTstat->dev_dct, 0x114, dct0_size);
|
||||
|
||||
if (dct1_size == 0)
|
||||
dct1_size = DctSelBase;
|
||||
val = Get_NB32(pDCTstat->dev_dct, 0x110);
|
||||
val &= 0x7F8;
|
||||
val |= dct1_size;
|
||||
val |= DctSelHi;
|
||||
val |= (DctSelIntLvAddr << 6) & 0xFF;
|
||||
Set_NB32(pDCTstat->dev_dct, 0x110, val);
|
||||
|
||||
if (HoleValid) {
|
||||
tmp = DramBase;
|
||||
val = DctSelBase;
|
||||
if (val < HoleBase) { /* DctSelBaseAddr < DramHoleBase */
|
||||
val -= DramBase;
|
||||
val >>= 1;
|
||||
tmp += val;
|
||||
}
|
||||
tmp += HoleSize;
|
||||
val = Get_NB32(pDCTstat->dev_map, 0xF0); /* DramHoleOffset */
|
||||
val &= 0xFFFF007F;
|
||||
val |= (tmp & ~0xFFFF007F);
|
||||
Set_NB32(pDCTstat->dev_map, 0xF0, val);
|
||||
}
|
||||
}
|
||||
printk(BIOS_DEBUG, "InterleaveChannels_D: Node %x\n", Node);
|
||||
printk(BIOS_DEBUG, "InterleaveChannels_D: Status %x\n", pDCTstat->Status);
|
||||
printk(BIOS_DEBUG, "InterleaveChannels_D: ErrStatus %x\n", pDCTstat->ErrStatus);
|
||||
printk(BIOS_DEBUG, "InterleaveChannels_D: ErrCode %x\n", pDCTstat->ErrCode);
|
||||
Node++;
|
||||
}
|
||||
}
|
||||
printk(BIOS_DEBUG, "InterleaveChannels_D: Done\n\n");
|
||||
}
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Low swap bit vs bank size encoding (physical, not logical address bit)
|
||||
* ;To calculate the number by hand, add the number of Bank address bits
|
||||
* ;(2 or 3) to the number of column address bits, plus 3 (the logical
|
||||
* ;page size), and subtract 8.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
#include <console/console.h>
|
||||
|
||||
static const u8 Tab_int_D[] = {6,7,7,8,8,8,8,8,9,9,8,9};
|
||||
|
||||
void InterleaveBanks_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u8 dct)
|
||||
{
|
||||
u8 ChipSel, EnChipSels;
|
||||
u32 AddrLoMask, AddrHiMask;
|
||||
u32 AddrLoMaskN, AddrHiMaskN, MemSize = 0;
|
||||
u8 DoIntlv, _CsIntCap;
|
||||
u32 BitDelta, BankEncd = 0;
|
||||
|
||||
u32 dev;
|
||||
u32 reg;
|
||||
u32 val;
|
||||
u32 val_lo, val_hi;
|
||||
|
||||
DoIntlv = mctGet_NVbits(NV_BankIntlv);
|
||||
_CsIntCap = 0;
|
||||
EnChipSels = 0;
|
||||
|
||||
dev = pDCTstat->dev_dct;
|
||||
|
||||
ChipSel = 0; /* Find out if current configuration is capable */
|
||||
while (DoIntlv && (ChipSel < MAX_CS_SUPPORTED)) {
|
||||
reg = 0x40+(ChipSel<<2); /* Dram CS Base 0 */
|
||||
val = Get_NB32_DCT(dev, dct, reg);
|
||||
if (val & (1<<CSEnable)) {
|
||||
EnChipSels++;
|
||||
reg = 0x60+((ChipSel>>1)<<2); /*Dram CS Mask 0 */
|
||||
val = Get_NB32_DCT(dev, dct, reg);
|
||||
val >>= 19;
|
||||
val &= 0x3ff;
|
||||
val++;
|
||||
if (EnChipSels == 1)
|
||||
MemSize = val;
|
||||
else
|
||||
/*If mask sizes not same then skip */
|
||||
if (val != MemSize)
|
||||
break;
|
||||
reg = 0x80; /*Dram Bank Addressing */
|
||||
val = Get_NB32_DCT(dev, dct, reg);
|
||||
val >>= (ChipSel>>1)<<2;
|
||||
val &= 0x0f;
|
||||
if (EnChipSels == 1)
|
||||
BankEncd = val;
|
||||
else
|
||||
/*If number of Rows/Columns not equal, skip */
|
||||
if (val != BankEncd)
|
||||
break;
|
||||
}
|
||||
ChipSel++;
|
||||
}
|
||||
if (ChipSel == MAX_CS_SUPPORTED) {
|
||||
if ((EnChipSels == 2) || (EnChipSels == 4) || (EnChipSels == 8))
|
||||
_CsIntCap = 1;
|
||||
}
|
||||
|
||||
if (DoIntlv) {
|
||||
if (!_CsIntCap) {
|
||||
pDCTstat->ErrStatus |= 1<<SB_BkIntDis;
|
||||
DoIntlv = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (DoIntlv) {
|
||||
val = Tab_int_D[BankEncd];
|
||||
if (pDCTstat->Status & (1<<SB_128bitmode))
|
||||
val++;
|
||||
|
||||
AddrLoMask = (EnChipSels - 1) << val;
|
||||
AddrLoMaskN = ~AddrLoMask;
|
||||
|
||||
val = bsf(MemSize) + 19;
|
||||
AddrHiMask = (EnChipSels -1) << val;
|
||||
AddrHiMaskN = ~AddrHiMask;
|
||||
|
||||
BitDelta = bsf(AddrHiMask) - bsf(AddrLoMask);
|
||||
|
||||
for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel++) {
|
||||
reg = 0x40 + (ChipSel<<2); /* Dram CS Base 0 */
|
||||
val = Get_NB32_DCT(dev, dct, reg);
|
||||
if (val & 3) {
|
||||
val_lo = val & AddrLoMask;
|
||||
val_hi = val & AddrHiMask;
|
||||
val &= AddrLoMaskN;
|
||||
val &= AddrHiMaskN;
|
||||
val_lo <<= BitDelta;
|
||||
val_hi >>= BitDelta;
|
||||
val |= val_lo;
|
||||
val |= val_hi;
|
||||
Set_NB32_DCT(dev, dct, reg, val);
|
||||
|
||||
if (ChipSel & 1)
|
||||
continue;
|
||||
|
||||
reg = 0x60 + ((ChipSel>>1)<<2); /* Dram CS Mask 0 */
|
||||
val = Get_NB32_DCT(dev, dct, reg);
|
||||
val_lo = val & AddrLoMask;
|
||||
val_hi = val & AddrHiMask;
|
||||
val &= AddrLoMaskN;
|
||||
val &= AddrHiMaskN;
|
||||
val_lo <<= BitDelta;
|
||||
val_hi >>= BitDelta;
|
||||
val |= val_lo;
|
||||
val |= val_hi;
|
||||
Set_NB32_DCT(dev, dct, reg, val);
|
||||
}
|
||||
}
|
||||
} /* DoIntlv */
|
||||
|
||||
/* dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2)); */
|
||||
|
||||
printk(BIOS_DEBUG, "InterleaveBanks_D: Status %x\n", pDCTstat->Status);
|
||||
printk(BIOS_DEBUG, "InterleaveBanks_D: ErrStatus %x\n", pDCTstat->ErrStatus);
|
||||
printk(BIOS_DEBUG, "InterleaveBanks_D: ErrCode %x\n", pDCTstat->ErrCode);
|
||||
printk(BIOS_DEBUG, "InterleaveBanks_D: Done\n\n");
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,389 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 - 2016 Raptor Engineering, LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <stdint.h>
|
||||
#include <console/console.h>
|
||||
#include <device/pci_ops.h>
|
||||
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
static void setSyncOnUnEccEn_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA);
|
||||
static u8 isDramECCEn_D(struct DCTStatStruc *pDCTstat);
|
||||
|
||||
static uint8_t is_fam15h(void)
|
||||
{
|
||||
uint8_t fam15h = 0;
|
||||
uint32_t family;
|
||||
|
||||
family = cpuid_eax(0x80000001);
|
||||
family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
|
||||
|
||||
if (family >= 0x6f)
|
||||
/* Family 15h or later */
|
||||
fam15h = 1;
|
||||
|
||||
return fam15h;
|
||||
}
|
||||
|
||||
/* Initialize ECC modes of Integrated Dram+Memory Controllers of a network of
|
||||
* Hammer processors. Use Dram background scrubber to fast initialize ECC bits
|
||||
* of all dram.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Order that items are set:
|
||||
* 1. eccen bit in NB
|
||||
* 2. Scrub Base
|
||||
* 3. Temp Node Base
|
||||
* 4. Temp Node Limit
|
||||
* 5. Redir bit in NB
|
||||
* 6. Scrub CTL
|
||||
*
|
||||
* Conditions for setting background scrubber.
|
||||
* 1. node is present
|
||||
* 2. node has dram functioning (WE = RE = 1)
|
||||
* 3. all eccdimms (or bit 17 of offset 90,fn 2)
|
||||
* 4. no chip-select gap exists
|
||||
*
|
||||
* The dram background scrubber is used under very controlled circumstances to
|
||||
* initialize all the ECC bits on the DIMMs of the entire dram address map
|
||||
* (including hidden or lost dram and dram above 4GB). We will turn the scrub
|
||||
* rate up to maximum, which should clear 4GB of dram in about 2.7 seconds.
|
||||
* We will activate the scrubbers of all nodes with ecc dram and let them run in
|
||||
* parallel, thereby reducing even further the time required to condition dram.
|
||||
* Finally, we will go through each node and either disable background scrubber,
|
||||
* or set the scrub rate to the user setup specified rate.
|
||||
*
|
||||
* To allow the NB to scrub, we need to wait a time period long enough to
|
||||
* guarantee that the NB scrubs the entire dram on its node. Do do this, we
|
||||
* simply sample the scrub ADDR once, for an initial value, then we sample and poll until the polled value of scrub ADDR
|
||||
* has wrapped around at least once: Scrub ADDRi+1 < Scrub ADDRi. Since we let all
|
||||
* Nodes run in parallel, we need to guarantee that all nodes have wrapped. To do
|
||||
* this efficiently, we need only to sample one of the nodes, the node with the
|
||||
* largest ammount of dram populated is the one which will take the longest amount
|
||||
* of time (the scrub rate is set to max, the same rate, on all nodes). So,
|
||||
* during setup of scrub Base, we determine how much memory and which node has
|
||||
* the largest memory installed.
|
||||
*
|
||||
* Scrubbing should not ordinarily be enabled on a Node with a chip-select gap
|
||||
* (aka SW memhole, cs hoisting, etc..).To init ECC memory on this node, the
|
||||
* scrubber is used in two steps. First, the Dram Limit for the node is adjusted
|
||||
* down to the bottom of the gap, and that ECC dram is initialized. Second, the
|
||||
* original Limit is restored, the Scrub base is set to 4GB, and scrubber is
|
||||
* allowed to run until the Scrub Addr wraps around to zero.
|
||||
*/
|
||||
u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
u8 Node;
|
||||
u8 AllECC;
|
||||
u16 OB_NBECC;
|
||||
u32 curBase;
|
||||
u16 OB_ECCRedir;
|
||||
u32 LDramECC;
|
||||
u32 OF_ScrubCTL;
|
||||
u16 OB_ChipKill;
|
||||
u8 MemClrECC;
|
||||
|
||||
u32 dev;
|
||||
u32 reg;
|
||||
u32 val;
|
||||
u16 nvbits;
|
||||
|
||||
uint32_t dword;
|
||||
uint8_t sync_flood_on_dram_err[MAX_NODES_SUPPORTED];
|
||||
uint8_t sync_flood_on_any_uc_err[MAX_NODES_SUPPORTED];
|
||||
|
||||
mctHookBeforeECC();
|
||||
|
||||
/* Construct these booleans, based on setup options, for easy handling
|
||||
later in this procedure */
|
||||
OB_NBECC = mctGet_NVbits(NV_NBECC); /* MCA ECC (MCE) enable bit */
|
||||
|
||||
OB_ECCRedir = mctGet_NVbits(NV_ECCRedir); /* ECC Redirection */
|
||||
|
||||
OB_ChipKill = mctGet_NVbits(NV_ChipKill); /* ECC Chip-kill mode */
|
||||
OF_ScrubCTL = 0; /* Scrub CTL for Dcache, L2, and dram */
|
||||
|
||||
if (!is_fam15h()) {
|
||||
nvbits = mctGet_NVbits(NV_DCBKScrub);
|
||||
/* mct_AdjustScrub_D(pDCTstatA, &nvbits); */ /* Need not adjust */
|
||||
OF_ScrubCTL |= (u32) nvbits << 16;
|
||||
|
||||
nvbits = mctGet_NVbits(NV_L2BKScrub);
|
||||
OF_ScrubCTL |= (u32) nvbits << 8;
|
||||
}
|
||||
|
||||
nvbits = mctGet_NVbits(NV_L3BKScrub);
|
||||
OF_ScrubCTL |= (nvbits & 0x1f) << 24; /* L3Scrub = NV_L3BKScrub */
|
||||
|
||||
nvbits = mctGet_NVbits(NV_DramBKScrub);
|
||||
OF_ScrubCTL |= nvbits; /* DramScrub = NV_DramBKScrub */
|
||||
|
||||
/* Prevent lockups on DRAM errors during ECC init */
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
|
||||
if (NodePresent_D(Node)) {
|
||||
dword = Get_NB32(pDCTstat->dev_nbmisc, 0x44);
|
||||
sync_flood_on_dram_err[Node] = (dword >> 30) & 0x1;
|
||||
sync_flood_on_any_uc_err[Node] = (dword >> 21) & 0x1;
|
||||
dword &= ~(0x1 << 30);
|
||||
dword &= ~(0x1 << 21);
|
||||
Set_NB32(pDCTstat->dev_nbmisc, 0x44, dword);
|
||||
|
||||
uint32_t mc4_status_high = pci_read_config32(pDCTstat->dev_nbmisc, 0x4c);
|
||||
uint32_t mc4_status_low = pci_read_config32(pDCTstat->dev_nbmisc, 0x48);
|
||||
if ((mc4_status_high & (0x1 << 31)) && (mc4_status_high != 0xffffffff)) {
|
||||
printk(BIOS_WARNING, "WARNING: MC4 Machine Check Exception detected!\n"
|
||||
"Signature: %08x%08x\n", mc4_status_high, mc4_status_low);
|
||||
}
|
||||
|
||||
/* Clear MC4 error status */
|
||||
pci_write_config32(pDCTstat->dev_nbmisc, 0x48, 0x0);
|
||||
pci_write_config32(pDCTstat->dev_nbmisc, 0x4c, 0x0);
|
||||
}
|
||||
}
|
||||
|
||||
AllECC = 1;
|
||||
MemClrECC = 0;
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
LDramECC = 0;
|
||||
if (NodePresent_D(Node)) { /*If Node is present */
|
||||
dev = pDCTstat->dev_map;
|
||||
reg = 0x40+(Node << 3); /* Dram Base Node 0 + index */
|
||||
val = Get_NB32(dev, reg);
|
||||
|
||||
/* WE/RE is checked */
|
||||
if ((val & 3) == 3) { /* Node has dram populated */
|
||||
/* Negate 'all nodes/dimms ECC' flag if non ecc
|
||||
memory populated */
|
||||
if (pDCTstat->Status & (1 << SB_ECCDIMMs)) {
|
||||
LDramECC = isDramECCEn_D(pDCTstat);
|
||||
if (pDCTstat->ErrCode != SC_RunningOK) {
|
||||
pDCTstat->Status &= ~(1 << SB_ECCDIMMs);
|
||||
if (!OB_NBECC) {
|
||||
pDCTstat->ErrStatus |= (1 << SB_DramECCDis);
|
||||
}
|
||||
AllECC = 0;
|
||||
LDramECC = 0;
|
||||
}
|
||||
} else {
|
||||
AllECC = 0;
|
||||
}
|
||||
if (LDramECC) { /* if ECC is enabled on this dram */
|
||||
if (OB_NBECC) {
|
||||
mct_EnableDatIntlv_D(pMCTstat, pDCTstat);
|
||||
val = Get_NB32(pDCTstat->dev_dct, 0x110);
|
||||
val |= 1 << 5; /* DctDatIntLv = 1 */
|
||||
Set_NB32(pDCTstat->dev_dct, 0x110, val);
|
||||
dev = pDCTstat->dev_nbmisc;
|
||||
reg = 0x44; /* MCA NB Configuration */
|
||||
val = Get_NB32(dev, reg);
|
||||
val |= 1 << 22; /* EccEn */
|
||||
Set_NB32(dev, reg, val);
|
||||
DCTMemClr_Init_D(pMCTstat, pDCTstat);
|
||||
MemClrECC = 1;
|
||||
printk(BIOS_DEBUG, " ECC enabled on node: %02x\n", Node);
|
||||
}
|
||||
} /* this node has ECC enabled dram */
|
||||
|
||||
if (MemClrECC) {
|
||||
DCTMemClr_Sync_D(pMCTstat, pDCTstat);
|
||||
}
|
||||
} else {
|
||||
LDramECC = 0;
|
||||
} /* Node has Dram */
|
||||
} /* if Node present */
|
||||
}
|
||||
|
||||
if (AllECC)
|
||||
pMCTstat->GStatus |= 1 << GSB_ECCDIMMs;
|
||||
else
|
||||
pMCTstat->GStatus &= ~(1 << GSB_ECCDIMMs);
|
||||
|
||||
/* Program the Dram BKScrub CTL to the proper (user selected) value.*/
|
||||
/* Reset MC4_STS. */
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
LDramECC = 0;
|
||||
if (NodePresent_D(Node)) { /* If Node is present */
|
||||
reg = 0x40+(Node << 3); /* Dram Base Node 0 + index */
|
||||
val = Get_NB32(pDCTstat->dev_map, reg);
|
||||
curBase = val & 0xffff0000;
|
||||
/*WE/RE is checked because memory config may have been */
|
||||
if ((val & 3) == 3) { /* Node has dram populated */
|
||||
if (isDramECCEn_D(pDCTstat)) { /* if ECC is enabled on this dram */
|
||||
dev = pDCTstat->dev_nbmisc;
|
||||
val = curBase << 8;
|
||||
if (OB_ECCRedir) {
|
||||
val |= (1 << 0); /* Enable redirection */
|
||||
}
|
||||
Set_NB32(dev, 0x5c, val); /* Dram Scrub Addr Low */
|
||||
val = curBase >> 24;
|
||||
Set_NB32(dev, 0x60, val); /* Dram Scrub Addr High */
|
||||
|
||||
/* Set scrub rate controls */
|
||||
if (is_fam15h()) {
|
||||
/* Erratum 505 */
|
||||
fam15h_switch_dct(pDCTstat->dev_map, 0);
|
||||
}
|
||||
Set_NB32(dev, 0x58, OF_ScrubCTL); /* Scrub Control */
|
||||
if (is_fam15h()) {
|
||||
fam15h_switch_dct(pDCTstat->dev_map, 1); /* Erratum 505 */
|
||||
Set_NB32(dev, 0x58, OF_ScrubCTL); /* Scrub Control */
|
||||
fam15h_switch_dct(pDCTstat->dev_map, 0); /* Erratum 505 */
|
||||
}
|
||||
|
||||
if (!is_fam15h()) {
|
||||
/* Divisor should not be set deeper than
|
||||
* divide by 16 when Dcache scrubber or
|
||||
* L2 scrubber is enabled.
|
||||
*/
|
||||
if ((OF_ScrubCTL & (0x1F << 16)) || (OF_ScrubCTL & (0x1F << 8))) {
|
||||
val = Get_NB32(dev, 0x84);
|
||||
if ((val & 0xE0000000) > 0x80000000) { /* Get F3x84h[31:29]ClkDivisor for C1 */
|
||||
val &= 0x1FFFFFFF; /* If ClkDivisor is deeper than divide-by-16 */
|
||||
val |= 0x80000000; /* set it to divide-by-16 */
|
||||
Set_NB32(dev, 0x84, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pDCTstat->LogicalCPUID & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) {
|
||||
/* Set up message triggered C1E */
|
||||
val = pci_read_config32(pDCTstat->dev_nbmisc, 0xd4);
|
||||
val &= ~(0x1 << 15); /* StutterScrubEn = DRAM scrub enabled */
|
||||
val |= (mctGet_NVbits(NV_DramBKScrub)?1:0) << 15;
|
||||
pci_write_config32(pDCTstat->dev_nbmisc, 0xd4, val);
|
||||
}
|
||||
} /* this node has ECC enabled dram */
|
||||
} /*Node has Dram */
|
||||
} /*if Node present */
|
||||
}
|
||||
|
||||
/* Restore previous MCA error handling settings */
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
|
||||
if (NodePresent_D(Node)) {
|
||||
dev = pDCTstat->dev_map;
|
||||
reg = 0x40 + (Node << 3); /* Dram Base Node 0 + index */
|
||||
val = Get_NB32(dev, reg);
|
||||
|
||||
/* WE/RE is checked */
|
||||
if ((val & 0x3) == 0x3) { /* Node has dram populated */
|
||||
uint32_t mc4_status_high = pci_read_config32(pDCTstat->dev_nbmisc, 0x4c);
|
||||
uint32_t mc4_status_low = pci_read_config32(pDCTstat->dev_nbmisc, 0x48);
|
||||
if ((mc4_status_high & (0x1 << 31)) && (mc4_status_high != 0xffffffff)) {
|
||||
printk(BIOS_WARNING, "WARNING: MC4 Machine Check Exception detected!\n"
|
||||
"Signature: %08x%08x\n", mc4_status_high, mc4_status_low);
|
||||
}
|
||||
|
||||
/* Clear MC4 error status */
|
||||
pci_write_config32(pDCTstat->dev_nbmisc, 0x48, 0x0);
|
||||
pci_write_config32(pDCTstat->dev_nbmisc, 0x4c, 0x0);
|
||||
|
||||
/* Restore previous MCA error handling settings */
|
||||
dword = Get_NB32(pDCTstat->dev_nbmisc, 0x44);
|
||||
dword |= (sync_flood_on_dram_err[Node] & 0x1) << 30;
|
||||
dword |= (sync_flood_on_any_uc_err[Node] & 0x1) << 21;
|
||||
Set_NB32(pDCTstat->dev_nbmisc, 0x44, dword);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mctGet_NVbits(NV_SyncOnUnEccEn))
|
||||
setSyncOnUnEccEn_D(pMCTstat, pDCTstatA);
|
||||
|
||||
mctHookAfterECC();
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
if (NodePresent_D(Node)) {
|
||||
printk(BIOS_DEBUG, "ECCInit: Node %02x\n", Node);
|
||||
printk(BIOS_DEBUG, "ECCInit: Status %x\n", pDCTstat->Status);
|
||||
printk(BIOS_DEBUG, "ECCInit: ErrStatus %x\n", pDCTstat->ErrStatus);
|
||||
printk(BIOS_DEBUG, "ECCInit: ErrCode %x\n", pDCTstat->ErrCode);
|
||||
printk(BIOS_DEBUG, "ECCInit: Done\n");
|
||||
}
|
||||
}
|
||||
return MemClrECC;
|
||||
}
|
||||
|
||||
static void setSyncOnUnEccEn_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
u32 Node;
|
||||
u32 reg;
|
||||
u32 dev;
|
||||
u32 val;
|
||||
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
if (NodePresent_D(Node)) { /* If Node is present*/
|
||||
reg = 0x40+(Node << 3); /* Dram Base Node 0 + index*/
|
||||
val = Get_NB32(pDCTstat->dev_map, reg);
|
||||
/*WE/RE is checked because memory config may have been*/
|
||||
if ((val & 3) == 3) { /* Node has dram populated*/
|
||||
if (isDramECCEn_D(pDCTstat)) {
|
||||
/*if ECC is enabled on this dram*/
|
||||
dev = pDCTstat->dev_nbmisc;
|
||||
reg = 0x44; /* MCA NB Configuration*/
|
||||
val = Get_NB32(dev, reg);
|
||||
val |= (1 << SyncOnUcEccEn);
|
||||
Set_NB32(dev, reg, val);
|
||||
}
|
||||
} /* Node has Dram*/
|
||||
} /* if Node present*/
|
||||
}
|
||||
}
|
||||
|
||||
static u8 isDramECCEn_D(struct DCTStatStruc *pDCTstat)
|
||||
{
|
||||
u32 reg;
|
||||
u32 val;
|
||||
u8 i;
|
||||
u32 dev = pDCTstat->dev_dct;
|
||||
u8 ch_end;
|
||||
u8 isDimmECCEn = 0;
|
||||
|
||||
if (pDCTstat->GangedMode) {
|
||||
ch_end = 1;
|
||||
} else {
|
||||
ch_end = 2;
|
||||
}
|
||||
for (i = 0; i < ch_end; i++) {
|
||||
if (pDCTstat->DIMMValidDCT[i] > 0) {
|
||||
reg = 0x90; /* Dram Config Low */
|
||||
val = Get_NB32_DCT(dev, i, reg);
|
||||
if (val & (1 << DimmEcEn)) {
|
||||
/* set local flag 'dram ecc capable' */
|
||||
isDimmECCEn = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isDimmECCEn;
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
void mct_DramInit_Hw_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u8 dct)
|
||||
{
|
||||
u32 val;
|
||||
u32 reg;
|
||||
u32 dev = pDCTstat->dev_dct;
|
||||
|
||||
/*flag for selecting HW/SW DRAM Init HW DRAM Init */
|
||||
reg = 0x90; /*DRAM Configuration Low */
|
||||
val = Get_NB32_DCT(dev, dct, reg);
|
||||
val |= (1<<InitDram);
|
||||
Set_NB32_DCT(dev, dct, reg, val);
|
||||
}
|
||||
|
|
@ -1,305 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <stdint.h>
|
||||
#include <console/console.h>
|
||||
#include <string.h>
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
static uint8_t is_fam15h(void)
|
||||
{
|
||||
uint8_t fam15h = 0;
|
||||
uint32_t family;
|
||||
|
||||
family = cpuid_eax(0x80000001);
|
||||
family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
|
||||
|
||||
if (family >= 0x6f)
|
||||
/* Family 15h or later */
|
||||
fam15h = 1;
|
||||
|
||||
return fam15h;
|
||||
}
|
||||
|
||||
static void SetEccWrDQS_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat)
|
||||
{
|
||||
u8 ByteLane, DimmNum, OddByte, Addl_Index, Channel;
|
||||
u8 EccRef1, EccRef2, EccDQSScale;
|
||||
u32 val;
|
||||
u16 word;
|
||||
|
||||
for (Channel = 0; Channel < 2; Channel ++) {
|
||||
for (DimmNum = 0; DimmNum < C_MAX_DIMMS; DimmNum ++) { /* we use DimmNum instead of DimmNumx3 */
|
||||
for (ByteLane = 0; ByteLane < 9; ByteLane ++) {
|
||||
/* Get RxEn initial value from WrDqs */
|
||||
if (ByteLane & 1)
|
||||
OddByte = 1;
|
||||
else
|
||||
OddByte = 0;
|
||||
if (ByteLane < 2)
|
||||
Addl_Index = 0x30;
|
||||
else if (ByteLane < 4)
|
||||
Addl_Index = 0x31;
|
||||
else if (ByteLane < 6)
|
||||
Addl_Index = 0x40;
|
||||
else if (ByteLane < 8)
|
||||
Addl_Index = 0x41;
|
||||
else
|
||||
Addl_Index = 0x32;
|
||||
Addl_Index += DimmNum * 3;
|
||||
|
||||
val = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, Channel, 0x98, Addl_Index);
|
||||
if (OddByte)
|
||||
val >>= 16;
|
||||
/* Save WrDqs to stack for later usage */
|
||||
pDCTstat->persistentData.CH_D_B_TxDqs[Channel][DimmNum][ByteLane] = val & 0xFF;
|
||||
EccDQSScale = pDCTstat->CH_EccDQSScale[Channel];
|
||||
word = pDCTstat->CH_EccDQSLike[Channel];
|
||||
if ((word & 0xFF) == ByteLane) EccRef1 = val & 0xFF;
|
||||
if (((word >> 8) & 0xFF) == ByteLane) EccRef2 = val & 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void EnableAutoRefresh_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x8C);
|
||||
val &= ~(1 << DisAutoRefresh);
|
||||
Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x8C, val);
|
||||
|
||||
val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x8C);
|
||||
val &= ~(1 << DisAutoRefresh);
|
||||
Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x8C, val);
|
||||
}
|
||||
|
||||
static void DisableAutoRefresh_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x8C);
|
||||
val |= 1 << DisAutoRefresh;
|
||||
Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x8C, val);
|
||||
|
||||
val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x8C);
|
||||
val |= 1 << DisAutoRefresh;
|
||||
Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x8C, val);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t PhyWLPass1(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u8 dct)
|
||||
{
|
||||
u8 dimm;
|
||||
u16 DIMMValid;
|
||||
uint8_t status = 0;
|
||||
void *DCTPtr;
|
||||
|
||||
dct &= 1;
|
||||
|
||||
DCTPtr = (void *)(pDCTstat->C_DCTPtr[dct]);
|
||||
pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct];
|
||||
pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct];
|
||||
|
||||
if (pDCTstat->GangedMode & 1)
|
||||
pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
|
||||
|
||||
if (pDCTstat->DIMMValid) {
|
||||
DIMMValid = pDCTstat->DIMMValid;
|
||||
PrepareC_DCT(pMCTstat, pDCTstat, dct);
|
||||
for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm ++) {
|
||||
if (DIMMValid & (1 << (dimm << 1))) {
|
||||
status |= AgesaHwWlPhase1(pMCTstat, pDCTstat, dct, dimm, FirstPass);
|
||||
status |= AgesaHwWlPhase2(pMCTstat, pDCTstat, dct, dimm, FirstPass);
|
||||
status |= AgesaHwWlPhase3(pMCTstat, pDCTstat, dct, dimm, FirstPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static uint8_t PhyWLPass2(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t final)
|
||||
{
|
||||
u8 dimm;
|
||||
u16 DIMMValid;
|
||||
uint8_t status = 0;
|
||||
void *DCTPtr;
|
||||
|
||||
dct &= 1;
|
||||
|
||||
DCTPtr = (void *)&(pDCTstat->C_DCTPtr[dct]); /* todo: */
|
||||
pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct];
|
||||
pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct];
|
||||
|
||||
if (pDCTstat->GangedMode & 1)
|
||||
pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
|
||||
|
||||
if (pDCTstat->DIMMValid) {
|
||||
DIMMValid = pDCTstat->DIMMValid;
|
||||
PrepareC_DCT(pMCTstat, pDCTstat, dct);
|
||||
pDCTstat->Speed = pDCTstat->DIMMAutoSpeed = pDCTstat->TargetFreq;
|
||||
pDCTstat->CASL = pDCTstat->DIMMCASL = pDCTstat->TargetCASL;
|
||||
SPD2ndTiming(pMCTstat, pDCTstat, dct);
|
||||
if (!is_fam15h()) {
|
||||
ProgDramMRSReg_D(pMCTstat, pDCTstat, dct);
|
||||
PlatformSpec_D(pMCTstat, pDCTstat, dct);
|
||||
fenceDynTraining_D(pMCTstat, pDCTstat, dct);
|
||||
}
|
||||
Restore_OnDimmMirror(pMCTstat, pDCTstat);
|
||||
StartupDCT_D(pMCTstat, pDCTstat, dct);
|
||||
Clear_OnDimmMirror(pMCTstat, pDCTstat);
|
||||
SetDllSpeedUp_D(pMCTstat, pDCTstat, dct);
|
||||
DisableAutoRefresh_D(pMCTstat, pDCTstat);
|
||||
for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm ++) {
|
||||
if (DIMMValid & (1 << (dimm << 1))) {
|
||||
status |= AgesaHwWlPhase1(pMCTstat, pDCTstat, dct, dimm, SecondPass);
|
||||
status |= AgesaHwWlPhase2(pMCTstat, pDCTstat, dct, dimm, SecondPass);
|
||||
status |= AgesaHwWlPhase3(pMCTstat, pDCTstat, dct, dimm, SecondPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static uint16_t fam15h_next_highest_memclk_freq(uint16_t memclk_freq)
|
||||
{
|
||||
uint16_t fam15h_next_highest_freq_tab[] = {0, 0, 0, 0, 0x6, 0, 0xa, 0, 0, 0, 0xe, 0, 0, 0, 0x12, 0, 0, 0, 0x16, 0, 0, 0, 0x16};
|
||||
return fam15h_next_highest_freq_tab[memclk_freq];
|
||||
}
|
||||
|
||||
/* Write Levelization Training
|
||||
* Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.1
|
||||
*/
|
||||
static void WriteLevelization_HW(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA, uint8_t Node, uint8_t Pass)
|
||||
{
|
||||
uint8_t status;
|
||||
uint8_t timeout;
|
||||
uint16_t final_target_freq;
|
||||
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
|
||||
pDCTstat->C_MCTPtr = &(pDCTstat->s_C_MCTPtr);
|
||||
pDCTstat->C_DCTPtr[0] = &(pDCTstat->s_C_DCTPtr[0]);
|
||||
pDCTstat->C_DCTPtr[1] = &(pDCTstat->s_C_DCTPtr[1]);
|
||||
|
||||
/* Disable auto refresh by configuring F2x[1, 0]8C[DisAutoRefresh] = 1 */
|
||||
DisableAutoRefresh_D(pMCTstat, pDCTstat);
|
||||
|
||||
/* Disable ZQ calibration short command by F2x[1,0]94[ZqcsInterval]=00b */
|
||||
DisableZQcalibration(pMCTstat, pDCTstat);
|
||||
PrepareC_MCT(pMCTstat, pDCTstat);
|
||||
|
||||
if (pDCTstat->GangedMode & (1 << 0)) {
|
||||
pDCTstat->DIMMValidDCT[1] = pDCTstat->DIMMValidDCT[0];
|
||||
}
|
||||
|
||||
if (Pass == FirstPass) {
|
||||
timeout = 0;
|
||||
do {
|
||||
status = 0;
|
||||
timeout++;
|
||||
status |= PhyWLPass1(pMCTstat, pDCTstat, 0);
|
||||
status |= PhyWLPass1(pMCTstat, pDCTstat, 1);
|
||||
if (status)
|
||||
printk(BIOS_INFO,
|
||||
"%s: Retrying write levelling due to invalid value(s) detected in first phase\n",
|
||||
__func__);
|
||||
} while (status && (timeout < 8));
|
||||
if (status)
|
||||
printk(BIOS_INFO,
|
||||
"%s: Uncorrectable invalid value(s) detected in first phase of write levelling\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
if (Pass == SecondPass) {
|
||||
if (pDCTstat->TargetFreq > mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) {
|
||||
/* 8.Prepare the memory subsystem for the target MEMCLK frequency.
|
||||
* NOTE: BIOS must program both DCTs to the same frequency.
|
||||
* NOTE: Fam15h steps the frequency, Fam10h slams the frequency.
|
||||
*/
|
||||
uint8_t global_phy_training_status = 0;
|
||||
final_target_freq = pDCTstat->TargetFreq;
|
||||
|
||||
while (pDCTstat->Speed != final_target_freq) {
|
||||
if (is_fam15h())
|
||||
pDCTstat->TargetFreq = fam15h_next_highest_memclk_freq(pDCTstat->Speed);
|
||||
else
|
||||
pDCTstat->TargetFreq = final_target_freq;
|
||||
SetTargetFreq(pMCTstat, pDCTstatA, Node);
|
||||
timeout = 0;
|
||||
do {
|
||||
status = 0;
|
||||
timeout++;
|
||||
status |= PhyWLPass2(pMCTstat, pDCTstat, 0, (pDCTstat->TargetFreq == final_target_freq));
|
||||
status |= PhyWLPass2(pMCTstat, pDCTstat, 1, (pDCTstat->TargetFreq == final_target_freq));
|
||||
if (status)
|
||||
printk(BIOS_INFO,
|
||||
"%s: Retrying write levelling due to invalid value(s) detected in last phase\n",
|
||||
__func__);
|
||||
} while (status && (timeout < 8));
|
||||
global_phy_training_status |= status;
|
||||
}
|
||||
|
||||
pDCTstat->TargetFreq = final_target_freq;
|
||||
|
||||
if (global_phy_training_status)
|
||||
printk(BIOS_WARNING,
|
||||
"%s: Uncorrectable invalid value(s) detected in second phase of write levelling; "
|
||||
"continuing but system may be unstable!\n",
|
||||
__func__);
|
||||
|
||||
uint8_t dct;
|
||||
for (dct = 0; dct < 2; dct++) {
|
||||
sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
|
||||
memcpy(pDCTData->WLGrossDelayFinalPass, pDCTData->WLGrossDelayPrevPass, sizeof(pDCTData->WLGrossDelayPrevPass));
|
||||
memcpy(pDCTData->WLFineDelayFinalPass, pDCTData->WLFineDelayPrevPass, sizeof(pDCTData->WLFineDelayPrevPass));
|
||||
pDCTData->WLCriticalGrossDelayFinalPass = pDCTData->WLCriticalGrossDelayPrevPass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetEccWrDQS_D(pMCTstat, pDCTstat);
|
||||
EnableAutoRefresh_D(pMCTstat, pDCTstat);
|
||||
EnableZQcalibration(pMCTstat, pDCTstat);
|
||||
}
|
||||
|
||||
void mct_WriteLevelization_HW(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA, uint8_t Pass)
|
||||
{
|
||||
u8 Node;
|
||||
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
|
||||
if (pDCTstat->NodePresent) {
|
||||
mctSMBhub_Init(Node);
|
||||
Clear_OnDimmMirror(pMCTstat, pDCTstat);
|
||||
WriteLevelization_HW(pMCTstat, pDCTstatA, Node, Pass);
|
||||
Restore_OnDimmMirror(pMCTstat, pDCTstat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <console/console.h>
|
||||
#include <cpu/amd/mtrr.h>
|
||||
#include <cpu/x86/mtrr.h>
|
||||
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
static void SetMTRRrangeWB_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr);
|
||||
static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr, u16 MtrrType);
|
||||
|
||||
void CPUMemTyping_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
/* BSP only. Set the fixed MTRRs for common legacy ranges.
|
||||
* Set TOP_MEM and TOM2.
|
||||
* Set some variable MTRRs with WB Uncacheable type.
|
||||
*/
|
||||
|
||||
u32 Bottom32bIO, Bottom40bIO, Cache32bTOP;
|
||||
u32 val;
|
||||
u32 addr;
|
||||
u32 lo, hi;
|
||||
|
||||
/* Set temporary top of memory from Node structure data.
|
||||
* Adjust temp top of memory down to accommodate 32-bit IO space.
|
||||
* Bottom40bIO = top of memory, right justified 8 bits
|
||||
* (defines dram versus IO space type)
|
||||
* Bottom32bIO = sub 4GB top of memory, right justified 8 bits
|
||||
* (defines dram versus IO space type)
|
||||
* Cache32bTOP = sub 4GB top of WB cacheable memory,
|
||||
* right justified 8 bits
|
||||
*/
|
||||
|
||||
val = mctGet_NVbits(NV_BottomIO);
|
||||
if (val == 0)
|
||||
val++;
|
||||
|
||||
Bottom32bIO = val << (24-8);
|
||||
|
||||
val = pMCTstat->SysLimit + 1;
|
||||
if (val <= _4GB_RJ8) {
|
||||
Bottom40bIO = 0;
|
||||
if (Bottom32bIO >= val)
|
||||
Bottom32bIO = val;
|
||||
} else {
|
||||
Bottom40bIO = val;
|
||||
}
|
||||
|
||||
Cache32bTOP = Bottom32bIO;
|
||||
|
||||
/*======================================================================
|
||||
Set default values for CPU registers
|
||||
======================================================================*/
|
||||
|
||||
/* NOTE : For coreboot, we don't need to set mtrr enables here because
|
||||
they are still enable from cache_as_ram.inc */
|
||||
|
||||
addr = MTRR_FIX_64K_00000;
|
||||
lo = 0x1E1E1E1E;
|
||||
hi = lo;
|
||||
_WRMSR(addr, lo, hi); /* 0 - 512K = WB Mem */
|
||||
addr = MTRR_FIX_16K_80000;
|
||||
_WRMSR(addr, lo, hi); /* 512K - 640K = WB Mem */
|
||||
|
||||
/*======================================================================
|
||||
Set variable MTRR values
|
||||
======================================================================*/
|
||||
/* NOTE: for coreboot change from 0x200 to 0x204: coreboot is using
|
||||
0x200, 0x201 for [1M, CONFIG_TOP_MEM)
|
||||
0x202, 0x203 for ROM Caching
|
||||
*/
|
||||
addr = MTRR_PHYS_BASE(2); /* MTRR phys base 2*/
|
||||
/* use TOP_MEM as limit*/
|
||||
/* Limit = TOP_MEM|TOM2*/
|
||||
/* Base = 0*/
|
||||
printk(BIOS_DEBUG, "\t CPUMemTyping: Cache32bTOP:%x\n", Cache32bTOP);
|
||||
SetMTRRrangeWB_D(0, &Cache32bTOP, &addr);
|
||||
/* Base */
|
||||
/* Limit */
|
||||
/* MtrrAddr */
|
||||
if (addr == -1) /* ran out of MTRRs?*/
|
||||
pMCTstat->GStatus |= 1<<GSB_MTRRshort;
|
||||
|
||||
pMCTstat->Sub4GCacheTop = Cache32bTOP<<8;
|
||||
|
||||
/*======================================================================
|
||||
Set TOP_MEM and TOM2 CPU registers
|
||||
======================================================================*/
|
||||
addr = TOP_MEM;
|
||||
lo = Bottom32bIO<<8;
|
||||
hi = Bottom32bIO>>24;
|
||||
_WRMSR(addr, lo, hi);
|
||||
printk(BIOS_DEBUG, "\t CPUMemTyping: Bottom32bIO:%x\n", Bottom32bIO);
|
||||
printk(BIOS_DEBUG, "\t CPUMemTyping: Bottom40bIO:%x\n", Bottom40bIO);
|
||||
if (Bottom40bIO) {
|
||||
hi = Bottom40bIO >> 24;
|
||||
lo = Bottom40bIO << 8;
|
||||
addr += 3; /* TOM2 */
|
||||
_WRMSR(addr, lo, hi);
|
||||
}
|
||||
addr = SYSCFG_MSR; /* SYS_CFG */
|
||||
_RDMSR(addr, &lo, &hi);
|
||||
if (Bottom40bIO) {
|
||||
lo |= SYSCFG_MSR_TOM2En; /* MtrrTom2En = 1 */
|
||||
lo |= SYSCFG_MSR_TOM2WB; /* Tom2ForceMemTypeWB */
|
||||
} else {
|
||||
lo &= ~SYSCFG_MSR_TOM2En; /* MtrrTom2En = 0 */
|
||||
lo &= ~SYSCFG_MSR_TOM2WB; /* Tom2ForceMemTypeWB */
|
||||
}
|
||||
_WRMSR(addr, lo, hi);
|
||||
}
|
||||
|
||||
static void SetMTRRrangeWB_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr)
|
||||
{
|
||||
/*set WB type*/
|
||||
SetMTRRrange_D(Base, pLimit, pMtrrAddr, 6);
|
||||
}
|
||||
|
||||
static void SetMTRRrange_D(u32 Base, u32 *pLimit, u32 *pMtrrAddr, u16 MtrrType)
|
||||
{
|
||||
/* Program MTRRs to describe given range as given cache type.
|
||||
* Use MTRR pairs starting with the given MTRRphys Base address,
|
||||
* and use as many as is required up to (excluding) MSR 020C, which
|
||||
* is reserved for OS.
|
||||
*
|
||||
* "Limit" in the context of this procedure is not the numerically
|
||||
* correct limit, but rather the Last address+1, for purposes of coding
|
||||
* efficiency and readability. Size of a region is then Limit-Base.
|
||||
*
|
||||
* 1. Size of each range must be a power of two
|
||||
* 2. Each range must be naturally aligned (Base is same as size)
|
||||
*
|
||||
* There are two code paths: the ascending path and descending path
|
||||
* (analogous to bsf and bsr), where the next limit is a function of the
|
||||
* next set bit in a forward or backward sequence of bits (as a function
|
||||
* of the Limit). We start with the ascending path, to ensure that
|
||||
* regions are naturally aligned, then we switch to the descending path
|
||||
* to maximize MTRR usage efficiency. Base = 0 is a special case where we
|
||||
* start with the descending path. Correct Mask for region is
|
||||
* 2comp(Size-1)-1, which is 2comp(Limit-Base-1)-1
|
||||
*/
|
||||
|
||||
u32 curBase, curLimit, curSize;
|
||||
u32 val, valx;
|
||||
u32 addr;
|
||||
|
||||
val = curBase = Base;
|
||||
curLimit = *pLimit;
|
||||
addr = *pMtrrAddr;
|
||||
while ((addr >= 0x200) && (addr < 0x20C) && (val < *pLimit)) {
|
||||
/* start with "ascending" code path */
|
||||
/* alignment (largest block size)*/
|
||||
valx = 1 << bsf(curBase);
|
||||
curSize = valx;
|
||||
|
||||
/* largest legal limit, given current non-zero range Base*/
|
||||
valx += curBase;
|
||||
if ((curBase == 0) || (*pLimit < valx)) {
|
||||
/* flop direction to "descending" code path*/
|
||||
valx = 1<<bsr(*pLimit - curBase);
|
||||
curSize = valx;
|
||||
valx += curBase;
|
||||
}
|
||||
curLimit = valx; /*eax = curBase, edx = curLimit*/
|
||||
valx = val>>24;
|
||||
val <<= 8;
|
||||
|
||||
/* now program the MTRR */
|
||||
val |= MtrrType; /* set cache type (UC or WB)*/
|
||||
_WRMSR(addr, val, valx); /* prog. MTRR with current region Base*/
|
||||
val = ((~(curSize - 1))+1) - 1; /* Size-1*/ /*Mask = 2comp(Size-1)-1*/
|
||||
valx = (val >> 24) | (0xff00); /* GH have 48 bits addr */
|
||||
val <<= 8;
|
||||
val |= (1 << 11); /* set MTRR valid*/
|
||||
addr++;
|
||||
_WRMSR(addr, val, valx); /* prog. MTRR with current region Mask*/
|
||||
val = curLimit;
|
||||
curBase = val; /* next Base = current Limit (loop exit)*/
|
||||
addr++; /* next MTRR pair addr */
|
||||
}
|
||||
if (val < *pLimit) {
|
||||
*pLimit = val;
|
||||
addr = -1;
|
||||
}
|
||||
*pMtrrAddr = addr;
|
||||
}
|
||||
|
||||
void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
/* UMA memory size may need splitting the MTRR configuration into two
|
||||
* Before training use NB_BottomIO or the physical memory size to set the MTRRs.
|
||||
* After training, add UMAMemTyping function to reconfigure the MTRRs based on
|
||||
* NV_BottomUMA (for UMA systems only).
|
||||
* This two-step process allows all memory to be cached for training
|
||||
*/
|
||||
|
||||
u32 Bottom32bIO, Cache32bTOP;
|
||||
u32 val;
|
||||
u32 addr;
|
||||
u32 lo, hi;
|
||||
|
||||
/*======================================================================
|
||||
* Adjust temp top of memory down to accommodate UMA memory start
|
||||
*======================================================================*/
|
||||
/* Bottom32bIO = sub 4GB top of memory, right justified 8 bits
|
||||
* (defines dram versus IO space type)
|
||||
* Cache32bTOP = sub 4GB top of WB cacheable memory, right justified 8 bits */
|
||||
|
||||
Bottom32bIO = pMCTstat->Sub4GCacheTop >> 8;
|
||||
|
||||
val = mctGet_NVbits(NV_BottomUMA);
|
||||
if (val == 0)
|
||||
val++;
|
||||
|
||||
val <<= (24-8);
|
||||
if (val < Bottom32bIO) {
|
||||
Cache32bTOP = val;
|
||||
pMCTstat->Sub4GCacheTop = val;
|
||||
|
||||
/*======================================================================
|
||||
* Clear variable MTRR values
|
||||
*======================================================================*/
|
||||
addr = MTRR_PHYS_BASE(0);
|
||||
lo = 0;
|
||||
hi = lo;
|
||||
while (addr < MTRR_PHYS_BASE(6)) {
|
||||
_WRMSR(addr, lo, hi); /* prog. MTRR with current region Mask */
|
||||
addr++; /* next MTRR pair addr */
|
||||
}
|
||||
|
||||
/*======================================================================
|
||||
* Set variable MTRR values
|
||||
*======================================================================*/
|
||||
printk(BIOS_DEBUG, "\t UMAMemTyping_D: Cache32bTOP:%x\n", Cache32bTOP);
|
||||
SetMTRRrangeWB_D(0, &Cache32bTOP, &addr);
|
||||
if (addr == -1) /* ran out of MTRRs?*/
|
||||
pMCTstat->GStatus |= 1<<GSB_MTRRshort;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,233 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <console/console.h>
|
||||
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
void InterleaveNodes_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
/* Applies Node memory interleaving if enabled and if all criteria are met. */
|
||||
u8 Node;
|
||||
u32 Base;
|
||||
u32 MemSize, MemSize0 = 0;
|
||||
u32 Dct0MemSize = 0, DctSelBase, DctSelBaseOffset = 0;
|
||||
u8 Nodes;
|
||||
u8 NodesWmem;
|
||||
u8 DoIntlv;
|
||||
u8 _NdIntCap;
|
||||
u8 _SWHole;
|
||||
u32 HWHoleSz;
|
||||
u32 DramHoleAddrReg;
|
||||
u32 HoleBase;
|
||||
u32 dev0;
|
||||
u32 reg0;
|
||||
u32 val;
|
||||
u8 i;
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
|
||||
DoIntlv = mctGet_NVbits(NV_NodeIntlv);
|
||||
|
||||
_NdIntCap = 0;
|
||||
HWHoleSz = 0; /*For HW remapping, NOT Node hoisting. */
|
||||
|
||||
pDCTstat = pDCTstatA + 0;
|
||||
dev0 = pDCTstat->dev_host;
|
||||
Nodes = ((Get_NB32(dev0, 0x60) >> 4) & 0x7) + 1;
|
||||
|
||||
dev0 = pDCTstat->dev_map;
|
||||
reg0 = 0x40;
|
||||
|
||||
NodesWmem = 0;
|
||||
Node = 0;
|
||||
|
||||
while (DoIntlv && (Node < Nodes)) {
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
if (pMCTstat->GStatus & (1 << GSB_SpIntRemapHole)) {
|
||||
pMCTstat->GStatus |= 1 << GSB_HWHole;
|
||||
_SWHole = 0;
|
||||
} else if (pDCTstat->Status & (1 << SB_SWNodeHole)) {
|
||||
_SWHole = 1;
|
||||
} else {
|
||||
_SWHole = 0;
|
||||
}
|
||||
|
||||
if (!_SWHole) {
|
||||
Base = Get_NB32(dev0, reg0);
|
||||
if (Base & 1) {
|
||||
NodesWmem++;
|
||||
Base &= 0xFFFF0000; /* Base[39:8] */
|
||||
|
||||
if (pDCTstat->Status & (1 << SB_HWHole)) {
|
||||
|
||||
/* to get true amount of dram,
|
||||
* subtract out memory hole if HW dram remapping */
|
||||
DramHoleAddrReg = Get_NB32(pDCTstat->dev_map, 0xF0);
|
||||
HWHoleSz = DramHoleAddrReg >> 16;
|
||||
HWHoleSz = (((~HWHoleSz) + 1) & 0xFF);
|
||||
HWHoleSz <<= 24-8;
|
||||
}
|
||||
/* check to see if the amount of memory on each channel
|
||||
* are the same on all nodes */
|
||||
|
||||
DctSelBase = Get_NB32(pDCTstat->dev_dct, 0x114);
|
||||
if (DctSelBase) {
|
||||
DctSelBase <<= 8;
|
||||
if (pDCTstat->Status & (1 << SB_HWHole)) {
|
||||
if (DctSelBase >= 0x1000000) {
|
||||
DctSelBase -= HWHoleSz;
|
||||
}
|
||||
}
|
||||
DctSelBaseOffset -= Base;
|
||||
if (Node == 0) {
|
||||
Dct0MemSize = DctSelBase;
|
||||
} else if (DctSelBase != Dct0MemSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MemSize = Get_NB32(dev0, reg0 + 4);
|
||||
MemSize &= 0xFFFF0000;
|
||||
MemSize += 0x00010000;
|
||||
MemSize -= Base;
|
||||
if (pDCTstat->Status & (1 << SB_HWHole)) {
|
||||
MemSize -= HWHoleSz;
|
||||
}
|
||||
if (Node == 0) {
|
||||
MemSize0 = MemSize;
|
||||
} else if (MemSize0 != MemSize) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
Node++;
|
||||
reg0 += 8;
|
||||
}
|
||||
|
||||
if (Node == Nodes) {
|
||||
/* if all nodes have memory and no Node had SW memhole */
|
||||
if (Nodes == 2 || Nodes == 4 || Nodes == 8)
|
||||
_NdIntCap = 1;
|
||||
}
|
||||
|
||||
if (!_NdIntCap)
|
||||
DoIntlv = 0;
|
||||
|
||||
if (pMCTstat->GStatus & 1 << (GSB_SpIntRemapHole)) {
|
||||
HWHoleSz = pMCTstat->HoleBase;
|
||||
if (HWHoleSz == 0) {
|
||||
HWHoleSz = mctGet_NVbits(NV_BottomIO) & 0xFF;
|
||||
HWHoleSz <<= 24-8;
|
||||
}
|
||||
HWHoleSz = ((~HWHoleSz) + 1) & 0x00FF0000;
|
||||
}
|
||||
|
||||
if (DoIntlv) {
|
||||
MCTMemClr_D(pMCTstat, pDCTstatA);
|
||||
/* Program Interleaving enabled on Node 0 map only.*/
|
||||
MemSize0 <<= bsf(Nodes); /* MemSize = MemSize*2 (or 4, or 8) */
|
||||
Dct0MemSize <<= bsf(Nodes);
|
||||
MemSize0 += HWHoleSz;
|
||||
Base = ((Nodes - 1) << 8) | 3;
|
||||
reg0 = 0x40;
|
||||
Node = 0;
|
||||
while (Node < Nodes) {
|
||||
Set_NB32(dev0, reg0, Base);
|
||||
MemSize = MemSize0;
|
||||
MemSize--;
|
||||
MemSize &= 0xFFFF0000;
|
||||
MemSize |= Node << 8; /* set IntlvSel[2:0] field */
|
||||
MemSize |= Node; /* set DstNode[2:0] field */
|
||||
Set_NB32(dev0, reg0 + 4, MemSize0);
|
||||
reg0 += 8;
|
||||
Node++;
|
||||
}
|
||||
|
||||
/* set base/limit to F1x120/124 per Node */
|
||||
Node = 0;
|
||||
while (Node < Nodes) {
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
pDCTstat->NodeSysBase = 0;
|
||||
MemSize = MemSize0;
|
||||
MemSize -= HWHoleSz;
|
||||
MemSize--;
|
||||
pDCTstat->NodeSysLimit = MemSize;
|
||||
Set_NB32(pDCTstat->dev_map, 0x120, Node << 21);
|
||||
MemSize = MemSize0;
|
||||
MemSize--;
|
||||
MemSize >>= 19;
|
||||
val = Base;
|
||||
val &= 0x700;
|
||||
val <<= 13;
|
||||
val |= MemSize;
|
||||
Set_NB32(pDCTstat->dev_map, 0x124, val);
|
||||
|
||||
if (pMCTstat->GStatus & (1 << GSB_HWHole)) {
|
||||
HoleBase = pMCTstat->HoleBase;
|
||||
if (Dct0MemSize >= HoleBase) {
|
||||
val = HWHoleSz;
|
||||
if (Node == 0) {
|
||||
val += Dct0MemSize;
|
||||
}
|
||||
} else {
|
||||
val = HWHoleSz + Dct0MemSize;
|
||||
}
|
||||
|
||||
val >>= 8; /* DramHoleOffset */
|
||||
HoleBase <<= 8; /* DramHoleBase */
|
||||
val |= HoleBase;
|
||||
val |= 1 << DramMemHoistValid;
|
||||
val |= 1 << DramHoleValid;
|
||||
Set_NB32(pDCTstat->dev_map, 0xF0, val);
|
||||
}
|
||||
|
||||
Set_NB32(pDCTstat->dev_dct, 0x114, Dct0MemSize >> 8); /* DctSelBaseOffset */
|
||||
val = Get_NB32(pDCTstat->dev_dct, 0x110);
|
||||
val &= 0x7FF;
|
||||
val |= Dct0MemSize >> 8;
|
||||
Set_NB32(pDCTstat->dev_dct, 0x110, val); /* DctSelBaseAddr */
|
||||
printk(BIOS_DEBUG, "InterleaveNodes: DRAM Controller Select Low Register = %x\n", val);
|
||||
Node++;
|
||||
}
|
||||
|
||||
/* Copy Node 0 into other Nodes' CSRs */
|
||||
Node = 1;
|
||||
while (Node < Nodes) {
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
|
||||
for (i = 0x40; i <= 0x80; i++) {
|
||||
val = Get_NB32(dev0, i);
|
||||
Set_NB32(pDCTstat->dev_map, i, val);
|
||||
}
|
||||
|
||||
val = Get_NB32(dev0, 0xF0);
|
||||
Set_NB32(pDCTstat->dev_map, 0xF0, val);
|
||||
Node++;
|
||||
}
|
||||
pMCTstat->GStatus = (1 << GSB_NodeIntlv);
|
||||
}
|
||||
printk(BIOS_DEBUG, "InterleaveNodes_D: Status %x\n", pDCTstat->Status);
|
||||
printk(BIOS_DEBUG, "InterleaveNodes_D: ErrStatus %x\n", pDCTstat->ErrStatus);
|
||||
printk(BIOS_DEBUG, "InterleaveNodes_D: ErrCode %x\n", pDCTstat->ErrCode);
|
||||
printk(BIOS_DEBUG, "InterleaveNodes_D: Done\n\n");
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
void mct_BeforeDQSTrainSamp(struct DCTStatStruc *pDCTstat)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (pDCTstat->LogicalCPUID & AMD_DR_Bx) {
|
||||
Set_NB32(pDCTstat->dev_dct, 0x98, 0x0D004007);
|
||||
val = Get_NB32(pDCTstat->dev_dct, 0x9C);
|
||||
val |= 0x3FF;
|
||||
Set_NB32(pDCTstat->dev_dct, 0x9C, val);
|
||||
Set_NB32(pDCTstat->dev_dct, 0x98, 0x4D0F4F07);
|
||||
|
||||
Set_NB32(pDCTstat->dev_dct, 0x198, 0x0D004007);
|
||||
val = Get_NB32(pDCTstat->dev_dct, 0x19C);
|
||||
val |= 0x3FF;
|
||||
Set_NB32(pDCTstat->dev_dct, 0x19C, val);
|
||||
Set_NB32(pDCTstat->dev_dct, 0x198, 0x4D0F4F07);
|
||||
}
|
||||
}
|
||||
|
||||
void mct_ExtMCTConfig_Bx(struct DCTStatStruc *pDCTstat)
|
||||
{
|
||||
if (pDCTstat->LogicalCPUID & (AMD_DR_Bx)) {
|
||||
Set_NB32(pDCTstat->dev_dct, 0x11C, 0x0FE40FC0 | 1 << 29/* FlushWrOnStpGnt */);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
/* mct_SetDramConfigMisc2_Cx & mct_SetDramConfigMisc2_Dx */
|
||||
u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat,
|
||||
uint8_t dct, uint32_t misc2, uint32_t DramControl)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
|
||||
|
||||
if (pDCTstat->LogicalCPUID & AMD_FAM15_ALL) {
|
||||
uint8_t cs_mux_45;
|
||||
uint8_t cs_mux_67;
|
||||
uint32_t f2x80;
|
||||
|
||||
misc2 &= ~(0x1 << 28); /* FastSelfRefEntryDis = 0x0 */
|
||||
if (MaxDimmsInstallable == 3) {
|
||||
/* FIXME 3 DIMMS per channel unimplemented */
|
||||
cs_mux_45 = 0;
|
||||
} else {
|
||||
uint32_t f2x60 = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x60);
|
||||
f2x80 = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x80);
|
||||
if ((((f2x80 & 0xf) == 0x7) || ((f2x80 & 0xf) == 0x9))
|
||||
&& ((f2x60 & 0x3) == 0x3))
|
||||
cs_mux_45 = 1;
|
||||
else if ((((f2x80 & 0xf) == 0xa) || ((f2x80 & 0xf) == 0xb))
|
||||
&& ((f2x60 & 0x3) > 0x1))
|
||||
cs_mux_45 = 1;
|
||||
else
|
||||
cs_mux_45 = 0;
|
||||
}
|
||||
|
||||
if (MaxDimmsInstallable == 1) {
|
||||
cs_mux_67 = 0;
|
||||
} else if (MaxDimmsInstallable == 2) {
|
||||
uint32_t f2x64 = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x64);
|
||||
f2x80 = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x80);
|
||||
if (((((f2x80 >> 4) & 0xf) == 0x7) || (((f2x80 >> 4) & 0xf) == 0x9))
|
||||
&& ((f2x64 & 0x3) == 0x3))
|
||||
cs_mux_67 = 1;
|
||||
else if (((((f2x80 >> 4) & 0xf) == 0xa) || (((f2x80 >> 4) & 0xf) == 0xb))
|
||||
&& ((f2x64 & 0x3) > 0x1))
|
||||
cs_mux_67 = 1;
|
||||
else
|
||||
cs_mux_67 = 0;
|
||||
} else {
|
||||
/* FIXME 3 DIMMS per channel unimplemented */
|
||||
cs_mux_67 = 0;
|
||||
}
|
||||
|
||||
misc2 &= ~(0x1 << 27); /* CsMux67 = cs_mux_67 */
|
||||
misc2 |= ((cs_mux_67 & 0x1) << 27);
|
||||
misc2 &= ~(0x1 << 26); /* CsMux45 = cs_mux_45 */
|
||||
misc2 |= ((cs_mux_45 & 0x1) << 26);
|
||||
} else if (pDCTstat->LogicalCPUID & (AMD_DR_Dx | AMD_DR_Cx)) {
|
||||
if (pDCTstat->Status & (1 << SB_Registered)) {
|
||||
misc2 |= 1 << SubMemclkRegDly;
|
||||
if (mctGet_NVbits(NV_MAX_DIMMS) == 8)
|
||||
misc2 |= 1 << Ddr3FourSocketCh;
|
||||
else
|
||||
misc2 &= ~(1 << Ddr3FourSocketCh);
|
||||
}
|
||||
|
||||
if (pDCTstat->LogicalCPUID & AMD_DR_Cx)
|
||||
misc2 |= 1 << OdtSwizzle;
|
||||
|
||||
val = DramControl;
|
||||
val &= 7;
|
||||
val = ((~val) & 0xff) + 1;
|
||||
val += 6;
|
||||
val &= 0x7;
|
||||
misc2 &= 0xfff8ffff;
|
||||
misc2 |= val << 16; /* DataTxFifoWrDly */
|
||||
if (pDCTstat->LogicalCPUID & AMD_DR_Dx)
|
||||
misc2 |= 1 << 7; /* ProgOdtEn */
|
||||
}
|
||||
return misc2;
|
||||
}
|
||||
|
||||
void mct_ExtMCTConfig_Cx(struct DCTStatStruc *pDCTstat)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (pDCTstat->LogicalCPUID & (AMD_DR_Cx)) {
|
||||
/* Revision C */
|
||||
Set_NB32(pDCTstat->dev_dct, 0x11c, 0x0ce00fc0 | 1 << 29/* FlushWrOnStpGnt */);
|
||||
|
||||
val = Get_NB32(pDCTstat->dev_dct, 0x1b0);
|
||||
val &= ~0x73f;
|
||||
val |= 0x101; /* BKDG recommended settings */
|
||||
|
||||
Set_NB32(pDCTstat->dev_dct, 0x1b0, val);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
void mct_ExtMCTConfig_Dx(struct DCTStatStruc *pDCTstat)
|
||||
{
|
||||
uint32_t dword;
|
||||
|
||||
if (pDCTstat->LogicalCPUID & AMD_DR_Dx) {
|
||||
dword = 0x0ce00f00 | 0x1 << 29; /* FlushWrOnStpGnt */
|
||||
if (!(pDCTstat->GangedMode))
|
||||
dword |= 0x18 << 2; /* MctWrLimit = 0x18 for unganged mode */
|
||||
else
|
||||
dword |= 0x10 << 2; /* MctWrLimit = 0x10 for ganged mode */
|
||||
Set_NB32(pDCTstat->dev_dct, 0x11c, dword);
|
||||
|
||||
dword = Get_NB32(pDCTstat->dev_dct, 0x1b0);
|
||||
dword &= ~0x3; /* AdapPrefMissRatio = 0x1 */
|
||||
dword |= 0x1;
|
||||
dword &= ~(0x3 << 2); /* AdapPrefPositiveStep = 0x0 */
|
||||
dword &= ~(0x3 << 4); /* AdapPrefNegativeStep = 0x0 */
|
||||
dword &= ~(0x7 << 8); /* CohPrefPrbLmt = 0x1 */
|
||||
dword |= (0x1 << 8);
|
||||
dword |= (0x7 << 22); /* PrefFourConf = 0x7 */
|
||||
dword |= (0x7 << 25); /* PrefFiveConf = 0x7 */
|
||||
|
||||
if (!(pDCTstat->GangedMode))
|
||||
dword |= (0x1 << 12); /* EnSplitDctLimits = 0x1 */
|
||||
else
|
||||
dword &= ~(0x1 << 12); /* EnSplitDctLimits = 0x0 */
|
||||
|
||||
dword &= ~(0xf << 28); /* DcqBwThrotWm = ... */
|
||||
switch (pDCTstat->Speed) {
|
||||
case 4:
|
||||
dword |= (0x5 << 28); /* ...5 for DDR800 */
|
||||
break;
|
||||
case 5:
|
||||
dword |= (0x6 << 28); /* ...6 for DDR1066 */
|
||||
break;
|
||||
case 6:
|
||||
dword |= (0x8 << 28); /* ...8 for DDR800 */
|
||||
break;
|
||||
default:
|
||||
dword |= (0x9 << 28); /* ...9 for DDR1600 */
|
||||
break;
|
||||
}
|
||||
Set_NB32(pDCTstat->dev_dct, 0x1b0, dword);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,474 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 - 2016 Raptor Engineering, LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <stdint.h>
|
||||
#include <console/console.h>
|
||||
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
static uint8_t is_fam15h(void)
|
||||
{
|
||||
uint8_t fam15h = 0;
|
||||
uint32_t family;
|
||||
|
||||
family = cpuid_eax(0x80000001);
|
||||
family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
|
||||
|
||||
if (family >= 0x6f)
|
||||
/* Family 15h or later */
|
||||
fam15h = 1;
|
||||
|
||||
return fam15h;
|
||||
}
|
||||
|
||||
static uint8_t fam15h_rdimm_rc2_ibt_code(struct DCTStatStruc *pDCTstat, uint8_t dct)
|
||||
{
|
||||
uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
|
||||
|
||||
uint8_t package_type;
|
||||
uint8_t control_code = 0;
|
||||
|
||||
package_type = mctGet_NVbits(NV_PACK_TYPE);
|
||||
uint16_t MemClkFreq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f;
|
||||
|
||||
/* Obtain number of DIMMs on channel */
|
||||
uint8_t dimm_count = pDCTstat->MAdimms[dct];
|
||||
|
||||
/* FIXME
|
||||
* Assume there is only one register on the RDIMM for now
|
||||
*/
|
||||
uint8_t num_registers = 1;
|
||||
|
||||
if (package_type == PT_GR) {
|
||||
/* Socket G34 */
|
||||
/* Fam15h BKDG Rev. 3.14 section 2.10.5.7.1.2.1 Table 85 */
|
||||
if (MaxDimmsInstallable == 1) {
|
||||
if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
|
||||
/* DDR3-667 - DDR3-800 */
|
||||
control_code = 0x1;
|
||||
} else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) {
|
||||
/* DDR3-1066 - DDR3-1333 */
|
||||
if (num_registers == 1) {
|
||||
control_code = 0x0;
|
||||
} else {
|
||||
control_code = 0x1;
|
||||
}
|
||||
} else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
|
||||
/* DDR3-1600 - DDR3-1866 */
|
||||
control_code = 0x0;
|
||||
}
|
||||
} else if (MaxDimmsInstallable == 2) {
|
||||
if (dimm_count == 1) {
|
||||
/* 1 DIMM detected */
|
||||
if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
|
||||
/* DDR3-667 - DDR3-800 */
|
||||
control_code = 0x1;
|
||||
} else if ((MemClkFreq >= 0xa) && (MemClkFreq <= 0x12)) {
|
||||
/* DDR3-1066 - DDR3-1600 */
|
||||
if (num_registers == 1) {
|
||||
control_code = 0x0;
|
||||
} else {
|
||||
control_code = 0x1;
|
||||
}
|
||||
}
|
||||
} else if (dimm_count == 2) {
|
||||
/* 2 DIMMs detected */
|
||||
if (num_registers == 1) {
|
||||
control_code = 0x1;
|
||||
} else {
|
||||
control_code = 0x8;
|
||||
}
|
||||
}
|
||||
} else if (MaxDimmsInstallable == 3) {
|
||||
/* TODO
|
||||
* 3 DIMM/channel support unimplemented
|
||||
*/
|
||||
}
|
||||
} else if (package_type == PT_C3) {
|
||||
/* Socket C32 */
|
||||
/* Fam15h BKDG Rev. 3.14 section 2.10.5.7.1.2.1 Table 86 */
|
||||
if (MaxDimmsInstallable == 1) {
|
||||
if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
|
||||
/* DDR3-667 - DDR3-800 */
|
||||
control_code = 0x1;
|
||||
} else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) {
|
||||
/* DDR3-1066 - DDR3-1333 */
|
||||
if (num_registers == 1) {
|
||||
control_code = 0x0;
|
||||
} else {
|
||||
control_code = 0x1;
|
||||
}
|
||||
} else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) {
|
||||
/* DDR3-1600 - DDR3-1866 */
|
||||
control_code = 0x0;
|
||||
}
|
||||
} else if (MaxDimmsInstallable == 2) {
|
||||
if (dimm_count == 1) {
|
||||
/* 1 DIMM detected */
|
||||
if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) {
|
||||
/* DDR3-667 - DDR3-800 */
|
||||
control_code = 0x1;
|
||||
} else if ((MemClkFreq >= 0xa) && (MemClkFreq <= 0x12)) {
|
||||
/* DDR3-1066 - DDR3-1600 */
|
||||
if (num_registers == 1) {
|
||||
control_code = 0x0;
|
||||
} else {
|
||||
control_code = 0x1;
|
||||
}
|
||||
}
|
||||
} else if (dimm_count == 2) {
|
||||
/* 2 DIMMs detected */
|
||||
if (num_registers == 1) {
|
||||
control_code = 0x1;
|
||||
} else {
|
||||
control_code = 0x8;
|
||||
}
|
||||
}
|
||||
} else if (MaxDimmsInstallable == 3) {
|
||||
/* TODO
|
||||
* 3 DIMM/channel support unimplemented
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
/* TODO
|
||||
* Other socket support unimplemented
|
||||
*/
|
||||
}
|
||||
|
||||
printk(BIOS_SPEW, "%s: DCT %d IBT code: %01x\n", __func__, dct, control_code);
|
||||
return control_code;
|
||||
}
|
||||
|
||||
static uint16_t memclk_to_freq(uint16_t memclk) {
|
||||
uint16_t fam10h_freq_tab[] = {0, 0, 0, 400, 533, 667, 800};
|
||||
uint16_t fam15h_freq_tab[] = {0, 0, 0, 0, 333, 0, 400, 0, 0, 0, 533, 0, 0, 0, 667, 0, 0, 0, 800, 0, 0, 0, 933};
|
||||
|
||||
uint16_t mem_freq = 0;
|
||||
|
||||
if (is_fam15h()) {
|
||||
if (memclk < 0x17) {
|
||||
mem_freq = fam15h_freq_tab[memclk];
|
||||
}
|
||||
} else {
|
||||
if ((memclk > 0x0) && (memclk < 0x8)) {
|
||||
mem_freq = fam10h_freq_tab[memclk - 1];
|
||||
}
|
||||
}
|
||||
|
||||
return mem_freq;
|
||||
}
|
||||
|
||||
static uint8_t rc_word_chip_select_lower_bit(void) {
|
||||
if (is_fam15h()) {
|
||||
return 21;
|
||||
} else {
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t rc_word_address_to_ctl_bits(uint32_t address) {
|
||||
if (is_fam15h()) {
|
||||
return (((address >> 3) & 0x1) << 2) << 18 | (address & 0x7);
|
||||
} else {
|
||||
return (((address >> 3) & 0x1) << 2) << 16 | (address & 0x7);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t rc_word_value_to_ctl_bits(uint32_t value) {
|
||||
if (is_fam15h()) {
|
||||
return ((value >> 2) & 0x3) << 18 | ((value & 0x3) << 3);
|
||||
} else {
|
||||
return ((value >> 2) & 0x3) << 16 | ((value & 0x3) << 3);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 mct_ControlRC(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, uint8_t dct, u32 MrsChipSel, u32 CtrlWordNum)
|
||||
{
|
||||
u8 Dimms, DimmNum;
|
||||
u32 val;
|
||||
uint8_t ddr_voltage_index;
|
||||
uint16_t mem_freq;
|
||||
uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE);
|
||||
uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
|
||||
|
||||
DimmNum = (MrsChipSel >> rc_word_chip_select_lower_bit()) & 0x7;
|
||||
|
||||
if (dct == 1)
|
||||
DimmNum++;
|
||||
|
||||
mem_freq = memclk_to_freq(pDCTstat->DIMMAutoSpeed);
|
||||
Dimms = pDCTstat->MAdimms[dct];
|
||||
|
||||
ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct);
|
||||
|
||||
val = 0;
|
||||
if (CtrlWordNum == 0)
|
||||
val = 0x2;
|
||||
else if (CtrlWordNum == 1) {
|
||||
if (!((pDCTstat->DimmDRPresent | pDCTstat->DimmQRPresent) & (1 << DimmNum)))
|
||||
val = 0xc; /* if single rank, set DBA1 and DBA0 */
|
||||
} else if (CtrlWordNum == 2) {
|
||||
if (is_fam15h()) {
|
||||
val = (fam15h_rdimm_rc2_ibt_code(pDCTstat, dct) & 0x1) << 2;
|
||||
} else {
|
||||
if (package_type == PT_GR) {
|
||||
/* Socket G34 */
|
||||
if (MaxDimmsInstallable == 2) {
|
||||
if (Dimms > 1)
|
||||
val = 0x4;
|
||||
}
|
||||
}
|
||||
else if (package_type == PT_C3) {
|
||||
/* Socket C32 */
|
||||
if (MaxDimmsInstallable == 2) {
|
||||
if (Dimms > 1)
|
||||
val = 0x4;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (CtrlWordNum == 3) {
|
||||
val = (pDCTstat->CtrlWrd3 >> (DimmNum << 2)) & 0xff;
|
||||
} else if (CtrlWordNum == 4) {
|
||||
val = (pDCTstat->CtrlWrd4 >> (DimmNum << 2)) & 0xff;
|
||||
} else if (CtrlWordNum == 5) {
|
||||
val = (pDCTstat->CtrlWrd5 >> (DimmNum << 2)) & 0xff;
|
||||
} else if (CtrlWordNum == 6) {
|
||||
val = ((pDCTstat->spd_data.spd_bytes[DimmNum][72] & 0xf) >> (DimmNum << 2)) & 0xff;
|
||||
} else if (CtrlWordNum == 7) {
|
||||
val = (((pDCTstat->spd_data.spd_bytes[DimmNum][72] >> 4) & 0xf) >> (DimmNum << 2)) & 0xff;
|
||||
} else if (CtrlWordNum == 8) {
|
||||
if (is_fam15h()) {
|
||||
val = (fam15h_rdimm_rc2_ibt_code(pDCTstat, dct) & 0xe) >> 1;
|
||||
} else {
|
||||
if (package_type == PT_GR) {
|
||||
/* Socket G34 */
|
||||
if (MaxDimmsInstallable == 2) {
|
||||
val = 0x0;
|
||||
}
|
||||
}
|
||||
else if (package_type == PT_C3) {
|
||||
/* Socket C32 */
|
||||
if (MaxDimmsInstallable == 2) {
|
||||
val = 0x0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (CtrlWordNum == 9) {
|
||||
val = 0xd; /* DBA1, DBA0, DA3 = 0 */
|
||||
} else if (CtrlWordNum == 10) {
|
||||
val = 0x0; /* Lowest operating frequency */
|
||||
} else if (CtrlWordNum == 11) {
|
||||
if (ddr_voltage_index & 0x4)
|
||||
val = 0x2; /* 1.25V */
|
||||
else if (ddr_voltage_index & 0x2)
|
||||
val = 0x1; /* 1.35V */
|
||||
else
|
||||
val = 0x0; /* 1.5V */
|
||||
} else if (CtrlWordNum == 12) {
|
||||
val = ((pDCTstat->spd_data.spd_bytes[DimmNum][75] & 0xf) >> (DimmNum << 2)) & 0xff;
|
||||
} else if (CtrlWordNum == 13) {
|
||||
val = (((pDCTstat->spd_data.spd_bytes[DimmNum][75] >> 4) & 0xf) >> (DimmNum << 2)) & 0xff;
|
||||
} else if (CtrlWordNum == 14) {
|
||||
val = ((pDCTstat->spd_data.spd_bytes[DimmNum][76] & 0xf) >> (DimmNum << 2)) & 0xff;
|
||||
} else if (CtrlWordNum == 15) {
|
||||
val = (((pDCTstat->spd_data.spd_bytes[DimmNum][76] >> 4) & 0xf) >> (DimmNum << 2)) & 0xff;
|
||||
}
|
||||
val &= 0xf;
|
||||
|
||||
printk(BIOS_SPEW, "%s: Preparing to send DCT %d DIMM %d RC%d: %02x\n", __func__, dct, DimmNum >> 1, CtrlWordNum, val);
|
||||
|
||||
val = MrsChipSel | rc_word_value_to_ctl_bits(val);
|
||||
val |= rc_word_address_to_ctl_bits(CtrlWordNum);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void mct_SendCtrlWrd(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, uint8_t dct, uint32_t val)
|
||||
{
|
||||
u32 dev = pDCTstat->dev_dct;
|
||||
|
||||
val |= Get_NB32_DCT(dev, dct, 0x7c) & ~0xffffff;
|
||||
val |= 1 << SendControlWord;
|
||||
Set_NB32_DCT(dev, dct, 0x7c, val);
|
||||
|
||||
do {
|
||||
val = Get_NB32_DCT(dev, dct, 0x7c);
|
||||
} while (val & (1 << SendControlWord));
|
||||
}
|
||||
|
||||
void mct_DramControlReg_Init_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, uint8_t dct)
|
||||
{
|
||||
u8 MrsChipSel;
|
||||
u32 dev = pDCTstat->dev_dct;
|
||||
u32 val, cw;
|
||||
|
||||
printk(BIOS_SPEW, "%s: Start\n", __func__);
|
||||
|
||||
if (!is_fam15h()) {
|
||||
mct_Wait(1600);
|
||||
mct_Wait(1200);
|
||||
}
|
||||
|
||||
pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct];
|
||||
if (pDCTstat->GangedMode & 1)
|
||||
pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
|
||||
|
||||
for (MrsChipSel = 0; MrsChipSel < 8; MrsChipSel += 2) {
|
||||
if (pDCTstat->CSPresent & (1 << MrsChipSel)) {
|
||||
val = Get_NB32_DCT(dev, dct, 0xa8);
|
||||
val &= ~(0xff << 8);
|
||||
|
||||
switch (MrsChipSel) {
|
||||
case 0:
|
||||
case 1:
|
||||
val |= 3 << 8;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
val |= (3 << 2) << 8;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
val |= (3 << 4) << 8;
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
val |= (3 << 6) << 8;
|
||||
break;
|
||||
}
|
||||
Set_NB32_DCT(dev, dct, 0xa8, val);
|
||||
printk(BIOS_SPEW, "%s: F2xA8: %08x\n", __func__, val);
|
||||
|
||||
if (is_fam15h()) {
|
||||
for (cw = 0; cw <=15; cw ++) {
|
||||
val = mct_ControlRC(pMCTstat, pDCTstat, dct, MrsChipSel << rc_word_chip_select_lower_bit(), cw);
|
||||
mct_SendCtrlWrd(pMCTstat, pDCTstat, dct, val);
|
||||
if ((cw == 2) || (cw == 8) || (cw == 10))
|
||||
precise_ndelay_fam15(pMCTstat, 6000);
|
||||
}
|
||||
} else {
|
||||
for (cw = 0; cw <=15; cw ++) {
|
||||
mct_Wait(1600);
|
||||
val = mct_ControlRC(pMCTstat, pDCTstat, dct, MrsChipSel << rc_word_chip_select_lower_bit(), cw);
|
||||
mct_SendCtrlWrd(pMCTstat, pDCTstat, dct, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mct_Wait(1200);
|
||||
|
||||
printk(BIOS_SPEW, "%s: Done\n", __func__);
|
||||
}
|
||||
|
||||
void FreqChgCtrlWrd(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, uint8_t dct)
|
||||
{
|
||||
u32 SaveSpeed = pDCTstat->DIMMAutoSpeed;
|
||||
u32 MrsChipSel;
|
||||
u32 dev = pDCTstat->dev_dct;
|
||||
u32 val;
|
||||
uint16_t mem_freq;
|
||||
|
||||
pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct];
|
||||
if (pDCTstat->GangedMode & 1)
|
||||
pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
|
||||
|
||||
pDCTstat->DIMMAutoSpeed = pDCTstat->TargetFreq;
|
||||
mem_freq = memclk_to_freq(pDCTstat->TargetFreq);
|
||||
for (MrsChipSel = 0; MrsChipSel < 8; MrsChipSel += 2) {
|
||||
if (pDCTstat->CSPresent & (1 << MrsChipSel)) {
|
||||
/* 2. Program F2x[1, 0]A8[CtrlWordCS]=bit mask for target chip selects. */
|
||||
val = Get_NB32_DCT(dev, dct, 0xa8);
|
||||
val &= ~(0xff << 8);
|
||||
|
||||
switch (MrsChipSel) {
|
||||
case 0:
|
||||
case 1:
|
||||
val |= 3 << 8;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
val |= (3 << 2) << 8;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
val |= (3 << 4) << 8;
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
val |= (3 << 6) << 8;
|
||||
break;
|
||||
}
|
||||
Set_NB32_DCT(dev, dct, 0xa8, val);
|
||||
|
||||
/* Resend control word 10 */
|
||||
uint8_t freq_ctl_val = 0;
|
||||
mct_Wait(1600);
|
||||
switch (mem_freq) {
|
||||
case 333:
|
||||
case 400:
|
||||
freq_ctl_val = 0x0;
|
||||
break;
|
||||
case 533:
|
||||
freq_ctl_val = 0x1;
|
||||
break;
|
||||
case 667:
|
||||
freq_ctl_val = 0x2;
|
||||
break;
|
||||
case 800:
|
||||
freq_ctl_val = 0x3;
|
||||
break;
|
||||
case 933:
|
||||
freq_ctl_val = 0x4;
|
||||
break;
|
||||
}
|
||||
|
||||
printk(BIOS_SPEW, "Preparing to send DCT %d DIMM %d RC%d: %02x (F2xA8: %08x)\n", dct, MrsChipSel >> 1, 10, freq_ctl_val, val);
|
||||
|
||||
mct_SendCtrlWrd(pMCTstat, pDCTstat, dct, (MrsChipSel << rc_word_chip_select_lower_bit()) | rc_word_address_to_ctl_bits(10) | rc_word_value_to_ctl_bits(freq_ctl_val));
|
||||
|
||||
if (is_fam15h())
|
||||
precise_ndelay_fam15(pMCTstat, 6000);
|
||||
else
|
||||
mct_Wait(1600);
|
||||
|
||||
/* Resend control word 2 */
|
||||
val = mct_ControlRC(pMCTstat, pDCTstat, dct, MrsChipSel << rc_word_chip_select_lower_bit(), 2);
|
||||
mct_SendCtrlWrd(pMCTstat, pDCTstat, dct, val);
|
||||
|
||||
if (is_fam15h())
|
||||
precise_ndelay_fam15(pMCTstat, 6000);
|
||||
else
|
||||
mct_Wait(1600);
|
||||
|
||||
/* Resend control word 8 */
|
||||
val = mct_ControlRC(pMCTstat, pDCTstat, dct, MrsChipSel << rc_word_chip_select_lower_bit(), 8);
|
||||
mct_SendCtrlWrd(pMCTstat, pDCTstat, dct, val);
|
||||
|
||||
if (is_fam15h())
|
||||
precise_ndelay_fam15(pMCTstat, 6000);
|
||||
else
|
||||
mct_Wait(1600);
|
||||
}
|
||||
}
|
||||
pDCTstat->DIMMAutoSpeed = SaveSpeed;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
static uint8_t is_fam15h(void)
|
||||
{
|
||||
uint8_t fam15h = 0;
|
||||
uint32_t family;
|
||||
|
||||
family = cpuid_eax(0x80000001);
|
||||
family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
|
||||
|
||||
if (family >= 0x6f)
|
||||
/* Family 15h or later */
|
||||
fam15h = 1;
|
||||
|
||||
return fam15h;
|
||||
}
|
||||
|
||||
u8 mct_checkNumberOfDqsRcvEn_1Pass(u8 pass)
|
||||
{
|
||||
u8 ret = 1;
|
||||
|
||||
if (is_fam15h()) {
|
||||
/* Fam15h needs two passes */
|
||||
ret = 1;
|
||||
} else {
|
||||
if (pass == SecondPass)
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 SetupDqsPattern_1PassA(u8 pass)
|
||||
{
|
||||
return (u32) TestPattern1_D;
|
||||
}
|
||||
|
||||
u32 SetupDqsPattern_1PassB(u8 pass)
|
||||
{
|
||||
return (u32) TestPattern0_D;
|
||||
}
|
||||
|
||||
static u16 mct_Average_RcvrEnDly_1Pass(struct DCTStatStruc *pDCTstat, u8 Channel, u8 Receiver,
|
||||
u8 Pass)
|
||||
{
|
||||
u16 i, MaxValue;
|
||||
u16 *p;
|
||||
u16 val;
|
||||
|
||||
MaxValue = 0;
|
||||
p = pDCTstat->CH_D_B_RCVRDLY[Channel][Receiver >> 1];
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
/* get left value from DCTStatStruc.CHA_D0_B0_RCVRDLY*/
|
||||
val = p[i];
|
||||
/* get right value from DCTStatStruc.CHA_D0_B0_RCVRDLY_1*/
|
||||
val += Pass1MemClkDly;
|
||||
/* write back the value to stack */
|
||||
if (val > MaxValue)
|
||||
MaxValue = val;
|
||||
|
||||
p[i] = val;
|
||||
}
|
||||
/* pDCTstat->DimmTrainFail &= ~(1<<Receiver+Channel); */
|
||||
|
||||
return MaxValue;
|
||||
}
|
||||
|
||||
u8 mct_SaveRcvEnDly_D_1Pass(struct DCTStatStruc *pDCTstat, u8 pass)
|
||||
{
|
||||
u8 ret;
|
||||
ret = 0;
|
||||
if ((pDCTstat->DqsRcvEn_Pass == 0xff) && (pass== FirstPass))
|
||||
ret = 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
u16 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
|
||||
u16 RcvrEnDly, u16 RcvrEnDlyLimit,
|
||||
u8 Channel, u8 Receiver, u8 Pass)
|
||||
|
||||
{
|
||||
return mct_Average_RcvrEnDly_1Pass(pDCTstat, Channel, Receiver, Pass);
|
||||
}
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
u8 mct_checkNumberOfDqsRcvEn_Pass(u8 pass)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
u32 SetupDqsPattern_PassA(u8 Pass)
|
||||
{
|
||||
u32 ret;
|
||||
if (Pass == FirstPass)
|
||||
ret = (u32) TestPattern1_D;
|
||||
else
|
||||
ret = (u32) TestPattern2_D;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 SetupDqsPattern_PassB(u8 Pass)
|
||||
{
|
||||
u32 ret;
|
||||
if (Pass == FirstPass)
|
||||
ret = (u32) TestPattern0_D;
|
||||
else
|
||||
ret = (u32) TestPattern2_D;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u8 mct_Get_Start_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
|
||||
u8 Channel, u8 Receiver,
|
||||
u8 Pass)
|
||||
{
|
||||
u8 RcvrEnDly;
|
||||
|
||||
if (Pass == FirstPass)
|
||||
RcvrEnDly = 0;
|
||||
else {
|
||||
u8 max = 0;
|
||||
u8 val;
|
||||
u8 i;
|
||||
u8 *p = pDCTstat->persistentData.CH_D_B_RCVRDLY[Channel][Receiver>>1];
|
||||
u8 bn;
|
||||
bn = 8;
|
||||
|
||||
for (i = 0; i < bn; i++) {
|
||||
val = p[i];
|
||||
|
||||
if (val > max) {
|
||||
max = val;
|
||||
}
|
||||
}
|
||||
RcvrEnDly = max;
|
||||
}
|
||||
|
||||
return RcvrEnDly;
|
||||
}
|
||||
|
||||
u16 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat,
|
||||
u16 RcvrEnDly, u16 RcvrEnDlyLimit,
|
||||
u8 Channel, u8 Receiver, u8 Pass)
|
||||
{
|
||||
u8 i;
|
||||
u16 *p;
|
||||
u16 *p_1;
|
||||
u16 val;
|
||||
u16 val_1;
|
||||
u8 valid = 1;
|
||||
u8 bn;
|
||||
|
||||
bn = 8;
|
||||
|
||||
p = pDCTstat->persistentData.CH_D_B_RCVRDLY[Channel][Receiver>>1];
|
||||
|
||||
if (Pass == SecondPass) { /* second pass must average values */
|
||||
/* FIXME: which byte? */
|
||||
p_1 = pDCTstat->B_RCVRDLY_1;
|
||||
/* p_1 = pDCTstat->persistentData.CH_D_B_RCVRDLY_1[Channel][Receiver>>1]; */
|
||||
for (i = 0; i < bn; i++) {
|
||||
val = p[i];
|
||||
/* left edge */
|
||||
if (val != (RcvrEnDlyLimit - 1)) {
|
||||
val -= Pass1MemClkDly;
|
||||
val_1 = p_1[i];
|
||||
val += val_1;
|
||||
val >>= 1;
|
||||
p[i] = val;
|
||||
} else {
|
||||
valid = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!valid) {
|
||||
pDCTstat->ErrStatus |= 1<<SB_NORCVREN;
|
||||
} else {
|
||||
pDCTstat->DimmTrainFail &= ~(1<<(Receiver + Channel));
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < bn; i++) {
|
||||
val = p[i];
|
||||
/* Add 1/2 Memlock delay */
|
||||
/* val += Pass1MemClkDly; */
|
||||
val += 0x5; /* NOTE: middle value with DQSRCVEN_SAVED_GOOD_TIMES */
|
||||
/* val += 0x02; */
|
||||
p[i] = val;
|
||||
pDCTstat->DimmTrainFail &= ~(1<<(Receiver + Channel));
|
||||
}
|
||||
}
|
||||
|
||||
return RcvrEnDly;
|
||||
}
|
||||
|
|
@ -1,398 +0,0 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2010 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Description: Max Read Latency Training feature for DDR 3 MCT
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <console/console.h>
|
||||
#include <cpu/amd/msr.h>
|
||||
#include <cpu/x86/cr.h>
|
||||
#include "mct_d.h"
|
||||
#include "mct_d_gcc.h"
|
||||
|
||||
static u8 CompareMaxRdLatTestPattern_D(u32 pattern_buf, u32 addr);
|
||||
static u32 GetMaxRdLatTestAddr_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u8 Channel,
|
||||
u8 *MaxRcvrEnDly, u8 *valid);
|
||||
u8 mct_GetStartMaxRdLat_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat, u8 Channel,
|
||||
u8 DQSRcvEnDly, u32 *Margin);
|
||||
static void maxRdLatencyTrain_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat);
|
||||
static void mct_setMaxRdLatTrnVal_D(struct DCTStatStruc *pDCTstat, u8 Channel,
|
||||
u16 MaxRdLatVal);
|
||||
|
||||
/*Warning: These must be located so they do not cross a logical 16-bit
|
||||
segment boundary!*/
|
||||
static const u32 TestMaxRdLAtPattern_D[] = {
|
||||
0x6E0E3FAC, 0x0C3CFF52,
|
||||
0x4A688181, 0x49C5B613,
|
||||
0x7C780BA6, 0x5C1650E3,
|
||||
0x0C4F9D76, 0x0C6753E6,
|
||||
0x205535A5, 0xBABFB6CA,
|
||||
0x610E6E5F, 0x0C5F1C87,
|
||||
0x488493CE, 0x14C9C383,
|
||||
0xF5B9A5CD, 0x9CE8F615,
|
||||
|
||||
0xAAD714B5, 0xC38F1B4C,
|
||||
0x72ED647C, 0x669F7562,
|
||||
0x5233F802, 0x4A898B30,
|
||||
0x10A40617, 0x3326B465,
|
||||
0x55386E04, 0xC807E3D3,
|
||||
0xAB49E193, 0x14B4E63A,
|
||||
0x67DF2495, 0xEA517C45,
|
||||
0x7624CE51, 0xF8140C51,
|
||||
|
||||
0x4824BD23, 0xB61DD0C9,
|
||||
0x072BCFBE, 0xE8F3807D,
|
||||
0x919EA373, 0x25E30C47,
|
||||
0xFEB12958, 0x4DA80A5A,
|
||||
0xE9A0DDF8, 0x792B0076,
|
||||
0xE81C73DC, 0xF025B496,
|
||||
0x1DB7E627, 0x808594FE,
|
||||
0x82668268, 0x655C7783,
|
||||
};
|
||||
|
||||
static u32 SetupMaxRdPattern(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat,
|
||||
u32 *buffer)
|
||||
{
|
||||
/* 1. Copy the alpha and Beta patterns from ROM to Cache,
|
||||
* aligning on 16 byte boundary
|
||||
* 2. Set the ptr to Cacheable copy in DCTStatstruc.PtrPatternBufA
|
||||
* for Alpha
|
||||
* 3. Set the ptr to Cacheable copy in DCTStatstruc.PtrPatternBufB
|
||||
* for Beta
|
||||
*/
|
||||
u32 *buf;
|
||||
u8 i;
|
||||
|
||||
buf = (u32 *)(((u32)buffer + 0x10) & (0xfffffff0));
|
||||
|
||||
for (i = 0; i < (16 * 3); i++) {
|
||||
buf[i] = TestMaxRdLAtPattern_D[i];
|
||||
}
|
||||
|
||||
return (u32)buf;
|
||||
}
|
||||
|
||||
void TrainMaxReadLatency_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstatA)
|
||||
{
|
||||
u8 Node;
|
||||
|
||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||
struct DCTStatStruc *pDCTstat;
|
||||
pDCTstat = pDCTstatA + Node;
|
||||
|
||||
if (!pDCTstat->NodePresent)
|
||||
break;
|
||||
|
||||
if (pDCTstat->DCTSysLimit)
|
||||
maxRdLatencyTrain_D(pMCTstat, pDCTstat);
|
||||
}
|
||||
}
|
||||
|
||||
static void maxRdLatencyTrain_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat)
|
||||
{
|
||||
u8 Channel;
|
||||
u32 TestAddr0;
|
||||
u8 _DisableDramECC = 0, _Wrap32Dis = 0, _SSE2 = 0;
|
||||
u16 MaxRdLatDly;
|
||||
u8 RcvrEnDly = 0;
|
||||
u32 PatternBuffer[60]; /* FIXME: why not 48 + 4 */
|
||||
u32 Margin;
|
||||
u32 addr;
|
||||
CRx_TYPE cr4;
|
||||
u32 lo, hi;
|
||||
|
||||
u8 valid;
|
||||
u32 pattern_buf;
|
||||
|
||||
cr4 = read_cr4();
|
||||
if (cr4 & (1<<9)) { /* save the old value */
|
||||
_SSE2 = 1;
|
||||
}
|
||||
cr4 |= (1<<9); /* OSFXSR enable SSE2 */
|
||||
write_cr4(cr4);
|
||||
|
||||
addr = HWCR_MSR;
|
||||
_RDMSR(addr, &lo, &hi);
|
||||
if (lo & (1<<17)) { /* save the old value */
|
||||
_Wrap32Dis = 1;
|
||||
}
|
||||
lo |= (1<<17); /* HWCR.wrap32dis */
|
||||
lo &= ~(1<<15); /* SSEDIS */
|
||||
/* Setting wrap32dis allows 64-bit memory references in
|
||||
real mode */
|
||||
_WRMSR(addr, lo, hi);
|
||||
|
||||
_DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat);
|
||||
|
||||
pattern_buf = SetupMaxRdPattern(pMCTstat, pDCTstat, PatternBuffer);
|
||||
|
||||
for (Channel = 0; Channel < 2; Channel++) {
|
||||
print_debug_dqs("\tMaxRdLatencyTrain51: Channel ",Channel, 1);
|
||||
pDCTstat->Channel = Channel;
|
||||
|
||||
if ((pDCTstat->Status & (1 << SB_128bitmode)) && Channel)
|
||||
break; /*if ganged mode, skip DCT 1 */
|
||||
|
||||
TestAddr0 = GetMaxRdLatTestAddr_D(pMCTstat, pDCTstat, Channel, &RcvrEnDly, &valid);
|
||||
if (!valid) /* Address not supported on current CS */
|
||||
continue;
|
||||
/* rank 1 of DIMM, testpattern 0 */
|
||||
WriteMaxRdLat1CLTestPattern_D(pattern_buf, TestAddr0);
|
||||
|
||||
MaxRdLatDly = mct_GetStartMaxRdLat_D(pMCTstat, pDCTstat, Channel, RcvrEnDly, &Margin);
|
||||
print_debug_dqs("\tMaxRdLatencyTrain52: MaxRdLatDly start ", MaxRdLatDly, 2);
|
||||
print_debug_dqs("\tMaxRdLatencyTrain52: MaxRdLatDly Margin ", Margin, 2);
|
||||
while (MaxRdLatDly < MAX_RD_LAT) { /* sweep Delay value here */
|
||||
mct_setMaxRdLatTrnVal_D(pDCTstat, Channel, MaxRdLatDly);
|
||||
ReadMaxRdLat1CLTestPattern_D(TestAddr0);
|
||||
if (CompareMaxRdLatTestPattern_D(pattern_buf, TestAddr0) == DQS_PASS)
|
||||
break;
|
||||
SetTargetWTIO_D(TestAddr0);
|
||||
FlushMaxRdLatTestPattern_D(TestAddr0);
|
||||
ResetTargetWTIO_D();
|
||||
MaxRdLatDly++;
|
||||
}
|
||||
print_debug_dqs("\tMaxRdLatencyTrain53: MaxRdLatDly end ", MaxRdLatDly, 2);
|
||||
mct_setMaxRdLatTrnVal_D(pDCTstat, Channel, MaxRdLatDly + Margin);
|
||||
}
|
||||
|
||||
if (_DisableDramECC) {
|
||||
mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC);
|
||||
}
|
||||
|
||||
if (!_Wrap32Dis) {
|
||||
addr = HWCR_MSR;
|
||||
_RDMSR(addr, &lo, &hi);
|
||||
lo &= ~(1<<17); /* restore HWCR.wrap32dis */
|
||||
_WRMSR(addr, lo, hi);
|
||||
}
|
||||
if (!_SSE2) {
|
||||
cr4 = read_cr4();
|
||||
cr4 &= ~(1<<9); /* restore cr4.OSFXSR */
|
||||
write_cr4(cr4);
|
||||
}
|
||||
|
||||
#if DQS_TRAIN_DEBUG > 0
|
||||
{
|
||||
u8 ChannelDTD;
|
||||
printk(BIOS_DEBUG, "maxRdLatencyTrain: CH_MaxRdLat:\n");
|
||||
for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) {
|
||||
printk(BIOS_DEBUG, "Channel: %02x: %02x\n", ChannelDTD, pDCTstat->CH_MaxRdLat[ChannelDTD][0]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mct_setMaxRdLatTrnVal_D(struct DCTStatStruc *pDCTstat,
|
||||
u8 Channel, u16 MaxRdLatVal)
|
||||
{
|
||||
u8 i;
|
||||
u32 reg;
|
||||
u32 dev;
|
||||
u32 val;
|
||||
|
||||
if (pDCTstat->GangedMode) {
|
||||
Channel = 0; /* for safe */
|
||||
for (i = 0; i < 2; i++)
|
||||
pDCTstat->CH_MaxRdLat[i][0] = MaxRdLatVal;
|
||||
} else {
|
||||
pDCTstat->CH_MaxRdLat[Channel][0] = MaxRdLatVal;
|
||||
}
|
||||
|
||||
dev = pDCTstat->dev_dct;
|
||||
reg = 0x78;
|
||||
val = Get_NB32_DCT(dev, Channel, reg);
|
||||
val &= ~(0x3ff<<22);
|
||||
val |= MaxRdLatVal<<22;
|
||||
/* program MaxRdLatency to correspond with current delay */
|
||||
Set_NB32_DCT(dev, Channel, reg, val);
|
||||
}
|
||||
|
||||
static u8 CompareMaxRdLatTestPattern_D(u32 pattern_buf, u32 addr)
|
||||
{
|
||||
/* Compare only the first beat of data. Since target addrs are cache
|
||||
* line aligned, the Channel parameter is used to determine which cache
|
||||
* QW to compare.
|
||||
*/
|
||||
|
||||
u32 *test_buf = (u32 *)pattern_buf;
|
||||
u32 addr_lo;
|
||||
u32 val, val_test;
|
||||
int i;
|
||||
u8 ret = DQS_PASS;
|
||||
|
||||
SetUpperFSbase(addr);
|
||||
addr_lo = addr<<8;
|
||||
|
||||
_EXECFENCE;
|
||||
for (i = 0; i < 16*3; i++) {
|
||||
val = read32_fs(addr_lo);
|
||||
val_test = test_buf[i];
|
||||
|
||||
print_debug_dqs_pair("\t\t\t\t\t\ttest_buf = ", (u32)test_buf, " value = ", val_test, 5);
|
||||
print_debug_dqs_pair("\t\t\t\t\t\ttaddr_lo = ", addr_lo, " value = ", val, 5);
|
||||
if (val != val_test) {
|
||||
ret = DQS_FAIL;
|
||||
break;
|
||||
}
|
||||
addr_lo += 4;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 GetMaxRdLatTestAddr_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat,
|
||||
u8 Channel, u8 *MaxRcvrEnDly,
|
||||
u8 *valid)
|
||||
{
|
||||
u8 Max = 0;
|
||||
|
||||
u8 Channel_Max = 0;
|
||||
u8 d;
|
||||
u8 d_Max = 0;
|
||||
|
||||
u8 Byte;
|
||||
u32 TestAddr0 = 0;
|
||||
u8 ch, ch_start, ch_end;
|
||||
u8 bn;
|
||||
|
||||
bn = 8;
|
||||
|
||||
if (pDCTstat->Status & (1 << SB_128bitmode)) {
|
||||
ch_start = 0;
|
||||
ch_end = 2;
|
||||
} else {
|
||||
ch_start = Channel;
|
||||
ch_end = Channel + 1;
|
||||
}
|
||||
|
||||
*valid = 0;
|
||||
|
||||
for (ch = ch_start; ch < ch_end; ch++) {
|
||||
for (d = 0; d < 4; d++) {
|
||||
for (Byte = 0; Byte < bn; Byte++) {
|
||||
u8 tmp;
|
||||
tmp = pDCTstat->CH_D_B_RCVRDLY[ch][d][Byte];
|
||||
if (tmp > Max) {
|
||||
Max = tmp;
|
||||
Channel_Max = Channel;
|
||||
d_Max = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel_Max, d_Max << 1)) {
|
||||
TestAddr0 = mct_GetMCTSysAddr_D(pMCTstat, pDCTstat, Channel_Max, d_Max << 1, valid);
|
||||
}
|
||||
|
||||
if (*valid)
|
||||
*MaxRcvrEnDly = Max;
|
||||
|
||||
return TestAddr0;
|
||||
}
|
||||
|
||||
u8 mct_GetStartMaxRdLat_D(struct MCTStatStruc *pMCTstat,
|
||||
struct DCTStatStruc *pDCTstat,
|
||||
u8 Channel, u8 DQSRcvEnDly, u32 *Margin)
|
||||
{
|
||||
u32 SubTotal;
|
||||
u32 val;
|
||||
u32 valx;
|
||||
u32 valxx;
|
||||
u32 index_reg;
|
||||
u32 dev;
|
||||
|
||||
if (pDCTstat->GangedMode)
|
||||
Channel = 0;
|
||||
|
||||
index_reg = 0x98;
|
||||
|
||||
dev = pDCTstat->dev_dct;
|
||||
|
||||
/* Multiply the CAS Latency by two to get a number of 1/2 MEMCLKs units.*/
|
||||
val = Get_NB32_DCT(dev, Channel, 0x88);
|
||||
SubTotal = ((val & 0x0f) + 1) << 1; /* SubTotal is 1/2 Memclk unit */
|
||||
|
||||
/* If registered DIMMs are being used then add 1 MEMCLK to the sub-total*/
|
||||
val = Get_NB32_DCT(dev, Channel, 0x90);
|
||||
if (!(val & (1 << UnBuffDimm)))
|
||||
SubTotal += 2;
|
||||
|
||||
/*If the address prelaunch is setup for 1/2 MEMCLKs then add 1,
|
||||
* else add 2 to the sub-total. if (AddrCmdSetup || CsOdtSetup
|
||||
* || CkeSetup) then K := K + 2; */
|
||||
val = Get_NB32_index_wait_DCT(dev, Channel, index_reg, 0x04);
|
||||
if (!(val & 0x00202020))
|
||||
SubTotal += 1;
|
||||
else
|
||||
SubTotal += 2;
|
||||
|
||||
/* If the F2x[1, 0]78[RdPtrInit] field is 4, 5, 6 or 7 MEMCLKs,
|
||||
* then add 4, 3, 2, or 1 MEMCLKs, respectively to the sub-total. */
|
||||
val = Get_NB32_DCT(dev, Channel, 0x78);
|
||||
SubTotal += 8 - (val & 0x0f);
|
||||
|
||||
/* Convert bits 7-5 (also referred to as the course delay) of the current
|
||||
* (or worst case) DQS receiver enable delay to 1/2 MEMCLKs units,
|
||||
* rounding up, and add this to the sub-total. */
|
||||
SubTotal += DQSRcvEnDly >> 5; /*BOZO-no rounding up */
|
||||
|
||||
SubTotal <<= 1; /*scale 1/2 MemClk to 1/4 MemClk */
|
||||
|
||||
/* Convert the sub-total (in 1/2 MEMCLKs) to northbridge clocks (NCLKs)
|
||||
* as follows (assuming DDR400 and assuming that no P-state or link speed
|
||||
* changes have occurred). */
|
||||
|
||||
/*New formula:
|
||||
SubTotal *= 3*(Fn2xD4[NBFid]+4)/(3+Fn2x94[MemClkFreq])/2 */
|
||||
val = Get_NB32_DCT(dev, Channel, 0x94);
|
||||
/* SubTotal div 4 to scale 1/4 MemClk back to MemClk */
|
||||
val &= 7;
|
||||
if (val >= 3) {
|
||||
val <<= 1;
|
||||
} else
|
||||
val += 3;
|
||||
valx = (val) << 2; /* SubTotal div 4 to scale 1/4 MemClk back to MemClk */
|
||||
|
||||
val = Get_NB32(pDCTstat->dev_nbmisc, 0xD4);
|
||||
val = ((val & 0x1f) + 4) * 3;
|
||||
|
||||
/* Calculate 1 MemClk + 1 NCLK delay in NCLKs for margin */
|
||||
valxx = val << 2;
|
||||
valxx /= valx;
|
||||
if (valxx % valx)
|
||||
valxx++; /* round up */
|
||||
valxx++; /* add 1NCLK */
|
||||
*Margin = valxx; /* one MemClk delay in NCLKs and one additional NCLK */
|
||||
|
||||
val *= SubTotal;
|
||||
|
||||
val /= valx;
|
||||
if (val % valx)
|
||||
val++; /* round up */
|
||||
|
||||
return val;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue