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:
Arthur Heymans
2019-11-19 15:46:49 +01:00
committed by Kyösti Mälkki
parent 1ca978ee65
commit ffcac3eb50
112 changed files with 5 additions and 48884 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)
}
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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_ */

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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");
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -1,5 +0,0 @@
ifeq ($(CONFIG_NORTHBRIDGE_AMD_AMDFAM10),y)
romstage-y += h3finit.c ht_wrapper.c comlib.c AsPsNb.c h3ncmn.c
endif

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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");
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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");
}

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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");
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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");
}

View File

@ -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 */);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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