diff options
author | Arthur Heymans <arthur@aheymans.xyz> | 2019-11-19 15:46:49 +0100 |
---|---|---|
committer | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2019-11-20 19:08:30 +0000 |
commit | ffcac3eb502bbe0acbb30d6fe804f00e07461a7a (patch) | |
tree | d5deda572bb252a683a5ece24a5c4916ee198836 /src/northbridge/amd | |
parent | 1ca978ee6529251ed80b47da679be7adc75fa46a (diff) |
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>
Diffstat (limited to 'src/northbridge/amd')
108 files changed, 1 insertions, 48872 deletions
diff --git a/src/northbridge/amd/agesa/family14/acpi/northbridge.asl b/src/northbridge/amd/agesa/family14/acpi/northbridge.asl index e95c95a019..06199a1b07 100644 --- a/src/northbridge/amd/agesa/family14/acpi/northbridge.asl +++ b/src/northbridge/amd/agesa/family14/acpi/northbridge.asl @@ -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 */ diff --git a/src/northbridge/amd/amdfam10/thermal_mixin.asl b/src/northbridge/amd/agesa/family14/acpi/thermal_mixin.asl index fb33772c1e..fb33772c1e 100644 --- a/src/northbridge/amd/amdfam10/thermal_mixin.asl +++ b/src/northbridge/amd/agesa/family14/acpi/thermal_mixin.asl diff --git a/src/northbridge/amd/amdfam10/Kconfig b/src/northbridge/amd/amdfam10/Kconfig deleted file mode 100644 index 64358875f1..0000000000 --- a/src/northbridge/amd/amdfam10/Kconfig +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdfam10/Makefile.inc b/src/northbridge/amd/amdfam10/Makefile.inc deleted file mode 100644 index 787f4444ce..0000000000 --- a/src/northbridge/amd/amdfam10/Makefile.inc +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdfam10/acpi.c b/src/northbridge/amd/amdfam10/acpi.c deleted file mode 100644 index dc139adb87..0000000000 --- a/src/northbridge/amd/amdfam10/acpi.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdfam10/amdfam10.h b/src/northbridge/amd/amdfam10/amdfam10.h deleted file mode 100644 index ad8d01365d..0000000000 --- a/src/northbridge/amd/amdfam10/amdfam10.h +++ /dev/null @@ -1,1025 +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 AMDFAM10_H -#define AMDFAM10_H - -#include <stdint.h> -#include <device/device.h> -#include "early_ht.h" - -#include "inline_helper.c" -struct DCTStatStruc; -struct MCTStatStruc; - - -/* Definitions for setup_resourcemap() variants. */ - -#define PCI_ADDR(SEGBUS, DEV, FN, WHERE) ( \ - (((SEGBUS) & 0xFFF) << 20) | \ - (((DEV) & 0x1F) << 15) | \ - (((FN) & 0x07) << 12) | \ - ((WHERE) & 0xFFF)) - -#define ADDRMAP_REG(r) PCI_ADDR(CONFIG_CBB, CONFIG_CDB, 1, r) - -#define RES_PCI_IO 0x10 -#define RES_PORT_IO_8 0x22 -#define RES_PORT_IO_32 0x20 -#define RES_MEM_IO 0x40 - -#define NODE_ID 0x60 -#define HT_INIT_CONTROL 0x6c -#define HTIC_ColdR_Detect (1<<4) -#define HTIC_BIOSR_Detect (1<<5) -#define HTIC_INIT_Detect (1<<6) - -/* Definitions of various FAM10 registers */ -/* Function 0 */ -#define HT_TRANSACTION_CONTROL 0x68 -#define HTTC_DIS_RD_B_P (1 << 0) -#define HTTC_DIS_RD_DW_P (1 << 1) -#define HTTC_DIS_WR_B_P (1 << 2) -#define HTTC_DIS_WR_DW_P (1 << 3) -#define HTTC_DIS_MTS (1 << 4) -#define HTTC_CPU1_EN (1 << 5) -#define HTTC_CPU_REQ_PASS_PW (1 << 6) -#define HTTC_CPU_RD_RSP_PASS_PW (1 << 7) -#define HTTC_DIS_P_MEM_C (1 << 8) -#define HTTC_DIS_RMT_MEM_C (1 << 9) -#define HTTC_DIS_FILL_P (1 << 10) -#define HTTC_RSP_PASS_PW (1 << 11) -#define HTTC_BUF_REL_PRI_SHIFT 13 -#define HTTC_BUF_REL_PRI_MASK 3 -#define HTTC_BUF_REL_PRI_64 0 -#define HTTC_BUF_REL_PRI_16 1 -#define HTTC_BUF_REL_PRI_8 2 -#define HTTC_BUF_REL_PRI_2 3 -#define HTTC_LIMIT_CLDT_CFG (1 << 15) -#define HTTC_LINT_EN (1 << 16) -#define HTTC_APIC_EXT_BRD_CST (1 << 17) -#define HTTC_APIC_EXT_ID (1 << 18) -#define HTTC_APIC_EXT_SPUR (1 << 19) -#define HTTC_SEQ_ID_SRC_NODE_EN (1 << 20) -#define HTTC_DS_NP_REQ_LIMIT_SHIFT 21 -#define HTTC_DS_NP_REQ_LIMIT_MASK 3 -#define HTTC_DS_NP_REQ_LIMIT_NONE 0 -#define HTTC_DS_NP_REQ_LIMIT_1 1 -#define HTTC_DS_NP_REQ_LIMIT_4 2 -#define HTTC_DS_NP_REQ_LIMIT_8 3 - - -/* Function 1 */ -#define PCI_IO_BASE0 0xc0 -#define PCI_IO_BASE1 0xc8 -#define PCI_IO_BASE2 0xd0 -#define PCI_IO_BASE3 0xd8 -#define PCI_IO_BASE_VGA_EN (1 << 4) -#define PCI_IO_BASE_NO_ISA (1 << 5) - -/* Function 2 */ -// 0x1xx is for DCT1 -#define DRAM_CSBASE 0x40 -#define DRAM_CSMASK 0x60 -#define DRAM_BANK_ADDR_MAP 0x80 - -#define DRAM_CTRL 0x78 -#define DC_RdPtrInit_SHIFT 0 -#define DC_RdPrtInit_MASK 0xf -#define DC_Twrrd3_2_SHIFT 8 /*DDR3 */ -#define DC_Twrrd3_2_MASK 3 -#define DC_Twrwr3_2_SHIFT 10 /*DDR3 */ -#define DC_Twrwr3_2_MASK 3 -#define DC_Trdrd3_2_SHIFT 12 /*DDR3 */ -#define DC_Trdrd3_2_MASK 3 -#define DC_AltVidC3MemClkTriEn (1<<16) -#define DC_DqsRcvEnTrain (1<<18) -#define DC_MaxRdLatency_SHIFT 22 -#define DC_MaxRdLatency_MASK 0x3ff - -#define DRAM_INIT 0x7c -#define DI_MrsAddress_SHIFT 0 -#define DI_MrsAddress_MASK 0xffff -#define DI_MrsBank_SHIFT 16 -#define DI_MrsBank_MASK 7 -#define DI_MrsChipSel_SHIFT 20 -#define DI_MrsChipSel_MASK 7 -#define DI_SendRchgAll (1<<24) -#define DI_SendAutoRefresh (1<<25) -#define DI_SendMrsCmd (1<<26) -#define DI_DeassertMemRstX (1<<27) -#define DI_AssertCke (1<<28) -#define DI_SendZQCmd (1<<29) /*DDR3 */ -#define DI_EnMrsCmd (1<<30) -#define DI_EnDramInit (1<<31) - -#define DRAM_MRS 0x84 -#define DM_BurstCtrl_SHIFT 0 -#define DM_BurstCtrl_MASK 3 -#define DM_DrvImpCtrl_SHIFT 2 /* DDR3 */ -#define DM_DrvImpCtrl_MASK 3 -#define DM_Twr_SHIFT 4 /* DDR3 */ -#define DM_Twr_MASK 7 -#define DM_Twr_BASE 4 -#define DM_Twr_MIN 5 -#define DM_Twr_MAX 12 -#define DM_DramTerm_SHIFT 7 /*DDR3 */ -#define DM_DramTerm_MASK 7 -#define DM_DramTermDyn_SHIFT 10 /* DDR3 */ -#define DM_DramTermDyn_MASK 3 -#define DM_Ooff (1<<13) -#define DM_ASR (1<<18) -#define DM_SRT (1<<19) -#define DM_Tcwl_SHIFT 20 -#define DM_Tcwl_MASK 7 -#define DM_PchgPDModeSel (1<<23) /* DDR3 */ -#define DM_MPrLoc_SHIFT 24 /* DDR3 */ -#define DM_MPrLoc_MASK 3 -#define DM_MprEn (1<<26) /* DDR3 */ - -#define DRAM_TIMING_LOW 0x88 -#define DTL_TCL_SHIFT 0 -#define DTL_TCL_MASK 0xf -#define DTL_TCL_BASE 1 /* DDR3 =4 */ -#define DTL_TCL_MIN 3 /* DDR3 =4 */ -#define DTL_TCL_MAX 6 /* DDR3 =12 */ -#define DTL_TRCD_SHIFT 4 -#define DTL_TRCD_MASK 3 /* DDR3 =7 */ -#define DTL_TRCD_BASE 3 /* DDR3 =5 */ -#define DTL_TRCD_MIN 3 /* DDR3 =5 */ -#define DTL_TRCD_MAX 6 /* DDR3 =12 */ -#define DTL_TRP_SHIFT 8 /* DDR3 =7 */ -#define DTL_TRP_MASK 3 /* DDR3 =7 */ -#define DTL_TRP_BASE 3 /* DDR3 =5 */ -#define DTL_TRP_MIN 3 /* DDR3 =5 */ -#define DTL_TRP_MAX 6 /* DDR3 =12 */ -#define DTL_TRTP_SHIFT 11 /*DDR3 =10 */ -#define DTL_TRTP_MASK 1 /*DDR3 =3 */ -#define DTL_TRTP_BASE 2 /* DDR3 =4 */ -#define DTL_TRTP_MIN 2 /* 4 for 64 bytes*/ /* DDR3 =4 for 32bytes or 64bytes */ -#define DTL_TRTP_MAX 3 /* 5 for 64 bytes */ /* DDR3 =7 for 32Bytes or 64bytes */ -#define DTL_TRAS_SHIFT 12 -#define DTL_TRAS_MASK 0xf -#define DTL_TRAS_BASE 3 /* DDR3 =15 */ -#define DTL_TRAS_MIN 5 /* DDR3 =15 */ -#define DTL_TRAS_MAX 18 /*DDR3 =30 */ -#define DTL_TRC_SHIFT 16 -#define DTL_TRC_MASK 0xf /* DDR3 =0x1f */ -#define DTL_TRC_BASE 11 -#define DTL_TRC_MIN 11 -#define DTL_TRC_MAX 26 /* DDR3 =43 */ -#define DTL_TWR_SHIFT 20 /* only for DDR2, DDR3's is on DC */ -#define DTL_TWR_MASK 3 -#define DTL_TWR_BASE 3 -#define DTL_TWR_MIN 3 -#define DTL_TWR_MAX 6 -#define DTL_TRRD_SHIFT 22 -#define DTL_TRRD_MASK 3 -#define DTL_TRRD_BASE 2 /* DDR3 =4 */ -#define DTL_TRRD_MIN 2 /* DDR3 =4 */ -#define DTL_TRRD_MAX 5 /* DDR3 =7 */ -#define DTL_MemClkDis_SHIFT 24 /* Channel A */ -#define DTL_MemClkDis3 (1 << 26) -#define DTL_MemClkDis2 (1 << 27) -#define DTL_MemClkDis1 (1 << 28) -#define DTL_MemClkDis0 (1 << 29) -/* DTL_MemClkDis for m2 and s1g1 is different */ - -#define DRAM_TIMING_HIGH 0x8c -#define DTH_TRWTWB_SHIFT 0 -#define DTH_TRWTWB_MASK 3 -#define DTH_TRWTWB_BASE 3 /* DDR3 =4 */ -#define DTH_TRWTWB_MIN 3 /* DDR3 =5 */ -#define DTH_TRWTWB_MAX 10 /* DDR3 =11 */ -#define DTH_TRWTTO_SHIFT 4 -#define DTH_TRWTTO_MASK 7 -#define DTH_TRWTTO_BASE 2 /* DDR3 =3 */ -#define DTH_TRWTTO_MIN 2 /* DDR3 =3 */ -#define DTH_TRWTTO_MAX 9 /* DDR3 =10 */ -#define DTH_TWTR_SHIFT 8 -#define DTH_TWTR_MASK 3 -#define DTH_TWTR_BASE 0 /* DDR3 =4 */ -#define DTH_TWTR_MIN 1 /* DDR3 =4 */ -#define DTH_TWTR_MAX 3 /* DDR3 =7 */ -#define DTH_TWRRD_SHIFT 10 -#define DTH_TWRRD_MASK 3 /* For DDR3 3_2 is at 0x78 DC */ -#define DTH_TWRRD_BASE 0 /* DDR3 =0 */ -#define DTH_TWRRD_MIN 0 /* DDR3 =2 */ -#define DTH_TWRRD_MAX 3 /* DDR3 =12 */ -#define DTH_TWRWR_SHIFT 12 -#define DTH_TWRWR_MASK 3 /* For DDR3 3_2 is at 0x78 DC */ -#define DTH_TWRWR_BASE 1 -#define DTH_TWRWR_MIN 1 /* DDR3 =3 */ -#define DTH_TWRWR_MAX 3 /* DDR3 =12 */ -#define DTH_TRDRD_SHIFT 14 -#define DTH_TRDRD_MASK 3 /* For DDR3 3_2 is at 0x78 DC */ -#define DTH_TRDRD_BASE 2 -#define DTH_TRDRD_MIN 2 -#define DTH_TRDRD_MAX 5 /* DDR3 =10 */ -#define DTH_TREF_SHIFT 16 -#define DTH_TREF_MASK 3 -#define DTH_TREF_7_8_US 2 -#define DTH_TREF_3_9_US 3 -#define DTH_DisAutoRefresh (1<<18) -#define DTH_TRFC0_SHIFT 20 /* for Logical DIMM0 */ -#define DTH_TRFC_MASK 7 -#define DTH_TRFC_75_256M 0 -#define DTH_TRFC_105_512M 1 -#define DTH_TRFC_127_5_1G 2 -#define DTH_TRFC_195_2G 3 -#define DTH_TRFC_327_5_4G 4 -#define DTH_TRFC1_SHIFT 23 /*for Logical DIMM1 */ -#define DTH_TRFC2_SHIFT 26 /*for Logical DIMM2 */ -#define DTH_TRFC3_SHIFT 29 /*for Logical DIMM3 */ - -#define DRAM_CONFIG_LOW 0x90 -#define DCL_InitDram (1<<0) -#define DCL_ExitSelfRef (1<<1) -#define DCL_PllLockTime_SHIFT 2 -#define DCL_PllLockTime_MASK 3 -#define DCL_PllLockTime_15US 0 -#define DCL_PllLockTime_6US 1 -#define DCL_DramTerm_SHIFT 4 -#define DCL_DramTerm_MASK 3 -#define DCL_DramTerm_No 0 -#define DCL_DramTerm_75_OH 1 -#define DCL_DramTerm_150_OH 2 -#define DCL_DramTerm_50_OH 3 -#define DCL_DisDqsBar (1<<6) /* only for DDR2 */ -#define DCL_DramDrvWeak (1<<7) /* only for DDR2 */ -#define DCL_ParEn (1<<8) -#define DCL_SelfRefRateEn (1<<9) /* only for DDR2 */ -#define DCL_BurstLength32 (1<<10) /* only for DDR3 */ -#define DCL_Width128 (1<<11) -#define DCL_X4Dimm_SHIFT 12 -#define DCL_X4Dimm_MASK 0xf -#define DCL_UnBuffDimm (1<<16) -#define DCL_EnPhyDqsRcvEnTr (1<<18) -#define DCL_DimmEccEn (1<<19) -#define DCL_DynPageCloseEn (1<<20) -#define DCL_IdleCycInit_SHIFT 21 -#define DCL_IdleCycInit_MASK 3 -#define DCL_IdleCycInit_16CLK 0 -#define DCL_IdleCycInit_32CLK 1 -#define DCL_IdleCycInit_64CLK 2 -#define DCL_IdleCycInit_96CLK 3 -#define DCL_ForceAutoPchg (1<<23) - -#define DRAM_CONFIG_HIGH 0x94 -#define DCH_MemClkFreq_SHIFT 0 -#define DCH_MemClkFreq_MASK 7 -#define DCH_MemClkFreq_200MHz 0 /* DDR2 */ -#define DCH_MemClkFreq_266MHz 1 /* DDR2 */ -#define DCH_MemClkFreq_333MHz 2 /* DDR2 */ -#define DCH_MemClkFreq_400MHz 3 /* DDR2 and DDR 3*/ -#define DCH_MemClkFreq_533MHz 4 /* DDR 3 */ -#define DCH_MemClkFreq_667MHz 5 /* DDR 3 */ -#define DCH_MemClkFreq_800MHz 6 /* DDR 3 */ -#define DCH_MemClkFreqVal (1<<3) -#define DCH_Ddr3Mode (1<<8) -#define DCH_LegacyBiosMode (1<<9) -#define DCH_ZqcsInterval_SHIFT 10 -#define DCH_ZqcsInterval_MASK 3 -#define DCH_ZqcsInterval_DIS 0 -#define DCH_ZqcsInterval_64MS 1 -#define DCH_ZqcsInterval_128MS 2 -#define DCH_ZqcsInterval_256MS 3 -#define DCH_RDqsEn (1<<12) /* only for DDR2 */ -#define DCH_DisSimulRdWr (1<<13) -#define DCH_DisDramInterface (1<<14) -#define DCH_PowerDownEn (1<<15) -#define DCH_PowerDownMode_SHIFT 16 -#define DCH_PowerDownMode_MASK 1 -#define DCH_PowerDownMode_Channel_CKE 0 -#define DCH_PowerDownMode_ChipSelect_CKE 1 -#define DCH_FourRankSODimm (1<<17) -#define DCH_FourRankRDimm (1<<18) -#define DCH_SlowAccessMode (1<<20) -#define DCH_BankSwizzleMode (1<<22) -#define DCH_DcqBypassMax_SHIFT 24 -#define DCH_DcqBypassMax_MASK 0xf -#define DCH_DcqBypassMax_BASE 0 -#define DCH_DcqBypassMax_MIN 0 -#define DCH_DcqBypassMax_MAX 15 -#define DCH_FourActWindow_SHIFT 28 -#define DCH_FourActWindow_MASK 0xf -#define DCH_FourActWindow_BASE 7 /* DDR3 15 */ -#define DCH_FourActWindow_MIN 8 /* DDR3 16 */ -#define DCH_FourActWindow_MAX 20 /* DDR3 30 */ - - -// for 0x98 index and 0x9c data for DCT0 -// for 0x198 index and 0x19c data for DCT1 -// even at ganged mode, 0x198/0x19c will be used for channel B - -#define DRAM_CTRL_ADDI_DATA_OFFSET 0x98 -#define DCAO_DctOffset_SHIFT 0 -#define DCAO_DctOffset_MASK 0x3fffffff -#define DCAO_DctAccessWrite (1<<30) -#define DCAO_DctAccessDone (1<<31) - -#define DRAM_CTRL_ADDI_DATA_PORT 0x9c - -#define DRAM_OUTPUT_DRV_COMP_CTRL 0x00 -#define DODCC_CkeDrvStren_SHIFT 0 -#define DODCC_CkeDrvStren_MASK 3 -#define DODCC_CkeDrvStren_1_0X 0 -#define DODCC_CkeDrvStren_1_25X 1 -#define DODCC_CkeDrvStren_1_5X 2 -#define DODCC_CkeDrvStren_2_0X 3 -#define DODCC_CsOdtDrvStren_SHIFT 4 -#define DODCC_CsOdtDrvStren_MASK 3 -#define DODCC_CsOdtDrvStren_1_0X 0 -#define DODCC_CsOdtDrvStren_1_25X 1 -#define DODCC_CsOdtDrvStren_1_5X 2 -#define DODCC_CsOdtDrvStren_2_0X 3 -#define DODCC_AddrCmdDrvStren_SHIFT 8 -#define DODCC_AddrCmdDrvStren_MASK 3 -#define DODCC_AddrCmdDrvStren_1_0X 0 -#define DODCC_AddrCmdDrvStren_1_25X 1 -#define DODCC_AddrCmdDrvStren_1_5X 2 -#define DODCC_AddrCmdDrvStren_2_0X 3 -#define DODCC_ClkDrvStren_SHIFT 12 -#define DODCC_ClkDrvStren_MASK 3 -#define DODCC_ClkDrvStren_0_75X 0 -#define DODCC_ClkDrvStren_1_0X 1 -#define DODCC_ClkDrvStren_1_25X 2 -#define DODCC_ClkDrvStren_1_5X 3 -#define DODCC_DataDrvStren_SHIFT 16 -#define DODCC_DataDrvStren_MASK 3 -#define DODCC_DataDrvStren_0_75X 0 -#define DODCC_DataDrvStren_1_0X 1 -#define DODCC_DataDrvStren_1_25X 2 -#define DODCC_DataDrvStren_1_5X 3 -#define DODCC_DqsDrvStren_SHIFT 20 -#define DODCC_DqsDrvStren_MASK 3 -#define DODCC_DqsDrvStren_0_75X 0 -#define DODCC_DqsDrvStren_1_0X 1 -#define DODCC_DqsDrvStren_1_25X 2 -#define DODCC_DqsDrvStren_1_5X 3 -#define DODCC_ProcOdt_SHIFT 28 -#define DODCC_ProcOdt_MASK 3 -#define DODCC_ProcOdt_300_OHMS 0 -#define DODCC_ProcOdt_150_OHMS 1 -#define DODCC_ProcOdt_75_OHMS 2 - -/* - for DDR2 400, 533, 667, F2x[1,0]9C_x[02:01], [03], [06:05], [07] control timing of all DIMMs - for DDR2 800, DDR3 800, 1067, 1333, 1600, F2x[1,0]9C_x[02:01], [03], [06:05], [07] control timing of DIMM0 - F2x[1,0]9C_x[102:101], [103], [106:105], [107] control timing of DIMM1 - So Socket F with Four Logical DIMM will only support DDR2 800 ? -*/ -/* there are index +100 ===> for DIMM1 -that are corresponding to 0x01, 0x02, 0x03, 0x05, 0x06, 0x07 -*/ -//02/15/2006 18:37 -#define DRAM_WRITE_DATA_TIMING_CTRL_LOW 0x01 -#define DWDTC_WrDatFineDlyByte0_SHIFT 0 -#define DWDTC_WrDatFineDlyByte_MASK 0x1f -#define DWDTC_WrDatFineDlyByte_BASE 0 -#define DWDTC_WrDatFineDlyByte_MIN 0 -#define DWDTC_WrDatFineDlyByte_MAX 31 // 1/64 MEMCLK -#define DWDTC_WrDatGrossDlyByte0_SHIFT 5 -#define DWDTC_WrDatGrossDlyByte_MASK 0x3 -#define DWDTC_WrDatGrossDlyByte_NO_DELAY 0 -#define DWDTC_WrDatGrossDlyByte_0_5_ 1 -#define DWDTC_WrDatGrossDlyByte_1 2 -#define DWDTC_WrDatFineDlyByte1_SHIFT 8 -#define DWDTC_WrDatGrossDlyByte1_SHIFT 13 -#define DWDTC_WrDatFineDlyByte2_SHIFT 16 -#define DWDTC_WrDatGrossDlyByte2_SHIFT 21 -#define DWDTC_WrDatFineDlyByte3_SHIFT 24 -#define DWDTC_WrDatGrossDlyByte3_SHIFT 29 - -#define DRAM_WRITE_DATA_TIMING_CTRL_HIGH 0x02 -#define DWDTC_WrDatFineDlyByte4_SHIFT 0 -#define DWDTC_WrDatGrossDlyByte4_SHIFT 5 -#define DWDTC_WrDatFineDlyByte5_SHIFT 8 -#define DWDTC_WrDatGrossDlyByte5_SHIFT 13 -#define DWDTC_WrDatFineDlyByte6_SHIFT 16 -#define DWDTC_WrDatGrossDlyByte6_SHIFT 21 -#define DWDTC_WrDatFineDlyByte7_SHIFT 24 -#define DWDTC_WrDatGrossDlyByte7_SHIFT 29 - -#define DRAM_WRITE_ECC_TIMING_CTRL 0x03 -#define DWETC_WrChkFinDly_SHIFT 0 -#define DWETC_WrChkGrossDly_SHIFT 5 - -#define DRAM_ADDR_CMD_TIMING_CTRL 0x04 -#define DACTC_CkeFineDelay_SHIFT 0 -#define DACTC_CkeFineDelay_MASK 0x1f -#define DACTC_CkeFineDelay_BASE 0 -#define DACTC_CkeFineDelay_MIN 0 -#define DACTC_CkeFineDelay_MAX 31 -#define DACTC_CkeSetup (1<<5) -#define DACTC_CsOdtFineDelay_SHIFT 8 -#define DACTC_CsOdtFineDelay_MASK 0x1f -#define DACTC_CsOdtFineDelay_BASE 0 -#define DACTC_CsOdtFineDelay_MIN 0 -#define DACTC_CsOdtFineDelay_MAX 31 -#define DACTC_CsOdtSetup (1<<13) -#define DACTC_AddrCmdFineDelay_SHIFT 16 -#define DACTC_AddrCmdFineDelay_MASK 0x1f -#define DACTC_AddrCmdFineDelay_BASE 0 -#define DACTC_AddrCmdFineDelay_MIN 0 -#define DACTC_AddrCmdFineDelay_MAX 31 -#define DACTC_AddrCmdSetup (1<<21) - -#define DRAM_READ_DQS_TIMING_CTRL_LOW 0x05 -#define DRDTC_RdDqsTimeByte0_SHIFT 0 -#define DRDTC_RdDqsTimeByte_MASK 0x3f -#define DRDTC_RdDqsTimeByte_BASE 0 -#define DRDTC_RdDqsTimeByte_MIN 0 -#define DRDTC_RdDqsTimeByte_MAX 63 // 1/128 MEMCLK -#define DRDTC_RdDqsTimeByte1_SHIFT 8 -#define DRDTC_RdDqsTimeByte2_SHIFT 16 -#define DRDTC_RdDqsTimeByte3_SHIFT 24 - -#define DRAM_READ_DQS_TIMING_CTRL_HIGH 0x06 -#define DRDTC_RdDqsTimeByte4_SHIFT 0 -#define DRDTC_RdDqsTimeByte5_SHIFT 8 -#define DRDTC_RdDqsTimeByte6_SHIFT 16 -#define DRDTC_RdDqsTimeByte7_SHIFT 24 - -#define DRAM_READ_DQS_ECC_TIMING_CTRL 0x07 -#define DRDETC_RdDqsTimeCheck_SHIFT 0 - -#define DRAM_PHY_CTRL 0x08 -#define DPC_WrtLvTrEn (1<<0) -#define DPC_WrtLvTrMode (1<<1) -#define DPC_TrNibbleSel (1<<2) -#define DPC_TrDimmSel_SHIFT 4 -#define DPC_TrDimmSel_MASK 3 /* 0-->dimm0, 1-->dimm1, 2--->dimm2, 3--->dimm3 */ -#define DPC_WrLvOdt_SHIFT 8 -#define DPC_WrLvOdt_MASK 0xf /* bit 0-->odt 0, ...*/ -#define DPC_WrLvODtEn (1<<12) -#define DPC_DqsRcvTrEn (1<<13) -#define DPC_DisAutoComp (1<<30) -#define DPC_AsyncCompUpdate (1<<31) - -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_0_0 0x10 //DIMM0 Channel A -#define DDRETC_DqsRcvEnFineDelayByte0_SHIFT 0 -#define DDRETC_DqsRcvEnFineDelayByte0_MASK 0x1f -#define DDRETC_DqsRcvEnGrossDelayByte0_SHIFT 5 -#define DDRETC_DqsRcvEnGrossDelayByte0_MASK 0x3 -#define DDRETC_DqsRcvEnFineDelayByte1_SHIFT 8 -#define DDRETC_DqsRcvEnGrossDelayByte1_SHIFT 13 -#define DDRETC_DqsRcvEnFineDelayByte2_SHIFT 16 -#define DDRETC_DqsRcvEnGrossDelayByte2_SHIFT 21 -#define DDRETC_DqsRcvEnFineDelayByte3_SHIFT 24 -#define DDRETC_DqsRcvEnGrossDelayByte3_SHIFT 29 - -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_0_1 0x11 //DIMM0 Channel A -#define DDRETC_DqsRcvEnFineDelayByte4_SHIFT 0 -#define DDRETC_DqsRcvEnGrossDelayByte4_SHIFT 5 -#define DDRETC_DqsRcvEnFineDelayByte5_SHIFT 8 -#define DDRETC_DqsRcvEnGrossDelayByte5_SHIFT 13 -#define DDRETC_DqsRcvEnFineDelayByte6_SHIFT 16 -#define DDRETC_DqsRcvEnGrossDelayByte6_SHIFT 21 -#define DDRETC_DqsRcvEnFineDelayByte7_SHIFT 24 -#define DDRETC_DqsRcvEnGrossDelayByte7_SHIFT 29 - -#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_0_0 0x12 -#define DDRETCE_WrChkFineDlyByte0_SHIFT 0 -#define DDRETCE_WrChkGrossDlyByte0_SHIFT 5 - -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_0_2 0x20 //DIMM0 channel B -#define DDRETC_DqsRcvEnFineDelayByte8_SHIFT 0 -#define DDRETC_DqsRcvEnGrossDelayByte8_SHIFT 5 -#define DDRETC_DqsRcvEnFineDelayByte9_SHIFT 8 -#define DDRETC_DqsRcvEnGrossDelayByte9_SHIFT 13 -#define DDRETC_DqsRcvEnFineDelayByte10_SHIFT 16 -#define DDRETC_DqsRcvEnGrossDelayByte10_SHIFT 21 -#define DDRETC_DqsRcvEnFineDelayByte11_SHIFT 24 -#define DDRETC_DqsRcvEnGrossDelayByte11_SHIFT 29 - -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_0_3 0x21 // DIMM0 Channel B -#define DDRETC_DqsRcvEnFineDelayByte12_SHIFT 0 -#define DDRETC_DqsRcvEnGrossDelayByte12_SHIFT 5 -#define DDRETC_DqsRcvEnFineDelayByte13_SHIFT 8 -#define DDRETC_DqsRcvEnGrossDelayByte13_SHIFT 13 -#define DDRETC_DqsRcvEnFineDelayByte14_SHIFT 16 -#define DDRETC_DqsRcvEnGrossDelayByte14_SHIFT 21 -#define DDRETC_DqsRcvEnFineDelayByte15_SHIFT 24 -#define DDRETC_DqsRcvEnGrossDelayByte15_SHIFT 29 - -#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_0_1 0x22 -#define DDRETCE_WrChkFineDlyByte1_SHIFT 0 -#define DDRETCE_WrChkGrossDlyByte1_SHIFT 5 - -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_1_0 0x13 //DIMM1 -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_1_1 0x14 -#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_1_0 0x15 -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_1_2 0x23 -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_1_3 0x24 -#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_1_1 0x25 - -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_2_0 0x16 // DIMM2 -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_2_1 0x17 -#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_2_0 0x18 -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_2_2 0x26 -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_2_3 0x27 -#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_2_1 0x28 - -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_3_0 0x19 // DIMM3 -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_3_1 0x1a -#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_3_0 0x1b -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_3_2 0x29 -#define DRAM_DQS_RECV_ENABLE_TIME_CTRL_3_3 0x2a -#define DRAM_DQS_RECV_ENABLE_TIMING_CTRL_ECC_3_1 0x2b - -/* 04.06.2006 19:12 */ - -#define DRAM_PHASE_RECOVERY_CTRL_0 0x50 -#define DPRC_PhRecFineDlyByte0_SHIFT 0 -#define DDWTC_PhRecFineDlyByte0_MASK 0x1f -#define DDWTC_PhRecGrossDlyByte0_SHIFT 5 -#define DDWTC_PhRecGrossDlyByte0_MASK 0x3 -#define DDWTC_PhRecFineDlyByte1_SHIFT 8 -#define DDWTC_PhRecGrossDlyByte1_SHIFT 13 -#define DDWTC_PhRecFineDlyByte2_SHIFT 16 -#define DDWTC_PhRecGrossDlyByte2_SHIFT 21 -#define DDWTC_PhRecFineDlyByte3_SHIFT 24 -#define DDWTC_PhRecGrossDlyByte3_SHIFT 29 - -#define DRAM_PHASE_RECOVERY_CTRL_1 0x51 -#define DPRC_PhRecFineDlyByte4_SHIFT 0 -#define DDWTC_PhRecGrossDlyByte4_SHIFT 5 -#define DDWTC_PhRecFineDlyByte5_SHIFT 8 -#define DDWTC_PhRecGrossDlyByte5_SHIFT 13 -#define DDWTC_PhRecFineDlyByte6_SHIFT 16 -#define DDWTC_PhRecGrossDlyByte6_SHIFT 21 -#define DDWTC_PhRecFineDlyByte7_SHIFT 24 -#define DDWTC_PhRecGrossDlyByte7_SHIFT 29 - -#define DRAM_ECC_PHASE_RECOVERY_CTRL 0x52 -#define DEPRC_PhRecEccDlyByte0_SHIFT 0 -#define DEPRC_PhRecEccGrossDlyByte0_SHIFT 5 - -#define DRAM_WRITE_LEVEL_ERROR 0x53 /* read only */ -#define DWLE_WrLvErr_SHIFT 0 -#define DWLE_WrLvErr_MASK 0xff - -#define DRAM_CTRL_MISC 0xa0 -#define DCM_MemCleared (1<<0) /* RD == F2x110 [MemCleared] */ -#define DCM_DramEnabled (1<<9) /* RD == F2x110 [DramEnabled] */ - -#define NB_TIME_STAMP_COUNT_LOW 0xb0 -#define TscLow_SHIFT 0 -#define TscLow_MASK 0xffffffff - -#define NB_TIME_STAMP_COUNT_HIGH 0xb4 -#define TscHigh_SHIFT 0 -#define TscHigh_Mask 0xff - -#define DCT_DEBUG_CTRL 0xf0 /* 0xf0 for DCT0, 0x1f0 is for DCT1*/ -#define DDC_DllAdjust_SHIFT 0 -#define DDC_DllAdjust_MASK 0xff -#define DDC_DllSlower (1<<8) -#define DDC_DllFaster (1<<9) -#define DDC_WrtDqsAdjust_SHIFT 16 -#define DDC_WrtDqsAdjust_MASK 0x7 -#define DDC_WrtDqsAdjustEn (1<<19) - -#define DRAM_CTRL_SEL_LOW 0x110 -#define DCSL_DctSelHiRngEn (1<<0) -#define DCSL_DctSelHi (1<<1) -#define DCSL_DctSelIntLvEn (1<<2) -#define DCSL_MemClrInit (1<<3) /* WR only */ -#define DCSL_DctGangEn (1<<4) -#define DCSL_DctDataIntLv (1<<5) -#define DCSL_DctSelIntLvAddr_SHIFT -#define DCSL_DctSelIntLvAddr_MASK 3 -#define DCSL_DramEnable (1<<8) /* RD only */ -#define DCSL_MemClrBusy (1<<9) /* RD only */ -#define DCSL_MemCleared (1<<10) /* RD only */ -#define DCSL_DctSelBaseAddr_47_27_SHIFT 11 -#define DCSL_DctSelBaseAddr_47_27_MASK 0x1fffff - -#define DRAM_CTRL_SEL_HIGH 0x114 -#define DCSH_DctSelBaseOffset_47_26_SHIFT 10 -#define DCSH_DctSelBaseOffset_47_26_MASK 0x3fffff - -#define MEM_CTRL_CONF_LOW 0x118 -#define MCCL_MctPriCpuRd (1<<0) -#define MCCL_MctPriCpuWr (1<<1) -#define MCCL_MctPriIsocRd_SHIFT 4 -#define MCCL_MctPriIsoc_MASK 0x3 -#define MCCL_MctPriIsocWr_SHIFT 6 -#define MCCL_MctPriIsocWe_MASK 0x3 -#define MCCL_MctPriDefault_SHIFT 8 -#define MCCL_MctPriDefault_MASK 0x3 -#define MCCL_MctPriWr_SHIFT 10 -#define MCCL_MctPriWr_MASK 0x3 -#define MCCL_MctPriIsoc_SHIFT 12 -#define MCCL_MctPriIsoc_MASK 0x3 -#define MCCL_MctPriTrace_SHIFT 14 -#define MCCL_MctPriTrace_MASK 0x3 -#define MCCL_MctPriScrub_SHIFT 16 -#define MCCL_MctPriScrub_MASK 0x3 -#define MCCL_McqMedPriByPassMax_SHIFT 20 -#define MCCL_McqMedPriByPassMax_MASK 0x7 -#define MCCL_McqHiPriByPassMax_SHIFT 24 -#define MCCL_McqHiPriByPassMax_MASK 0x7 -#define MCCL_MctVarPriCntLmt_SHIFT 28 -#define MCCL_MctVarPriCntLmt_MASK 0x7 - -#define MEM_CTRL_CONF_HIGH 0x11c -#define MCCH_DctWrLimit_SHIFT 0 -#define MCCH_DctWrLimit_MASK 0x3 -#define MCCH_MctWrLimit_SHIFT 2 -#define MCCH_MctWrLimit_MASK 0x1f -#define MCCH_MctPrefReqLimit_SHIFT 7 -#define MCCH_MctPrefReqLimit_MASK 0x1f -#define MCCH_PrefCpuDis (1<<12) -#define MCCH_PrefIoDis (1<<13) -#define MCCH_PrefIoFixStrideEn (1<<14) -#define MCCH_PrefFixStrideEn (1<<15) -#define MCCH_PrefFixDist_SHIFT 16 -#define MCCH_PrefFixDist_MASK 0x3 -#define MCCH_PrefConfSat_SHIFT 18 -#define MCCH_PrefConfSat_MASK 0x3 -#define MCCH_PrefOneConf_SHIFT 20 -#define MCCH_PrefOneConf_MASK 0x3 -#define MCCH_PrefTwoConf_SHIFT 22 -#define MCCH_PrefTwoConf_MASK 0x7 -#define MCCH_PrefThreeConf_SHIFT 25 -#define MCCH_prefThreeConf_MASK 0x7 -#define MCCH_PrefDramTrainMode (1<<28) -#define MCCH_FlushWrOnStpGnt (1<<29) -#define MCCH_FlushWr (1<<30) -#define MCCH_MctScrubEn (1<<31) - - -/* Function 3 */ -#define MCA_NB_CONTROL 0x40 -#define MNCT_CorrEccEn (1<<0) -#define MNCT_UnCorrEccEn (1<<1) -#define MNCT_CrcErr0En (1<<2) /* Link 0 */ -#define MNCT_CrcErr1En (1<<3) -#define MNCT_CrcErr2En (1<<4) -#define MBCT_SyncPkt0En (1<<5) /* Link 0 */ -#define MBCT_SyncPkt1En (1<<6) -#define MBCT_SyncPkt2En (1<<7) -#define MBCT_MstrAbrtEn (1<<8) -#define MBCT_TgtAbrtEn (1<<9) -#define MBCT_GartTblEkEn (1<<10) -#define MBCT_AtomicRMWEn (1<<11) -#define MBCT_WdogTmrRptEn (1<<12) -#define MBCT_DevErrEn (1<<13) -#define MBCT_L3ArrayCorEn (1<<14) -#define MBCT_L3ArrayUncEn (1<<15) -#define MBCT_HtProtEn (1<<16) -#define MBCT_HtDataEn (1<<17) -#define MBCT_DramParEn (1<<18) -#define MBCT_RtryHt0En (1<<19) /* Link 0 */ -#define MBCT_RtryHt1En (1<<20) -#define MBCT_RtryHt2En (1<<21) -#define MBCT_RtryHt3En (1<<22) -#define MBCT_CrcErr3En (1<<23) /* Link 3*/ -#define MBCT_SyncPkt3En (1<<24) /* Link 4 */ -#define MBCT_McaUsPwDatErrEn (1<<25) -#define MBCT_NbArrayParEn (1<<26) -#define MBCT_TblWlkDatErrEn (1<<27) -#define MBCT_FbDimmCorErrEn (1<<28) -#define MBCT_FbDimmUnCorErrEn (1<<29) - - - -#define MCA_NB_CONFIG 0x44 -#define MNC_CpuRdDatErrEn (1<<1) -#define MNC_SyncOnUcEccEn (1<<2) -#define MNC_SynvPktGenDis (1<<3) -#define MNC_SyncPktPropDis (1<<4) -#define MNC_IoMstAbortDis (1<<5) -#define MNC_CpuErrDis (1<<6) -#define MNC_IoErrDis (1<<7) -#define MNC_WdogTmrDis (1<<8) -#define MNC_WdogTmrCntSel_2_0_SHIFT 9 /* 3 is ar f3x180 */ -#define MNC_WdogTmrCntSel_2_0_MASK 0x3 -#define MNC_WdogTmrBaseSel_SHIFT 12 -#define MNC_WdogTmrBaseSel_MASK 0x3 -#define MNC_LdtLinkSel_SHIFT 14 -#define MNC_LdtLinkSel_MASK 0x3 -#define MNC_GenCrcErrByte0 (1<<16) -#define MNC_GenCrcErrByte1 (1<<17) -#define MNC_SubLinkSel_SHIFT 18 -#define MNC_SubLinkSel_MASK 0x3 -#define MNC_SyncOnWdogEn (1<<20) -#define MNC_SyncOnAnyErrEn (1<<21) -#define MNC_DramEccEn (1<<22) -#define MNC_ChipKillEccEn (1<<23) -#define MNC_IoRdDatErrEn (1<<24) -#define MNC_DisPciCfgCpuErrRsp (1<<25) -#define MNC_CorrMcaExcEn (1<<26) -#define MNC_NbMcaToMstCpuEn (1<<27) -#define MNC_DisTgtAbtCpuErrRsp (1<<28) -#define MNC_DisMstAbtCpuErrRsp (1<<29) -#define MNC_SyncOnDramAdrParErrEn (1<<30) -#define MNC_NbMcaLogEn (1<<31) - -#define MCA_NB_STATUS_LOW 0x48 -#define MNSL_ErrorCode_SHIFT 0 -#define MNSL_ErrorCode_MASK 0xffff -#define MNSL_ErrorCodeExt_SHIFT 16 -#define MNSL_ErrorCodeExt_MASK 0x1f -#define MNSL_Syndrome_15_8_SHIFT 24 -#define MNSL_Syndrome_15_8_MASK 0xff - -#define MCA_NB_STATUS_HIGH 0x4c -#define MNSH_ErrCPU_SHIFT 0 -#define MNSH_ErrCPU_MASK 0xf -#define MNSH_LDTLink_SHIFT 4 -#define MNSH_LDTLink_MASK 0xf -#define MNSH_ErrScrub (1<<8) -#define MNSH_SubLink (1<<9) -#define MNSH_McaStatusSubCache_SHIFT 10 -#define MNSH_McaStatusSubCache_MASK 0x3 -#define MNSH_Deffered (1<<12) -#define MNSH_UnCorrECC (1<<13) -#define MNSH_CorrECC (1<<14) -#define MNSH_Syndrome_7_0_SHIFT 15 -#define MNSH_Syndrome_7_0_MASK 0xff -#define MNSH_PCC (1<<25) -#define MNSH_ErrAddrVal (1<<26) -#define MNSH_ErrMiscVal (1<<27) -#define MNSH_ErrEn (1<<28) -#define MNSH_ErrUnCorr (1<<29) -#define MNSH_ErrOver (1<<30) -#define MNSH_ErrValid (1<<31) - -#define MCA_NB_ADDR_LOW 0x50 -#define MNAL_ErrAddr_31_1_SHIFT 1 -#define MNAL_ErrAddr_31_1_MASK 0x7fffffff - -#define MCA_NB_ADDR_HIGH 0x54 -#define MNAL_ErrAddr_47_32_SHIFT 0 -#define MNAL_ErrAddr_47_32_MASK 0xffff - -#define DRAM_SCRUB_RATE_CTRL 0x58 -#define SCRUB_NONE 0 -#define SCRUB_40ns 1 -#define SCRUB_80ns 2 -#define SCRUB_160ns 3 -#define SCRUB_320ns 4 -#define SCRUB_640ns 5 -#define SCRUB_1_28us 6 -#define SCRUB_2_56us 7 -#define SCRUB_5_12us 8 -#define SCRUB_10_2us 9 -#define SCRUB_20_5us 0xa -#define SCRUB_41_0us 0xb -#define SCRUB_81_9us 0xc -#define SCRUB_163_8us 0xd -#define SCRUB_327_7us 0xe -#define SCRUB_655_4us 0xf -#define SCRUB_1_31ms 0x10 -#define SCRUB_2_62ms 0x11 -#define SCRUB_5_24ms 0x12 -#define SCRUB_10_49ms 0x13 -#define SCRUB_20_97ms 0x14 -#define SCRUB_42ms 0x15 -#define SCRUB_84ms 0x16 -#define DSRC_DramScrub_SHFIT 0 -#define DSRC_DramScrub_MASK 0x1f -#define DSRC_L2Scrub_SHIFT 8 -#define DSRC_L2Scrub_MASK 0x1f -#define DSRC_DcacheScrub_SHIFT 16 -#define DSRC_DcacheScrub_MASK 0x1f -#define DSRC_L3Scrub_SHIFT 24 -#define DSRC_L3Scrub_MASK 0x1f - -#define DRAM_SCRUB_ADDR_LOW 0x5C -#define DSAL_ScrubReDirEn (1<<0) -#define DSAL_ScrubAddrLo_SHIFT 6 -#define DSAL_ScrubAddrLo_MASK 0x3ffffff - -#define DRAM_SCRUB_ADDR_HIGH 0x60 -#define DSAH_ScrubAddrHi_SHIFT 0 -#define DSAH_ScrubAddrHi_MASK 0xffff - -#define HW_THERMAL_CTRL 0x64 - -#define SW_THERMAL_CTRL 0x68 - -#define DATA_BUF_CNT 0x6c - -#define SRI_XBAR_CMD_BUF_CNT 0x70 - -#define XBAR_SRI_CMD_BUF_CNT 0x74 - -#define MCT_XBAR_CMD_BUF_CNT 0x78 - -#define ACPI_PWR_STATE_CTRL 0x80 /* till 0x84 */ - -#define NB_CONFIG_LOW 0x88 -#define NB_CONFIG_HIGH 0x8c - -#define GART_APERTURE_CTRL 0x90 - -#define GART_APERTURE_BASE 0x94 - -#define GART_TBL_BASE 0x98 - -#define GART_CACHE_CTRL 0x9c - -#define PWR_CTRL_MISC 0xa0 - -#define RPT_TEMP_CTRL 0xa4 - -#define ON_LINE_SPARE_CTRL 0xb0 - -#define SBI_P_STATE_LIMIT 0xc4 - -#define CLK_PWR_TIMING_CTRL0 0xd4 -#define CLK_PWR_TIMING_CTRL1 0xd8 -#define CLK_PWR_TIMING_CTRL2 0xdc - -#define THERMTRIP_STATUS 0xE4 - - -#define NORTHBRIDGE_CAP 0xE8 -#define NBCAP_TwoChanDRAMcap (1 << 0) -#define NBCAP_DualNodeMPcap (1 << 1) -#define NBCAP_EightNodeMPcap (1 << 2) -#define NBCAP_ECCcap (1 << 3) -#define NBCAP_ChipkillECCcap (1 << 4) -#define NBCAP_DdrMaxRate_SHIFT 5 -#define NBCAP_DdrMaxRate_MASK 7 -#define NBCAP_DdrMaxRate_400 7 -#define NBCAP_DdrMaxRate_533 6 -#define NBCAP_DdrMaxRate_667 5 -#define NBCAP_DdrMaxRate_800 4 -#define NBCAP_DdrMaxRate_1067 3 -#define NBCAP_DdrMaxRate_1333 2 -#define NBCAP_DdrMaxRate_1600 1 -#define NBCAP_DdrMaxRate_3_2G 6 -#define NBCAP_DdrMaxRate_4_0G 5 -#define NBCAP_DdrMaxRate_4_8G 4 -#define NBCAP_DdrMaxRate_6_4G 3 -#define NBCAP_DdrMaxRate_8_0G 2 -#define NBCAP_DdrMaxRate_9_6G 1 -#define NBCAP_Mem_ctrl_cap (1 << 8) -#define MBCAP_SVMCap (1<<9) -#define NBCAP_HtcCap (1<<10) -#define NBCAP_CmpCap_SHIFT 12 -#define NBCAP_CmpCap_MASK 3 -#define NBCAP_MpCap_SHIFT 16 -#define NBCAP_MpCap_MASK 7 -#define NBCAP_MpCap_1N 7 -#define NBCAP_MpCap_2N 6 -#define NBCAP_MpCap_4N 5 -#define NBCAP_MpCap_8N 4 -#define NBCAP_MpCap_32N 0 -#define NBCAP_UnGangEn_SHIFT 20 -#define NBCAP_UnGangEn_MASK 0xf -#define NBCAP_L3Cap (1<<25) -#define NBCAP_HtAcCap (1<<26) - -/* 04/04/2006 18:00 */ - -#define EXT_NB_MCA_CTRL 0x180 - -#define NB_EXT_CONF 0x188 -#define DOWNCORE_CTRL 0x190 -#define DWNCC_DisCore_SHIFT 0 -#define DWNCC_DisCore_MASK 0xf - -/* Function 5 for FBDIMM */ -#define FBD_DRAM_TIMING_LOW - -#define LinkConnected (1 << 0) -#define InitComplete (1 << 1) -#define NonCoherent (1 << 2) -#define ConnectionPending (1 << 4) - -// Use the LAPIC timer count register to hold each core's init status -// Format: byte 0 - state -// byte 1 - fid_max -// byte 2 - nb_cof_vid_update -// byte 3 - apic id - -#define LAPIC_MSG_REG 0x380 -#define F10_APSTATE_STARTED 0x13 // start of AP execution -#define F10_APSTATE_ASLEEP 0x14 // AP sleeping -#define F10_APSTATE_STOPPED 0x15 // allow AP to stop -#define F10_APSTATE_RESET 0x01 // waiting for warm reset - -#define MAX_CORES_SUPPORTED 128 - -#include "nums.h" - -#if NODE_NUMS == 64 - #define NODE_PCI(x, fn) ((x < 32)?(PCI_DEV(CONFIG_CBB,(CONFIG_CDB+x),fn)):(PCI_DEV((CONFIG_CBB-1),(CONFIG_CDB+x-32),fn))) -#else - #define NODE_PCI(x, fn) PCI_DEV(CONFIG_CBB,(CONFIG_CDB+x),fn) -#endif - -/* Include wrapper for MCT (works for DDR2 or DDR3) */ -#include <northbridge/amd/amdmct/wrappers/mcti.h> - -struct link_pair_t { - pci_devfn_t udev; - u32 upos; - u32 uoffs; - pci_devfn_t dev; - u32 pos; - u32 offs; - u8 host; - u8 nodeid; - u8 linkn; - u8 rsv; -} __packed; - -struct nodes_info_t { - u32 nodes_in_group; // could be 2, 3, 4, 5, 6, 7, 8 - u32 groups_in_plane; // could be 1, 2, 3, 4, 5 - u32 planes; // could be 1, 2 - u32 up_planes; // down planes will be [up_planes, planes) -} __packed; - -struct ht_link_config { - uint32_t ht_speed_limit; // Speed in MHz; 0 for autodetect (default) -}; - -/* be careful with the alignment of sysinfo, bacause sysinfo may be shared by coreboot_car and ramstage stage. and ramstage may be running at 64bit later.*/ - -struct sys_info { - int32_t needs_reset; - - u8 ln[NODE_NUMS*NODE_NUMS];// [0, 3] link n, [4, 7] will be hop num - u16 ln_tn[NODE_NUMS*8]; // for 0x0zzz: bit [0,7] target node num, bit[8,11] respone link from target num; 0x80ff mean not inited, 0x4yyy mean non coherent and yyy is link pair index - struct nodes_info_t nodes_info; - u32 nodes; - - u8 host_link_freq[NODE_NUMS*8]; // record freq for every link from cpu, 0x0f means don't need to touch it - u16 host_link_freq_cap[NODE_NUMS*8]; //cap - - struct ht_link_config ht_link_cfg; - - u32 segbit; - u32 sbdn; - u32 sblk; - u32 sbbusn; - - u32 ht_c_num; - u32 ht_c_conf_bus[HC_NUMS]; // 4-->32 - - struct link_pair_t link_pair[HC_NUMS*4];// enough? only in_conherent, 32 chain and every chain have 4 HT device - u32 link_pair_num; - - struct mem_controller ctrl[NODE_NUMS]; - - struct MCTStatStruc MCTstat; - struct DCTStatStruc DCTstatA[NODE_NUMS]; -} __packed; - -struct device *get_node_pci(u32 nodeid, u32 fn); - -void showallroutes(int level, pci_devfn_t dev); - -void setup_resource_map_offset(const u32 *register_values, u32 max, u32 - offset_pci_dev, u32 offset_io_base); - -void setup_resource_map_x_offset(const u32 *register_values, u32 max, u32 - offset_pci_dev, u32 offset_io_base); - -void setup_resource_map_x(const u32 *register_values, u32 max); -void setup_resource_map(const u32 *register_values, u32 max); -void setup_mb_resource_map(void); - -/* reset_test.c */ -u32 cpu_init_detected(u8 nodeid); -u32 bios_reset_detected(void); -u32 cold_reset_detected(void); -u32 other_reset_detected(void); -u32 warm_reset_detect(u8 nodeid); -void distinguish_cpu_resets(u8 nodeid); -u32 get_sblk(void); -u8 get_sbbusn(u8 sblk); -void set_bios_reset(void); - -#include "northbridge/amd/amdht/porting.h" -BOOL AMD_CB_ManualBUIDSwapList(u8 Node, u8 Link, const u8 **List); - -struct acpi_rsdp; - -unsigned long northbridge_write_acpi_tables(struct device *device, - unsigned long start, - struct acpi_rsdp *rsdp); -void northbridge_acpi_write_vars(struct device *device); - -#endif /* AMDFAM10_H */ diff --git a/src/northbridge/amd/amdfam10/amdfam10_util.asl b/src/northbridge/amd/amdfam10/amdfam10_util.asl deleted file mode 100644 index 6e2118d1ae..0000000000 --- a/src/northbridge/amd/amdfam10/amdfam10_util.asl +++ /dev/null @@ -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) - } -} diff --git a/src/northbridge/amd/amdfam10/amdfam10_util.c b/src/northbridge/amd/amdfam10/amdfam10_util.c deleted file mode 100644 index 23e92323a8..0000000000 --- a/src/northbridge/amd/amdfam10/amdfam10_util.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdfam10/bootblock.c b/src/northbridge/amd/amdfam10/bootblock.c deleted file mode 100644 index f2d5f89ec7..0000000000 --- a/src/northbridge/amd/amdfam10/bootblock.c +++ /dev/null @@ -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(); -} diff --git a/src/northbridge/amd/amdfam10/chip.h b/src/northbridge/amd/amdfam10/chip.h deleted file mode 100644 index daf429d91a..0000000000 --- a/src/northbridge/amd/amdfam10/chip.h +++ /dev/null @@ -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_ */ diff --git a/src/northbridge/amd/amdfam10/debug.c b/src/northbridge/amd/amdfam10/debug.c deleted file mode 100644 index 5090352e9a..0000000000 --- a/src/northbridge/amd/amdfam10/debug.c +++ /dev/null @@ -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 -} diff --git a/src/northbridge/amd/amdfam10/debug.h b/src/northbridge/amd/amdfam10/debug.h deleted file mode 100644 index 01d87d96af..0000000000 --- a/src/northbridge/amd/amdfam10/debug.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdfam10/early_ht.c b/src/northbridge/amd/amdfam10/early_ht.c deleted file mode 100644 index dc0f6840e2..0000000000 --- a/src/northbridge/amd/amdfam10/early_ht.c +++ /dev/null @@ -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 -} diff --git a/src/northbridge/amd/amdfam10/early_ht.h b/src/northbridge/amd/amdfam10/early_ht.h deleted file mode 100644 index 67476fd849..0000000000 --- a/src/northbridge/amd/amdfam10/early_ht.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdfam10/get_pci1234.c b/src/northbridge/amd/amdfam10/get_pci1234.c deleted file mode 100644 index 94ec831d65..0000000000 --- a/src/northbridge/amd/amdfam10/get_pci1234.c +++ /dev/null @@ -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); diff --git a/src/northbridge/amd/amdfam10/ht_config.c b/src/northbridge/amd/amdfam10/ht_config.c deleted file mode 100644 index 8499dbb623..0000000000 --- a/src/northbridge/amd/amdfam10/ht_config.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2007 Advanced Micro Devices, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <stdint.h> -#include <console/console.h> -#include <device/device.h> -#include <device/pci_ops.h> - -#include <cpu/amd/amdfam10_sysconf.h> -#include "northbridge.h" -#include "amdfam10.h" -#include "ht_config.h" - -struct dram_base_mask_t get_dram_base_mask(u32 nodeid) -{ - struct dram_base_mask_t d; - struct device *dev = __f1_dev[0]; - - u32 temp; - temp = pci_read_config32(dev, 0x44 + (nodeid << 3)); //[39:24] at [31:16] - d.mask = ((temp & 0xfff80000)>>(8+3)); // mask out DramMask [26:24] too - temp = pci_read_config32(dev, 0x144 + (nodeid <<3)) & 0xff; //[47:40] at [7:0] - d.mask |= temp<<21; - - temp = pci_read_config32(dev, 0x40 + (nodeid << 3)); //[39:24] at [31:16] - d.mask |= (temp & 1); // enable bit - - d.base = ((temp & 0xfff80000)>>(8+3)); // mask out DramBase [26:24) too - temp = pci_read_config32(dev, 0x140 + (nodeid <<3)) & 0xff; //[47:40] at [7:0] - d.base |= temp<<21; - return d; -} - -void set_config_map_reg(struct bus *link) -{ - u32 tempreg; - u32 i; - u32 ht_c_index = get_ht_c_index(link); - u32 linkn = link->link_num & 0x0f; - u32 busn_min = (link->secondary >> sysconf.segbit) & 0xff; - u32 busn_max = (link->subordinate >> sysconf.segbit) & 0xff; - u32 nodeid = amdfam10_nodeid(link->dev); - - tempreg = ((nodeid & 0x30) << (12-4)) | ((nodeid & 0xf) << 4) | 3; - tempreg |= (busn_max << 24)|(busn_min << 16)|(linkn << 8); - - for (i = 0; i < sysconf.nodes; i++) { - struct device *dev = __f1_dev[i]; - pci_write_config32(dev, 0xe0 + ht_c_index * 4, tempreg); - } -} - -void clear_config_map_reg(struct bus *link) -{ - u32 i; - u32 ht_c_index = get_ht_c_index(link); - - for (i = 0; i < sysconf.nodes; i++) { - struct device *dev = __f1_dev[i]; - pci_write_config32(dev, 0xe0 + ht_c_index * 4, 0); - } -} - - -static u32 ht_c_key(struct bus *link) -{ - u32 nodeid = amdfam10_nodeid(link->dev); - u32 linkn = link->link_num & 0x0f; - u32 val = (linkn << 8) | ((nodeid & 0x3f) << 2) | 3; - return val; -} - -static u32 get_ht_c_index_by_key(u32 key, sys_info_conf_t *sysinfo) -{ - u32 ht_c_index = 0; - - for (ht_c_index = 0; ht_c_index < 32; ht_c_index++) { - if ((sysinfo->ht_c_conf_bus[ht_c_index] & 0xfff) == key) { - return ht_c_index; - } - } - - for (ht_c_index = 0; ht_c_index < 32; ht_c_index++) { - if (sysinfo->ht_c_conf_bus[ht_c_index] == 0) { - return ht_c_index; - } - } - - return -1; -} - -u32 get_ht_c_index(struct bus *link) -{ - u32 val = ht_c_key(link); - return get_ht_c_index_by_key(val, &sysconf); -} - -void store_ht_c_conf_bus(struct bus *link) -{ - u32 val = ht_c_key(link); - u32 ht_c_index = get_ht_c_index_by_key(val, &sysconf); - - u32 segn = (link->subordinate >> 8) & 0x0f; - u32 busn_min = link->secondary & 0xff; - u32 busn_max = link->subordinate & 0xff; - - val |= (segn << 28) | (busn_max << 20) | (busn_min << 12); - - sysconf.ht_c_conf_bus[ht_c_index] = val; - sysconf.hcdn_reg[ht_c_index] = link->hcdn_reg; - sysconf.ht_c_num++; -} - -u32 get_io_addr_index(u32 nodeid, u32 linkn) -{ - u32 index; - - for (index = 0; index < 256; index++) { - - if (index + 4 >= ARRAY_SIZE(sysconf.conf_io_addrx)) - die("Error! Out of bounds read in %s:%s\n", __FILE__, __func__); - - if (sysconf.conf_io_addrx[index+4] == 0) { - sysconf.conf_io_addr[index+4] = (nodeid & 0x3f); - sysconf.conf_io_addrx[index+4] = 1 | ((linkn & 0x7)<<4); - return index; - } - } - - return 0; -} - -u32 get_mmio_addr_index(u32 nodeid, u32 linkn) -{ - u32 index; - - for (index = 0; index < 64; index++) { - - if (index + 8 >= ARRAY_SIZE(sysconf.conf_mmio_addrx)) - die("Error! Out of bounds read in %s:%s\n", __FILE__, __func__); - - if (sysconf.conf_mmio_addrx[index+8] == 0) { - sysconf.conf_mmio_addr[index+8] = (nodeid & 0x3f); - sysconf.conf_mmio_addrx[index+8] = 1 | ((linkn & 0x7)<<4); - return index; - } - } - - return 0; -} - - -void store_conf_io_addr(u32 nodeid, u32 linkn, u32 reg, u32 index, - u32 io_min, u32 io_max) -{ - u32 val; - - /* io range allocation */ - index = (reg-0xc0)>>3; - - val = (nodeid & 0x3f); // 6 bits used - sysconf.conf_io_addr[index] = val | ((io_max<<8) & 0xfffff000); //limit : with nodeid - val = 3 | ((linkn & 0x7)<<4); // 8 bits used - sysconf.conf_io_addrx[index] = val | ((io_min<<8) & 0xfffff000); // base : with enable bit - - if (sysconf.io_addr_num < (index+1)) - sysconf.io_addr_num = index+1; -} - - -void store_conf_mmio_addr(u32 nodeid, u32 linkn, u32 reg, u32 index, - u32 mmio_min, u32 mmio_max) -{ - u32 val; - - /* io range allocation */ - index = (reg-0x80)>>3; - - val = (nodeid & 0x3f); // 6 bits used - sysconf.conf_mmio_addr[index] = val | (mmio_max & 0xffffff00); //limit : with nodeid and linkn - val = 3 | ((linkn & 0x7)<<4); // 8 bits used - sysconf.conf_mmio_addrx[index] = val | (mmio_min & 0xffffff00); // base : with enable bit - - if (sysconf.mmio_addr_num<(index+1)) - sysconf.mmio_addr_num = index+1; -} - - -void set_io_addr_reg(struct device *dev, u32 nodeid, u32 linkn, u32 reg, - u32 io_min, u32 io_max) -{ - u32 i; - u32 tempreg; - - /* io range allocation */ - tempreg = (nodeid&0xf) | ((nodeid & 0x30)<<(8-4)) | (linkn<<4) | ((io_max&0xf0)<<(12-4)); //limit - for (i = 0; i < sysconf.nodes; i++) - pci_write_config32(__f1_dev[i], reg+4, tempreg); - - tempreg = 3 /*| (3<<4)*/ | ((io_min&0xf0)<<(12-4)); //base :ISA and VGA ? - for (i = 0; i < sysconf.nodes; i++) - pci_write_config32(__f1_dev[i], reg, tempreg); -} - -void set_mmio_addr_reg(u32 nodeid, u32 linkn, u32 reg, u32 index, u32 mmio_min, u32 mmio_max, u32 nodes) -{ - u32 i; - u32 tempreg; - - /* io range allocation */ - tempreg = (nodeid&0xf) | (linkn<<4) | (mmio_max&0xffffff00); //limit - for (i = 0; i < nodes; i++) - pci_write_config32(__f1_dev[i], reg+4, tempreg); - tempreg = 3 | (nodeid & 0x30) | (mmio_min&0xffffff00); - for (i = 0; i < sysconf.nodes; i++) - pci_write_config32(__f1_dev[i], reg, tempreg); -} diff --git a/src/northbridge/amd/amdfam10/ht_config.h b/src/northbridge/amd/amdfam10/ht_config.h deleted file mode 100644 index 748a9818c1..0000000000 --- a/src/northbridge/amd/amdfam10/ht_config.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdfam10/inline_helper.c b/src/northbridge/amd/amdfam10/inline_helper.c deleted file mode 100644 index 7f260318f7..0000000000 --- a/src/northbridge/amd/amdfam10/inline_helper.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdfam10/link_control.c b/src/northbridge/amd/amdfam10/link_control.c deleted file mode 100644 index 384772374b..0000000000 --- a/src/northbridge/amd/amdfam10/link_control.c +++ /dev/null @@ -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, -}; diff --git a/src/northbridge/amd/amdfam10/misc_control.c b/src/northbridge/amd/amdfam10/misc_control.c deleted file mode 100644 index b0a1ab679a..0000000000 --- a/src/northbridge/amd/amdfam10/misc_control.c +++ /dev/null @@ -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, -}; diff --git a/src/northbridge/amd/amdfam10/nb_control.c b/src/northbridge/amd/amdfam10/nb_control.c deleted file mode 100644 index a9bdb18415..0000000000 --- a/src/northbridge/amd/amdfam10/nb_control.c +++ /dev/null @@ -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, -}; diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c deleted file mode 100644 index df1d947cdb..0000000000 --- a/src/northbridge/amd/amdfam10/northbridge.c +++ /dev/null @@ -1,1928 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2016 Damien Zammit <damien@zamaudio.com> - * Copyright (C) 2015 - 2017 Timothy Pearson <tpearson@raptorengineering.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 <device/pci_ops.h> -#include <stdint.h> -#include <device/device.h> -#include <device/pci.h> -#include <device/pci_ids.h> -#include <device/hypertransport.h> -#include <stdlib.h> -#include <string.h> -#include <lib.h> -#include <smbios.h> -#include <cpu/cpu.h> -#include <delay.h> -#include <cpu/x86/lapic.h> -#include <cpu/x86/cache.h> -#include <cpu/amd/mtrr.h> -#include <cpu/amd/amdfam10_sysconf.h> -#include <cpu/amd/msr.h> -#include <cpu/amd/family_10h-family_15h/ram_calc.h> -#include <types.h> - -#if CONFIG(LOGICAL_CPUS) -#include <cpu/amd/multicore.h> -#include <pc80/mc146818rtc.h> -#endif - -#include "northbridge.h" -#include "amdfam10.h" -#include "ht_config.h" -#include "chip.h" - -#if CONFIG_HW_MEM_HOLE_SIZEK != 0 -#include <cpu/amd/model_10xxx_rev.h> -#endif - -#if CONFIG(DIMM_DDR3) -#include "../amdmct/mct_ddr3/s3utils.h" -#endif - -struct amdfam10_sysconf_t sysconf; -u8 pirq_router_bus; - -#define FX_DEVS NODE_NUMS -static struct device *__f0_dev[FX_DEVS]; -struct device *__f1_dev[FX_DEVS]; -static struct device *__f2_dev[FX_DEVS]; -static struct device *__f4_dev[FX_DEVS]; -static unsigned int fx_devs = 0; - -struct device *get_node_pci(u32 nodeid, u32 fn) -{ -#if NODE_NUMS + CONFIG_CDB >= 32 - if ((CONFIG_CDB + nodeid) < 32) { - return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB + nodeid, fn)); - } else { - return dev_find_slot(CONFIG_CBB-1, PCI_DEVFN(CONFIG_CDB + nodeid - 32, fn)); - } - -#else - return dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB + nodeid, fn)); -#endif -} - -static void get_fx_devs(void) -{ - int i; - for (i = 0; i < FX_DEVS; i++) { - __f0_dev[i] = get_node_pci(i, 0); - __f1_dev[i] = get_node_pci(i, 1); - __f2_dev[i] = get_node_pci(i, 2); - __f4_dev[i] = get_node_pci(i, 4); - if (__f0_dev[i] != NULL && __f1_dev[i] != NULL) - fx_devs = i+1; - } - if (__f1_dev[0] == NULL || __f0_dev[0] == NULL || fx_devs == 0) { - die("Cannot find 0:0x18.[0|1]\n"); - } -} - -static u32 f1_read_config32(unsigned int reg) -{ - if (fx_devs == 0) - get_fx_devs(); - return pci_read_config32(__f1_dev[0], reg); -} - -static void f1_write_config32(unsigned int reg, u32 value) -{ - int i; - if (fx_devs == 0) - get_fx_devs(); - for (i = 0; i < fx_devs; i++) { - struct device *dev; - dev = __f1_dev[i]; - if (dev && dev->enabled) { - pci_write_config32(dev, reg, value); - } - } -} - -u32 amdfam10_nodeid(struct device *dev) -{ -#if NODE_NUMS == 64 - unsigned int busn; - busn = dev->bus->secondary; - if (busn != CONFIG_CBB) { - return (dev->path.pci.devfn >> 3) - CONFIG_CDB + 32; - } else { - return (dev->path.pci.devfn >> 3) - CONFIG_CDB; - } - -#else - return (dev->path.pci.devfn >> 3) - CONFIG_CDB; -#endif -} - -static void set_vga_enable_reg(u32 nodeid, u32 linkn) -{ - u32 val; - - val = 1 | (nodeid<<4) | (linkn<<12); - /* it will routing (1)mmio 0xa0000:0xbffff (2) io 0x3b0:0x3bb, - 0x3c0:0x3df */ - f1_write_config32(0xf4, val); - -} - -typedef enum { - HT_ROUTE_CLOSE, - HT_ROUTE_SCAN, - HT_ROUTE_FINAL, -} scan_state; - -static void ht_route_link(struct bus *link, scan_state mode) -{ - struct bus *parent = link->dev->bus; - u32 busses; - - if (mode == HT_ROUTE_SCAN) { - if (parent->subordinate == 0) - link->secondary = 0; - else - link->secondary = parent->subordinate + 1; - - link->subordinate = link->secondary; - } - - /* Configure the bus numbers for this bridge: the configuration - * transactions will not be propagated by the bridge if it is - * not correctly configured - */ - busses = pci_read_config32(link->dev, link->cap + 0x14); - busses &= ~(0xff << 8); - busses |= parent->secondary & 0xff; - if (mode == HT_ROUTE_CLOSE) - busses |= 0xff << 8; - else if (mode == HT_ROUTE_SCAN) - busses |= ((u32) link->secondary & 0xff) << 8; - else if (mode == HT_ROUTE_FINAL) - busses |= ((u32) link->secondary & 0xff) << 8; - pci_write_config32(link->dev, link->cap + 0x14, busses); - - if (mode == HT_ROUTE_FINAL) { - if (CONFIG(HT_CHAIN_DISTRIBUTE)) - parent->subordinate = ALIGN_UP(link->subordinate, 8) - 1; - else - parent->subordinate = link->subordinate; - } -} - -static void amd_g34_fixup(struct bus *link, struct device *dev) -{ - uint32_t nodeid = amdfam10_nodeid(dev); - uint8_t rev_gte_d = 0; - uint8_t dual_node = 0; - uint32_t f3xe8; - - if (cpuid_eax(0x80000001) >= 0x8) - /* Revision D or later */ - rev_gte_d = 1; - - if (rev_gte_d || is_fam15h()) { - f3xe8 = pci_read_config32(get_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 BKDG Rev 3.62 section 2.7.1.5 for details. - */ - f3xe8 = pci_read_config32(get_node_pci(nodeid, 3), 0xe8); - uint8_t internal_node_number = ((f3xe8 & 0xc0000000) >> 30); - if (internal_node_number == 0) { - /* Node 0 */ - if (link->link_num == 6) /* Link 2 Sublink 1 */ - printk(BIOS_DEBUG, "amdfam10_scan_chain(): node %d (internal node ID %d): skipping defective HT link\n", nodeid, internal_node_number); - } else { - /* Node 1 */ - if (link->link_num == 5) /* Link 1 Sublink 1 */ - printk(BIOS_DEBUG, "amdfam10_scan_chain(): node %d (internal node ID %d): skipping defective HT link\n", nodeid, internal_node_number); - } - } - } -} - -static void amdfam10_scan_chain(struct bus *link) -{ - unsigned int next_unitid; - - /* See if there is an available configuration space mapping - * register in function 1. - */ - if (get_ht_c_index(link) >= 4) - return; - - /* Set up the primary, secondary and subordinate bus numbers. - * We have no idea how many busses are behind this bridge yet, - * so we set the subordinate bus number to 0xff for the moment. - */ - - ht_route_link(link, HT_ROUTE_SCAN); - - /* set the config map space */ - set_config_map_reg(link); - - /* Now we can scan all of the subordinate busses i.e. the - * chain on the hypertranport link - */ - - next_unitid = hypertransport_scan_chain(link); - - /* Now that nothing is overlapping it is safe to scan the children. */ - pci_scan_bus(link, 0x00, ((next_unitid - 1) << 3) | 7); - - ht_route_link(link, HT_ROUTE_FINAL); - - /* We know the number of busses behind this bridge. Set the - * subordinate bus number to it's real value - */ - if (0) { - /* Clear the extend reg. */ - clear_config_map_reg(link); - } - - set_config_map_reg(link); - - store_ht_c_conf_bus(link); -} - -/* Do sb ht chain at first, in case s2885 put sb chain - * (8131/8111) on link2, but put 8151 on link0. - */ -static void relocate_sb_ht_chain(void) -{ - struct device *dev; - struct bus *link, *prev = NULL; - u8 sblink; - - dev = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 0)); - sblink = (pci_read_config32(dev, 0x64)>>8) & 7; - link = dev->link_list; - - while (link) { - if (link->link_num == sblink) { - if (!prev) - return; - prev->next = link->next; - link->next = dev->link_list; - dev->link_list = link; - return; - } - prev = link; - link = link->next; - } -} - -static void trim_ht_chain(struct device *dev) -{ - struct bus *link; - - /* Check for connected link. */ - for (link = dev->link_list; link; link = link->next) { - link->cap = 0x80 + (link->link_num * 0x20); - link->ht_link_up = ht_is_non_coherent_link(link); - } -} - -static void amdfam10_scan_chains(struct device *dev) -{ - struct bus *link; - -#if CONFIG(CPU_AMD_SOCKET_G34_NON_AGESA) - if (is_fam15h()) { - uint8_t current_link_number = 0; - - for (link = dev->link_list; link; link = link->next) { - /* The following links have changed position in Fam15h G34 processors: - * Fam10 Fam15 - * Node 0 - * L3 --> L1 - * L0 --> L3 - * L1 --> L2 - * L2 --> L0 - * Node 1 - * L0 --> L0 - * L1 --> L3 - * L2 --> L1 - * L3 --> L2 - */ - if (link->link_num == 0) - link->link_num = 3; - else if (link->link_num == 1) - link->link_num = 2; - else if (link->link_num == 2) - link->link_num = 0; - else if (link->link_num == 3) - link->link_num = 1; - else if (link->link_num == 5) - link->link_num = 7; - else if (link->link_num == 6) - link->link_num = 5; - else if (link->link_num == 7) - link->link_num = 6; - - current_link_number++; - if (current_link_number > 3) - current_link_number = 0; - } - } -#endif - - /* Do sb ht chain at first, in case s2885 put sb chain (8131/8111) on link2, but put 8151 on link0 */ - trim_ht_chain(dev); - - for (link = dev->link_list; link; link = link->next) { - if (link->ht_link_up) { - if (CONFIG(CPU_AMD_MODEL_10XXX)) - amd_g34_fixup(link, dev); - amdfam10_scan_chain(link); - } - } -} - - -static int reg_useable(unsigned int reg, struct device *goal_dev, unsigned int goal_nodeid, - unsigned int goal_link) -{ - struct resource *res; - unsigned int nodeid, link = 0; - int result; - res = 0; - for (nodeid = 0; !res && (nodeid < fx_devs); nodeid++) { - struct device *dev; - dev = __f0_dev[nodeid]; - if (!dev) - continue; - for (link = 0; !res && (link < 8); link++) { - res = probe_resource(dev, IOINDEX(0x1000 + reg, link)); - } - } - result = 2; - if (res) { - result = 0; - if ( (goal_link == (link - 1)) && - (goal_nodeid == (nodeid - 1)) && - (res->flags <= 1)) { - result = 1; - } - } - return result; -} - -static struct resource *amdfam10_find_iopair(struct device *dev, unsigned int nodeid, unsigned int link) -{ - struct resource *resource; - u32 free_reg, reg; - resource = 0; - free_reg = 0; - for (reg = 0xc0; reg <= 0xd8; reg += 0x8) { - int result; - result = reg_useable(reg, dev, nodeid, link); - if (result == 1) { - /* I have been allocated this one */ - break; - } else if (result > 1) { - /* I have a free register pair */ - free_reg = reg; - } - } - if (reg > 0xd8) { - reg = free_reg; // if no free, the free_reg still be 0 - } - - //Ext conf space - if (!reg) { - //because of Extend conf space, we will never run out of reg, but we need one index to differ them. so same node and same link can have multi range - u32 index = get_io_addr_index(nodeid, link); - reg = 0x110+ (index<<24) + (4<<20); // index could be 0, 255 - } - - resource = new_resource(dev, IOINDEX(0x1000 + reg, link)); - - return resource; -} - -static struct resource *amdfam10_find_mempair(struct device *dev, u32 nodeid, u32 link) -{ - struct resource *resource; - u32 free_reg, reg; - resource = 0; - free_reg = 0; - for (reg = 0x80; reg <= 0xb8; reg += 0x8) { - int result; - result = reg_useable(reg, dev, nodeid, link); - if (result == 1) { - /* I have been allocated this one */ - break; - } else if (result > 1) { - /* I have a free register pair */ - free_reg = reg; - } - } - if (reg > 0xb8) { - reg = free_reg; - } - - //Ext conf space - if (!reg) { - //because of Extend conf space, we will never run out of reg, - // but we need one index to differ them. so same node and - // same link can have multi range - u32 index = get_mmio_addr_index(nodeid, link); - reg = 0x110+ (index<<24) + (6<<20); // index could be 0, 63 - - } - resource = new_resource(dev, IOINDEX(0x1000 + reg, link)); - return resource; -} - - -static void amdfam10_link_read_bases(struct device *dev, u32 nodeid, u32 link) -{ - struct resource *resource; - - /* Initialize the io space constraints on the current bus */ - resource = amdfam10_find_iopair(dev, nodeid, link); - if (resource) { - u32 align; - align = log2(HT_IO_HOST_ALIGN); - resource->base = 0; - resource->size = 0; - resource->align = align; - resource->gran = align; - resource->limit = 0xffffUL; - resource->flags = IORESOURCE_IO | IORESOURCE_BRIDGE; - } - - /* Initialize the prefetchable memory constraints on the current bus */ - resource = amdfam10_find_mempair(dev, nodeid, link); - if (resource) { - resource->base = 0; - resource->size = 0; - resource->align = log2(HT_MEM_HOST_ALIGN); - resource->gran = log2(HT_MEM_HOST_ALIGN); - resource->limit = 0xffffffffffULL; - resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH; - resource->flags |= IORESOURCE_BRIDGE; - } - - /* Initialize the memory constraints on the current bus */ - resource = amdfam10_find_mempair(dev, nodeid, link); - if (resource) { - resource->base = 0; - resource->size = 0; - resource->align = log2(HT_MEM_HOST_ALIGN); - resource->gran = log2(HT_MEM_HOST_ALIGN); - resource->limit = 0xffffffffffULL; - resource->flags = IORESOURCE_MEM | IORESOURCE_BRIDGE; - } -} - -static void amdfam10_read_resources(struct device *dev) -{ - u32 nodeid; - struct bus *link; - nodeid = amdfam10_nodeid(dev); - for (link = dev->link_list; link; link = link->next) { - if (link->children) { - amdfam10_link_read_bases(dev, nodeid, link->link_num); - } - } -} - -static void amdfam10_set_resource(struct device *dev, struct resource *resource, - u32 nodeid) -{ - resource_t rbase, rend; - unsigned int reg, link_num; - char buf[50]; - - /* Make certain the resource has actually been set */ - if (!(resource->flags & IORESOURCE_ASSIGNED)) { - return; - } - - /* If I have already stored this resource don't worry about it */ - if (resource->flags & IORESOURCE_STORED) { - return; - } - - /* Only handle PCI memory and IO resources */ - if (!(resource->flags & (IORESOURCE_MEM | IORESOURCE_IO))) - return; - - /* Ensure I am actually looking at a resource of function 1 */ - if ((resource->index & 0xffff) < 0x1000) { - return; - } - /* Get the base address */ - rbase = resource->base; - - /* Get the limit (rounded up) */ - rend = resource_end(resource); - - /* Get the register and link */ - reg = resource->index & 0xfff; // 4k - link_num = IOINDEX_LINK(resource->index); - - if (resource->flags & IORESOURCE_IO) { - - set_io_addr_reg(dev, nodeid, link_num, reg, rbase>>8, rend>>8); - store_conf_io_addr(nodeid, link_num, reg, (resource->index >> 24), rbase>>8, rend>>8); - } else if (resource->flags & IORESOURCE_MEM) { - set_mmio_addr_reg(nodeid, link_num, reg, (resource->index >>24), rbase>>8, rend>>8, sysconf.nodes); // [39:8] - store_conf_mmio_addr(nodeid, link_num, reg, (resource->index >>24), rbase>>8, rend>>8); - } - resource->flags |= IORESOURCE_STORED; - snprintf(buf, sizeof(buf), " <node %x link %x>", - nodeid, link_num); - report_resource_stored(dev, resource, buf); -} - -/** - * I tried to reuse the resource allocation code in amdfam10_set_resource() - * but it is too difficult to deal with the resource allocation magic. - */ - -static void amdfam10_create_vga_resource(struct device *dev, unsigned int nodeid) -{ - struct bus *link; - struct resource *res; - - /* find out which link the VGA card is connected, - * we only deal with the 'first' vga card */ - for (link = dev->link_list; link; link = link->next) { - if (link->bridge_ctrl & PCI_BRIDGE_CTL_VGA) { -#if CONFIG(MULTIPLE_VGA_ADAPTERS) - extern struct device *vga_pri; // the primary vga device, defined in device.c - printk(BIOS_DEBUG, "VGA: vga_pri bus num = %d bus range [%d,%d]\n", vga_pri->bus->secondary, - link->secondary,link->subordinate); - /* We need to make sure the vga_pri is under the link */ - if ((vga_pri->bus->secondary >= link->secondary) && - (vga_pri->bus->secondary <= link->subordinate)) -#endif - break; - } - } - - /* no VGA card installed */ - if (link == NULL) - return; - - printk(BIOS_DEBUG, "VGA: %s (aka node %d) link %d has VGA device\n", dev_path(dev), nodeid, link->link_num); - set_vga_enable_reg(nodeid, link->link_num); - - /* Redirect VGA memory access to MMIO - * This signals the Family 10h resource parser - * to add a new MMIO mapping to the Range 11 - * MMIO control registers (starting at F1x1B8), - * and also reserves the resource in the E820 map. - */ - res = new_resource(dev, IOINDEX(0x1000 + 0x1b8, link->link_num)); - res->base = 0xa0000; - res->size = 0x20000; - res->flags = IORESOURCE_MEM | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; - amdfam10_set_resource(dev, res, nodeid); -} - -static void amdfam10_set_resources(struct device *dev) -{ - unsigned int nodeid; - struct bus *bus; - struct resource *res; - - /* Find the nodeid */ - nodeid = amdfam10_nodeid(dev); - - amdfam10_create_vga_resource(dev, nodeid); - - /* Set each resource we have found */ - for (res = dev->resource_list; res; res = res->next) { - amdfam10_set_resource(dev, res, nodeid); - } - - for (bus = dev->link_list; bus; bus = bus->next) { - if (bus->children) { - assign_resources(bus); - } - } -} - -static void mcf0_control_init(struct device *dev) -{ -} - -#if CONFIG(HAVE_ACPI_TABLES) -static const char *amdfam10_northbridge_acpi_name(const struct device *dev) -{ - return ""; -} -#endif - -static struct device_operations northbridge_operations = { - .read_resources = amdfam10_read_resources, - .set_resources = amdfam10_set_resources, - .enable_resources = pci_dev_enable_resources, - .init = mcf0_control_init, - .scan_bus = amdfam10_scan_chains, -#if CONFIG(HAVE_ACPI_TABLES) - .write_acpi_tables = northbridge_write_acpi_tables, - .acpi_fill_ssdt_generator = northbridge_acpi_write_vars, - .acpi_name = amdfam10_northbridge_acpi_name, -#endif - .enable = 0, - .ops_pci = 0, -}; - -static const struct pci_driver mcf0_driver __pci_driver = { - .ops = &northbridge_operations, - .vendor = PCI_VENDOR_ID_AMD, - .device = 0x1200, -}; - -static void amdfam10_nb_init(void *chip_info) -{ - relocate_sb_ht_chain(); -} - -static const struct pci_driver mcf0_driver_fam15_model10 __pci_driver = { - .ops = &northbridge_operations, - .vendor = PCI_VENDOR_ID_AMD, - .device = 0x1400, -}; - -static const struct pci_driver mcf0_driver_fam15 __pci_driver = { - .ops = &northbridge_operations, - .vendor = PCI_VENDOR_ID_AMD, - .device = 0x1600, -}; - -struct chip_operations northbridge_amd_amdfam10_ops = { - CHIP_NAME("AMD Family 10h/15h Northbridge") - .enable_dev = 0, - .init = amdfam10_nb_init, -}; - -static void amdfam10_domain_read_resources(struct device *dev) -{ - unsigned int reg; - uint8_t nvram; - uint8_t enable_cc6; - - /* Find the already assigned resource pairs */ - get_fx_devs(); - for (reg = 0x80; reg <= 0xd8; reg+= 0x08) { - u32 base, limit; - base = f1_read_config32(reg); - limit = f1_read_config32(reg + 0x04); - /* Is this register allocated? */ - if ((base & 3) != 0) { - unsigned int nodeid, reg_link; - struct device *reg_dev; - if (reg < 0xc0) { // mmio - nodeid = (limit & 0xf) + (base&0x30); - } else { // io - nodeid = (limit & 0xf) + ((base>>4)&0x30); - } - reg_link = (limit >> 4) & 7; - reg_dev = __f0_dev[nodeid]; - if (reg_dev) { - /* Reserve the resource */ - struct resource *res; - res = new_resource(reg_dev, IOINDEX(0x1000 + reg, reg_link)); - if (res) { - res->flags = 1; - } - } - } - } - /* FIXME: do we need to check extend conf space? - I don't believe that much preset value */ - - pci_domain_read_resources(dev); - - /* We have MMCONF_SUPPORT, create the resource window. */ - mmconf_resource(dev, MMIO_CONF_BASE); - - /* Reserve lower DRAM region to force PCI MMIO region to correct location above 0xefffffff */ - ram_resource(dev, 7, 0, rdmsr(TOP_MEM).lo >> 10); - - if (is_fam15h()) { - enable_cc6 = 0; - if (get_option(&nvram, "cpu_cc6_state") == CB_SUCCESS) - enable_cc6 = !!nvram; - - if (enable_cc6) { - uint8_t node; - uint8_t interleaved; - int8_t range; - uint8_t max_node; - uint64_t max_range_limit; - uint32_t dword; - uint32_t dword2; - uint64_t qword; - uint8_t num_nodes; - - /* Find highest DRAM range (DramLimitAddr) */ - num_nodes = 0; - max_node = 0; - interleaved = 0; - max_range_limit = 0; - struct device *node_dev; - for (node = 0; node < FX_DEVS; node++) { - node_dev = get_node_pci(node, 0); - /* Test for node presence */ - if ((!node_dev) || (pci_read_config32(node_dev, PCI_VENDOR_ID) == 0xffffffff)) - continue; - - num_nodes++; - for (range = 0; range < 8; range++) { - dword = pci_read_config32(get_node_pci(node, 1), 0x40 + (range * 0x8)); - if (!(dword & 0x3)) - continue; - - if ((dword >> 8) & 0x7) - interleaved = 1; - - dword = pci_read_config32(get_node_pci(node, 1), 0x44 + (range * 0x8)); - dword2 = pci_read_config32(get_node_pci(node, 1), 0x144 + (range * 0x8)); - qword = 0xffffff; - qword |= ((((uint64_t)dword) >> 16) & 0xffff) << 24; - qword |= (((uint64_t)dword2) & 0xff) << 40; - - if (qword > max_range_limit) { - max_range_limit = qword; - max_node = dword & 0x7; - } - } - } - - /* Calculate CC6 storage area size */ - if (interleaved) - qword = (uint64_t)0x1000000 * num_nodes; - else - qword = 0x1000000; - - /* FIXME - * The BKDG appears to be incorrect as to the location of the CC6 save region - * lower boundary on non-interleaved systems, causing lockups on attempted write - * to the CC6 save region. - * - * For now, work around by allocating the maximum possible CC6 save region size. - * - * Determine if this is a BKDG error or a setup problem and remove this warning! - */ - qword = (0x1 << 27); - max_range_limit = (((uint64_t)(pci_read_config32(get_node_pci(max_node, 1), 0x124) & 0x1fffff)) << 27) - 1; - - printk(BIOS_INFO, "Reserving CC6 save segment base: %08llx size: %08llx\n", (max_range_limit + 1), qword); - - /* Reserve the CC6 save segment */ - reserved_ram_resource(dev, 8, (max_range_limit + 1) >> 10, qword >> 10); - } - } -} - -static u32 my_find_pci_tolm(struct bus *bus, u32 tolm) -{ - struct resource *min; - min = 0; - search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min); - if (min && tolm > min->base) { - tolm = min->base; - } - return tolm; -} - -#if CONFIG_HW_MEM_HOLE_SIZEK != 0 - -struct hw_mem_hole_info { - unsigned int hole_startk; - int node_id; -}; - -static struct hw_mem_hole_info get_hw_mem_hole_info(void) -{ - struct hw_mem_hole_info mem_hole; - int i; - - mem_hole.hole_startk = CONFIG_HW_MEM_HOLE_SIZEK; - mem_hole.node_id = -1; - - for (i = 0; i < sysconf.nodes; i++) { - struct dram_base_mask_t d; - u32 hole; - d = get_dram_base_mask(i); - if (!(d.mask & 1)) continue; // no memory on this node - - hole = pci_read_config32(__f1_dev[i], 0xf0); - if (hole & 1) { // we find the hole - mem_hole.hole_startk = (hole & (0xff<<24)) >> 10; - mem_hole.node_id = i; // record the node No with hole - break; // only one hole - } - } - - /* We need to double check if there is special set on base reg and limit reg - * are not continuous instead of hole, it will find out its hole_startk. - */ - if (mem_hole.node_id==-1) { - resource_t limitk_pri = 0; - for (i = 0; i < sysconf.nodes; i++) { - struct dram_base_mask_t d; - resource_t base_k, limit_k; - d = get_dram_base_mask(i); - if (!(d.base & 1)) continue; - - base_k = ((resource_t)(d.base & 0x1fffff00)) <<9; - if (base_k > 4 *1024 * 1024) break; // don't need to go to check - if (limitk_pri != base_k) { // we find the hole - mem_hole.hole_startk = (unsigned int)limitk_pri; // must beblow 4G - mem_hole.node_id = i; - break; //only one hole - } - - limit_k = ((resource_t)((d.mask + 0x00000100) & 0x1fffff00)) << 9; - limitk_pri = limit_k; - } - } - return mem_hole; -} - -#endif - -#include <cbmem.h> - -static void setup_uma_memory(void) -{ -#if CONFIG(GFXUMA) - uint32_t topmem = (uint32_t) bsp_topmem(); - uma_memory_size = get_uma_memory_size(topmem); - uma_memory_base = topmem - uma_memory_size; /* TOP_MEM1 */ - printk(BIOS_INFO, "%s: uma size 0x%08llx, memory start 0x%08llx\n", - __func__, uma_memory_size, uma_memory_base); -#endif -} - -static void amdfam10_domain_set_resources(struct device *dev) -{ - unsigned long mmio_basek; - u32 pci_tolm; - int i, idx; - struct bus *link; -#if CONFIG_HW_MEM_HOLE_SIZEK != 0 - struct hw_mem_hole_info mem_hole; -#endif - - pci_tolm = 0xffffffffUL; - for (link = dev->link_list; link; link = link->next) { - pci_tolm = my_find_pci_tolm(link, pci_tolm); - } - - // FIXME handle interleaved nodes. If you fix this here, please fix - // amdk8, too. - mmio_basek = pci_tolm >> 10; - /* Round mmio_basek to something the processor can support */ - mmio_basek &= ~((1 << 6) -1); - - // FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M - // MMIO hole. If you fix this here, please fix amdk8, too. - /* Round the mmio hole to 64M */ - mmio_basek &= ~((64*1024) - 1); - -#if CONFIG_HW_MEM_HOLE_SIZEK != 0 -/* if the hw mem hole is already set in raminit stage, here we will compare - * mmio_basek and hole_basek. if mmio_basek is bigger that hole_basek and will - * use hole_basek as mmio_basek and we don't need to reset hole. - * otherwise We reset the hole to the mmio_basek - */ - - mem_hole = get_hw_mem_hole_info(); - - // Use hole_basek as mmio_basek, and we don't need to reset hole anymore - if ((mem_hole.node_id != -1) && (mmio_basek > mem_hole.hole_startk)) { - mmio_basek = mem_hole.hole_startk; - } - -#endif - - idx = 0x10; - for (i = 0; i < sysconf.nodes; i++) { - struct dram_base_mask_t d; - resource_t basek, limitk, sizek; // 4 1T - d = get_dram_base_mask(i); - - if (!(d.mask & 1)) continue; - basek = ((resource_t)(d.base & 0x1fffff00)) << 9; // could overflow, we may lost 6 bit here - limitk = ((resource_t)((d.mask + 0x00000100) & 0x1fffff00)) << 9; - sizek = limitk - basek; - - /* see if we need a hole from 0xa0000 to 0xbffff */ - if ((basek < ((8*64)+(8*16))) && (sizek > ((8*64)+(16*16)))) { - ram_resource(dev, (idx | i), basek, ((8*64)+(8*16)) - basek); - idx += 0x10; - basek = (8*64)+(16*16); - sizek = limitk - ((8*64)+(16*16)); - - } - - /* split the region to accommodate pci memory space */ - if ((basek < 4*1024*1024) && (limitk > mmio_basek)) { - if (basek <= mmio_basek) { - unsigned int pre_sizek; - pre_sizek = mmio_basek - basek; - if (pre_sizek > 0) { - ram_resource(dev, (idx | i), basek, pre_sizek); - idx += 0x10; - sizek -= pre_sizek; - } - basek = mmio_basek; - } - if ((basek + sizek) <= 4*1024*1024) { - sizek = 0; - } else { - basek = 4*1024*1024; - sizek -= (4*1024*1024 - mmio_basek); - } - } - - ram_resource(dev, (idx | i), basek, sizek); - idx += 0x10; - printk(BIOS_DEBUG, "%d: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n", - i, mmio_basek, basek, limitk); - } - -#if CONFIG(GFXUMA) - uma_resource(dev, 7, uma_memory_base >> 10, uma_memory_size >> 10); -#endif - - for (link = dev->link_list; link; link = link->next) { - if (link->children) { - assign_resources(link); - } - } -} - -static void amdfam10_domain_scan_bus(struct device *dev) -{ - u32 reg; - int i; - struct bus *link; - /* Unmap all of the HT chains */ - for (reg = 0xe0; reg <= 0xec; reg += 4) { - f1_write_config32(reg, 0); - } - - for (link = dev->link_list; link; link = link->next) { - link->secondary = dev->bus->subordinate; - pci_scan_bus(link, PCI_DEVFN(CONFIG_CDB, 0), 0xff); - dev->bus->subordinate = link->subordinate; - } - - /* Tune the hypertransport transaction for best performance. - * Including enabling relaxed ordering if it is safe. - */ - get_fx_devs(); - for (i = 0; i < fx_devs; i++) { - struct device *f0_dev; - f0_dev = __f0_dev[i]; - if (f0_dev && f0_dev->enabled) { - u32 httc; - httc = pci_read_config32(f0_dev, HT_TRANSACTION_CONTROL); - httc &= ~HTTC_RSP_PASS_PW; - if (!dev->link_list->disable_relaxed_ordering) { - httc |= HTTC_RSP_PASS_PW; - } - printk(BIOS_SPEW, "%s passpw: %s\n", - dev_path(dev), - (!dev->link_list->disable_relaxed_ordering)? - "enabled":"disabled"); - pci_write_config32(f0_dev, HT_TRANSACTION_CONTROL, httc); - } - } -} - -#if CONFIG(GENERATE_SMBIOS_TABLES) -static int amdfam10_get_smbios_data16(int *count, int handle, - unsigned long *current) -{ - struct amdmct_memory_info *mem_info; - mem_info = cbmem_find(CBMEM_ID_AMDMCT_MEMINFO); - if (mem_info == NULL) - return 0; /* can't find amdmct information in cbmem */ - - struct device *dev = get_node_pci(0, 0); - struct northbridge_amd_amdfam10_config *config = dev->chip_info; - - int node; - int slot; - - struct smbios_type16 *t = (struct smbios_type16 *)*current; - int len = sizeof(struct smbios_type16); - - memset(t, 0, sizeof(struct smbios_type16)); - t->type = SMBIOS_PHYS_MEMORY_ARRAY; - t->handle = handle; - t->length = len - 2; - t->location = MEMORY_ARRAY_LOCATION_SYSTEM_BOARD; - t->use = MEMORY_ARRAY_USE_SYSTEM; - t->memory_error_correction = MEMORY_ARRAY_ECC_NONE; - if ((mem_info->ecc_enabled) - && (mem_info->mct_stat.GStatus & (1 << GSB_ECCDIMMs)) - && !(mem_info->mct_stat.GStatus & (1 << GSB_DramECCDis))) - /* Single-bit ECC enabled */ - t->memory_error_correction = MEMORY_ARRAY_ECC_SINGLE_BIT; - t->maximum_capacity = config->maximum_memory_capacity / 1024; /* Convert to kilobytes */ - t->memory_error_information_handle = 0xFFFE; /* no error information handle available */ - - t->number_of_memory_devices = 0; - /* Check all nodes for installed DIMMs */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) - /* Check all slots for installed DIMMs */ - for (slot = 0; slot < MAX_DIMMS_SUPPORTED; slot++) - if (mem_info->dct_stat[node].DIMMPresent & (1 << slot)) - /* Found an installed DIMM; increment count */ - t->number_of_memory_devices++; - - *current += len; - *count += 1; - return len; -} - -static uint16_t amdmct_mct_speed_enum_to_mhz(uint8_t speed) -{ - if (is_fam15h()) { - if (CONFIG(DIMM_DDR3)) { - switch (speed) { - case 0x4: - return 333; - case 0x6: - return 400; - case 0xa: - return 533; - case 0xe: - return 667; - case 0x12: - return 800; - case 0x16: - return 933; - default: - return 0; - } - } else { - return 0; - } - } else { - if (CONFIG(DIMM_DDR2)) { - switch (speed) { - case 1: - return 200; - case 2: - return 266; - case 3: - return 333; - case 4: - return 400; - case 5: - return 533; - default: - return 0; - } - } else if (CONFIG(DIMM_DDR3)) { - switch (speed) { - case 3: - return 333; - case 4: - return 400; - case 5: - return 533; - case 6: - return 667; - case 7: - return 800; - default: - return 0; - } - } else { - return 0; - } - } -} - -static int amdfam10_get_smbios_data17(int *count, int handle, int parent_handle, - unsigned long *current) -{ - struct amdmct_memory_info *mem_info; - mem_info = cbmem_find(CBMEM_ID_AMDMCT_MEMINFO); - if (mem_info == NULL) - return 0; /* can't find amdmct information in cbmem */ - - int single_len; - int len = 0; - int node; - int slot; - - /* Check all nodes for installed DIMMs */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - /* Get configured RAM bus speed */ - uint16_t speed; - speed = amdmct_mct_speed_enum_to_mhz(mem_info->dct_stat[node].Speed); - - /* Get maximum RAM bus speed */ - uint16_t max_speed; - max_speed = amdmct_mct_speed_enum_to_mhz(mem_info->dct_stat[node].DIMMAutoSpeed); - - /* Check all slots for installed DIMMs */ - for (slot = 0; slot < MAX_DIMMS_SUPPORTED; slot++) { - if (mem_info->dct_stat[node].DIMMPresent & (1 << slot)) { - /* Found an installed DIMM; populate tables */ - struct smbios_type17 *t = (struct smbios_type17 *)*current; - char string_buffer[256]; - - /* Initialize structure */ - memset(t, 0, sizeof(struct smbios_type17)); - - /* Calculate the total module size in bytes: - * Primary data width * 2^(#rows) * 2^(#cols) * #banks * #ranks - */ - uint8_t width, rows, cols, banks, ranks; - uint64_t chip_size; - uint32_t chip_width; - rows = mem_info->dct_stat[node].DimmRows[slot]; - cols = mem_info->dct_stat[node].DimmCols[slot]; - ranks = mem_info->dct_stat[node].DimmRanks[slot]; - banks = mem_info->dct_stat[node].DimmBanks[slot]; -#if CONFIG(DIMM_DDR3) - chip_size = mem_info->dct_stat[node].DimmChipSize[slot]; - chip_width = mem_info->dct_stat[node].DimmChipWidth[slot]; -#else - chip_size = 0; - chip_width = 0; -#endif - uint64_t dimm_size_bytes; - if (CONFIG(DIMM_DDR3)) { - width = mem_info->dct_stat[node].DimmWidth[slot]; - dimm_size_bytes = ((width / chip_width) * chip_size * ranks) / 8; - } else { - width = 8; - dimm_size_bytes = width * (1ULL << rows) * (1ULL << cols) * banks * ranks; - } - - memset(t, 0, sizeof(struct smbios_type17)); - t->type = SMBIOS_MEMORY_DEVICE; - t->handle = handle; - t->phys_memory_array_handle = parent_handle; - t->length = sizeof(struct smbios_type17) - 2; - if (dimm_size_bytes > 0x800000000) { - t->size = 0x7FFF; - t->extended_size = dimm_size_bytes >> 16; - } else { - t->size = dimm_size_bytes / (1024*1024); - t->size &= (~0x8000); /* size specified in megabytes */ - } - t->total_width = t->data_width = 64; - if (mem_info->dct_stat[node].DimmECCPresent & (1 << slot)) - t->total_width += 8; - t->attributes = 0; - t->attributes |= ranks & 0xf; /* rank number is stored in the lowest 4 bits of the attributes field */ - t->form_factor = MEMORY_FORMFACTOR_DIMM; - if (mem_info->dct_stat[node].Dual_Node_Package) { - snprintf(string_buffer, sizeof(string_buffer), "NODE %d DIMM_%s%d", node >> 1, - (mem_info->dct_stat[node].Internal_Node_ID)?((slot & 0x1)?"D":"C"):((slot & 0x1)?"B":"A"), (slot >> 1) + 1); - } else { - snprintf(string_buffer, sizeof(string_buffer), "NODE %d DIMM_%s%d", node, (slot & 0x1)?"B":"A", (slot >> 1) + 1); - } - t->device_locator = smbios_add_string(t->eos, string_buffer); - if (CONFIG(DIMM_DDR2)) - t->memory_type = MEMORY_TYPE_DDR2; - else if (CONFIG(DIMM_DDR3)) - t->memory_type = MEMORY_TYPE_DDR3; - t->type_detail = MEMORY_TYPE_DETAIL_SYNCHRONOUS; - if (mem_info->dct_stat[node].DimmRegistered[slot]) - t->type_detail |= MEMORY_TYPE_DETAIL_REGISTERED; - else - t->type_detail |= MEMORY_TYPE_DETAIL_UNBUFFERED; - t->speed = max_speed; - t->clock_speed = speed; - smbios_fill_dimm_manufacturer_from_id(mem_info->dct_stat[node].DimmManufacturerID[slot], t); - t->part_number = smbios_add_string(t->eos, mem_info->dct_stat[node].DimmPartNumber[slot]); - if (mem_info->dct_stat[node].DimmSerialNumber[slot] == 0) { - t->serial_number = smbios_add_string(t->eos, "None"); - } else { - snprintf(string_buffer, sizeof(string_buffer), "%08X", mem_info->dct_stat[node].DimmSerialNumber[slot]); - t->serial_number = smbios_add_string(t->eos, string_buffer); - } - if (CONFIG(DIMM_DDR2)) { - /* JEDEC specifies 1.8V only, so assume that the memory is configured for 1.8V */ - t->minimum_voltage = 1800; - t->maximum_voltage = 1800; - t->configured_voltage = 1800; - } else if (CONFIG(DIMM_DDR3)) { -#if CONFIG(DIMM_DDR3) - /* Find the maximum and minimum supported voltages */ - uint8_t supported_voltages = mem_info->dct_stat[node].DimmSupportedVoltages[slot]; - uint8_t configured_voltage = mem_info->dct_stat[node].DimmConfiguredVoltage[slot]; - - if (supported_voltages & 0x8) - t->minimum_voltage = 1150; - else if (supported_voltages & 0x4) - t->minimum_voltage = 1250; - else if (supported_voltages & 0x2) - t->minimum_voltage = 1350; - else if (supported_voltages & 0x1) - t->minimum_voltage = 1500; - - if (supported_voltages & 0x1) - t->maximum_voltage = 1500; - else if (supported_voltages & 0x2) - t->maximum_voltage = 1350; - else if (supported_voltages & 0x4) - t->maximum_voltage = 1250; - else if (supported_voltages & 0x8) - t->maximum_voltage = 1150; - - if (configured_voltage & 0x8) - t->configured_voltage = 1150; - else if (configured_voltage & 0x4) - t->configured_voltage = 1250; - else if (configured_voltage & 0x2) - t->configured_voltage = 1350; - else if (configured_voltage & 0x1) - t->configured_voltage = 1500; -#endif - } - t->memory_error_information_handle = 0xFFFE; /* no error information handle available */ - single_len = t->length + smbios_string_table_len(t->eos); - len += single_len; - *current += single_len; - handle++; - *count += 1; - } - } - } - - return len; -} - -static int amdfam10_get_smbios_data(struct device *dev, int *handle, unsigned long *current) -{ - int len; - int count = 0; - len = amdfam10_get_smbios_data16(&count, *handle, current); - len += amdfam10_get_smbios_data17(&count, *handle + 1, *handle, current); - *handle += count; - return len; -} -#endif - -#if CONFIG(HAVE_ACPI_TABLES) -static const char *amdfam10_domain_acpi_name(const struct device *dev) -{ - if (dev->path.type == DEVICE_PATH_DOMAIN) - return "PCI0"; - - return NULL; -} -#endif - -static struct device_operations pci_domain_ops = { - .read_resources = amdfam10_domain_read_resources, - .set_resources = amdfam10_domain_set_resources, - .enable_resources = NULL, - .init = NULL, - .scan_bus = amdfam10_domain_scan_bus, -#if CONFIG(HAVE_ACPI_TABLES) - .acpi_name = amdfam10_domain_acpi_name, -#endif -#if CONFIG(GENERATE_SMBIOS_TABLES) - .get_smbios_data = amdfam10_get_smbios_data, -#endif -}; - -static void sysconf_init(struct device *dev) // first node -{ - sysconf.sblk = (pci_read_config32(dev, 0x64)>>8) & 7; // don't forget sublink1 - sysconf.segbit = 0; - sysconf.ht_c_num = 0; - - unsigned int ht_c_index; - - for (ht_c_index = 0; ht_c_index < 32; ht_c_index++) { - sysconf.ht_c_conf_bus[ht_c_index] = 0; - } - - sysconf.nodes = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1; -#if CONFIG_MAX_PHYSICAL_CPUS > 8 - sysconf.nodes += (((pci_read_config32(dev, 0x160)>>4) & 7)<<3); -#endif - - sysconf.enabled_apic_ext_id = 0; - sysconf.lift_bsp_apicid = 0; - - /* Find the bootstrap processors apicid */ - sysconf.bsp_apicid = lapicid(); - sysconf.apicid_offset = sysconf.bsp_apicid; - -#if CONFIG(ENABLE_APIC_EXT_ID) - if (pci_read_config32(dev, 0x68) & (HTTC_APIC_EXT_ID|HTTC_APIC_EXT_BRD_CST)) - { - sysconf.enabled_apic_ext_id = 1; - } - #if (CONFIG_APIC_ID_OFFSET > 0) - if (sysconf.enabled_apic_ext_id) { - if (sysconf.bsp_apicid == 0) { - /* bsp apic id is not changed */ - sysconf.apicid_offset = CONFIG_APIC_ID_OFFSET; - } else { - sysconf.lift_bsp_apicid = 1; - } - } - #endif -#endif -} - -static void remap_bsp_lapic(struct bus *cpu_bus) -{ - struct device_path cpu_path; - struct device *cpu; - u32 bsp_lapic_id = lapicid(); - - if (bsp_lapic_id) { - cpu_path.type = DEVICE_PATH_APIC; - cpu_path.apic.apic_id = 0; - cpu = find_dev_path(cpu_bus, &cpu_path); - if (cpu) - cpu->path.apic.apic_id = bsp_lapic_id; - } -} - -static void cpu_bus_scan(struct device *dev) -{ - struct bus *cpu_bus; - struct device *dev_mc; -#if CONFIG_CBB - struct device *pci_domain; -#endif - int nvram = 0; - int i,j; - int nodes; - unsigned int nb_cfg_54; - unsigned int siblings; - int cores_found; - int disable_siblings; - uint8_t disable_cu_siblings = 0; - unsigned int ApicIdCoreIdSize; - - nb_cfg_54 = 0; - ApicIdCoreIdSize = (cpuid_ecx(0x80000008)>>12 & 0xf); - if (ApicIdCoreIdSize) { - siblings = (1<<ApicIdCoreIdSize)-1; - } else { - siblings = 3; //quad core - } - - disable_siblings = !CONFIG(LOGICAL_CPUS); -#if CONFIG(LOGICAL_CPUS) - get_option(&disable_siblings, "multi_core"); -#endif - - // How can I get the nb_cfg_54 of every node's nb_cfg_54 in bsp??? - nb_cfg_54 = read_nb_cfg_54(); - -#if CONFIG_CBB - dev_mc = pcidev_on_root(CONFIG_CDB, 0); //0x00 - if (dev_mc && dev_mc->bus) { - printk(BIOS_DEBUG, "%s found", dev_path(dev_mc)); - pci_domain = dev_mc->bus->dev; - if (pci_domain && (pci_domain->path.type == DEVICE_PATH_DOMAIN)) { - printk(BIOS_DEBUG, "\n%s move to ",dev_path(dev_mc)); - dev_mc->bus->secondary = CONFIG_CBB; // move to 0xff - printk(BIOS_DEBUG, "%s",dev_path(dev_mc)); - - } else { - printk(BIOS_DEBUG, " but it is not under pci_domain directly "); - } - printk(BIOS_DEBUG, "\n"); - } - dev_mc = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 0)); - if (!dev_mc) { - dev_mc = pcidev_on_root(0x18, 0); - if (dev_mc && dev_mc->bus) { - printk(BIOS_DEBUG, "%s found\n", dev_path(dev_mc)); - pci_domain = dev_mc->bus->dev; - if (pci_domain && (pci_domain->path.type == DEVICE_PATH_DOMAIN)) { - if ((pci_domain->link_list) && (pci_domain->link_list->children == dev_mc)) { - printk(BIOS_DEBUG, "%s move to ",dev_path(dev_mc)); - dev_mc->bus->secondary = CONFIG_CBB; // move to 0xff - printk(BIOS_DEBUG, "%s\n",dev_path(dev_mc)); - while (dev_mc) { - printk(BIOS_DEBUG, "%s move to ",dev_path(dev_mc)); - dev_mc->path.pci.devfn -= PCI_DEVFN(0x18,0); - printk(BIOS_DEBUG, "%s\n",dev_path(dev_mc)); - dev_mc = dev_mc->sibling; - } - } - } - } - } - -#endif - - dev_mc = dev_find_slot(CONFIG_CBB, PCI_DEVFN(CONFIG_CDB, 0)); - if (!dev_mc) { - printk(BIOS_ERR, "%02x:%02x.0 not found", CONFIG_CBB, CONFIG_CDB); - die(""); - } - - sysconf_init(dev_mc); - - nodes = sysconf.nodes; - -#if CONFIG_CBB && (NODE_NUMS > 32) - if (nodes > 32) { // need to put node 32 to node 63 to bus 0xfe - if (pci_domain->link_list && !pci_domain->link_list->next) { - struct bus *new_link = new_link(pci_domain); - pci_domain->link_list->next = new_link; - new_link->link_num = 1; - new_link->dev = pci_domain; - new_link->children = 0; - printk(BIOS_DEBUG, "%s links now 2\n", dev_path(pci_domain)); - } - pci_domain->link_list->next->secondary = CONFIG_CBB - 1; - } -#endif - /* Find which cpus are present */ - cpu_bus = dev->link_list; - - /* Always use the devicetree node with lapic_id 0 for BSP. */ - remap_bsp_lapic(cpu_bus); - - if (get_option(&nvram, "compute_unit_siblings") == CB_SUCCESS) - disable_cu_siblings = !!nvram; - - if (disable_cu_siblings) - printk(BIOS_DEBUG, "Disabling siblings on each compute unit as requested\n"); - - for (i = 0; i < nodes; i++) { - struct device *cdb_dev; - unsigned int busn, devn; - struct bus *pbus; - - uint8_t fam15h = 0; - uint8_t rev_gte_d = 0; - uint8_t dual_node = 0; - uint32_t f3xe8; - uint32_t model; - - busn = CONFIG_CBB; - devn = CONFIG_CDB+i; - pbus = dev_mc->bus; -#if CONFIG_CBB && (NODE_NUMS > 32) - if (i >= 32) { - busn--; - devn-=32; - pbus = pci_domain->link_list->next; - } -#endif - - /* Find the cpu's pci device */ - cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 0)); - if (!cdb_dev) { - /* If I am probing things in a weird order - * ensure all of the cpu's pci devices are found. - */ - int fn; - for (fn = 0; fn <= 5; fn++) { //FBDIMM? - cdb_dev = pci_probe_dev(NULL, pbus, - PCI_DEVFN(devn, fn)); - } - } - - - /* Ok, We need to set the links for that device. - * otherwise the device under it will not be scanned - */ - cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 0)); - if (cdb_dev) - add_more_links(cdb_dev, 4); - - cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 4)); - if (cdb_dev) - add_more_links(cdb_dev, 4); - - f3xe8 = pci_read_config32(get_node_pci(0, 3), 0xe8); - - model = cpuid_eax(0x80000001); - model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4); - - if (is_fam15h()) { - /* Family 15h or later */ - fam15h = 1; - nb_cfg_54 = 1; - } - - if ((model >= 0x8) || fam15h) - /* Revision D or later */ - rev_gte_d = 1; - - if (rev_gte_d) - /* Check for dual node capability */ - if (f3xe8 & 0x20000000) - dual_node = 1; - - cores_found = 0; // one core - if (fam15h) - cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 5)); - else - cdb_dev = dev_find_slot(busn, PCI_DEVFN(devn, 3)); - int enable_node = cdb_dev && cdb_dev->enabled; - if (enable_node) { - if (fam15h) { - cores_found = pci_read_config32(cdb_dev, 0x84) & 0xff; - } else { - j = pci_read_config32(cdb_dev, 0xe8); - cores_found = (j >> 12) & 3; // dev is func 3 - if (siblings > 3) - cores_found |= (j >> 13) & 4; - } - printk(BIOS_DEBUG, " %s siblings=%d\n", dev_path(cdb_dev), cores_found); - } - - if (siblings > cores_found) - siblings = cores_found; - - u32 jj; - if (disable_siblings) { - jj = 0; - } else - { - jj = cores_found; - } - - for (j = 0; j <=jj; j++) { - u32 apic_id; - - if (dual_node) { - apic_id = 0; - if (fam15h) { - apic_id |= ((i >> 1) & 0x3) << 5; /* Node ID */ - apic_id |= ((i & 0x1) * (siblings + 1)) + j; /* Core ID */ - } else { - if (nb_cfg_54) { - apic_id |= ((i >> 1) & 0x3) << 4; /* Node ID */ - apic_id |= ((i & 0x1) * (siblings + 1)) + j; /* Core ID */ - } else { - apic_id |= i & 0x3; /* Node ID */ - apic_id |= (((i & 0x1) * (siblings + 1)) + j) << 4; /* Core ID */ - } - } - } else { - if (fam15h) { - apic_id = 0; - apic_id |= (i & 0x7) << 4; /* Node ID */ - apic_id |= j & 0xf; /* Core ID */ - } else { - apic_id = i * (nb_cfg_54?(siblings+1):1) + j * (nb_cfg_54?1:64); // ? - } - } - -#if CONFIG(ENABLE_APIC_EXT_ID) && (CONFIG_APIC_ID_OFFSET > 0) - if (sysconf.enabled_apic_ext_id) { - if (apic_id != 0 || sysconf.lift_bsp_apicid) { - apic_id += sysconf.apicid_offset; - } - } -#endif - if (disable_cu_siblings && (j & 0x1)) - continue; - - struct device *cpu = add_cpu_device(cpu_bus, apic_id, enable_node); - if (cpu) - amd_cpu_topology(cpu, i, j); - } - } -} - -static void detect_and_enable_probe_filter(struct device *dev) -{ - uint32_t dword; - - uint8_t nvram; - uint8_t enable_probe_filter; - - /* Check to see if the probe filter is allowed */ - enable_probe_filter = 1; - if (get_option(&nvram, "probe_filter") == CB_SUCCESS) - enable_probe_filter = !!nvram; - - if (!enable_probe_filter) - return; - - uint8_t fam15h = 0; - uint8_t rev_gte_d = 0; - uint32_t model; - - model = cpuid_eax(0x80000001); - model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4); - - if (is_fam15h()) { - /* Family 15h or later */ - fam15h = 1; - } - - if ((model >= 0x8) || fam15h) - /* Revision D or later */ - rev_gte_d = 1; - - if (rev_gte_d && (sysconf.nodes > 1)) { - /* Enable the probe filter */ - uint8_t i; - uint8_t pfmode = 0x0; - - uint32_t f3x58[MAX_NODES_SUPPORTED]; - uint32_t f3x5c[MAX_NODES_SUPPORTED]; - - printk(BIOS_DEBUG, "Enabling probe filter\n"); - - /* Disable L3 and DRAM scrubbers and configure system for probe filter support */ - for (i = 0; i < sysconf.nodes; i++) { - struct device *f2x_dev = pcidev_on_root(0x18 + i, 2); - struct device *f3x_dev = pcidev_on_root(0x18 + i, 3); - - f3x58[i] = pci_read_config32(f3x_dev, 0x58); - f3x5c[i] = pci_read_config32(f3x_dev, 0x5c); - pci_write_config32(f3x_dev, 0x58, f3x58[i] & ~((0x1f << 24) | 0x1f)); - pci_write_config32(f3x_dev, 0x5c, f3x5c[i] & ~0x1); - - dword = pci_read_config32(f2x_dev, 0x1b0); - dword &= ~(0x7 << 8); /* CohPrefPrbLmt = 0x0 */ - pci_write_config32(f2x_dev, 0x1b0, dword); - - msr_t msr = rdmsr_amd(BU_CFG2_MSR); - msr.hi |= 1 << (42 - 32); - wrmsr_amd(BU_CFG2_MSR, msr); - - if (is_fam15h()) { - uint8_t subcache_size = 0x0; - uint8_t pref_so_repl = 0x0; - uint32_t f3x1c4 = pci_read_config32(f3x_dev, 0x1c4); - if ((f3x1c4 & 0xffff) == 0xcccc) { - subcache_size = 0x1; - pref_so_repl = 0x2; - pfmode = 0x3; - } else { - pfmode = 0x2; - } - - dword = pci_read_config32(f3x_dev, 0x1d4); - dword |= 0x1 << 29; /* PFLoIndexHashEn = 0x1 */ - dword &= ~(0x3 << 20); /* PFPreferredSORepl = pref_so_repl */ - dword |= (pref_so_repl & 0x3) << 20; - dword |= 0x1 << 17; /* PFWayHashEn = 0x1 */ - dword |= 0xf << 12; /* PFSubCacheEn = 0xf */ - dword &= ~(0x3 << 10); /* PFSubCacheSize3 = subcache_size */ - dword |= (subcache_size & 0x3) << 10; - dword &= ~(0x3 << 8); /* PFSubCacheSize2 = subcache_size */ - dword |= (subcache_size & 0x3) << 8; - dword &= ~(0x3 << 6); /* PFSubCacheSize1 = subcache_size */ - dword |= (subcache_size & 0x3) << 6; - dword &= ~(0x3 << 4); /* PFSubCacheSize0 = subcache_size */ - dword |= (subcache_size & 0x3) << 4; - dword &= ~(0x3 << 2); /* PFWayNum = 0x2 */ - dword |= 0x2 << 2; - pci_write_config32(f3x_dev, 0x1d4, dword); - } else { - pfmode = 0x2; - - dword = pci_read_config32(f3x_dev, 0x1d4); - dword |= 0x1 << 29; /* PFLoIndexHashEn = 0x1 */ - dword &= ~(0x3 << 20); /* PFPreferredSORepl = 0x2 */ - dword |= 0x2 << 20; - dword |= 0xf << 12; /* PFSubCacheEn = 0xf */ - dword &= ~(0x3 << 10); /* PFSubCacheSize3 = 0x0 */ - dword &= ~(0x3 << 8); /* PFSubCacheSize2 = 0x0 */ - dword &= ~(0x3 << 6); /* PFSubCacheSize1 = 0x0 */ - dword &= ~(0x3 << 4); /* PFSubCacheSize0 = 0x0 */ - dword &= ~(0x3 << 2); /* PFWayNum = 0x2 */ - dword |= 0x2 << 2; - pci_write_config32(f3x_dev, 0x1d4, dword); - } - } - - udelay(40); - - disable_cache(); - wbinvd(); - - /* Enable probe filter */ - for (i = 0; i < sysconf.nodes; i++) { - struct device *f3x_dev = pcidev_on_root(0x18 + i, 3); - - dword = pci_read_config32(f3x_dev, 0x1c4); - dword |= (0x1 << 31); /* L3TagInit = 1 */ - pci_write_config32(f3x_dev, 0x1c4, dword); - do { - } while (pci_read_config32(f3x_dev, 0x1c4) & (0x1 << 31)); - - dword = pci_read_config32(f3x_dev, 0x1d4); - dword &= ~0x3; /* PFMode = pfmode */ - dword |= pfmode & 0x3; - pci_write_config32(f3x_dev, 0x1d4, dword); - do { - } while (!(pci_read_config32(f3x_dev, 0x1d4) & (0x1 << 19))); - } - - if (is_fam15h()) { - printk(BIOS_DEBUG, "Enabling ATM mode\n"); - - /* Enable ATM mode */ - for (i = 0; i < sysconf.nodes; i++) { - struct device *f0x_dev = - pcidev_on_root(0x18 + i, 0); - struct device *f3x_dev = - pcidev_on_root(0x18 + i, 3); - - dword = pci_read_config32(f0x_dev, 0x68); - dword |= (0x1 << 12); /* ATMModeEn = 1 */ - pci_write_config32(f0x_dev, 0x68, dword); - - dword = pci_read_config32(f3x_dev, 0x1b8); - dword |= (0x1 << 27); /* L3ATMModeEn = 1 */ - pci_write_config32(f3x_dev, 0x1b8, dword); - } - } - - enable_cache(); - - /* Reenable L3 and DRAM scrubbers */ - for (i = 0; i < sysconf.nodes; i++) { - struct device *f3x_dev = pcidev_on_root(0x18 + i, 3); - - pci_write_config32(f3x_dev, 0x58, f3x58[i]); - pci_write_config32(f3x_dev, 0x5c, f3x5c[i]); - } - - } -} - -static void detect_and_enable_cache_partitioning(struct device *dev) -{ - uint8_t i; - uint32_t dword; - - uint8_t nvram; - uint8_t enable_l3_cache_partitioning; - - /* Check to see if cache partitioning is allowed */ - enable_l3_cache_partitioning = 0; - if (get_option(&nvram, "l3_cache_partitioning") == CB_SUCCESS) - enable_l3_cache_partitioning = !!nvram; - - if (!enable_l3_cache_partitioning) - return; - - if (is_fam15h()) { - printk(BIOS_DEBUG, "Enabling L3 cache partitioning\n"); - - uint32_t f5x80; - uint8_t cu_enabled; - uint8_t compute_unit_count = 0; - - for (i = 0; i < sysconf.nodes; i++) { - struct device *f3x_dev = pcidev_on_root(0x18 + i, 3); - struct device *f4x_dev = pcidev_on_root(0x18 + i, 4); - struct device *f5x_dev = pcidev_on_root(0x18 + i, 5); - - /* Determine the number of active compute units on this node */ - f5x80 = pci_read_config32(f5x_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; - - /* Disable BAN mode */ - dword = pci_read_config32(f3x_dev, 0x1b8); - dword &= ~(0x7 << 19); /* L3BanMode = 0x0 */ - pci_write_config32(f3x_dev, 0x1b8, dword); - - /* Set up cache mapping */ - dword = pci_read_config32(f4x_dev, 0x1d4); - if (compute_unit_count == 1) { - dword |= 0xf; /* ComputeUnit0SubCacheEn = 0xf */ - } - if (compute_unit_count == 2) { - dword &= ~(0xf << 4); /* ComputeUnit1SubCacheEn = 0xc */ - dword |= (0xc << 4); - dword &= ~0xf; /* ComputeUnit0SubCacheEn = 0x3 */ - dword |= 0x3; - } - if (compute_unit_count == 3) { - dword &= ~(0xf << 8); /* ComputeUnit2SubCacheEn = 0x8 */ - dword |= (0x8 << 8); - dword &= ~(0xf << 4); /* ComputeUnit1SubCacheEn = 0x4 */ - dword |= (0x4 << 4); - dword &= ~0xf; /* ComputeUnit0SubCacheEn = 0x3 */ - dword |= 0x3; - } - if (compute_unit_count == 4) { - dword &= ~(0xf << 12); /* ComputeUnit3SubCacheEn = 0x8 */ - dword |= (0x8 << 12); - dword &= ~(0xf << 8); /* ComputeUnit2SubCacheEn = 0x4 */ - dword |= (0x4 << 8); - dword &= ~(0xf << 4); /* ComputeUnit1SubCacheEn = 0x2 */ - dword |= (0x2 << 4); - dword &= ~0xf; /* ComputeUnit0SubCacheEn = 0x1 */ - dword |= 0x1; - } - pci_write_config32(f4x_dev, 0x1d4, dword); - - /* Enable cache partitioning */ - pci_write_config32(f4x_dev, 0x1d4, dword); - if (compute_unit_count == 1) { - dword &= ~(0xf << 26); /* MaskUpdateForComputeUnit = 0x1 */ - dword |= (0x1 << 26); - } else if (compute_unit_count == 2) { - dword &= ~(0xf << 26); /* MaskUpdateForComputeUnit = 0x3 */ - dword |= (0x3 << 26); - } else if (compute_unit_count == 3) { - dword &= ~(0xf << 26); /* MaskUpdateForComputeUnit = 0x7 */ - dword |= (0x7 << 26); - } else if (compute_unit_count == 4) { - dword |= (0xf << 26); /* MaskUpdateForComputeUnit = 0xf */ - } - pci_write_config32(f4x_dev, 0x1d4, dword); - } - } -} - -static void cpu_bus_init(struct device *dev) -{ - detect_and_enable_probe_filter(dev); - detect_and_enable_cache_partitioning(dev); - initialize_cpus(dev->link_list); -} - -static struct device_operations cpu_bus_ops = { - .read_resources = DEVICE_NOOP, - .set_resources = DEVICE_NOOP, - .enable_resources = DEVICE_NOOP, - .init = cpu_bus_init, - .scan_bus = cpu_bus_scan, -}; - -static void root_complex_enable_dev(struct device *dev) -{ - static int done = 0; - - /* Do not delay UMA setup, as a device on the PCI bus may evaluate - the global uma_memory variables already in its enable function. */ - if (!done) { - setup_bsp_ramtop(); - setup_uma_memory(); - done = 1; - } - - /* Set the operations if it is a special bus type */ - if (dev->path.type == DEVICE_PATH_DOMAIN) { - dev->ops = &pci_domain_ops; - } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) { - dev->ops = &cpu_bus_ops; - } -} - -static void root_complex_finalize(void *chip_info) { -#if CONFIG(HAVE_ACPI_RESUME) && CONFIG(DIMM_DDR3) - save_mct_information_to_nvram(); -#endif -} - -struct chip_operations northbridge_amd_amdfam10_root_complex_ops = { - CHIP_NAME("AMD Family 10h/15h Root Complex") - .enable_dev = root_complex_enable_dev, - .final = root_complex_finalize, -}; diff --git a/src/northbridge/amd/amdfam10/northbridge.h b/src/northbridge/amd/amdfam10/northbridge.h deleted file mode 100644 index fdfd4c8c2c..0000000000 --- a/src/northbridge/amd/amdfam10/northbridge.h +++ /dev/null @@ -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 */ diff --git a/src/northbridge/amd/amdfam10/nums.h b/src/northbridge/amd/amdfam10/nums.h deleted file mode 100644 index 771ef12b95..0000000000 --- a/src/northbridge/amd/amdfam10/nums.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdfam10/pci.c b/src/northbridge/amd/amdfam10/pci.c deleted file mode 100644 index 410923a01e..0000000000 --- a/src/northbridge/amd/amdfam10/pci.c +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdfam10/pci.h b/src/northbridge/amd/amdfam10/pci.h deleted file mode 100644 index 21623c1168..0000000000 --- a/src/northbridge/amd/amdfam10/pci.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdfam10/raminit.h b/src/northbridge/amd/amdfam10/raminit.h deleted file mode 100644 index c9c57ff2c2..0000000000 --- a/src/northbridge/amd/amdfam10/raminit.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdfam10/raminit_amdmct.c b/src/northbridge/amd/amdfam10/raminit_amdmct.c deleted file mode 100644 index a25a1510c8..0000000000 --- a/src/northbridge/amd/amdfam10/raminit_amdmct.c +++ /dev/null @@ -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 - } -} diff --git a/src/northbridge/amd/amdfam10/raminit_sysinfo_in_ram.c b/src/northbridge/amd/amdfam10/raminit_sysinfo_in_ram.c deleted file mode 100644 index 218df75887..0000000000 --- a/src/northbridge/amd/amdfam10/raminit_sysinfo_in_ram.c +++ /dev/null @@ -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); -} diff --git a/src/northbridge/amd/amdfam10/reset_test.c b/src/northbridge/amd/amdfam10/reset_test.c deleted file mode 100644 index 76d1144e7d..0000000000 --- a/src/northbridge/amd/amdfam10/reset_test.c +++ /dev/null @@ -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); -} diff --git a/src/northbridge/amd/amdfam10/resourcemap.c b/src/northbridge/amd/amdfam10/resourcemap.c deleted file mode 100644 index fa4ab3cfd7..0000000000 --- a/src/northbridge/amd/amdfam10/resourcemap.c +++ /dev/null @@ -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); -} diff --git a/src/northbridge/amd/amdfam10/setup_resource_map.c b/src/northbridge/amd/amdfam10/setup_resource_map.c deleted file mode 100644 index 735d72bbf7..0000000000 --- a/src/northbridge/amd/amdfam10/setup_resource_map.c +++ /dev/null @@ -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"); -} diff --git a/src/northbridge/amd/amdfam10/util.c b/src/northbridge/amd/amdfam10/util.c deleted file mode 100644 index ed5556ff70..0000000000 --- a/src/northbridge/amd/amdfam10/util.c +++ /dev/null @@ -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); -} diff --git a/src/northbridge/amd/amdht/AsPsDefs.h b/src/northbridge/amd/amdht/AsPsDefs.h deleted file mode 100644 index 30f4d759b6..0000000000 --- a/src/northbridge/amd/amdht/AsPsDefs.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdht/AsPsNb.c b/src/northbridge/amd/amdht/AsPsNb.c deleted file mode 100644 index 70dbacfbab..0000000000 --- a/src/northbridge/amd/amdht/AsPsNb.c +++ /dev/null @@ -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); -} diff --git a/src/northbridge/amd/amdht/AsPsNb.h b/src/northbridge/amd/amdht/AsPsNb.h deleted file mode 100644 index 35008920fe..0000000000 --- a/src/northbridge/amd/amdht/AsPsNb.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdht/Makefile.inc b/src/northbridge/amd/amdht/Makefile.inc deleted file mode 100644 index 0b33352e7c..0000000000 --- a/src/northbridge/amd/amdht/Makefile.inc +++ /dev/null @@ -1,5 +0,0 @@ -ifeq ($(CONFIG_NORTHBRIDGE_AMD_AMDFAM10),y) - -romstage-y += h3finit.c ht_wrapper.c comlib.c AsPsNb.c h3ncmn.c - -endif diff --git a/src/northbridge/amd/amdht/comlib.c b/src/northbridge/amd/amdht/comlib.c deleted file mode 100644 index 883f634c74..0000000000 --- a/src/northbridge/amd/amdht/comlib.c +++ /dev/null @@ -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); -} diff --git a/src/northbridge/amd/amdht/comlib.h b/src/northbridge/amd/amdht/comlib.h deleted file mode 100644 index 98326b280f..0000000000 --- a/src/northbridge/amd/amdht/comlib.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdht/h3ffeat.h b/src/northbridge/amd/amdht/h3ffeat.h deleted file mode 100644 index 2cf4bd1a1c..0000000000 --- a/src/northbridge/amd/amdht/h3ffeat.h +++ /dev/null @@ -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 */ diff --git a/src/northbridge/amd/amdht/h3finit.c b/src/northbridge/amd/amdht/h3finit.c deleted file mode 100644 index cda0a28cef..0000000000 --- a/src/northbridge/amd/amdht/h3finit.c +++ /dev/null @@ -1,1879 +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. - */ - -/* - *---------------------------------------------------------------------------- - * MODULES USED - * - *---------------------------------------------------------------------------- - */ - -#include "h3finit.h" -#include "h3ffeat.h" -#include "h3ncmn.h" -#include "h3gtopo.h" -#include "AsPsNb.h" - -#include <arch/cpu.h> -#include <device/pci.h> -#include <device/pci_ops.h> -#include <console/console.h> -#include <cpu/x86/lapic_def.h> -#include <cpu/amd/msr.h> -#include <device/pci_def.h> -#include <northbridge/amd/amdfam10/raminit.h> -#include <northbridge/amd/amdfam10/amdfam10.h> -#include <types.h> - -/*---------------------------------------------------------------------------- - * DEFINITIONS AND MACROS - * - *---------------------------------------------------------------------------- - */ - -#define NVRAM_LIMIT_HT_SPEED_200 0x12 -#define NVRAM_LIMIT_HT_SPEED_300 0x11 -#define NVRAM_LIMIT_HT_SPEED_400 0x10 -#define NVRAM_LIMIT_HT_SPEED_500 0xf -#define NVRAM_LIMIT_HT_SPEED_600 0xe -#define NVRAM_LIMIT_HT_SPEED_800 0xd -#define NVRAM_LIMIT_HT_SPEED_1000 0xc -#define NVRAM_LIMIT_HT_SPEED_1200 0xb -#define NVRAM_LIMIT_HT_SPEED_1400 0xa -#define NVRAM_LIMIT_HT_SPEED_1600 0x9 -#define NVRAM_LIMIT_HT_SPEED_1800 0x8 -#define NVRAM_LIMIT_HT_SPEED_2000 0x7 -#define NVRAM_LIMIT_HT_SPEED_2200 0x6 -#define NVRAM_LIMIT_HT_SPEED_2400 0x5 -#define NVRAM_LIMIT_HT_SPEED_2600 0x4 -#define NVRAM_LIMIT_HT_SPEED_2800 0x3 -#define NVRAM_LIMIT_HT_SPEED_3000 0x2 -#define NVRAM_LIMIT_HT_SPEED_3200 0x1 -#define NVRAM_LIMIT_HT_SPEED_AUTO 0x0 - -static const uint32_t ht_speed_limit[20] = - {0xFFFFF, 0xFFFFF, 0x7FFFF, 0x3FFFF, - 0x0FFFF, 0x07FFF, 0x03FFF, 0x01FFF, - 0x00FFF, 0x007FF, 0x003FF, 0x001FF, - 0x000FF, 0x0007F, 0x0003F, 0x0001F, - 0x0000F, 0x00007, 0x00003, 0x00001}; - -static const struct ht_speed_limit_map_t { - uint16_t mhz; - uint8_t nvram; -} ht_speed_limit_map[] = { - {0, NVRAM_LIMIT_HT_SPEED_AUTO}, - {200, NVRAM_LIMIT_HT_SPEED_200}, - {300, NVRAM_LIMIT_HT_SPEED_300}, - {400, NVRAM_LIMIT_HT_SPEED_400}, - {500, NVRAM_LIMIT_HT_SPEED_500}, - {600, NVRAM_LIMIT_HT_SPEED_600}, - {800, NVRAM_LIMIT_HT_SPEED_800}, - {1000, NVRAM_LIMIT_HT_SPEED_1000}, - {1200, NVRAM_LIMIT_HT_SPEED_1200}, - {1400, NVRAM_LIMIT_HT_SPEED_1400}, - {1600, NVRAM_LIMIT_HT_SPEED_1600}, - {1800, NVRAM_LIMIT_HT_SPEED_1800}, - {2000, NVRAM_LIMIT_HT_SPEED_2000}, - {2200, NVRAM_LIMIT_HT_SPEED_2200}, - {2400, NVRAM_LIMIT_HT_SPEED_2400}, - {2600, NVRAM_LIMIT_HT_SPEED_2600}, - {2800, NVRAM_LIMIT_HT_SPEED_2800}, - {3000, NVRAM_LIMIT_HT_SPEED_3000}, - {3200, NVRAM_LIMIT_HT_SPEED_3200}, -}; - -static const uint32_t ht_speed_mhz_to_hw(uint16_t mhz) -{ - size_t i; - for (i = 0; i < ARRAY_SIZE(ht_speed_limit_map); i++) - if (ht_speed_limit_map[i].mhz == mhz) - return ht_speed_limit[ht_speed_limit_map[i].nvram]; - - printk(BIOS_WARNING, - "WARNING: Invalid HT link limit frequency %d specified, ignoring...\n", - mhz); - return ht_speed_limit[NVRAM_LIMIT_HT_SPEED_AUTO]; -} - -/*---------------------------------------------------------------------------- - * TYPEDEFS AND STRUCTURES - * - *---------------------------------------------------------------------------- - */ - -/*---------------------------------------------------------------------------- - * PROTOTYPES OF LOCAL FUNCTIONS - * - *---------------------------------------------------------------------------- - */ - -/*---------------------------------------------------------------------------- - * EXPORTED FUNCTIONS - * - *---------------------------------------------------------------------------- - */ - -/*---------------------------------------------------------------------------- - * LOCAL FUNCTIONS - * - *---------------------------------------------------------------------------- - */ -#ifndef HT_BUILD_NC_ONLY -/* - ************************************************************************** - * Routing table decompressor - ************************************************************************** - */ - -/* - ************************************************************************** - * Graph Support routines - * These routines provide support for dealing with the graph representation - * of the topologies, along with the routing table information for that topology. - * The routing information is compressed and these routines currently decompress - * 'on the fly'. A graph is represented as a set of routes. All the edges in the - * graph are routes; a direct route from node i to node j exists in the graph IFF - * there is an edge directly connecting node i to node j. All other routes designate - * the edge which the route to that node initially takes, by designating a node - * to which a direct connection exists. That is, the route to non-adjacent node j - * from node i specifies node k where node i directly connects to node k. - * - * - * pseudo definition of compressed graph: - * typedef struct - * { - * BIT broadcast[8]; - * uint4 responseRoute; - * uint4 requestRoute; - * } sRoute; - * typedef struct - * { - * u8 size; - * sRoute graph[size][size]; - * } sGraph; - * - ************************************************************************** - */ - -/*---------------------------------------------------------------------------------------- - * u8 - * graphHowManyNodes(u8 *graph) - * - * Description: - * Returns the number of nodes in the compressed graph - * - * Parameters: - * @param[in] graph = a compressed graph - * @param[out] results = the number of nodes in the graph - * --------------------------------------------------------------------------------------- - */ -static u8 graphHowManyNodes(u8 *graph) -{ - return graph[0]; -} - -/*---------------------------------------------------------------------------------------- - * BOOL - * graphIsAdjacent(u8 *graph, u8 nodeA, u8 nodeB) - * - * Description: - * Returns true if NodeA is directly connected to NodeB, false otherwise - * (if NodeA == NodeB also returns false) - * Relies on rule that directly connected nodes always route requests directly. - * - * Parameters: - * @param[in] graph = the graph to examine - * @param[in] nodeA = the node number of the first node - * @param[in] nodeB = the node number of the second node - * @param[out] results = true if nodeA connects to nodeB false if not - * --------------------------------------------------------------------------------------- - */ -static BOOL graphIsAdjacent(u8 *graph, u8 nodeA, u8 nodeB) -{ - u8 size = graph[0]; - ASSERT(size <= MAX_NODES); - ASSERT((nodeA < size) && (nodeB < size)); - return (graph[1+(nodeA*size+nodeB)*2+1] & 0x0F) == nodeB; -} - -/*---------------------------------------------------------------------------------------- - * u8 - * graphGetRsp(u8 *graph, u8 nodeA, u8 nodeB) - * - * Description: - * Returns the graph node used by nodeA to route responses targeted at nodeB. - * This will be a node directly connected to nodeA (possibly nodeB itself), - * or "Route to Self" if nodeA and nodeB are the same node. - * Note that all node numbers are abstract node numbers of the topology graph, - * it is the responsibility of the caller to apply any permutation needed. - * - * Parameters: - * @param[in] u8 graph = the graph to examine - * @param[in] u8 nodeA = the node number of the first node - * @param[in] u8 nodeB = the node number of the second node - * @param[out] u8 results = The response route node - * --------------------------------------------------------------------------------------- - */ -static u8 graphGetRsp(u8 *graph, u8 nodeA, u8 nodeB) -{ - u8 size = graph[0]; - ASSERT(size <= MAX_NODES); - ASSERT((nodeA < size) && (nodeB < size)); - return (graph[1+(nodeA*size+nodeB)*2+1] & 0xF0)>>4; -} - -/*---------------------------------------------------------------------------------------- - * u8 - * graphGetReq(u8 *graph, u8 nodeA, u8 nodeB) - * - * Description: - * Returns the graph node used by nodeA to route requests targeted at nodeB. - * This will be a node directly connected to nodeA (possibly nodeB itself), - * or "Route to Self" if nodeA and nodeB are the same node. - * Note that all node numbers are abstract node numbers of the topology graph, - * it is the responsibility of the caller to apply any permutation needed. - * - * Parameters: - * @param[in] graph = the graph to examine - * @param[in] nodeA = the node number of the first node - * @param[in] nodeB = the node number of the second node - * @param[out] results = The request route node - * --------------------------------------------------------------------------------------- - */ -static u8 graphGetReq(u8 *graph, u8 nodeA, u8 nodeB) -{ - u8 size = graph[0]; - ASSERT(size <= MAX_NODES); - ASSERT((nodeA < size) && (nodeB < size)); - return (graph[1+(nodeA*size+nodeB)*2+1] & 0x0F); -} - -/*---------------------------------------------------------------------------------------- - * u8 - * graphGetBc(u8 *graph, u8 nodeA, u8 nodeB) - * - * Description: - * Returns a bit vector of nodes that nodeA should forward a broadcast from - * nodeB towards - * - * Parameters: - * @param[in] graph = the graph to examine - * @param[in] nodeA = the node number of the first node - * @param[in] nodeB = the node number of the second node - * OU results = the broadcast routes for nodeA from nodeB - * --------------------------------------------------------------------------------------- - */ -static u8 graphGetBc(u8 *graph, u8 nodeA, u8 nodeB) -{ - u8 size = graph[0]; - ASSERT(size <= MAX_NODES); - ASSERT((nodeA < size) && (nodeB < size)); - return graph[1+(nodeA*size+nodeB)*2]; -} - - -/*************************************************************************** - *** GENERIC HYPERTRANSPORT DISCOVERY CODE *** - ***************************************************************************/ - -/*---------------------------------------------------------------------------------------- - * void - * routeFromBSP(u8 targetNode, u8 actualTarget, sMainData *pDat) - * - * Description: - * Ensure a request / response route from target node to bsp. Since target node is - * always a predecessor of actual target node, each node gets a route to actual target - * on the link that goes to target. The routing produced by this routine is adequate - * for config access during discovery, but NOT for coherency. - * - * Parameters: - * @param[in] u8 targetNode = the path to actual target goes through target - * @param[in] u8 actualTarget = the ultimate target being routed to - * @param[in] sMainData* pDat = our global state, port config info - * --------------------------------------------------------------------------------------- - */ -static void routeFromBSP(u8 targetNode, u8 actualTarget, sMainData *pDat) -{ - u8 predecessorNode, predecessorLink, currentPair; - - if (targetNode == 0) - return; /* BSP has no predecessor, stop */ - - /* Search for the link that connects targetNode to its predecessor */ - currentPair = 0; - while (pDat->PortList[currentPair*2+1].NodeID != targetNode) - { - currentPair++; - ASSERT(currentPair < pDat->TotalLinks); - } - - predecessorNode = pDat->PortList[currentPair*2].NodeID; - predecessorLink = pDat->PortList[currentPair*2].Link; - - /* Recursively call self to ensure the route from the BSP to the Predecessor */ - /* Node is established */ - routeFromBSP(predecessorNode, actualTarget, pDat); - - pDat->nb->writeRoutingTable(predecessorNode, actualTarget, predecessorLink, pDat->nb); -} - -/*---------------------------------------------------------------------------*/ - -/** - * u8 - * convertNodeToLink(u8 srcNode, u8 targetNode, sMainData *pDat) - * - * Description: - * Return the link on source node which connects to target node - * - * Parameters: - * @param[in] srcNode = the source node - * @param[in] targetNode = the target node to find the link to - * @param[in] pDat = our global state - * @return the link on source which connects to target - * - */ -static u8 convertNodeToLink(u8 srcNode, u8 targetNode, sMainData *pDat) -{ - u8 targetlink = INVALID_LINK; - u8 k; - - for (k = 0; k < pDat->TotalLinks*2; k += 2) - { - if ((pDat->PortList[k+0].NodeID == srcNode) && (pDat->PortList[k+1].NodeID == targetNode)) - { - targetlink = pDat->PortList[k+0].Link; - break; - } - else if ((pDat->PortList[k+1].NodeID == srcNode) && (pDat->PortList[k+0].NodeID == targetNode)) - { - targetlink = pDat->PortList[k+1].Link; - break; - } - } - ASSERT(targetlink != INVALID_LINK); - - return targetlink; -} - - -/*---------------------------------------------------------------------------------------- - * void - * htDiscoveryFloodFill(sMainData *pDat) - * - * Description: - * Discover all coherent devices in the system, initializing some basics like node IDs - * and total nodes found in the process. As we go we also build a representation of the - * discovered system which we will use later to program the routing tables. During this - * step, the routing is via default link back to BSP and to each new node on the link it - * was discovered on (no coherency is active yet). - * - * Parameters: - * @param[in] sMainData* pDat = our global state - * --------------------------------------------------------------------------------------- - */ -static void htDiscoveryFloodFill(sMainData *pDat) -{ - uint8_t currentNode = 0; - uint8_t currentLink; - uint8_t currentLinkID; - - /* NOTE - * Each node inside a dual node (socket G34) processor must share - * an adjacent node ID. Alter the link scan order such that the - * other internal node is always scanned first... - */ - uint8_t currentLinkScanOrder_Default[8] = {0, 1, 2, 3, 4, 5, 6, 7}; - uint8_t currentLinkScanOrder_G34_Fam10[8] = {1, 0, 2, 3, 4, 5, 6, 7}; - uint8_t currentLinkScanOrder_G34_Fam15[8] = {2, 0, 1, 3, 4, 5, 6, 7}; - - uint8_t fam15h = 0; - uint8_t rev_gte_d = 0; - uint8_t dual_node = 0; - uint32_t f3xe8; - uint32_t family; - uint32_t model; - - f3xe8 = pci_read_config32(NODE_PCI(0, 3), 0xe8); - - family = model = cpuid_eax(0x80000001); - model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4); - family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8); - - if (family >= 0x6f) { - /* Family 15h or later */ - fam15h = 1; - } - - if ((model >= 0x8) || fam15h) - /* Revision D or later */ - rev_gte_d = 1; - - if (rev_gte_d) - /* Check for dual node capability */ - if (f3xe8 & 0x20000000) - dual_node = 1; - - /* Entries are always added in pairs, the even indices are the 'source' - * side closest to the BSP, the odd indices are the 'destination' side - */ - while (currentNode <= pDat->NodesDiscovered) - { - u32 temp; - - if (currentNode != 0) - { - /* Set path from BSP to currentNode */ - routeFromBSP(currentNode, currentNode, pDat); - - /* Set path from BSP to currentNode for currentNode+1 if - * currentNode+1 != MAX_NODES - */ - if (currentNode+1 != MAX_NODES) - routeFromBSP(currentNode, currentNode+1, pDat); - - /* Configure currentNode to route traffic to the BSP through its - * default link - */ - pDat->nb->writeRoutingTable(currentNode, 0, pDat->nb->readDefLnk(currentNode, pDat->nb), pDat->nb); - } - - /* Set currentNode's NodeID field to currentNode */ - pDat->nb->writeNodeID(currentNode, currentNode, pDat->nb); - - /* Enable routing tables on currentNode */ - pDat->nb->enableRoutingTables(currentNode, pDat->nb); - - for (currentLinkID = 0; currentLinkID < pDat->nb->maxLinks; currentLinkID++) - { - BOOL linkfound; - u8 token; - - if (currentLinkID < 8) { - if (dual_node) { - if (fam15h) - currentLink = currentLinkScanOrder_G34_Fam15[currentLinkID]; - else - currentLink = currentLinkScanOrder_G34_Fam10[currentLinkID]; - } else { - currentLink = currentLinkScanOrder_Default[currentLinkID]; - } - } else { - currentLink = currentLinkID; - } - - if (pDat->HtBlock->AMD_CB_IgnoreLink && pDat->HtBlock->AMD_CB_IgnoreLink(currentNode, currentLink)) - continue; - - if (pDat->nb->readTrueLinkFailStatus(currentNode, currentLink, pDat, pDat->nb)) - continue; - - /* Make sure that the link is connected, coherent, and ready */ - if (!pDat->nb->verifyLinkIsCoherent(currentNode, currentLink, pDat->nb)) - continue; - - - /* Test to see if the currentLink has already been explored */ - linkfound = FALSE; - for (temp = 0; temp < pDat->TotalLinks; temp++) - { - if ((pDat->PortList[temp*2+1].NodeID == currentNode) && - (pDat->PortList[temp*2+1].Link == currentLink)) - { - linkfound = TRUE; - break; - } - } - if (linkfound) - { - /* We had already expored this link */ - continue; - } - - if (pDat->nb->handleSpecialLinkCase(currentNode, currentLink, pDat, pDat->nb)) - { - continue; - } - - /* Modify currentNode's routing table to use currentLink to send - * traffic to currentNode+1 - */ - pDat->nb->writeRoutingTable(currentNode, currentNode+1, currentLink, pDat->nb); - - /* Check the northbridge of the node we just found, to make sure it is compatible - * before doing anything else to it. - */ - if (!pDat->nb->isCompatible(currentNode+1, pDat->nb)) - { - u8 nodeToKill; - - /* Notify BIOS of event (while variables are still the same) */ - if (pDat->HtBlock->AMD_CB_EventNotify) - { - sHtEventCohFamilyFeud evt; - evt.eSize = sizeof(sHtEventCohFamilyFeud); - evt.node = currentNode; - evt.link = currentLink; - evt.totalNodes = pDat->NodesDiscovered; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_ERROR, - HT_EVENT_COH_FAMILY_FEUD, - (u8 *)&evt); - } - - /* If node is not compatible, force boot to 1P - * If they are not compatible stop cHT init and: - * 1. Disable all cHT links on the BSP - * 2. Configure the BSP routing tables as a UP. - * 3. Notify main BIOS. - */ - pDat->NodesDiscovered = 0; - currentNode = 0; - pDat->TotalLinks = 0; - /* Abandon our coherent link data structure. At this point there may - * be coherent links on the BSP that are not yet in the portList, and - * we have to turn them off anyway. So depend on the hardware to tell us. - */ - for (currentLink = 0; currentLink < pDat->nb->maxLinks; currentLink++) - { - /* Stop all links which are connected, coherent, and ready */ - if (pDat->nb->verifyLinkIsCoherent(currentNode, currentLink, pDat->nb)) - pDat->nb->stopLink(currentNode, currentLink, pDat->nb); - } - - for (nodeToKill = 0; nodeToKill < pDat->nb->maxNodes; nodeToKill++) - { - pDat->nb->writeFullRoutingTable(0, nodeToKill, ROUTETOSELF, ROUTETOSELF, 0, pDat->nb); - } - - /* End Coherent Discovery */ - STOP_HERE; - break; - } - - /* Read token from Current+1 */ - token = pDat->nb->readToken(currentNode+1, pDat->nb); - ASSERT(token <= pDat->NodesDiscovered); - if (token == 0) - { - pDat->NodesDiscovered++; - ASSERT(pDat->NodesDiscovered < pDat->nb->maxNodes); - /* Check the capability of northbridges against the currently known configuration */ - if (!pDat->nb->isCapable(currentNode+1, pDat, pDat->nb)) - { - u8 nodeToKill; - - /* Notify BIOS of event */ - if (pDat->HtBlock->AMD_CB_EventNotify) - { - sHtEventCohMpCapMismatch evt; - evt.eSize = sizeof(sHtEventCohMpCapMismatch); - evt.node = currentNode; - evt.link = currentLink; - evt.sysMpCap = pDat->sysMpCap; - evt.totalNodes = pDat->NodesDiscovered; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_ERROR, - HT_EVENT_COH_MPCAP_MISMATCH, - (u8 *)&evt); - } - - pDat->NodesDiscovered = 0; - currentNode = 0; - pDat->TotalLinks = 0; - - for (nodeToKill = 0; nodeToKill < pDat->nb->maxNodes; nodeToKill++) - { - pDat->nb->writeFullRoutingTable(0, nodeToKill, ROUTETOSELF, ROUTETOSELF, 0, pDat->nb); - } - - /* End Coherent Discovery */ - STOP_HERE; - break; - } - - token = pDat->NodesDiscovered; - pDat->nb->writeToken(currentNode+1, token, pDat->nb); - /* Inform that we have discovered a node, so that logical id to - * socket mapping info can be recorded. - */ - if (pDat->HtBlock->AMD_CB_EventNotify) - { - sHtEventCohNodeDiscovered evt; - evt.eSize = sizeof(sHtEventCohNodeDiscovered); - evt.node = currentNode; - evt.link = currentLink; - evt.newNode = token; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_INFO, - HT_EVENT_COH_NODE_DISCOVERED, - (u8 *)&evt); - } - } - - if (pDat->TotalLinks == MAX_PLATFORM_LINKS) - { - /* - * Exceeded our capacity to describe all coherent links found in the system. - * Error strategy: - * Auto recovery is not possible because data space is already all used. - * If the callback is not implemented or returns we will continue to initialize - * the fabric we are capable of representing, adding no more nodes or links. - * This should yield a bootable topology, but likely not the one intended. - * We cannot continue discovery, there may not be any way to route a new - * node back to the BSP if we can't add links to our representation of the system. - */ - if (pDat->HtBlock->AMD_CB_EventNotify) - { - sHtEventCohLinkExceed evt; - evt.eSize = sizeof(sHtEventCohLinkExceed); - evt.node = currentNode; - evt.link = currentLink; - evt.targetNode = token; - evt.totalNodes = pDat->NodesDiscovered; - evt.maxLinks = pDat->nb->maxLinks; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_ERROR, - HT_EVENT_COH_LINK_EXCEED, - (u8 *)&evt); - } - /* Force link and node loops to halt */ - STOP_HERE; - currentNode = pDat->NodesDiscovered; - break; - } - - pDat->PortList[pDat->TotalLinks*2].Type = PORTLIST_TYPE_CPU; - pDat->PortList[pDat->TotalLinks*2].Link = currentLink; - pDat->PortList[pDat->TotalLinks*2].NodeID = currentNode; - - pDat->PortList[pDat->TotalLinks*2+1].Type = PORTLIST_TYPE_CPU; - pDat->PortList[pDat->TotalLinks*2+1].Link = pDat->nb->readDefLnk(currentNode+1, pDat->nb); - pDat->PortList[pDat->TotalLinks*2+1].NodeID = token; - - pDat->TotalLinks++; - - if (!pDat->sysMatrix[currentNode][token]) - { - pDat->sysDegree[currentNode]++; - pDat->sysDegree[token]++; - pDat->sysMatrix[currentNode][token] = TRUE; - pDat->sysMatrix[token][currentNode] = TRUE; - } - } - currentNode++; - } -} - - -/*************************************************************************** - *** ISOMORPHISM BASED ROUTING TABLE GENERATION CODE *** - ***************************************************************************/ - -/*---------------------------------------------------------------------------------------- - * BOOL - * isoMorph(u8 i, sMainData *pDat) - * - * Description: - * Is graphA isomorphic to graphB? - * if this function returns true, then Perm will contain the permutation - * required to transform graphB into graphA. - * We also use the degree of each node, that is the number of connections it has, to - * speed up rejection of non-isomorphic graphs (if there is a node in graphA with n - * connections, there must be at least one unmatched in graphB with n connections). - * - * Parameters: - * @param[in] u8 i = the discovered node which we are trying to match - * with a permutation the topology - * @param[in]/@param[out] sMainData* pDat = our global state, degree and adjacency matrix, - * output a permutation if successful - * @param[out] BOOL results = the graphs are (or are not) isomorphic - * --------------------------------------------------------------------------------------- - */ -static BOOL isoMorph(u8 i, sMainData *pDat) -{ - u8 j, k; - u8 nodecnt; - - /* We have only been called if nodecnt == pSelected->size ! */ - nodecnt = pDat->NodesDiscovered+1; - - if (i != nodecnt) - { - /* Keep building the permutation */ - for (j = 0; j < nodecnt; j++) - { - /* Make sure the degree matches */ - if (pDat->sysDegree[i] != pDat->dbDegree[j]) - continue; - - /* Make sure that j hasn't been used yet (ought to use a "used" */ - /* array instead, might be faster) */ - for (k = 0; k < i; k++) - { - if (pDat->Perm[k] == j) - break; - } - if (k != i) - continue; - pDat->Perm[i] = j; - if (isoMorph(i+1, pDat)) - return TRUE; - } - return FALSE; - } else { - /* Test to see if the permutation is isomorphic */ - for (j = 0; j < nodecnt; j++) - { - for (k = 0; k < nodecnt; k++) - { - if (pDat->sysMatrix[j][k] != - pDat->dbMatrix[pDat->Perm[j]][pDat->Perm[k]]) - return FALSE; - } - } - return TRUE; - } -} - - -/*---------------------------------------------------------------------------------------- - * void - * lookupComputeAndLoadRoutingTables(sMainData *pDat) - * - * Description: - * Using the description of the fabric topology we discovered, try to find a match - * among the supported topologies. A supported topology description matches - * the discovered fabric if the nodes can be matched in such a way that all the nodes connected - * in one set are exactly the nodes connected in the other (formally, that the graphs are - * isomorphic). Which links are used is not really important to matching. If the graphs - * match, then there is a permutation of one that translates the node positions and linkages - * to the other. - * - * In order to make the isomorphism test efficient, we test for matched number of nodes - * (a 4 node fabric is not isomorphic to a 2 node topology), and provide degrees of nodes - * to the isomorphism test. - * - * The generic routing table solution for any topology is predetermined and represented - * as part of the topology. The permutation we computed tells us how to interpret the - * routing onto the fabric we discovered. We do this working backward from the last - * node discovered to the BSP, writing the routing tables as we go. - * - * Parameters: - * @param[in] sMainData* pDat = our global state, the discovered fabric, - * @param[out] degree matrix, permutation - * --------------------------------------------------------------------------------------- - */ -static void lookupComputeAndLoadRoutingTables(sMainData *pDat) -{ - u8 **pTopologyList; - u8 *pSelected; - - int i, j, k, size; - - size = pDat->NodesDiscovered + 1; - /* Use the provided topology list or the internal, default one. */ - pTopologyList = pDat->HtBlock->topolist; - if (pTopologyList == NULL) - { - getAmdTopolist(&pTopologyList); - } - - pSelected = *pTopologyList; - while (pSelected != NULL) - { - if (graphHowManyNodes(pSelected) == size) - { - /* Build Degree vector and Adjency Matrix for this entry */ - for (i = 0; i < size; i++) - { - pDat->dbDegree[i] = 0; - for (j = 0; j < size; j++) - { - if (graphIsAdjacent(pSelected, i, j)) - { - pDat->dbMatrix[i][j] = 1; - pDat->dbDegree[i]++; - } - else - { - pDat->dbMatrix[i][j] = 0; - } - } - } - if (isoMorph(0, pDat)) - break; /* A matching topology was found */ - } - - pTopologyList++; - pSelected = *pTopologyList; - } - - if (pSelected != NULL) - { - /* Compute the reverse Permutation */ - for (i = 0; i < size; i++) - { - pDat->ReversePerm[pDat->Perm[i]] = i; - } - - /* Start with the last discovered node, and move towards the BSP */ - for (i = size-1; i >= 0; i--) - { - for (j = 0; j < size; j++) - { - u8 ReqTargetLink, RspTargetLink; - u8 ReqTargetNode, RspTargetNode; - - u8 AbstractBcTargetNodes = graphGetBc(pSelected, pDat->Perm[i], pDat->Perm[j]); - u32 BcTargetLinks = 0; - - for (k = 0; k < MAX_NODES; k++) - { - if (AbstractBcTargetNodes & ((u32)1<<k)) - { - BcTargetLinks |= (u32)1 << convertNodeToLink(i, pDat->ReversePerm[k], pDat); - } - } - - if (i == j) - { - ReqTargetLink = ROUTETOSELF; - RspTargetLink = ROUTETOSELF; - } - else - { - ReqTargetNode = graphGetReq(pSelected, pDat->Perm[i], pDat->Perm[j]); - ReqTargetLink = convertNodeToLink(i, pDat->ReversePerm[ReqTargetNode], pDat); - - RspTargetNode = graphGetRsp(pSelected, pDat->Perm[i], pDat->Perm[j]); - RspTargetLink = convertNodeToLink(i, pDat->ReversePerm[RspTargetNode], pDat); - } - - pDat->nb->writeFullRoutingTable(i, j, ReqTargetLink, RspTargetLink, BcTargetLinks, pDat->nb); - } - /* Clean up discovery 'footprint' that otherwise remains in the routing table. It didn't hurt - * anything, but might cause confusion during debug and validation. Do this by setting the - * route back to all self routes. Since it's the node that would be one more than actually installed, - * this only applies if less than maxNodes were found. - */ - if (size < pDat->nb->maxNodes) - { - pDat->nb->writeFullRoutingTable(i, size, ROUTETOSELF, ROUTETOSELF, 0, pDat->nb); - } - } - - } - else - { - /* - * No Matching Topology was found - * Error Strategy: - * Auto recovery doesn't seem likely, Force boot as 1P. - * For reporting, logging, provide number of nodes - * If not implemented or returns, boot as BSP uniprocessor. - */ - if (pDat->HtBlock->AMD_CB_EventNotify) - { - sHtEventCohNoTopology evt; - evt.eSize = sizeof(sHtEventCohNoTopology); - evt.totalNodes = pDat->NodesDiscovered; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_ERROR, - HT_EVENT_COH_NO_TOPOLOGY, - (u8 *)&evt); - } - STOP_HERE; - /* Force 1P */ - pDat->NodesDiscovered = 0; - pDat->TotalLinks = 0; - pDat->nb->enableRoutingTables(0, pDat->nb); - } -} -#endif /* HT_BUILD_NC_ONLY */ - - -/*---------------------------------------------------------------------------------------- - * void - * finializeCoherentInit(sMainData *pDat) - * - * Description: - * Find the total number of cores and update the number of nodes and cores in all cpus. - * Limit CPU config access to installed cpus. - * - * Parameters: - * @param[in] sMainData* pDat = our global state, number of nodes discovered. - * --------------------------------------------------------------------------------------- - */ -static void finializeCoherentInit(sMainData *pDat) -{ - u8 curNode; - - u8 totalCores = 0; - for (curNode = 0; curNode < pDat->NodesDiscovered+1; curNode++) - { - totalCores += pDat->nb->getNumCoresOnNode(curNode, pDat->nb); - } - - for (curNode = 0; curNode < pDat->NodesDiscovered+1; curNode++) - { - pDat->nb->setTotalNodesAndCores(curNode, pDat->NodesDiscovered+1, totalCores, pDat->nb); - } - - for (curNode = 0; curNode < pDat->NodesDiscovered+1; curNode++) - { - pDat->nb->limitNodes(curNode, pDat->nb); - } - -} - -/*---------------------------------------------------------------------------------------- - * void - * coherentInit(sMainData *pDat) - * - * Description: - * Perform discovery and initialization of the coherent fabric. - * - * Parameters: - * @param[in] sMainData* pDat = our global state - * --------------------------------------------------------------------------------------- - */ -static void coherentInit(sMainData *pDat) -{ -#ifdef HT_BUILD_NC_ONLY - /* Replace discovery process with: - * No other nodes, no coherent links - * Enable routing tables on currentNode, for power on self route - */ - pDat->NodesDiscovered = 0; - pDat->TotalLinks = 0; - pDat->nb->enableRoutingTables(0, pDat->nb); -#else - u8 i, j; - - pDat->NodesDiscovered = 0; - pDat->TotalLinks = 0; - for (i = 0; i < MAX_NODES; i++) - { - pDat->sysDegree[i] = 0; - for (j = 0; j < MAX_NODES; j++) - { - pDat->sysMatrix[i][j] = 0; - } - } - - htDiscoveryFloodFill(pDat); - lookupComputeAndLoadRoutingTables(pDat); -#endif - finializeCoherentInit(pDat); -} - -/*************************************************************************** - *** Non-coherent init code *** - *** Algorithms *** - ***************************************************************************/ -/*---------------------------------------------------------------------------------------- - * void - * processLink(u8 node, u8 link, sMainData *pDat) - * - * Description: - * Process a non-coherent link, enabling a range of bus numbers, and setting the device - * ID for all devices found - * - * Parameters: - * @param[in] u8 node = Node on which to process nc init - * @param[in] u8 link = The non-coherent link on that node - * @param[in] sMainData* pDat = our global state - * --------------------------------------------------------------------------------------- - */ -static void processLink(u8 node, u8 link, sMainData *pDat) -{ - u8 secBus, subBus; - u32 currentBUID; - u32 temp; - u32 unitIDcnt; - SBDFO currentPtr; - u8 depth; - const u8 *pSwapPtr; - - SBDFO lastSBDFO = ILLEGAL_SBDFO; - u8 lastLink = 0; - - ASSERT(node < pDat->nb->maxNodes && link < pDat->nb->maxLinks); - - if ((pDat->HtBlock->AMD_CB_OverrideBusNumbers == NULL) - || !pDat->HtBlock->AMD_CB_OverrideBusNumbers(node, link, &secBus, &subBus)) - { - /* Assign Bus numbers */ - if (pDat->AutoBusCurrent >= pDat->HtBlock->AutoBusMax) - { - /* If we run out of Bus Numbers notify, if call back unimplemented or if it - * returns, skip this chain - */ - if (pDat->HtBlock->AMD_CB_EventNotify) - { - sHTEventNcohBusMaxExceed evt; - evt.eSize = sizeof(sHTEventNcohBusMaxExceed); - evt.node = node; - evt.link = link; - evt.bus = pDat->AutoBusCurrent; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_ERROR,HT_EVENT_NCOH_BUS_MAX_EXCEED,(u8 *)&evt); - } - STOP_HERE; - return; - } - - if (pDat->UsedCfgMapEntires >= 4) - { - /* If we have used all the PCI Config maps we can't add another chain. - * Notify and if call back is unimplemented or returns, skip this chain. - */ - if (pDat->HtBlock->AMD_CB_EventNotify) - { - sHtEventNcohCfgMapExceed evt; - evt.eSize = sizeof(sHtEventNcohCfgMapExceed); - evt.node = node; - evt.link = link; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_ERROR, - HT_EVENT_NCOH_CFG_MAP_EXCEED, - (u8 *)&evt); - } - STOP_HERE; - return; - } - - secBus = pDat->AutoBusCurrent; - subBus = secBus + pDat->HtBlock->AutoBusIncrement-1; - pDat->AutoBusCurrent += pDat->HtBlock->AutoBusIncrement; - } - - pDat->nb->setCFGAddrMap(pDat->UsedCfgMapEntires, secBus, subBus, node, link, pDat, pDat->nb); - pDat->UsedCfgMapEntires++; - - if ((pDat->HtBlock->AMD_CB_ManualBUIDSwapList != NULL) - && pDat->HtBlock->AMD_CB_ManualBUIDSwapList(node, link, &pSwapPtr)) - { - /* Manual non-coherent BUID assignment */ - currentBUID = 1; - - /* Assign BUID's per manual override */ - while (*pSwapPtr != 0xFF) - { - currentPtr = MAKE_SBDFO(0, secBus, *pSwapPtr, 0, 0); - pSwapPtr++; - - do - { - AmdPCIFindNextCap(¤tPtr); - ASSERT(currentPtr != ILLEGAL_SBDFO); - AmdPCIRead(currentPtr, &temp); - } while (!IS_HT_SLAVE_CAPABILITY(temp)); - - currentBUID = *pSwapPtr; - pSwapPtr++; - AmdPCIWriteBits(currentPtr, 20, 16, ¤tBUID); - } - - /* Build chain of devices */ - depth = 0; - pSwapPtr++; - while (*pSwapPtr != 0xFF) - { - pDat->PortList[pDat->TotalLinks*2].NodeID = node; - if (depth == 0) - { - pDat->PortList[pDat->TotalLinks*2].Type = PORTLIST_TYPE_CPU; - pDat->PortList[pDat->TotalLinks*2].Link = link; - } - else - { - pDat->PortList[pDat->TotalLinks*2].Type = PORTLIST_TYPE_IO; - pDat->PortList[pDat->TotalLinks*2].Link = 1-lastLink; - pDat->PortList[pDat->TotalLinks*2].HostLink = link; - pDat->PortList[pDat->TotalLinks*2].HostDepth = depth-1; - pDat->PortList[pDat->TotalLinks*2].Pointer = lastSBDFO; - } - - pDat->PortList[pDat->TotalLinks*2+1].Type = PORTLIST_TYPE_IO; - pDat->PortList[pDat->TotalLinks*2+1].NodeID = node; - pDat->PortList[pDat->TotalLinks*2+1].HostLink = link; - pDat->PortList[pDat->TotalLinks*2+1].HostDepth = depth; - - currentPtr = MAKE_SBDFO(0, secBus, (*pSwapPtr & 0x3F), 0, 0); - do - { - AmdPCIFindNextCap(¤tPtr); - ASSERT(currentPtr != ILLEGAL_SBDFO); - AmdPCIRead(currentPtr, &temp); - } while (!IS_HT_SLAVE_CAPABILITY(temp)); - pDat->PortList[pDat->TotalLinks*2+1].Pointer = currentPtr; - lastSBDFO = currentPtr; - - /* Bit 6 indicates whether orientation override is desired. - * Bit 7 indicates the upstream link if overriding. - */ - /* assert catches at least the one known incorrect setting */ - ASSERT ((*pSwapPtr & 0x40) || (!(*pSwapPtr & 0x80))); - if (*pSwapPtr & 0x40) - { - /* Override the device's orientation */ - lastLink = *pSwapPtr >> 7; - } - else - { - /* Detect the device's orientation */ - AmdPCIReadBits(currentPtr, 26, 26, &temp); - lastLink = (u8)temp; - } - pDat->PortList[pDat->TotalLinks*2+1].Link = lastLink; - - depth++; - pDat->TotalLinks++; - pSwapPtr++; - } - } - else - { - /* Automatic non-coherent device detection */ - depth = 0; - currentBUID = 1; - while (1) - { - currentPtr = MAKE_SBDFO(0, secBus, 0, 0, 0); - - AmdPCIRead(currentPtr, &temp); - if (temp == 0xFFFFFFFF) - /* No device found at currentPtr */ - break; - - if (pDat->TotalLinks == MAX_PLATFORM_LINKS) - { - /* - * Exceeded our capacity to describe all non-coherent links found in the system. - * Error strategy: - * Auto recovery is not possible because data space is already all used. - */ - if (pDat->HtBlock->AMD_CB_EventNotify) - { - sHtEventNcohLinkExceed evt; - evt.eSize = sizeof(sHtEventNcohLinkExceed); - evt.node = node; - evt.link = link; - evt.depth = depth; - evt.maxLinks = pDat->nb->maxLinks; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_ERROR, - HT_EVENT_NCOH_LINK_EXCEED, - (u8 *)&evt); - } - /* Force link loop to halt */ - STOP_HERE; - break; - } - - pDat->PortList[pDat->TotalLinks*2].NodeID = node; - if (depth == 0) - { - pDat->PortList[pDat->TotalLinks*2].Type = PORTLIST_TYPE_CPU; - pDat->PortList[pDat->TotalLinks*2].Link = link; - } - else - { - pDat->PortList[pDat->TotalLinks*2].Type = PORTLIST_TYPE_IO; - pDat->PortList[pDat->TotalLinks*2].Link = 1-lastLink; - pDat->PortList[pDat->TotalLinks*2].HostLink = link; - pDat->PortList[pDat->TotalLinks*2].HostDepth = depth-1; - pDat->PortList[pDat->TotalLinks*2].Pointer = lastSBDFO; - } - - pDat->PortList[pDat->TotalLinks*2+1].Type = PORTLIST_TYPE_IO; - pDat->PortList[pDat->TotalLinks*2+1].NodeID = node; - pDat->PortList[pDat->TotalLinks*2+1].HostLink = link; - pDat->PortList[pDat->TotalLinks*2+1].HostDepth = depth; - - do - { - AmdPCIFindNextCap(¤tPtr); - ASSERT(currentPtr != ILLEGAL_SBDFO); - AmdPCIRead(currentPtr, &temp); - } while (!IS_HT_SLAVE_CAPABILITY(temp)); - - AmdPCIReadBits(currentPtr, 25, 21, &unitIDcnt); - if ((unitIDcnt + currentBUID > 31) || ((secBus == 0) && (unitIDcnt + currentBUID > 24))) - { - /* An error handler for the case where we run out of BUID's on a chain */ - if (pDat->HtBlock->AMD_CB_EventNotify) - { - sHtEventNcohBuidExceed evt; - evt.eSize = sizeof(sHtEventNcohBuidExceed); - evt.node = node; - evt.link = link; - evt.depth = depth; - evt.currentBUID = (uint8)currentBUID; - evt.unitCount = (uint8)unitIDcnt; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_ERROR,HT_EVENT_NCOH_BUID_EXCEED,(u8 *)&evt); - } - STOP_HERE; - break; - } - AmdPCIWriteBits(currentPtr, 20, 16, ¤tBUID); - - - currentPtr += MAKE_SBDFO(0, 0, currentBUID, 0, 0); - AmdPCIReadBits(currentPtr, 20, 16, &temp); - if (temp != currentBUID) - { - /* An error handler for this critical error */ - if (pDat->HtBlock->AMD_CB_EventNotify) - { - sHtEventNcohDeviceFailed evt; - evt.eSize = sizeof(sHtEventNcohDeviceFailed); - evt.node = node; - evt.link = link; - evt.depth = depth; - evt.attemptedBUID = (uint8)currentBUID; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_ERROR,HT_EVENT_NCOH_DEVICE_FAILED,(u8 *)&evt); - } - STOP_HERE; - break; - } - - AmdPCIReadBits(currentPtr, 26, 26, &temp); - pDat->PortList[pDat->TotalLinks*2+1].Link = (u8)temp; - pDat->PortList[pDat->TotalLinks*2+1].Pointer = currentPtr; - - lastLink = (u8)temp; - lastSBDFO = currentPtr; - - depth++; - pDat->TotalLinks++; - currentBUID += unitIDcnt; - } - if (pDat->HtBlock->AMD_CB_EventNotify) - { - /* Provide information on automatic device results */ - sHtEventNcohAutoDepth evt; - evt.eSize = sizeof(sHtEventNcohAutoDepth); - evt.node = node; - evt.link = link; - evt.depth = (depth - 1); - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_INFO,HT_EVENT_NCOH_AUTO_DEPTH,(u8 *)&evt); - } - } -} - - -/*---------------------------------------------------------------------------------------- - * void - * ncInit(sMainData *pDat) - * - * Description: - * Initialize the non-coherent fabric. Begin with the compat link on the BSP, then - * find and initialize all other non-coherent chains. - * - * Parameters: - * @param[in] sMainData* pDat = our global state - * --------------------------------------------------------------------------------------- - */ -static void ncInit(sMainData *pDat) -{ - u8 node, link; - u8 compatLink; - - compatLink = pDat->nb->readSbLink(pDat->nb); - processLink(0, compatLink, pDat); - - for (node = 0; node <= pDat->NodesDiscovered; node++) - { - for (link = 0; link < pDat->nb->maxLinks; link++) - { - if (pDat->HtBlock->AMD_CB_IgnoreLink && pDat->HtBlock->AMD_CB_IgnoreLink(node, link)) - continue; /* Skip the link */ - - if (node == 0 && link == compatLink) - continue; - - if (pDat->nb->readTrueLinkFailStatus(node, link, pDat, pDat->nb)) - continue; - - if (pDat->nb->verifyLinkIsNonCoherent(node, link, pDat->nb)) - processLink(node, link, pDat); - } - } -} - -/*************************************************************************** - *** Link Optimization *** - ***************************************************************************/ - -/*---------------------------------------------------------------------------------------- - * void - * regangLinks(sMainData *pDat) - * - * Description: - * Test the sublinks of a link to see if they qualify to be reganged. If they do, - * update the port list data to indicate that this should be done. Note that no - * actual hardware state is changed in this routine. - * - * Parameters: - * @param[in,out] sMainData* pDat = our global state - * --------------------------------------------------------------------------------------- - */ -static void regangLinks(sMainData *pDat) -{ -#ifndef HT_BUILD_NC_ONLY - u8 i, j; - for (i = 0; i < pDat->TotalLinks*2; i += 2) - { - ASSERT(pDat->PortList[i].Type < 2 && pDat->PortList[i].Link < pDat->nb->maxLinks); /* Data validation */ - ASSERT(pDat->PortList[i+1].Type < 2 && pDat->PortList[i+1].Link < pDat->nb->maxLinks); /* data validation */ - ASSERT(!(pDat->PortList[i].Type == PORTLIST_TYPE_IO && pDat->PortList[i+1].Type == PORTLIST_TYPE_CPU)); /* ensure src is closer to the bsp than dst */ - - /* Regang is false unless we pass all conditions below */ - pDat->PortList[i].SelRegang = FALSE; - pDat->PortList[i+1].SelRegang = FALSE; - - if ((pDat->PortList[i].Type != PORTLIST_TYPE_CPU) || (pDat->PortList[i+1].Type != PORTLIST_TYPE_CPU)) - continue; /* Only process CPU to CPU links */ - - for (j = i+2; j < pDat->TotalLinks*2; j += 2) - { - if ((pDat->PortList[j].Type != PORTLIST_TYPE_CPU) || (pDat->PortList[j+1].Type != PORTLIST_TYPE_CPU)) - continue; /* Only process CPU to CPU links */ - - if (pDat->PortList[i].NodeID != pDat->PortList[j].NodeID) - continue; /* Links must be from the same source */ - - if (pDat->PortList[i+1].NodeID != pDat->PortList[j+1].NodeID) - continue; /* Link must be to the same target */ - - if ((pDat->PortList[i].Link & 3) != (pDat->PortList[j].Link & 3)) - continue; /* Ensure same source base port */ - - if ((pDat->PortList[i+1].Link & 3) != (pDat->PortList[j+1].Link & 3)) - continue; /* Ensure same destination base port */ - - if ((pDat->PortList[i].Link & 4) != (pDat->PortList[i+1].Link & 4)) - continue; /* Ensure sublink0 routes to sublink0 */ - - ASSERT((pDat->PortList[j].Link & 4) == (pDat->PortList[j+1].Link & 4)); /* (therefore sublink1 routes to sublink1) */ - - if (pDat->HtBlock->AMD_CB_SkipRegang && - pDat->HtBlock->AMD_CB_SkipRegang(pDat->PortList[i].NodeID, - pDat->PortList[i].Link & 0x03, - pDat->PortList[i+1].NodeID, - pDat->PortList[i+1].Link & 0x03)) - { - continue; /* Skip regang */ - } - - - pDat->PortList[i].Link &= 0x03; /* Force to point to sublink0 */ - pDat->PortList[i+1].Link &= 0x03; - pDat->PortList[i].SelRegang = TRUE; /* Enable link reganging */ - pDat->PortList[i+1].SelRegang = TRUE; - pDat->PortList[i].PrvWidthOutCap = HT_WIDTH_16_BITS; - pDat->PortList[i+1].PrvWidthOutCap = HT_WIDTH_16_BITS; - pDat->PortList[i].PrvWidthInCap = HT_WIDTH_16_BITS; - pDat->PortList[i+1].PrvWidthInCap = HT_WIDTH_16_BITS; - - /* Delete PortList[j, j+1], slow but easy to debug implementation */ - pDat->TotalLinks--; - Amdmemcpy(&(pDat->PortList[j]), &(pDat->PortList[j+2]), sizeof(sPortDescriptor)*(pDat->TotalLinks*2-j)); - Amdmemset(&(pDat->PortList[pDat->TotalLinks*2]), INVALID_LINK, sizeof(sPortDescriptor)*2); - - /* //High performance, but would make debuging harder due to 'shuffling' of the records */ - /* //Amdmemcpy(PortList[TotalPorts-2], PortList[j], SIZEOF(sPortDescriptor)*2); */ - /* //TotalPorts -=2; */ - - break; /* Exit loop, advance to PortList[i+2] */ - } - } -#endif /* HT_BUILD_NC_ONLY */ -} - -static void detectIoLinkIsochronousCapable(sMainData *pDat) -{ - uint8_t i; - unsigned char iommu; - uint8_t isochronous_capable = 0; - - iommu = 1; - get_option(&iommu, "iommu"); - - for (i = 0; i < pDat->TotalLinks*2; i += 2) { - if ((pDat->PortList[i].Type == PORTLIST_TYPE_CPU) && (pDat->PortList[i+1].Type == PORTLIST_TYPE_IO)) { - if ((pDat->PortList[i].PrvFeatureCap & 0x1) && (pDat->PortList[i+1].PrvFeatureCap & 0x1)) { - pDat->PortList[i].enable_isochronous_mode = 1; - pDat->PortList[i+1].enable_isochronous_mode = 1; - isochronous_capable = 1; - } else { - pDat->PortList[i].enable_isochronous_mode = 0; - pDat->PortList[i+1].enable_isochronous_mode = 0; - } - } - } - - if (isochronous_capable && iommu) { - printk(BIOS_DEBUG, "Forcing HT links to isochronous mode due to enabled IOMMU\n"); - /* Isochronous mode must be set on all links if the IOMMU is enabled */ - for (i = 0; i < pDat->TotalLinks*2; i += 2) { - pDat->PortList[i].enable_isochronous_mode = 1; - pDat->PortList[i+1].enable_isochronous_mode = 1; - } - } -} - -/*---------------------------------------------------------------------------------------- - * void - * selectOptimalWidthAndFrequency(sMainData *pDat) - * - * Description: - * For all links: - * Examine both sides of a link and determine the optimal frequency and width, - * taking into account externally provided limits and enforcing any other limit - * or matching rules as applicable except sublink balancing. Update the port - * list date with the optimal settings. - * Note no hardware state changes in this routine. - * - * Parameters: - * @param[in,out] sMainData* pDat = our global state, port list data - * --------------------------------------------------------------------------------------- - */ -static void selectOptimalWidthAndFrequency(sMainData *pDat) -{ - u8 i, j; - uint32_t temp; - uint32_t cbPCBFreqLimit; - uint32_t cbPCBFreqLimit_NVRAM; - u8 cbPCBABDownstreamWidth; - u8 cbPCBBAUpstreamWidth; - - cbPCBFreqLimit_NVRAM = 0xfffff; - if (get_option(&temp, "hypertransport_speed_limit") == CB_SUCCESS) - cbPCBFreqLimit_NVRAM = ht_speed_limit[temp & 0xf]; - - if (!is_fam15h()) { - /* FIXME - * By default limit frequency to 2.6 GHz as there are residual - * problems with HT v3.1 implementation on at least some Socket G34 - * mainboards / Fam10h CPUs. - * Debug the issues and reenable this... - */ - if (cbPCBFreqLimit_NVRAM > 0xffff) - cbPCBFreqLimit_NVRAM = 0xffff; - } - - for (i = 0; i < pDat->TotalLinks*2; i += 2) - { - cbPCBFreqLimit = 0xfffff; // Maximum allowed by autoconfiguration - if (pDat->HtBlock->ht_link_configuration) - cbPCBFreqLimit = ht_speed_mhz_to_hw(pDat->HtBlock->ht_link_configuration->ht_speed_limit); - cbPCBFreqLimit = min(cbPCBFreqLimit, cbPCBFreqLimit_NVRAM); - -#if CONFIG(LIMIT_HT_DOWN_WIDTH_8) - cbPCBABDownstreamWidth = 8; -#else - cbPCBABDownstreamWidth = 16; -#endif - -#if CONFIG(LIMIT_HT_UP_WIDTH_8) - cbPCBBAUpstreamWidth = 8; -#else - cbPCBBAUpstreamWidth = 16; -#endif - - if ((pDat->PortList[i].Type == PORTLIST_TYPE_CPU) && (pDat->PortList[i+1].Type == PORTLIST_TYPE_CPU)) - { - if (pDat->HtBlock->AMD_CB_Cpu2CpuPCBLimits) - { - pDat->HtBlock->AMD_CB_Cpu2CpuPCBLimits( - pDat->PortList[i].NodeID, - pDat->PortList[i].Link, - pDat->PortList[i+1].NodeID, - pDat->PortList[i+1].Link, - &cbPCBABDownstreamWidth, - &cbPCBBAUpstreamWidth, &cbPCBFreqLimit - ); - } - } - else - { - if (pDat->HtBlock->AMD_CB_IOPCBLimits) - { - pDat->HtBlock->AMD_CB_IOPCBLimits( - pDat->PortList[i+1].NodeID, - pDat->PortList[i+1].HostLink, - pDat->PortList[i+1].HostDepth, - &cbPCBABDownstreamWidth, - &cbPCBBAUpstreamWidth, &cbPCBFreqLimit - ); - } - } - - temp = pDat->PortList[i].PrvFrequencyCap; - temp &= pDat->PortList[i+1].PrvFrequencyCap; - temp &= cbPCBFreqLimit; - pDat->PortList[i].CompositeFrequencyCap = temp; - pDat->PortList[i+1].CompositeFrequencyCap = temp; - - ASSERT (temp != 0); - for (j = 19;; j--) - { - if ((j == 16) || (j == 15)) - continue; - if (temp & ((uint32_t)1 << j)) - break; - } - - pDat->PortList[i].SelFrequency = j; - pDat->PortList[i+1].SelFrequency = j; - - temp = pDat->PortList[i].PrvWidthOutCap; - if (pDat->PortList[i+1].PrvWidthInCap < temp) - temp = pDat->PortList[i+1].PrvWidthInCap; - if (cbPCBABDownstreamWidth < temp) - temp = cbPCBABDownstreamWidth; - pDat->PortList[i].SelWidthOut = (u8)temp; - pDat->PortList[i+1].SelWidthIn = (u8)temp; - - temp = pDat->PortList[i].PrvWidthInCap; - if (pDat->PortList[i+1].PrvWidthOutCap < temp) - temp = pDat->PortList[i+1].PrvWidthOutCap; - if (cbPCBBAUpstreamWidth < temp) - temp = cbPCBBAUpstreamWidth; - pDat->PortList[i].SelWidthIn = (u8)temp; - pDat->PortList[i+1].SelWidthOut = (u8)temp; - } -} - -/*---------------------------------------------------------------------------------------- - * void - * hammerSublinkFixup(sMainData *pDat) - * - * Description: - * Iterate through all links, checking the frequency of each sublink pair. Make the - * adjustment to the port list data so that the frequencies are at a valid ratio, - * reducing frequency as needed to achieve this. (All links support the minimum 200 MHz - * frequency.) Repeat the above until no adjustments are needed. - * Note no hardware state changes in this routine. - * - * Parameters: - * @param[in,out] sMainData* pDat = our global state, link state and port list - * --------------------------------------------------------------------------------------- - */ -static void hammerSublinkFixup(sMainData *pDat) -{ -#ifndef HT_BUILD_NC_ONLY - u8 i, j, k; - BOOL changes, downgrade; - - u8 hiIndex; - u8 hiFreq, loFreq; - - u32 temp; - - do - { - changes = FALSE; - for (i = 0; i < pDat->TotalLinks*2; i++) - { - if (pDat->PortList[i].Type != PORTLIST_TYPE_CPU) /* Must be a CPU link */ - continue; - if (pDat->PortList[i].Link < 4) /* Only look for sublink1's */ - continue; - - for (j = 0; j < pDat->TotalLinks*2; j++) - { - /* Step 1. Find the matching sublink0 */ - if (pDat->PortList[j].Type != PORTLIST_TYPE_CPU) - continue; - if (pDat->PortList[j].NodeID != pDat->PortList[i].NodeID) - continue; - if (pDat->PortList[j].Link != (pDat->PortList[i].Link & 0x03)) - continue; - - /* Step 2. Check for an illegal frequency ratio */ - if (pDat->PortList[i].SelFrequency >= pDat->PortList[j].SelFrequency) - { - hiIndex = i; - hiFreq = pDat->PortList[i].SelFrequency; - loFreq = pDat->PortList[j].SelFrequency; - } - else - { - hiIndex = j; - hiFreq = pDat->PortList[j].SelFrequency; - loFreq = pDat->PortList[i].SelFrequency; - } - - if (hiFreq == loFreq) - break; /* The frequencies are 1:1, no need to do anything */ - - downgrade = FALSE; - - if (hiFreq == 13) - { - if ((loFreq != 7) && /* {13, 7} 2400MHz / 1200MHz 2:1 */ - (loFreq != 4) && /* {13, 4} 2400MHz / 600MHz 4:1 */ - (loFreq != 2)) /* {13, 2} 2400MHz / 400MHz 6:1 */ - downgrade = TRUE; - } - else if (hiFreq == 11) - { - if ((loFreq != 6)) /* {11, 6} 2000MHz / 1000MHz 2:1 */ - downgrade = TRUE; - } - else if (hiFreq == 9) - { - if ((loFreq != 5) && /* { 9, 5} 1600MHz / 800MHz 2:1 */ - (loFreq != 2) && /* { 9, 2} 1600MHz / 400MHz 4:1 */ - (loFreq != 0)) /* { 9, 0} 1600MHz / 200MHz 8:1 */ - downgrade = TRUE; - } - else if (hiFreq == 7) - { - if ((loFreq != 4) && /* { 7, 4} 1200MHz / 600MHz 2:1 */ - (loFreq != 0)) /* { 7, 0} 1200MHz / 200MHz 6:1 */ - downgrade = TRUE; - } - else if (hiFreq == 5) - { - if ((loFreq != 2) && /* { 5, 2} 800MHz / 400MHz 2:1 */ - (loFreq != 0)) /* { 5, 0} 800MHz / 200MHz 4:1 */ - downgrade = TRUE; - } - else if (hiFreq == 2) - { - if ((loFreq != 0)) /* { 2, 0} 400MHz / 200MHz 2:1 */ - downgrade = TRUE; - } - else - { - downgrade = TRUE; /* no legal ratios for hiFreq */ - } - - /* Step 3. Downgrade the higher of the two frequencies, and set nochanges to FALSE */ - if (downgrade) - { - /* Although the problem was with the port specified by hiIndex, we need to */ - /* downgrade both ends of the link. */ - hiIndex = hiIndex & 0xFE; /* Select the 'upstream' (i.e. even) port */ - - temp = pDat->PortList[hiIndex].CompositeFrequencyCap; - - /* Remove hiFreq from the list of valid frequencies */ - temp = temp & ~((uint32)1 << hiFreq); - ASSERT (temp != 0); - pDat->PortList[hiIndex].CompositeFrequencyCap = temp; - pDat->PortList[hiIndex+1].CompositeFrequencyCap = temp; - - for (k = 19;; k--) - { - if ((j == 16) || (j == 15)) - continue; - if (temp & ((uint32_t)1 << k)) - break; - } - - pDat->PortList[hiIndex].SelFrequency = k; - pDat->PortList[hiIndex+1].SelFrequency = k; - - changes = TRUE; - } - } - } - } while (changes); /* Repeat until a valid configuration is reached */ -#endif /* HT_BUILD_NC_ONLY */ -} - -/*---------------------------------------------------------------------------------------- - * void - * linkOptimization(sMainData *pDat) - * - * Description: - * Based on link capabilities, apply optimization rules to come up with the real best - * settings, including several external limit decision from call backs. This includes - * handling of sublinks. Finally, after the port list data is updated, set the hardware - * state for all links. - * - * Parameters: - * @param[in] sMainData* pDat = our global state - * --------------------------------------------------------------------------------------- - */ -static void linkOptimization(sMainData *pDat) -{ - pDat->nb->gatherLinkData(pDat, pDat->nb); - regangLinks(pDat); - if (is_fam15h()) - detectIoLinkIsochronousCapable(pDat); - selectOptimalWidthAndFrequency(pDat); - hammerSublinkFixup(pDat); - pDat->nb->setLinkData(pDat, pDat->nb); -} - - -/*---------------------------------------------------------------------------------------- - * void - * trafficDistribution(sMainData *pDat) - * - * Description: - * In the case of a two node system with both sublinks used, enable the traffic - * distribution feature. - * - * Parameters: - * @param[in] sMainData* pDat = our global state, port list data - * --------------------------------------------------------------------------------------- - */ -static void trafficDistribution(sMainData *pDat) -{ -#ifndef HT_BUILD_NC_ONLY - u32 links01, links10; - u8 linkCount; - u8 i; - - /* Traffic Distribution is only used when there are exactly two nodes in the system */ - if (pDat->NodesDiscovered+1 != 2) - return; - - links01 = 0; - links10 = 0; - linkCount = 0; - for (i = 0; i < pDat->TotalLinks*2; i += 2) - { - if ((pDat->PortList[i].Type == PORTLIST_TYPE_CPU) && (pDat->PortList[i+1].Type == PORTLIST_TYPE_CPU)) - { - links01 |= (u32)1 << pDat->PortList[i].Link; - links10 |= (u32)1 << pDat->PortList[i+1].Link; - linkCount++; - } - } - ASSERT(linkCount != 0); - if (linkCount == 1) - return; /* Don't setup Traffic Distribution if only one link is being used */ - - pDat->nb->writeTrafficDistribution(links01, links10, pDat->nb); -#endif /* HT_BUILD_NC_ONLY */ -} - -/*---------------------------------------------------------------------------------------- - * void - * tuning(sMainData *pDat) - * - * Description: - * Handle system and performance tunings, such as traffic distribution, fifo and - * buffer tuning, and special config tunings. - * - * Parameters: - * @param[in] sMainData* pDat = our global state, port list data - * --------------------------------------------------------------------------------------- - */ -static void tuning(sMainData *pDat) -{ - u8 i; - - /* See if traffic distribution can be done and do it if so - * or allow system specific customization - */ - if ((pDat->HtBlock->AMD_CB_CustomizeTrafficDistribution == NULL) - || !pDat->HtBlock->AMD_CB_CustomizeTrafficDistribution()) - { - trafficDistribution(pDat); - } - - /* For each node, invoke northbridge specific buffer tunings or - * system specific customizations. - */ - for (i = 0; i < pDat->NodesDiscovered + 1; i++) - { - if ((pDat->HtBlock->AMD_CB_CustomizeBuffers == NULL) - || !pDat->HtBlock->AMD_CB_CustomizeBuffers(i)) - { - pDat->nb->bufferOptimizations(i, pDat, pDat->nb); - } - } -} - -/*---------------------------------------------------------------------------------------- - * BOOL - * isSanityCheckOk() - * - * Description: - * Perform any general sanity checks which should prevent HT from running if they fail. - * Currently only the "Must run on BSP only" check. - * - * Parameters: - * @param[out] result BOOL = true if check is ok, false if it failed - * --------------------------------------------------------------------------------------- - */ -static BOOL isSanityCheckOk(void) -{ - uint64 qValue; - - AmdMSRRead(LAPIC_BASE_MSR, &qValue); - - return ((qValue.lo & LAPIC_BASE_MSR_BOOTSTRAP_PROCESSOR) != 0); -} - -/*************************************************************************** - *** HT Initialize *** - ***************************************************************************/ - -/*---------------------------------------------------------------------------------------- - * void - * htInitialize(AMD_HTBLOCK *pBlock) - * - * Description: - * This is the top level external interface for Hypertransport Initialization. - * Create our initial internal state, initialize the coherent fabric, - * initialize the non-coherent chains, and perform any required fabric tuning or - * optimization. - * - * Parameters: - * @param[in] AMD_HTBLOCK* pBlock = Our Initial State including possible - * topologies and routings, non coherent bus - * assignment info, and actual - * wrapper or OEM call back routines. - * --------------------------------------------------------------------------------------- - */ -void amdHtInitialize(AMD_HTBLOCK *pBlock) -{ - sMainData pDat; - cNorthBridge nb; - - if (isSanityCheckOk()) - { - newNorthBridge(0, &nb); - - pDat.HtBlock = pBlock; - pDat.nb = &nb; - pDat.sysMpCap = nb.maxNodes; - nb.isCapable(0, &pDat, pDat.nb); - coherentInit(&pDat); - - pDat.AutoBusCurrent = pBlock->AutoBusStart; - pDat.UsedCfgMapEntires = 0; - ncInit(&pDat); - linkOptimization(&pDat); - tuning(&pDat); - } -} diff --git a/src/northbridge/amd/amdht/h3finit.h b/src/northbridge/amd/amdht/h3finit.h deleted file mode 100644 index 743ae97065..0000000000 --- a/src/northbridge/amd/amdht/h3finit.h +++ /dev/null @@ -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 */ diff --git a/src/northbridge/amd/amdht/h3gtopo.h b/src/northbridge/amd/amdht/h3gtopo.h deleted file mode 100644 index e211d4c006..0000000000 --- a/src/northbridge/amd/amdht/h3gtopo.h +++ /dev/null @@ -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 */ diff --git a/src/northbridge/amd/amdht/h3ncmn.c b/src/northbridge/amd/amdht/h3ncmn.c deleted file mode 100644 index 830e9888c9..0000000000 --- a/src/northbridge/amd/amdht/h3ncmn.c +++ /dev/null @@ -1,2549 +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. - */ - - -/*---------------------------------------------------------------------------- - * MODULES USED - * - *---------------------------------------------------------------------------- - */ - -#include "h3ncmn.h" -#include "h3finit.h" -#include "h3ffeat.h" -#include "AsPsNb.h" - -#include <arch/cpu.h> -#include <device/pci.h> -#include <cpu/amd/msr.h> -#include <device/pci_def.h> -#include <northbridge/amd/amdfam10/raminit.h> -#include <northbridge/amd/amdfam10/amdfam10.h> - -/*---------------------------------------------------------------------------- - * DEFINITIONS AND MACROS - * - *---------------------------------------------------------------------------- - */ - -/* CPU Northbridge Functions */ -#define CPU_HTNB_FUNC_00 0 -#define CPU_HTNB_FUNC_04 4 -#define CPU_ADDR_FUNC_01 1 -#define CPU_NB_FUNC_03 3 -#define CPU_NB_FUNC_05 5 - -/* Function 0 registers */ -#define REG_ROUTE0_0X40 0x40 -#define REG_ROUTE1_0X44 0x44 -#define REG_NODE_ID_0X60 0x60 -#define REG_UNIT_ID_0X64 0x64 -#define REG_LINK_TRANS_CONTROL_0X68 0x68 -#define REG_LINK_INIT_CONTROL_0X6C 0x6c -#define REG_HT_CAP_BASE_0X80 0x80 -#define REG_NORTHBRIDGE_CFG_3X8C 0x8c -#define REG_HT_LINK_RETRY0_0X130 0x130 -#define REG_HT_TRAFFIC_DIST_0X164 0x164 -#define REG_HT_LINK_EXT_CONTROL0_0X170 0x170 - -#define HT_CONTROL_CLEAR_CRC (~(3 << 8)) - -/* Function 1 registers */ -#define REG_ADDR_CONFIG_MAP0_1XE0 0xE0 -#define CPU_ADDR_NUM_CONFIG_MAPS 4 - -/* Function 3 registers */ -#define REG_NB_SRI_XBAR_BUF_3X70 0x70 -#define REG_NB_MCT_XBAR_BUF_3X78 0x78 -#define REG_NB_FIFOPTR_3XDC 0xDC -#define REG_NB_CAPABILITY_3XE8 0xE8 -#define REG_NB_CPUID_3XFC 0xFC -#define REG_NB_LINK_XCS_TOKEN0_3X148 0x148 -#define REG_NB_DOWNCORE_3X190 0x190 -#define REG_NB_CAPABILITY_5X84 0x84 - -/* Function 4 registers */ - - -/*---------------------------------------------------------------------------- - * TYPEDEFS AND STRUCTURES - * - *---------------------------------------------------------------------------- - */ -/*---------------------------------------------------------------------------- - * PROTOTYPES OF LOCAL FUNCTIONS - * - *---------------------------------------------------------------------------- - */ - -/*************************************************************************** - *** FAMILY/NORTHBRIDGE SPECIFIC FUNCTIONS *** - ***************************************************************************/ - -inline uint8_t is_gt_rev_d(void) -{ - uint8_t fam15h = 0; - uint8_t rev_gte_d = 0; - uint32_t family; - uint32_t model; - - family = model = cpuid_eax(0x80000001); - model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4); - family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8); - - if (family >= 0x6f) - /* Family 15h or later */ - fam15h = 1; - - if ((model >= 0x8) || fam15h) - /* Revision D or later */ - rev_gte_d = 1; - - return rev_gte_d; -} - -/***************************************************************************//** - * - * SBDFO - * makeLinkBase(u8 currentNode, u8 currentLink) - * - * Description: - * Private to northbridge implementation. Return the HT Host capability base - * PCI config address for a link. - * - * Parameters: - * @param[in] node = the node this link is on - * @param[in] link = the link - * - *****************************************************************************/ -static SBDFO makeLinkBase(u8 node, u8 link) -{ - SBDFO linkBase; - - /* With rev F can not be called with a 4th link or with the sublinks */ - if (link < 4) - linkBase = MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_HTNB_FUNC_00, - REG_HT_CAP_BASE_0X80 + link*HT_HOST_CAP_SIZE); - else - linkBase = MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_HTNB_FUNC_04, - REG_HT_CAP_BASE_0X80 + (link-4)*HT_HOST_CAP_SIZE); - return linkBase; -} - -/***************************************************************************//** - * - * void - * setHtControlRegisterBits(SBDFO reg, u8 hiBit, u8 loBit, u32 *pValue) - * - * Description: - * Private to northbridge implementation. Provide a common routine for accessing the - * HT Link Control registers (84, a4, c4, e4), to enforce not clearing the - * HT CRC error bits. Replaces direct use of AmdPCIWriteBits(). - * NOTE: This routine is called for IO Devices as well as CPUs! - * - * Parameters: - * @param[in] reg = the PCI config address the control register - * @param[in] hiBit = the high bit number - * @param[in] loBit = the low bit number - * @param[in] pValue = the value to write to that bit range. Bit 0 => loBit. - * - *****************************************************************************/ -static void setHtControlRegisterBits(SBDFO reg, u8 hiBit, u8 loBit, u32 *pValue) -{ - u32 temp, mask; - - ASSERT((hiBit < 32) && (loBit < 32) && (hiBit >= loBit) && ((reg & 0x3) == 0)); - ASSERT((hiBit < 8) || (loBit > 9)); - - /* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */ - if ((hiBit-loBit) != 31) - mask = (((u32)1 << (hiBit-loBit+1))-1); - else - mask = (u32)0xFFFFFFFF; - - AmdPCIRead(reg, &temp); - temp &= ~(mask << loBit); - temp |= (*pValue & mask) << loBit; - temp &= (u32)HT_CONTROL_CLEAR_CRC; - AmdPCIWrite(reg, &temp); -} - -/***************************************************************************//** - * - * static void - * writeRoutingTable(u8 node, u8 target, u8 Link, cNorthBridge *nb) - * - * Description: - * This routine will modify the routing tables on the - * SourceNode to cause it to route both request and response traffic to the - * targetNode through the specified Link. - * - * NOTE: This routine is to be used for early discovery and initialization. The - * final routing tables must be loaded some other way because this - * routine does not address the issue of probes, or independent request - * response paths. - * - * Parameters: - * @param[in] node = the node that will have it's routing tables modified. - * @param[in] target = For routing to node target - * @param[in] link = Link from node to target - * @param[in] *nb = this northbridge - * - *****************************************************************************/ - -static void writeRoutingTable(u8 node, u8 target, u8 link, cNorthBridge *nb) -{ -#ifndef HT_BUILD_NC_ONLY - u32 temp = (nb->selfRouteResponseMask | nb->selfRouteRequestMask) << (link + 1); - ASSERT((node < nb->maxNodes) && (target < nb->maxNodes) && (link < nb->maxLinks)); - AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_HTNB_FUNC_00, - REG_ROUTE0_0X40 + target*4), - &temp); -#else - STOP_HERE; -#endif -} - -/***************************************************************************//** - * - * static void - * writeNodeID(u8 node, u8 nodeID, cNorthBridge *nb) - * - * Description: - * Modifies the NodeID register on the target node - * - * Parameters: - * @param[in] node = the node that will have its NodeID altered. - * @param[in] nodeID = the new value for NodeID - * @param[in] *nb = this northbridge - * - *****************************************************************************/ - -static void writeNodeID(u8 node, u8 nodeID, cNorthBridge *nb) -{ - u32 temp; - ASSERT((node < nb->maxNodes) && (nodeID < nb->maxNodes)); - if (is_fam15h()) { - temp = 1; - AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NORTHBRIDGE_CFG_3X8C), - 22, 22, &temp); - } - temp = nodeID; - AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_HTNB_FUNC_00, - REG_NODE_ID_0X60), - 2, 0, &temp); -} - -/***************************************************************************//** - * - * static void - * readDefLnk(u8 node, cNorthBridge *nb) - * - * Description: - * Read the DefLnk (the source link of the current packet) - * from node - * - * Parameters: - * @param[in] node = the node that will have its NodeID altered. - * @param[in] *nb = this northbridge - * @return The HyperTransport link where the request to - * read the default link came from. Since this - * code is running on the BSP, this should be the link - * pointing back towards the BSP. - * - *****************************************************************************/ - -static u8 readDefLnk(u8 node, cNorthBridge *nb) -{ - u32 deflink = 0; - SBDFO licr; - u32 temp; - - licr = MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_HTNB_FUNC_00, - REG_LINK_INIT_CONTROL_0X6C); - - ASSERT((node < nb->maxNodes)); - AmdPCIReadBits(licr, 3, 2, &deflink); - AmdPCIReadBits(licr, 8, 8, &temp); /* on rev F, this bit is reserved == 0 */ - deflink |= temp << 2; - return (u8)deflink; -} - -/***************************************************************************//** - * - * static void - * enableRoutingTables(u8 node, cNorthBridge *nb) - * - * Description: - * Turns routing tables on for a given node - * - * Parameters: - * @param[in] node = the node that will have it's routing tables enabled - * @param[in] *nb = this northbridge - * - *****************************************************************************/ - -static void enableRoutingTables(u8 node, cNorthBridge *nb) -{ - u32 temp = 0; - ASSERT((node < nb->maxNodes)); - AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_HTNB_FUNC_00, - REG_LINK_INIT_CONTROL_0X6C), - 0, 0, &temp); -} - - -/***************************************************************************//** - * - * static BOOL - * verifyLinkIsCoherent(u8 node, u8 Link, cNorthBridge *nbk) - * - * Description: - * Verify that the link is coherent, connected, and ready - * - * Parameters: - * @param[in] node = the node that will be examined - * @param[in] link = the link on that Node to examine - * @param[in] *nb = this northbridge - * @return true - The link has the following status - * linkCon = 1, Link is connected - * InitComplete = 1, Link initialization is complete - * NC = 0, Link is coherent - * UniP-cLDT = 0, Link is not Uniprocessor cLDT - * LinkConPend = 0 Link connection is not pending - * false- The link has some other status - * - *****************************************************************************/ - -static BOOL verifyLinkIsCoherent(u8 node, u8 link, cNorthBridge *nb) -{ -#ifndef HT_BUILD_NC_ONLY - - u32 linkType; - SBDFO linkBase; - - ASSERT((node < nb->maxNodes) && (link < nb->maxLinks)); - - linkBase = makeLinkBase(node, link); - - /* FN0_98/A4/C4 = LDT Type Register */ - AmdPCIRead(linkBase + HTHOST_LINK_TYPE_REG, &linkType); - - /* Verify LinkCon = 1, InitComplete = 1, NC = 0, UniP-cLDT = 0, LinkConPend = 0 */ - return (linkType & HTHOST_TYPE_MASK) == HTHOST_TYPE_COHERENT; -#else - return 0; -#endif /* HT_BUILD_NC_ONLY */ -} - -/***************************************************************************//** - * - * static bool - * readTrueLinkFailStatus(u8 node, u8 link, sMainData *pDat, cNorthBridge *nb) - * - * Description: - * Return the LinkFailed status AFTER an attempt is made to clear the bit. - * Also, call event notify if a Hardware Fault caused a synch flood on a previous boot. - * - * The table below summarizes correct responses of this routine. - * Family before after unconnected Notify? return - * 0F 0 0 0 No 0 - * 0F 1 0 0 Yes 0 - * 0F 1 1 X No 1 - * 10 0 0 0 No 0 - * 10 1 0 0 Yes 0 - * 10 1 0 3 No 1 - * - * Parameters: - * @param[in] node = the node that will be examined - * @param[in] link = the link on that node to examine - * @param[in] *pDat = access to call back routine - * @param[in] *nb = this northbridge - * @return true - the link is not connected or has hard error - * false- if the link is connected - * - *****************************************************************************/ - -static BOOL readTrueLinkFailStatus(u8 node, u8 link, sMainData *pDat, cNorthBridge *nb) -{ - u32 before, after, unconnected, crc; - SBDFO linkBase; - - ASSERT((node < nb->maxNodes) && (link < nb->maxLinks)); - - linkBase = makeLinkBase(node, link); - - /* Save the CRC status before doing anything else. - * Read, Clear, the Re-read the error bits in the Link Control Register - * FN0_84/A4/C4[4] = LinkFail bit - * and the connection status, TransOff and EndOfChain - */ - AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 9, 8, &crc); - AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 4, 4, &before); - setHtControlRegisterBits(linkBase + HTHOST_LINK_CONTROL_REG, 4, 4, &before); - AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 4, 4, &after); - AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 7, 6, &unconnected); - - if (before != after) - { - if (!unconnected) - { - if (crc != 0) - { - /* A synch flood occurred due to HT CRC */ - if (pDat->HtBlock->AMD_CB_EventNotify) - { - /* Pass the node and link on which the generic synch flood event occurred. */ - sHtEventHWHtCrc evt; - evt.eSize = sizeof(sHtEventHWHtCrc); - evt.node = node; - evt.link = link; - evt.laneMask = (uint8)crc; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_HW_FAULT, - HT_EVENT_HW_HTCRC, - (u8 *)&evt); - } - } - else - { - /* Some synch flood occurred */ - if (pDat->HtBlock->AMD_CB_EventNotify) - { - /* Pass the node and link on which the generic synch flood event occurred. */ - sHtEventHWSynchFlood evt; - evt.eSize = sizeof(sHtEventHWSynchFlood); - evt.node = node; - evt.link = link; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_HW_FAULT, - HT_EVENT_HW_SYNCHFLOOD, - (u8 *)&evt); - } - } - } - } - return ((after != 0) || unconnected); -} - - -/***************************************************************************//** - * - * static u8 - * readToken(u8 node, cNorthBridge *nb) - * - * Description: - * Read the token stored in the scratchpad register - * NOTE: The location used to store the token is arbitrary. The only - * requirement is that the location warm resets to zero, and that - * using it will have no ill-effects during HyperTransport initialization. - * - * Parameters: - * @param[in] node = the node that will be examined - * @param[in] *nb = this northbridge - * @return the Token read from the node - * - *****************************************************************************/ -static u8 readToken(u8 node, cNorthBridge *nb) -{ - u32 temp; - - ASSERT((node < nb->maxNodes)); - /* Use CpuCnt as a scratch register */ - /* Limiting use to 4 bits makes code GH to rev F compatible. */ - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_HTNB_FUNC_00, - REG_NODE_ID_0X60), - 19, 16, &temp); - - return (u8)temp; -} - - -/***************************************************************************//** - * - * static void - * writeToken(u8 node, u8 Value, cNorthBridge *nb) - * - * Description: - * Write the token stored in the scratchpad register - * NOTE: The location used to store the token is arbitrary. The only - * requirement is that the location warm resets to zero, and that - * using it will have no ill-effects during HyperTransport initialization. - * Limiting use to 4 bits makes code GH to rev F compatible. - * - * Parameters: - * @param[in] node = the node that will be examined - * @param value - * @param[in] *nb = this northbridge - * - *****************************************************************************/ -static void writeToken(u8 node, u8 value, cNorthBridge *nb) -{ - u32 temp = value; - ASSERT((node < nb->maxNodes)); - /* Use CpuCnt as a scratch register */ - /* Limiting use to 4 bits makes code GH to rev F compatible. */ - AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_HTNB_FUNC_00, - REG_NODE_ID_0X60), - 19, 16, &temp); -} - -/***************************************************************************//** - * - * static u8 - * fam0FGetNumCoresOnNode(u8 node, cNorthBridge *nb) - * - * Description: - * Return the number of cores (1 based count) on node. - * - * Parameters: - * @param[in] node = the node that will be examined - * @param[in] *nb = this northbridge - * @return = the number of cores - * - * --------------------------------------------------------------------------------------- - */ -static u8 fam0FGetNumCoresOnNode(u8 node, cNorthBridge *nb) -{ - u32 temp; - - ASSERT((node < nb->maxNodes)); - /* Read CmpCap */ - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_CAPABILITY_3XE8), - 13, 12, &temp); - - /* and add one */ - return (u8)(temp+1); -} - -/***************************************************************************//** - * - * static u8 - * fam10GetNumCoresOnNode(u8 node, cNorthBridge *nb) - * - * Description: - * Return the number of cores (1 based count) on node. - * - * Parameters: - * @param[in] node = the node that will be examined - * @param[in] *nb = this northbridge - * @return = the number of cores - * - * - */ -static u8 fam10GetNumCoresOnNode(u8 node, cNorthBridge *nb) -{ - u32 temp, leveling, cores; - u8 i; - - ASSERT((node < nb->maxNodes)); - /* Read CmpCap [2][1:0] */ - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_CAPABILITY_3XE8), - 15, 12, &temp); - - /* bits[15,13,12] specify the cores */ - temp = ((temp & 8) >> 1) + (temp & 3); - cores = temp + 1; - - /* Support Downcoring */ - AmdPCIReadBits (MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_DOWNCORE_3X190), - 3, 0, &leveling); - for (i = 0; i < cores; i++) - { - if (leveling & ((u32) 1 << i)) - { - temp--; - } - } - return (u8)(temp+1); -} - -/***************************************************************************//** - * - * static u8 - * fam15GetNumCoresOnNode(u8 node, cNorthBridge *nb) - * - * Description: - * Return the number of cores (1 based count) on node. - * - * Parameters: - * @param[in] node = the node that will be examined - * @param[in] *nb = this northbridge - * @return = the number of cores - * - * - */ -static u8 fam15GetNumCoresOnNode(u8 node, cNorthBridge *nb) -{ - u32 temp, leveling, cores; - u8 i; - - ASSERT((node < nb->maxNodes)); - /* Read CmpCap [7:0] */ - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_05, - REG_NB_CAPABILITY_5X84), - 7, 0, &temp); - - /* bits[7:0] specify the cores */ - temp = temp & 0xff; - cores = temp + 1; - - /* Support Downcoring */ - AmdPCIReadBits (MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_DOWNCORE_3X190), - 31, 0, &leveling); - for (i = 0; i < cores; i++) - { - if (leveling & ((u32) 1 << i)) - { - temp--; - } - } - return (u8)(temp+1); -} - -/***************************************************************************//** - * - * static void - * setTotalNodesAndCores(u8 node, u8 totalNodes, u8 totalCores, cNorthBridge *nb) - * - * Description: - * Write the total number of cores and nodes to the node - * - * Parameters: - * @param[in] node = the node that will be examined - * @param[in] totalNodes = the total number of nodes - * @param[in] totalCores = the total number of cores - * @param[in] *nb = this northbridge - * - * --------------------------------------------------------------------------------------- - */ -static void setTotalNodesAndCores(u8 node, u8 totalNodes, u8 totalCores, cNorthBridge *nb) -{ - SBDFO nodeIDReg; - u32 temp; - - ASSERT((node < nb->maxNodes) && (totalNodes <= nb->maxNodes)); - nodeIDReg = MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_HTNB_FUNC_00, - REG_NODE_ID_0X60); - - temp = totalCores-1; - /* Rely on max number of nodes:cores for rev F and GH to make - * this code work, even though we write reserved bit 20 on rev F it will be - * zero in that case. - */ - AmdPCIWriteBits(nodeIDReg, 20, 16, &temp); - temp = totalNodes-1; - AmdPCIWriteBits(nodeIDReg, 6, 4, &temp); -} - -/***************************************************************************//** - * - * static void - * limitNodes(u8 node, cNorthBridge *nb) - * - * Description: - * Limit coherent config accesses to cpus as indicated by nodecnt. - * - * Parameters: - * @param[in] node = the node that will be examined - * @param[in] *nb = this northbridge - * - * --------------------------------------------------------------------------------------- - */ -static void limitNodes(u8 node, cNorthBridge *nb) -{ - u32 temp = 1; - ASSERT((node < nb->maxNodes)); - AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_HTNB_FUNC_00, - REG_LINK_TRANS_CONTROL_0X68), - 15, 15, &temp); -} - -/***************************************************************************//** - * - * static void - * writeFullRoutingTable(u8 node, u8 target, u8 reqLink, u8 rspLink, u32 BClinks, cNorthBridge *nb) - * - * Description: - * Write the routing table entry for node to target, using the request link, response - * link, and broadcast links provided. - * - * Parameters: - * @param[in] node = the node that will be examined - * @param[in] target = the target node for these routes - * @param[in] reqLink = the link for requests to target - * @param[in] rspLink = the link for responses to target - * @param[in] bClinks = the broadcast links - * @param[in] *nb = this northbridge - * - * --------------------------------------------------------------------------------------- - */ -static void writeFullRoutingTable(u8 node, u8 target, u8 reqLink, u8 rspLink, u32 bClinks, cNorthBridge *nb) -{ -#ifndef HT_BUILD_NC_ONLY - u32 value = 0; - - ASSERT((node < nb->maxNodes) && (target < nb->maxNodes)); - if (reqLink == ROUTETOSELF) - value |= nb->selfRouteRequestMask; - else - value |= nb->selfRouteRequestMask << (reqLink+1); - - if (rspLink == ROUTETOSELF) - value |= nb->selfRouteResponseMask; - else - value |= nb->selfRouteResponseMask << (rspLink+1); - - /* Allow us to accept a Broadcast ourselves, then set broadcasts for routes */ - value |= (u32)1 << nb->broadcastSelfBit; - value |= (u32)bClinks << (nb->broadcastSelfBit + 1); - - AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_HTNB_FUNC_00, - REG_ROUTE0_0X40 + target*4), &value); -#else - STOP_HERE; -#endif /* HT_BUILD_NC_ONLY */ -} - -/***************************************************************************//** - * - * static u32 - * makeKey(u8 currentNode) - * - * Description: - * Private routine to northbridge code. - * Determine whether a node is compatible with the discovered configuration so - * far. Currently, that means the family, extended family of the new node are the - * same as the BSP's. - * - * Parameters: - * @param[in] node = the node - * @return = the key value - * - * --------------------------------------------------------------------------------------- - */ -static u32 makeKey(u8 node) -{ - u32 extFam, baseFam; - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_CPUID_3XFC), - 27, 20, &extFam); - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_CPUID_3XFC), - 11, 8, &baseFam); - return ((u32)(baseFam << 8) | extFam); -} - - -/***************************************************************************//** - * - * static BOOL - * isCompatible(u8 currentNode, cNorthBridge *nb) - * - * Description: - * Determine whether a node is compatible with the discovered configuration so - * far. Currently, that means the family, extended family of the new node are the - * same as the BSP's. - * - * Parameters: - * @param[in] node = the node - * @param[in] *nb = this northbridge - * @return = true: the new is compatible, false: it is not - * - * --------------------------------------------------------------------------------------- - */ -static BOOL isCompatible(u8 node, cNorthBridge *nb) -{ - return (makeKey(node) == nb->compatibleKey); -} - -/***************************************************************************//** - * - * static BOOL - * fam0fIsCapable(u8 node, sMainData *pDat, cNorthBridge *nb) - * - * Description: - * Get node capability and update the minimum supported system capability. - * Return whether the current configuration exceeds the capability. - * - * Parameters: - * @param[in] node = the node - * @param[in,out] *pDat = sysMpCap (updated) and NodesDiscovered - * @param[in] *nb = this northbridge - * @return true: system is capable of current config. - * false: system is not capable of current config. - * - * --------------------------------------------------------------------------------------- - */ -static BOOL fam0fIsCapable(u8 node, sMainData *pDat, cNorthBridge *nb) -{ -#ifndef HT_BUILD_NC_ONLY - u32 temp; - u8 maxNodes; - - ASSERT(node < nb->maxNodes); - - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_CAPABILITY_3XE8), - 2, 1, &temp); - if (temp > 1) - { - maxNodes = 8; - } else { - if (temp == 1) - { - maxNodes = 2; - } else { - maxNodes = 1; - } - } - if (pDat->sysMpCap > maxNodes) - { - pDat->sysMpCap = maxNodes; - } - /* Note since sysMpCap is one based and NodesDiscovered is zero based, equal is false */ - return (pDat->sysMpCap > pDat->NodesDiscovered); -#else - return 1; -#endif -} - -/***************************************************************************//** - * - * static BOOL - * fam10IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb) - * - * Description: - * Get node capability and update the minimum supported system capability. - * Return whether the current configuration exceeds the capability. - * - * Parameters: - * @param[in] node = the node - * @param[in,out] *pDat = sysMpCap (updated) and NodesDiscovered - * @param[in] *nb = this northbridge - * @return true: system is capable of current config. - * false: system is not capable of current config. - * - * --------------------------------------------------------------------------------------- - */ -static BOOL fam10IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb) -{ -#ifndef HT_BUILD_NC_ONLY - u32 temp; - u8 maxNodes; - - ASSERT(node < nb->maxNodes); - - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_CAPABILITY_3XE8), - 18, 16, &temp); - - if (temp != 0) - { - maxNodes = (1 << (~temp & 0x3)); /* That is, 1, 2, 4, or 8 */ - } - else - { - maxNodes = 8; - } - - if (pDat->sysMpCap > maxNodes) - { - pDat->sysMpCap = maxNodes; - } - /* Note since sysMpCap is one based and NodesDiscovered is zero based, equal is false */ - return (pDat->sysMpCap > pDat->NodesDiscovered); -#else - return 1; -#endif -} - -/***************************************************************************//** - * - * static BOOL - * fam15IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb) - * - * Description: - * Get node capability and update the minimum supported system capability. - * Return whether the current configuration exceeds the capability. - * - * Parameters: - * @param[in] node = the node - * @param[in,out] *pDat = sysMpCap (updated) and NodesDiscovered - * @param[in] *nb = this northbridge - * @return true: system is capable of current config. - * false: system is not capable of current config. - * - * --------------------------------------------------------------------------------------- - */ -static BOOL fam15IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb) -{ -#ifndef HT_BUILD_NC_ONLY - u32 temp; - u8 maxNodes; - - ASSERT(node < nb->maxNodes); - - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_CAPABILITY_3XE8), - 18, 16, &temp); - - if (temp != 0) - { - maxNodes = (1 << (~temp & 0x3)); /* That is, 1, 2, 4, or 8 */ - } - else - { - /* Check if CPU package is dual node */ - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_CAPABILITY_3XE8), - 29, 29, &temp); - if (temp) - maxNodes = 4; - else - maxNodes = 8; - } - - if (pDat->sysMpCap > maxNodes) - { - pDat->sysMpCap = maxNodes; - } - /* Note since sysMpCap is one based and NodesDiscovered is zero based, equal is false */ - return (pDat->sysMpCap > pDat->NodesDiscovered); -#else - return 1; -#endif -} - -/***************************************************************************//** - * - * static void - * fam0fStopLink(u8 currentNode, u8 currentLink, cNorthBridge *nb) - * - * Description: - * Disable a cHT link on node by setting F0x[E4, C4, A4, 84][TransOff, EndOfChain]=1 - * - * Parameters: - * @param[in] node = the node this link is on - * @param[in] link = the link to stop - * @param[in] *nb = this northbridge - * - * --------------------------------------------------------------------------------------- - */ -static void fam0fStopLink(u8 node, u8 link, cNorthBridge *nb) -{ -#ifndef HT_BUILD_NC_ONLY - u32 temp; - SBDFO linkBase; - - ASSERT((node < nb->maxNodes) && (link < nb->maxLinks)); - - linkBase = makeLinkBase(node, link); - - /* Set TransOff, EndOfChain */ - temp = 3; - setHtControlRegisterBits(linkBase + HTHOST_LINK_CONTROL_REG, 7, 6, &temp); -#endif -} - -/***************************************************************************//** - * - * static void - * commonVoid() - * - * Description: - * Nothing. - * - * Parameters: - * None. - * - * --------------------------------------------------------------------------------------- - */ -static void commonVoid(void) -{ -} - -/***************************************************************************//** - * - * static BOOL - * commonReturnFalse() - * - * Description: - * Return False. - * - * Parameters: - * @return = false - * - */ -static BOOL commonReturnFalse(void) -{ - return 0; -} - -/*************************************************************************** - *** Non-coherent init code *** - *** Northbridge access routines *** - ***************************************************************************/ - -/***************************************************************************//** - * - * static u8 - * readSbLink(cNorthBridge *nb) - * - * Description: - * Return the link to the Southbridge - * - * Parameters: - * @param[in] *nb = this northbridge - * @return the link to the southbridge - * - * --------------------------------------------------------------------------------------- - */ -static u8 readSbLink(cNorthBridge *nb) -{ - u32 temp; - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(0), - makePCIBusFromNode(0), - makePCIDeviceFromNode(0), - CPU_HTNB_FUNC_00, - REG_UNIT_ID_0X64), - 10, 8, &temp); - return (u8)temp; -} - -/***************************************************************************//** - * - * static BOOL - * verifyLinkIsNonCoherent(u8 node, u8 link, cNorthBridge *nb) - * - * Description: - * Verify that the link is non-coherent, connected, and ready - * - * Parameters: - * @param[in] node = the node that will be examined - * @param[in] link = the Link on that node to examine - * @param[in] *nb = this northbridge - * @return = true - The link has the following status - * LinkCon = 1, Link is connected - * InitComplete = 1,Link initialization is complete - * NC = 1, Link is coherent - * UniP-cLDT = 0, Link is not Uniprocessor cLDT - * LinkConPend = 0 Link connection is not pending - * false- The link has some other status - * - * --------------------------------------------------------------------------------------- - */ -static BOOL verifyLinkIsNonCoherent(u8 node, u8 link, cNorthBridge *nb) -{ - u32 linkType; - SBDFO linkBase; - - ASSERT((node < nb->maxNodes) && (link < nb->maxLinks)); - - linkBase = makeLinkBase(node, link); - - /* FN0_98/A4/C4 = LDT Type Register */ - AmdPCIRead(linkBase + HTHOST_LINK_TYPE_REG, &linkType); - - /* Verify linkCon = 1, InitComplete = 1, NC = 0, UniP-cLDT = 0, LinkConPend = 0 */ - return (linkType & HTHOST_TYPE_MASK) == HTHOST_TYPE_NONCOHERENT; -} - -/***************************************************************************//** - * - * static void - * ht3SetCFGAddrMap(u8 cfgMapIndex, u8 secBus, u8 subBus, u8 targetNode, u8 targetLink, sMainData *pDat, cNorthBridge *nb) - * - * Description: - * Configure and enable config access to a non-coherent chain for the given bus range. - * - * Parameters: - * @param[in] cfgMapIndex = the map entry to set - * @param[in] secBus = The secondary bus number to use - * @param[in] subBus = The subordinate bus number to use - * @param[in] targetNode = The node that shall be the recipient of the traffic - * @param[in] targetLink = The link that shall be the recipient of the traffic - * @param[in] pDat = our global state - * @param[in] *nb = this northbridge - * - * --------------------------------------------------------------------------------------- - */ -static void ht3SetCFGAddrMap(u8 cfgMapIndex, u8 secBus, u8 subBus, u8 targetNode, u8 targetLink, sMainData *pDat, cNorthBridge *nb) -{ - u8 curNode; - SBDFO linkBase; - u32 temp; - - linkBase = makeLinkBase(targetNode, targetLink); - - ASSERT(secBus <= subBus); - temp = secBus; - AmdPCIWriteBits(linkBase + HTHOST_ISOC_REG, 15, 8, &temp); - - /* For target link, note that rev F uses bits 9:8 and only with GH is bit 10 - * set to indicate a sublink. For node, we are currently not supporting Extended - * routing tables. - */ - temp = ((u32)subBus << 24) + ((u32)secBus << 16) + ((u32)targetLink << 8) - + ((u32)targetNode << 4) + (u32)3; - for (curNode = 0; curNode < pDat->NodesDiscovered+1; curNode++) - AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(curNode), - makePCIBusFromNode(curNode), - makePCIDeviceFromNode(curNode), - CPU_ADDR_FUNC_01, - REG_ADDR_CONFIG_MAP0_1XE0 + 4*cfgMapIndex), - &temp); -} - -/***************************************************************************//** - * - * static void - * ht1SetCFGAddrMap(u8 cfgMapIndex, u8 secBus, u8 subBus, u8 targetNode, u8 targetLink, sMainData *pDat, cNorthBridge *nb) - * - * Description: - * Configure and enable config access to a non-coherent chain for the given bus range. - * - * Parameters: - * @param[in] cfgMapIndex = the map entry to set - * @param[in] secBus = The secondary bus number to use - * @param[in] subBus = The subordinate bus number to use - * @param[in] targetNode = The node that shall be the recipient of the traffic - * @param[in] targetLink = The link that shall be the recipient of the traffic - * @param[in] pDat = our global state - * @param[in] *nb = this northbridge - * - ******************************************************************************/ -static void ht1SetCFGAddrMap(u8 cfgMapIndex, u8 secBus, u8 subBus, u8 targetNode, u8 targetLink, sMainData *pDat, cNorthBridge *nb) -{ - u8 curNode; - SBDFO linkBase; - u32 temp; - - linkBase = makeLinkBase(targetNode, targetLink); - - ASSERT(secBus <= subBus); - temp = secBus; - AmdPCIWriteBits(linkBase + HTHOST_ISOC_REG, 15, 8, &temp); - - temp = subBus; - AmdPCIWriteBits(linkBase + HTHOST_ISOC_REG, 23, 16, &temp); - - /* For target link, note that rev F uses bits 9:8 and only with GH is bit 10 - * set to indicate a sublink. For node, we are currently not supporting Extended - * routing tables. - */ - temp = ((u32)subBus << 24) + ((u32)secBus << 16) + ((u32)targetLink << 8) - + ((u32)targetNode << 4) + (u32)3; - for (curNode = 0; curNode < pDat->NodesDiscovered+1; curNode++) - AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(curNode), - makePCIBusFromNode(curNode), - makePCIDeviceFromNode(curNode), - CPU_ADDR_FUNC_01, - REG_ADDR_CONFIG_MAP0_1XE0 + 4*cfgMapIndex), - &temp); -} - -/*************************************************************************** - *** Link Optimization *** - ***************************************************************************/ - -/** - * static u8 - * convertBitsToWidth(u8 value, cNorthBridge *nb) - * - * Description: - * Given the bits set in the register field, return the width it represents - * - * Parameters: - * @param[in] value = The bits for the register - * @param[in] *nb = this northbridge - * @return The width - * - ******************************************************************************/ -static u8 convertBitsToWidth(u8 value, cNorthBridge *nb) -{ - switch (value) { - case 1: return 16; - case 0: return 8; - case 5: return 4; - case 4: return 2; - default: STOP_HERE; /* This is an error internal condition */ - } - return 0; // shut up GCC. -} - -/***************************************************************************//** - * - * static u8 - * convertWidthToBits(u8 value, cNorthBridge *nb) - * - * Description: - * Translate a desired width setting to the bits to set in the register field - * - * Parameters: - * @param[in] value = The width - * @param[in] *nb = this northbridge - * @return The bits for the register - * - ******************************************************************************/ -static u8 convertWidthToBits(u8 value, cNorthBridge *nb) -{ - switch (value) { - case 16: return 1; - case 8: return 0; - case 4: return 5; - case 2: return 4; - default: STOP_HERE; /* This is an internal error condition */ - } - return 0; // shut up GCC -} - -/***************************************************************************//** - * - * static u16 - * ht1NorthBridgeFreqMask(u8 NodeID, cNorthBridge *nb) - * - * Description: - * Return a mask that eliminates HT frequencies that cannot be used due to a slow - * northbridge frequency. - * - * Parameters: - * @param[in] node = Result could (later) be for a specific node - * @param[in] *nb = this northbridge - * @return Frequency mask - * - ******************************************************************************/ -static uint32_t ht1NorthBridgeFreqMask(u8 node, cNorthBridge *nb) -{ - /* only up to HT1 speeds */ - return (HT_FREQUENCY_LIMIT_HT1_ONLY); -} - -/***************************************************************************//** - * - * static u16 - * fam10NorthBridgeFreqMask(u8 NodeID, cNorthBridge *nb) - * - * Description: - * Return a mask that eliminates HT frequencies that cannot be used due to a slow - * northbridge frequency. - * - * Parameters: - * @param[in] node = Result could (later) be for a specific node - * @param[in] *nb = this northbridge - * @return = Frequency mask - * - ******************************************************************************/ -static uint32_t fam10NorthBridgeFreqMask(u8 node, cNorthBridge *nb) -{ - u8 nbCOF; - uint32_t supported; - - nbCOF = getMinNbCOF(); - /* - * nbCOF is minimum northbridge speed in hundreds of MHz. - * HT can not go faster than the minimum speed of the northbridge. - */ - if ((nbCOF >= 6) && (nbCOF < 10)) - { - /* Generation 1 HT link frequency */ - /* Convert frequency to bit and all less significant bits, - * by setting next power of 2 and subtracting 1. - */ - supported = ((uint32_t)1 << ((nbCOF >> 1) + 2)) - 1; - } - else if ((nbCOF >= 10) && (nbCOF <= 32)) - { - /* Generation 3 HT link frequency - * Assume error retry is enabled on all Gen 3 links - */ - if (is_gt_rev_d()) { - nbCOF *= 2; - if (nbCOF > 32) - nbCOF = 32; - } - - /* Convert frequency to bit and all less significant bits, - * by setting next power of 2 and subtracting 1. - */ - supported = ((uint32_t)1 << ((nbCOF >> 1) + 2)) - 1; - } - else if (nbCOF > 32) - { - supported = HT_FREQUENCY_LIMIT_3200M; - } - /* unlikely cases, but include as a defensive measure, also avoid trick above */ - else if (nbCOF == 4) - { - supported = HT_FREQUENCY_LIMIT_400M; - } - else if (nbCOF == 2) - { - supported = HT_FREQUENCY_LIMIT_200M; - } - else - { - STOP_HERE; - supported = HT_FREQUENCY_LIMIT_200M; - } - - return (fixEarlySampleFreqCapability(supported)); -} - -/***************************************************************************//** - * - * static u16 - * fam15NorthBridgeFreqMask(u8 NodeID, cNorthBridge *nb) - * - * Description: - * Return a mask that eliminates HT frequencies that cannot be used due to a slow - * northbridge frequency. - * - * Parameters: - * @param[in] node = Result could (later) be for a specific node - * @param[in] *nb = this northbridge - * @return = Frequency mask - * - ******************************************************************************/ -static uint32_t fam15NorthBridgeFreqMask(u8 node, cNorthBridge *nb) -{ - u8 nbCOF; - uint32_t supported; - - nbCOF = getMinNbCOF(); - /* - * nbCOF is minimum northbridge speed in hundreds of MHz. - * HT can not go faster than the minimum speed of the northbridge. - */ - if ((nbCOF >= 6) && (nbCOF < 10)) - { - /* Generation 1 HT link frequency */ - /* Convert frequency to bit and all less significant bits, - * by setting next power of 2 and subtracting 1. - */ - supported = ((uint32_t)1 << ((nbCOF >> 1) + 2)) - 1; - } - else if ((nbCOF >= 10) && (nbCOF <= 32)) - { - /* Generation 3 HT link frequency - * Assume error retry is enabled on all Gen 3 links - */ - nbCOF *= 2; - if (nbCOF > 32) - nbCOF = 32; - - /* Convert frequency to bit and all less significant bits, - * by setting next power of 2 and subtracting 1. - */ - supported = ((uint32_t)1 << ((nbCOF >> 1) + 2)) - 1; - } - else if (nbCOF > 32) - { - supported = HT_FREQUENCY_LIMIT_3200M; - } - /* unlikely cases, but include as a defensive measure, also avoid trick above */ - else if (nbCOF == 4) - { - supported = HT_FREQUENCY_LIMIT_400M; - } - else if (nbCOF == 2) - { - supported = HT_FREQUENCY_LIMIT_200M; - } - else - { - STOP_HERE; - supported = HT_FREQUENCY_LIMIT_200M; - } - - return (fixEarlySampleFreqCapability(supported)); -} - -/***************************************************************************//** - * - * static void - * gatherLinkData(sMainData *pDat, cNorthBridge *nb) - * - * Description: - * For all discovered links, populate the port list with the frequency and width - * capabilities. - * - * Parameters: - * @param[in,out] pDat = our global state, port list - * @param[in] *nb = this northbridge - * - ******************************************************************************/ -static void gatherLinkData(sMainData *pDat, cNorthBridge *nb) -{ - u8 i; - SBDFO linkBase; - u32 temp; - - for (i = 0; i < pDat->TotalLinks*2; i++) - { - if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU) - { - linkBase = makeLinkBase(pDat->PortList[i].NodeID, pDat->PortList[i].Link); - - pDat->PortList[i].Pointer = linkBase; - - AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 22, 20, &temp); - pDat->PortList[i].PrvWidthOutCap = convertBitsToWidth((u8)temp, pDat->nb); - - AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 18, 16, &temp); - pDat->PortList[i].PrvWidthInCap = convertBitsToWidth((u8)temp, pDat->nb); - - AmdPCIReadBits(linkBase + HTHOST_FREQ_REV_REG, 31, 16, &temp); - pDat->PortList[i].PrvFrequencyCap = temp & 0x7FFF /* Mask off bit 15, reserved value */ - & nb->northBridgeFreqMask(pDat->PortList[i].NodeID, pDat->nb); - if (is_gt_rev_d()) { - AmdPCIReadBits(linkBase + HTHOST_FREQ_REV_REG_2, 15, 1, &temp); - temp &= 0x7; /* Mask off reserved values */ - pDat->PortList[i].PrvFrequencyCap |= (temp << 17); - } - - AmdPCIReadBits(linkBase + HTHOST_FEATURE_CAP_REG, 9, 0, &temp); - pDat->PortList[i].PrvFeatureCap = (u16)temp; - } - else - { - linkBase = pDat->PortList[i].Pointer; - if (pDat->PortList[i].Link == 1) - linkBase += HTSLAVE_LINK01_OFFSET; - - AmdPCIReadBits(linkBase + HTSLAVE_LINK_CONTROL_0_REG, 22, 20, &temp); - pDat->PortList[i].PrvWidthOutCap = convertBitsToWidth((u8)temp, pDat->nb); - - AmdPCIReadBits(linkBase + HTSLAVE_LINK_CONTROL_0_REG, 18, 16, &temp); - pDat->PortList[i].PrvWidthInCap = convertBitsToWidth((u8)temp, pDat->nb); - - AmdPCIReadBits(linkBase + HTSLAVE_FREQ_REV_0_REG, 31, 16, &temp); - pDat->PortList[i].PrvFrequencyCap = (u16)temp; - - AmdPCIReadBits(linkBase + HTSLAVE_FEATURE_CAP_REG, 7, 0, &temp); - pDat->PortList[i].PrvFeatureCap = (u16)temp; - - if (pDat->HtBlock->AMD_CB_DeviceCapOverride) - { - linkBase &= 0xFFFFF000; - AmdPCIRead(linkBase, &temp); - - pDat->HtBlock->AMD_CB_DeviceCapOverride( - pDat->PortList[i].NodeID, - pDat->PortList[i].HostLink, - pDat->PortList[i].HostDepth, - (u8)SBDFO_SEG(pDat->PortList[i].Pointer), - (u8)SBDFO_BUS(pDat->PortList[i].Pointer), - (u8)SBDFO_DEV(pDat->PortList[i].Pointer), - temp, - pDat->PortList[i].Link, - &(pDat->PortList[i].PrvWidthInCap), - &(pDat->PortList[i].PrvWidthOutCap), - &(pDat->PortList[i].PrvFrequencyCap), - &(pDat->PortList[i].PrvFeatureCap)); - } - } - } -} - -/***************************************************************************//** - * - * static void - * setLinkData(sMainData *pDat, cNorthBridge *nb) - * - * Description: - * Change the hardware state for all links according to the now optimized data in the - * port list data structure. - * - * Parameters: - * @param[in] pDat = our global state, port list - * @param[in] *nb = this northbridge - * - ******************************************************************************/ -static void setLinkData(sMainData *pDat, cNorthBridge *nb) -{ - u8 i; - SBDFO linkBase; - u32 temp, temp2, frequency_index, widthin, widthout, bits; - - for (i = 0; i < pDat->TotalLinks*2; i++) - { - - ASSERT(pDat->PortList[i&0xFE].SelWidthOut == pDat->PortList[(i&0xFE)+1].SelWidthIn); - ASSERT(pDat->PortList[i&0xFE].SelWidthIn == pDat->PortList[(i&0xFE)+1].SelWidthOut); - ASSERT(pDat->PortList[i&0xFE].SelFrequency == pDat->PortList[(i&0xFE)+1].SelFrequency); - - if (pDat->PortList[i].SelRegang) - { - ASSERT(pDat->PortList[i].Type == PORTLIST_TYPE_CPU); - ASSERT(pDat->PortList[i].Link < 4); - temp = 1; - AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID), - makePCIBusFromNode(pDat->PortList[i].NodeID), - makePCIDeviceFromNode(pDat->PortList[i].NodeID), - CPU_HTNB_FUNC_00, - REG_HT_LINK_EXT_CONTROL0_0X170 + 4*pDat->PortList[i].Link), - 0, 0, &temp); - } - - if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU) - { - if (pDat->HtBlock->AMD_CB_OverrideCpuPort) - pDat->HtBlock->AMD_CB_OverrideCpuPort(pDat->PortList[i].NodeID, - pDat->PortList[i].Link, - &(pDat->PortList[i].SelWidthIn), - &(pDat->PortList[i].SelWidthOut), - &(pDat->PortList[i].SelFrequency)); - } - else - { - if (pDat->HtBlock->AMD_CB_OverrideDevicePort) - pDat->HtBlock->AMD_CB_OverrideDevicePort(pDat->PortList[i].NodeID, - pDat->PortList[i].HostLink, - pDat->PortList[i].HostDepth, - pDat->PortList[i].Link, - &(pDat->PortList[i].SelWidthIn), - &(pDat->PortList[i].SelWidthOut), - &(pDat->PortList[i].SelFrequency)); - } - - linkBase = pDat->PortList[i].Pointer; - if ((pDat->PortList[i].Type == PORTLIST_TYPE_IO) && (pDat->PortList[i].Link == 1)) - linkBase += HTSLAVE_LINK01_OFFSET; - - /* Some IO devices don't work properly when setting widths, so write them in a single operation, - * rather than individually. - */ - widthout = convertWidthToBits(pDat->PortList[i].SelWidthOut, pDat->nb); - ASSERT(widthout == 1 || widthout == 0 || widthout == 5 || widthout == 4); - widthin = convertWidthToBits(pDat->PortList[i].SelWidthIn, pDat->nb); - ASSERT(widthin == 1 || widthin == 0 || widthin == 5 || widthin == 4); - - temp = (widthin & 7) | ((widthout & 7) << 4); - setHtControlRegisterBits(linkBase + HTHOST_LINK_CONTROL_REG, 31, 24, &temp); - - temp = pDat->PortList[i].SelFrequency; - if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU) - { - ASSERT((temp >= HT_FREQUENCY_600M && temp <= HT_FREQUENCY_3200M) - || (temp == HT_FREQUENCY_200M) || (temp == HT_FREQUENCY_400M)); - frequency_index = temp; - if (temp > 0xf) { - temp2 = (temp >> 4) & 0x1; - temp &= 0xf; - } else { - temp2 = 0x0; - } - /* NOTE - * The Family 15h BKDG Rev. 3.14 is wrong - * Freq[4] must be set before Freq[3:0], otherwise the register writes will be ignored! - */ - if (is_gt_rev_d()) - AmdPCIWriteBits(linkBase + HTHOST_FREQ_REV_REG_2, 0, 0, &temp2); - AmdPCIWriteBits(linkBase + HTHOST_FREQ_REV_REG, 11, 8, &temp); - - /* Enable isochronous flow control mode if supported by chipset */ - if (is_fam15h()) { - if (pDat->PortList[i].enable_isochronous_mode) - temp = 1; - else - temp = 0; - setHtControlRegisterBits(linkBase + HTHOST_LINK_CONTROL_REG, 12, 12, &temp); - } - - if (frequency_index > HT_FREQUENCY_1000M) /* Gen1 = 200MHz -> 1000MHz, Gen3 = 1200MHz -> 3200MHz */ - { - /* Enable for Gen3 frequencies */ - temp = 1; - } - else - { - /* Disable for Gen1 frequencies */ - temp = 0; - } - /* HT3 retry mode enable / disable */ - AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID), - makePCIBusFromNode(pDat->PortList[i].NodeID), - makePCIDeviceFromNode(pDat->PortList[i].NodeID), - CPU_HTNB_FUNC_00, - REG_HT_LINK_RETRY0_0X130 + 4*pDat->PortList[i].Link), - 0, 0, &temp); - - /* and Scrambling enable / disable */ - AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID), - makePCIBusFromNode(pDat->PortList[i].NodeID), - makePCIDeviceFromNode(pDat->PortList[i].NodeID), - CPU_HTNB_FUNC_00, - REG_HT_LINK_EXT_CONTROL0_0X170 + 4*pDat->PortList[i].Link), - 3, 3, &temp); - } - else - { - SBDFO currentPtr; - BOOL isFound; - - ASSERT(temp <= HT_FREQUENCY_3200M); - /* Write the frequency setting */ - AmdPCIWriteBits(linkBase + HTSLAVE_FREQ_REV_0_REG, 11, 8, &temp); - - /* Handle additional HT3 frequency requirements, if needed, - * or clear them if switching down to ht1 on a warm reset. - * Gen1 = 200MHz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz - * - * Even though we assert if debugging, we need to check that the capability was found - * always, since this is an unknown hardware device, also we are taking - * unqualified frequency from the call backs - * (could be trying to do ht3 on an ht1 IO device). - */ - - if (temp > HT_FREQUENCY_1000M) - { - /* Enabling features if gen 3 */ - bits = 1; - } - else - { - /* Disabling features if gen 1 */ - bits = 0; - } - - /* Enable isochronous flow control mode if supported by chipset */ - if (is_fam15h()) { - if (pDat->PortList[i].enable_isochronous_mode) - temp = 1; - else - temp = 0; - } - - /* Retry Enable */ - isFound = FALSE; - currentPtr = linkBase & (u32)0xFFFFF000; /* Set PCI Offset to 0 */ - do - { - AmdPCIFindNextCap(¤tPtr); - if (currentPtr != ILLEGAL_SBDFO) - { - AmdPCIRead(currentPtr, &temp); - /* HyperTransport Retry Capability? */ - if (IS_HT_RETRY_CAPABILITY(temp)) - { - ASSERT(pDat->PortList[i].Link < 2); - AmdPCIWriteBits(currentPtr + HTRETRY_CONTROL_REG, - pDat->PortList[i].Link*16, - pDat->PortList[i].Link*16, - &bits); - isFound = TRUE; - } - /* Some other capability, keep looking */ - } - else - { - /* If we are turning it off, that may mean the device was only ht1 capable, - * so don't complain that we can't do it. - */ - if (bits != 0) - { - if (pDat->HtBlock->AMD_CB_EventNotify) - { - sHtEventOptRequiredCap evt; - evt.eSize = sizeof(sHtEventOptRequiredCap); - evt.node = pDat->PortList[i].NodeID; - evt.link = pDat->PortList[i].HostLink; - evt.depth = pDat->PortList[i].HostDepth; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_WARNING, - HT_EVENT_OPT_REQUIRED_CAP_RETRY, - (u8 *)&evt); - } - STOP_HERE; - } - isFound = TRUE; - } - } while (!isFound); - - /* Scrambling enable */ - isFound = FALSE; - currentPtr = linkBase & (u32)0xFFFFF000; /* Set PCI Offset to 0 */ - do - { - AmdPCIFindNextCap(¤tPtr); - if (currentPtr != ILLEGAL_SBDFO) - { - AmdPCIRead(currentPtr, &temp); - /* HyperTransport Gen3 Capability? */ - if (IS_HT_GEN3_CAPABILITY(temp)) - { - ASSERT(pDat->PortList[i].Link < 2); - AmdPCIWriteBits((currentPtr + - HTGEN3_LINK_TRAINING_0_REG + - pDat->PortList[i].Link*HTGEN3_LINK01_OFFSET), - 3, 3, &bits); - isFound = TRUE; - } - /* Some other capability, keep looking */ - } - else - { - /* If we are turning it off, that may mean the device was only ht1 capable, - * so don't complain that we can't do it. - */ - if (bits != 0) - { - if (pDat->HtBlock->AMD_CB_EventNotify) - { - sHtEventOptRequiredCap evt; - evt.eSize = sizeof(sHtEventOptRequiredCap); - evt.node = pDat->PortList[i].NodeID; - evt.link = pDat->PortList[i].HostLink; - evt.depth = pDat->PortList[i].HostDepth; - - pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_WARNING, - HT_EVENT_OPT_REQUIRED_CAP_GEN3, - (u8 *)&evt); - } - STOP_HERE; - } - isFound = TRUE; - } - } while (!isFound); - } - } -} - -/***************************************************************************//** - * - * void - * fam0fWriteHTLinkCmdBufferAlloc(u8 node, u8 link, u8 req, u8 preq, u8 rsp, u8 prb) - * - * Description: - * Set the command buffer allocations in the buffer count register for the node and link. - * The command buffer settings in the low 16 bits are the same on both - * family 10h and family 0fh northbridges. - * - * Parameters: - * @param[in] node = The node to set allocations on - * @param[in] link = the link to set allocations on - * @param[in] req = non-posted Request Command Buffers - * @param[in] preq = Posted Request Command Buffers - * @param[in] rsp = Response Command Buffers - * @param[in] prb = Probe Command Buffers - * - ******************************************************************************/ -#ifndef HT_BUILD_NC_ONLY - -static void fam0fWriteHTLinkCmdBufferAlloc(u8 node, u8 link, u8 req, u8 preq, u8 rsp, u8 prb) -{ - u32 temp; - SBDFO currentPtr; - - currentPtr = makeLinkBase(node, link); - currentPtr += HTHOST_BUFFER_COUNT_REG; - - /* non-posted Request Command Buffers */ - temp = req; - AmdPCIWriteBits(currentPtr, 3, 0, &temp); - /* Posted Request Command Buffers */ - temp = preq; - AmdPCIWriteBits(currentPtr, 7, 4, &temp); - /* Response Command Buffers */ - temp = rsp; - AmdPCIWriteBits(currentPtr, 11, 8, &temp); - /* Probe Command Buffers */ - temp = prb; - AmdPCIWriteBits(currentPtr, 15, 12, &temp); - /* LockBc */ - temp = 1; - AmdPCIWriteBits(currentPtr, 31, 31, &temp); -} -#endif /* HT_BUILD_NC_ONLY */ - -/***************************************************************************//** - * - * void - * fam0fWriteHTLinkDatBufferAlloc(u8 node, u8 link, u8 reqD, u8 preqD, u8 rspD) - * - * Description: - * Set the data buffer allocations in the buffer count register for the node and link. - * The command buffer settings in the high 16 bits are not the same on both - * family 10h and family 0fh northbridges. - * - * Parameters: - * @param[in] node = The node to set allocations on - * @param[in] link = the link to set allocations on - * @param[in] reqD = non-posted Request Data Buffers - * @param[in] preqD = Posted Request Data Buffers - * @param[in] rspD = Response Data Buffers - * - ******************************************************************************/ -#ifndef HT_BUILD_NC_ONLY - -static void fam0fWriteHTLinkDatBufferAlloc(u8 node, u8 link, u8 reqD, u8 preqD, u8 rspD) -{ - u32 temp; - SBDFO currentPtr; - - currentPtr = makeLinkBase(node, link); - currentPtr += HTHOST_BUFFER_COUNT_REG; - - /* Request Data Buffers */ - temp = reqD; - AmdPCIWriteBits(currentPtr, 18, 16, &temp); - /* Posted Request Data Buffers */ - temp = preqD; - AmdPCIWriteBits(currentPtr, 22, 20, &temp); - /* Response Data Buffers */ - temp = rspD; - AmdPCIWriteBits(currentPtr, 26, 24, &temp); -} -#endif /* HT_BUILD_NC_ONLY */ - -/***************************************************************************//** - * - * static void - * ht3WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb) - * - * Description: - * Set the traffic distribution register for the links provided. - * - * Parameters: - * @param[in] links01 = coherent links from node 0 to 1 - * @param[in] links10 = coherent links from node 1 to 0 - * @param[in] nb = this northbridge - * - ******************************************************************************/ -static void ht3WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb) -{ -#ifndef HT_BUILD_NC_ONLY - u32 temp; - - /* Node 0 */ - /* DstLnk */ - AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(0), - makePCIBusFromNode(0), - makePCIDeviceFromNode(0), - CPU_HTNB_FUNC_00, - REG_HT_TRAFFIC_DIST_0X164), - 23, 16, &links01); - /* DstNode = 1, cHTPrbDistEn = 1, cHTRspDistEn = 1, cHTReqDistEn = 1 */ - temp = 0x0107; - AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(0), - makePCIBusFromNode(0), - makePCIDeviceFromNode(0), - CPU_HTNB_FUNC_00, - REG_HT_TRAFFIC_DIST_0X164), - 15, 0, &temp); - - /* Node 1 */ - /* DstLnk */ - AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(1), - makePCIBusFromNode(1), - makePCIDeviceFromNode(1), - CPU_HTNB_FUNC_00, - REG_HT_TRAFFIC_DIST_0X164), - 23, 16, &links10); - /* DstNode = 0, cHTPrbDistEn = 1, cHTRspDistEn = 1, cHTReqDistEn = 1 */ - temp = 0x0007; - AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(1), - makePCIBusFromNode(1), - makePCIDeviceFromNode(1), - CPU_HTNB_FUNC_00, - REG_HT_TRAFFIC_DIST_0X164), - 15, 0, &temp); -#endif /* HT_BUILD_NC_ONLY */ -} - -/***************************************************************************//** - * - * static void - * ht1WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb) - * - * Description: - * Traffic distribution is more complex in this case as the routing table must be - * adjusted to use one link for requests and the other for responses. Also, - * perform the buffer tunings on the links required for this config. - * - * Parameters: - * @param[in] links01 = coherent links from node 0 to 1 - * @param[in] links10 = coherent links from node 1 to 0 - * @param[in] nb = this northbridge - * - ******************************************************************************/ -static void ht1WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb) -{ -#ifndef HT_BUILD_NC_ONLY - u32 route01, route10; - u8 req0, req1, rsp0, rsp1, nclink; - - /* - * Get the current request route for 0->1 and 1->0. This will indicate which of the links - * in links01 are connected to which links in links10. Since we have to route to distribute - * traffic, we need to know that. The link used by htinit will become the request, probe link. - * the other link will be used for responses. - */ - - /* Get the routes, and hang on to them, we will write them back updated. */ - AmdPCIRead(MAKE_SBDFO(makePCISegmentFromNode(0), - makePCIBusFromNode(0), - makePCIDeviceFromNode(0), - CPU_HTNB_FUNC_00, - REG_ROUTE1_0X44), - &route01); - AmdPCIRead(MAKE_SBDFO(makePCISegmentFromNode(1), - makePCIBusFromNode(1), - makePCIDeviceFromNode(1), - CPU_HTNB_FUNC_00, - REG_ROUTE0_0X40), - &route10); - - /* Convert the request routes to a link number. Note "0xE" is ht1 nb specific. - * Find the response link numbers. - */ - ASSERT((route01 & 0xE) && (route10 & 0xE)); /* no route! error! */ - req0 = (u8)AmdBitScanReverse((route01 & 0xE)) - 1; - req1 = (u8)AmdBitScanReverse((route10 & 0xE)) - 1; - /* Now, find the other link for the responses */ - rsp0 = (u8)AmdBitScanReverse((links01 & ~((u32)1 << req0))); - rsp1 = (u8)AmdBitScanReverse((links10 & ~((u32)1 << req1))); - - /* ht1 nb restriction, must have exactly two links */ - ASSERT(((((links01 & ~((u32)1 << req0)) & ~((u32)1 << rsp0))) == 0) - && ((((links10 & ~((u32)1 << req1)) & ~((u32)1 << rsp1))) == 0)); - - route01 = (route01 & ~0x0E00) | ((u32)0x0100<<(rsp0 + 1)); - route10 = (route10 & ~0x0E00) | ((u32)0x0100<<(rsp1 + 1)); - - AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(0), - makePCIBusFromNode(0), - makePCIDeviceFromNode(0), - CPU_HTNB_FUNC_00, - REG_ROUTE1_0X44), - &route01); - - AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(1), - makePCIBusFromNode(1), - makePCIDeviceFromNode(1), - CPU_HTNB_FUNC_00, - REG_ROUTE0_0X40), - &route10); - - /* While we otherwise do buffer tunings elsewhere, for the dual cHT DP case with - * ht1 northbridges like family 0Fh, do the tunings here where we have all the - * link and route info at hand and don't need to recalculate it. - */ - - /* Node 0, Request / Probe Link (note family F only has links < 4) */ - fam0fWriteHTLinkCmdBufferAlloc(0, req0, 6, 3, 1, 6); - fam0fWriteHTLinkDatBufferAlloc(0, req0, 4, 3, 1); - /* Node 0, Response Link (note family F only has links < 4) */ - fam0fWriteHTLinkCmdBufferAlloc(0, rsp0, 1, 0, 15, 0); - fam0fWriteHTLinkDatBufferAlloc(0, rsp0, 1, 1, 6); - /* Node 1, Request / Probe Link (note family F only has links < 4) */ - fam0fWriteHTLinkCmdBufferAlloc(1, req1, 6, 3, 1, 6); - fam0fWriteHTLinkDatBufferAlloc(1, req1, 4, 3, 1); - /* Node 1, Response Link (note family F only has links < 4) */ - fam0fWriteHTLinkCmdBufferAlloc(1, rsp1, 1, 0, 15, 0); - fam0fWriteHTLinkDatBufferAlloc(1, rsp1, 1, 1, 6); - - /* Node 0, is the third link non-coherent? */ - nclink = (u8)AmdBitScanReverse(((u8)0x07 & ~((u32)1 << req0) & ~((u32)1 << rsp0))); - if (nb->verifyLinkIsNonCoherent(0, nclink, nb)) - { - fam0fWriteHTLinkCmdBufferAlloc(0, nclink, 6, 5, 2, 0); - } - - /* Node 1, is the third link non-coherent? */ - nclink = (u8)AmdBitScanReverse(((u8)0x07 & ~((u32)1 << req1) & ~((u32)1 << rsp1))); - if (nb->verifyLinkIsNonCoherent(1, nclink, nb)) - { - fam0fWriteHTLinkCmdBufferAlloc(1, nclink, 6, 5, 2, 0); - } -#endif /* HT_BUILD_NC_ONLY */ -} - -/***************************************************************************//** - * - * static void - * fam0fBufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb) - * - * Description: - * Buffer tunings are inherently northbridge specific. Check for specific configs - * which require adjustments and apply any standard workarounds to this node. - * - * Parameters: - * @param[in] node = the node to - * @param[in] *pDat = coherent links from node 0 to 1 - * @param[in] nb = this northbridge - * - ******************************************************************************/ -static void fam0fBufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb) -{ -#ifndef HT_BUILD_NC_ONLY - u8 i; - u32 temp; - SBDFO currentPtr; - - ASSERT(node < nb->maxNodes); - - /* Fix the FIFO pointer register before changing speeds */ - currentPtr = MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_FIFOPTR_3XDC); - for (i = 0; i < nb->maxLinks; i++) - { - temp = 0; - if (nb->verifyLinkIsCoherent(node, i, nb)) - { - temp = 0x26; - ASSERT(i < 3); - AmdPCIWriteBits(currentPtr, 8*i + 5, 8*i, &temp); - } - else - { - if (nb->verifyLinkIsNonCoherent(node, i, nb)) - { - temp = 0x25; - ASSERT(i < 3); - AmdPCIWriteBits(currentPtr, 8*i + 5, 8*i, &temp); - } - } - } - /* - * 8P Buffer tuning. - * Either apply the BKDG tunings or, if applicable, apply the more restrictive errata 153 - * workaround. - * If 8 nodes, Check this node for 'inner' or 'outer'. - * Tune each link based on coherent or non-coherent - */ - if (pDat->NodesDiscovered >= 6) - { - u8 j; - BOOL isOuter; - BOOL isErrata153; - - /* This is for family 0Fh, so assuming dual core max then 7 or 8 nodes are required - * to be in the situation of 14 or more cores. We checked nodes above, cross check - * that the number of cores is 14 or more. We want both 14 cores with at least 7 or 8 nodes - * not one condition alone, to apply the errata 153 workaround. Otherwise, 7 or 8 rev F - * nodes use the BKDG tuning. - */ - - isErrata153 = 0; - - AmdPCIReadBits (MAKE_SBDFO(makePCISegmentFromNode(0), - makePCIBusFromNode(0), - makePCIDeviceFromNode(0), - CPU_HTNB_FUNC_00, - REG_NODE_ID_0X60), - 19, 16, &temp); - - if (temp >= 14) - { - /* Check whether we need to do errata 153 tuning or BKDG tuning. - * Errata 153 applies to JH-1, JH-2 and older. It is fixed in JH-3 - * (and, one assumes, from there on). - */ - for (i = 0; i < (pDat->NodesDiscovered +1); i++) - { - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(i), - makePCIBusFromNode(i), - makePCIDeviceFromNode(i), - CPU_NB_FUNC_03, - REG_NB_CPUID_3XFC), - 7, 0, &temp); - if (((u8)temp & ~0x40) < 0x13) - { - isErrata153 = 1; - break; - } - } - } - - for (i = 0; i < CPU_ADDR_NUM_CONFIG_MAPS; i++) - { - isOuter = FALSE; - /* Check for outer node by scanning the config maps on node 0 for one - * which is assigned to this node. - */ - currentPtr = MAKE_SBDFO(makePCISegmentFromNode(0), - makePCIBusFromNode(0), - makePCIDeviceFromNode(0), - CPU_ADDR_FUNC_01, - REG_ADDR_CONFIG_MAP0_1XE0 + (4 * i)); - AmdPCIReadBits (currentPtr, 1, 0, &temp); - /* Make sure this config map is valid, if it is it will be enabled for read/write */ - if (temp == 3) - { - /* It's valid, get the node (that node is an outer node) */ - AmdPCIReadBits (currentPtr, 6, 4, &temp); - /* Is the node we're working on now? */ - if (node == (u8)temp) - { - /* This is an outer node. Tune it appropriately. */ - for (j = 0; j < nb->maxLinks; j++) - { - if (isErrata153) - { - if (nb->verifyLinkIsCoherent(node, j, nb)) - { - fam0fWriteHTLinkCmdBufferAlloc(node, j, 1, 1, 6, 4); - } - else - { - if (nb->verifyLinkIsNonCoherent(node, j, nb)) - { - fam0fWriteHTLinkCmdBufferAlloc(node, j, 5, 4, 1, 0); - } - } - } - else - { - if (nb->verifyLinkIsCoherent(node, j, nb)) - { - fam0fWriteHTLinkCmdBufferAlloc(node, j, 1, 1, 8, 5); - } - } - } - /* - * SRI to XBAR Buffer Counts are correct for outer node at power on defaults. - */ - isOuter = TRUE; - break; - } - } - /* We fill config maps in ascending order, so if we didn't use this one, we're done. */ - else break; - } - if (!isOuter) - { - if (isErrata153) - { - /* Tuning for inner node coherent links */ - for (j = 0; j < nb->maxLinks; j++) - { - if (nb->verifyLinkIsCoherent(node, j, nb)) - { - fam0fWriteHTLinkCmdBufferAlloc(node, j, 2, 1, 5, 4); - } - - } - /* SRI to XBAR Buffer Count for inner nodes, zero DReq and DPReq */ - temp = 0; - AmdPCIWriteBits (MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_SRI_XBAR_BUF_3X70), - 31, 28, &temp); - } - } - - /* - * Tune MCT to XBAR Buffer Count the same an all nodes, 2 Probes, 5 Response - */ - if (isErrata153) - { - temp = 0x25; - AmdPCIWriteBits (MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_MCT_XBAR_BUF_3X78), - 14, 8, &temp); - } - } -#endif /* HT_BUILD_NC_ONLY */ -} - -/***************************************************************************//** - * - * static void - * fam10BufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb) - * - * Description: - * Buffer tunings are inherently northbridge specific. Check for specific configs - * which require adjustments and apply any standard workarounds to this node. - * - * Parameters: - * @param[in] node = the node to tune - * @param[in] *pDat = global state - * @param[in] nb = this northbridge - * - ******************************************************************************/ -static void fam10BufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb) -{ - u32 temp; - SBDFO currentPtr; - u8 i; - - ASSERT(node < nb->maxNodes); - - /* - * Link to XCS Token Count Tuning - * - * For each active link that we reganged (so this unfortunately can't go into the PCI reg - * table), we have to switch the Link to XCS Token Counts to the ganged state. - * We do this here for the non-uma case, which is to write the values that would have - * been power on defaults if the link was ganged at cold reset. - */ - for (i = 0; i < pDat->TotalLinks*2; i++) - { - if ((pDat->PortList[i].NodeID == node) && (pDat->PortList[i].Type == PORTLIST_TYPE_CPU)) - { - /* If the link is greater than 4, this is a sublink 1, so it is not reganged. */ - if (pDat->PortList[i].Link < 4) - { - currentPtr = MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_LINK_XCS_TOKEN0_3X148 + 4*pDat->PortList[i].Link); - if (pDat->PortList[i].SelRegang) - { - /* Handle all the regang Token count adjustments */ - - /* Sublink 0: [Probe0tok] = 2 [Rsp0tok] = 2 [PReq0tok] = 2 [Req0tok] = 2 */ - temp = 0xAA; - AmdPCIWriteBits(currentPtr, 7, 0, &temp); - /* Sublink 1: [Probe1tok] = 0 [Rsp1tok] = 0 [PReq1tok] = 0 [Req1tok] = 0 */ - temp = 0; - AmdPCIWriteBits(currentPtr, 23, 16, &temp); - /* [FreeTok] = 3 */ - temp = 3; - AmdPCIWriteBits(currentPtr, 15, 14, &temp); - } - else - { - /* Read the regang bit in hardware */ - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID), - makePCIBusFromNode(pDat->PortList[i].NodeID), - makePCIDeviceFromNode(pDat->PortList[i].NodeID), - CPU_HTNB_FUNC_00, - REG_HT_LINK_EXT_CONTROL0_0X170 + 4*pDat->PortList[i].Link), - 0, 0, &temp); - if (temp == 1) - { - /* handle a minor adjustment for stapped ganged links. If SelRegang is false we - * didn't do the regang, so if the bit is on then it's hardware strapped. - */ - - /* [FreeTok] = 3 */ - temp = 3; - AmdPCIWriteBits(currentPtr, 15, 14, &temp); - } - } - } - } - } -} - -/***************************************************************************//** - * - * static void - * fam15BufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb) - * - * Description: - * Buffer tunings are inherently northbridge specific. Check for specific configs - * which require adjustments and apply any standard workarounds to this node. - * - * Parameters: - * @param[in] node = the node to tune - * @param[in] *pDat = global state - * @param[in] nb = this northbridge - * - ******************************************************************************/ -static void fam15BufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb) -{ - /* Buffer count setup on Family 15h is currently handled in cpuSetAMDPCI */ -} - -/* - * North Bridge 'constructor'. - * - */ - -/***************************************************************************//** - * - * void - * newNorthBridge(u8 node, cNorthBridge *nb) - * - * Description: - * Construct a new northbridge. This routine encapsulates knowledge of how to tell - * significant differences between families of supported northbridges and what routines - * can be used in common and which are unique. A fully populated northbridge interface - * is provided by nb. - * - * Parameters: - * @param node - * @param[out] nb = the caller's northbridge structure to initialize. - * - ******************************************************************************/ -void newNorthBridge(u8 node, cNorthBridge *nb) -{ - u32 match; - u32 extFam, baseFam, model; - - cNorthBridge fam15 = - { -#ifdef HT_BUILD_NC_ONLY - 8, - 1, - 12, -#else - 8, - 8, - 64, -#endif /* HT_BUILD_NC_ONLY*/ - writeRoutingTable, - writeNodeID, - readDefLnk, - enableRoutingTables, - verifyLinkIsCoherent, - readTrueLinkFailStatus, - readToken, - writeToken, - fam15GetNumCoresOnNode, - setTotalNodesAndCores, - limitNodes, - writeFullRoutingTable, - isCompatible, - fam15IsCapable, - (void (*)(u8, u8, cNorthBridge*))commonVoid, - (BOOL (*)(u8, u8, sMainData*, cNorthBridge*))commonReturnFalse, - readSbLink, - verifyLinkIsNonCoherent, - ht3SetCFGAddrMap, - convertBitsToWidth, - convertWidthToBits, - fam15NorthBridgeFreqMask, - gatherLinkData, - setLinkData, - ht3WriteTrafficDistribution, - fam15BufferOptimizations, - 0x00000001, - 0x00000200, - 18, - 0x00000f06 - }; - - cNorthBridge fam10 = - { -#ifdef HT_BUILD_NC_ONLY - 8, - 1, - 12, -#else - 8, - 8, - 64, -#endif /* HT_BUILD_NC_ONLY*/ - writeRoutingTable, - writeNodeID, - readDefLnk, - enableRoutingTables, - verifyLinkIsCoherent, - readTrueLinkFailStatus, - readToken, - writeToken, - fam10GetNumCoresOnNode, - setTotalNodesAndCores, - limitNodes, - writeFullRoutingTable, - isCompatible, - fam10IsCapable, - (void (*)(u8, u8, cNorthBridge*))commonVoid, - (BOOL (*)(u8, u8, sMainData*, cNorthBridge*))commonReturnFalse, - readSbLink, - verifyLinkIsNonCoherent, - ht3SetCFGAddrMap, - convertBitsToWidth, - convertWidthToBits, - fam10NorthBridgeFreqMask, - gatherLinkData, - setLinkData, - ht3WriteTrafficDistribution, - fam10BufferOptimizations, - 0x00000001, - 0x00000200, - 18, - 0x00000f01 - }; - - cNorthBridge fam0f = - { -#ifdef HT_BUILD_NC_ONLY - 3, - 1, - 12, -#else - 3, - 8, - 32, -#endif /* HT_BUILD_NC_ONLY*/ - writeRoutingTable, - writeNodeID, - readDefLnk, - enableRoutingTables, - verifyLinkIsCoherent, - readTrueLinkFailStatus, - readToken, - writeToken, - fam0FGetNumCoresOnNode, - setTotalNodesAndCores, - limitNodes, - writeFullRoutingTable, - isCompatible, - fam0fIsCapable, - fam0fStopLink, - (BOOL (*)(u8, u8, sMainData*, cNorthBridge*))commonReturnFalse, - readSbLink, - verifyLinkIsNonCoherent, - ht1SetCFGAddrMap, - convertBitsToWidth, - convertWidthToBits, - ht1NorthBridgeFreqMask, - gatherLinkData, - setLinkData, - ht1WriteTrafficDistribution, - fam0fBufferOptimizations, - 0x00000001, - 0x00000100, - 16, - 0x00000f00 - }; - - /* Start with enough of the key to identify the northbridge interface */ - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_CPUID_3XFC), - 27, 20, &extFam); - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_CPUID_3XFC), - 11, 8, &baseFam); - AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node), - makePCIBusFromNode(node), - makePCIDeviceFromNode(node), - CPU_NB_FUNC_03, - REG_NB_CPUID_3XFC), - 7, 4, &model); - match = (u32)((baseFam << 8) | extFam); - - /* Test each in turn looking for a match. - * Initialize the struct if found. - */ - if (match == fam15.compatibleKey) - { - Amdmemcpy((void *)nb, (const void *)&fam15, (u32) sizeof(cNorthBridge)); - } - else if (match == fam10.compatibleKey) - { - Amdmemcpy((void *)nb, (const void *)&fam10, (u32) sizeof(cNorthBridge)); - } - else - { - if (match == fam0f.compatibleKey) - { - Amdmemcpy((void *)nb, (const void *)&fam0f, (u32) sizeof(cNorthBridge)); - } - else - { - STOP_HERE; - } - } - - /* Update the initial limited key to the real one, which may include other matching info */ - nb->compatibleKey = makeKey(node); -} diff --git a/src/northbridge/amd/amdht/h3ncmn.h b/src/northbridge/amd/amdht/h3ncmn.h deleted file mode 100644 index db057c0f1c..0000000000 --- a/src/northbridge/amd/amdht/h3ncmn.h +++ /dev/null @@ -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 */ diff --git a/src/northbridge/amd/amdht/ht_wrapper.c b/src/northbridge/amd/amdht/ht_wrapper.c deleted file mode 100644 index 89ff46eae3..0000000000 --- a/src/northbridge/amd/amdht/ht_wrapper.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdht/ht_wrapper.h b/src/northbridge/amd/amdht/ht_wrapper.h deleted file mode 100644 index 629e08f4fe..0000000000 --- a/src/northbridge/amd/amdht/ht_wrapper.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdht/porting.h b/src/northbridge/amd/amdht/porting.h deleted file mode 100644 index 9058d4d0e1..0000000000 --- a/src/northbridge/amd/amdht/porting.h +++ /dev/null @@ -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 */ diff --git a/src/northbridge/amd/amdk8/amdk8.h b/src/northbridge/amd/amdk8/amdk8.h deleted file mode 100644 index 2b821b7c9e..0000000000 --- a/src/northbridge/amd/amdk8/amdk8.h +++ /dev/null @@ -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 */ diff --git a/src/northbridge/amd/amdk8/reset_test.c b/src/northbridge/amd/amdk8/reset_test.c deleted file mode 100644 index 214aed448a..0000000000 --- a/src/northbridge/amd/amdk8/reset_test.c +++ /dev/null @@ -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); -} diff --git a/src/northbridge/amd/amdmct/amddefs.h b/src/northbridge/amd/amdmct/amddefs.h deleted file mode 100644 index 1a442082ff..0000000000 --- a/src/northbridge/amd/amdmct/amddefs.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdmct/mct/Makefile.inc b/src/northbridge/amd/amdmct/mct/Makefile.inc deleted file mode 100644 index f986201c6d..0000000000 --- a/src/northbridge/amd/amdmct/mct/Makefile.inc +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdmct/mct/mct.h b/src/northbridge/amd/amdmct/mct/mct.h deleted file mode 100644 index 598ab37e76..0000000000 --- a/src/northbridge/amd/amdmct/mct/mct.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdmct/mct/mct_d.c b/src/northbridge/amd/amdmct/mct/mct_d.c deleted file mode 100644 index 60a2c66de3..0000000000 --- a/src/northbridge/amd/amdmct/mct/mct_d.c +++ /dev/null @@ -1,3980 +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: Main memory controller system configuration for DDR 2 */ - - -/* KNOWN ISSUES - ERRATA - * - * Trtp is not calculated correctly when the controller is in 64-bit mode, it - * is 1 busclock off. No fix planned. The controller is not ordinarily in - * 64-bit mode. - * - * 32 Byte burst not supported. No fix planned. The controller is not - * ordinarily in 64-bit mode. - * - * Trc precision does not use extra Jedec defined fractional component. - * Instead Trc (course) is rounded up to nearest 1 ns. - * - * Mini and Micro DIMM not supported. Only RDIMM, UDIMM, SO-DIMM defined types - * supported. - */ - -#include <string.h> -#include <console/console.h> -#include <cpu/amd/msr.h> -#include <device/pci_ops.h> - -#include "mct_d.h" - -static u8 ReconfigureDIMMspare_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void DQSTiming_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void StartupDCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void ClearDCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 AutoCycTiming_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 PlatformSpec_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 mct_PlatformSpec(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void SPDSetBanks_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void StitchMemory_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 Get_DefTrc_k_D(u8 k); -static u16 Get_40Tk_D(u8 k); -static u16 Get_Fk_D(u8 k); -static u8 Dimm_Supports_D(struct DCTStatStruc *pDCTstat, u8 i, u8 j, u8 k); -static u8 Sys_Capability_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, int j, int k); -static u8 Get_DIMMAddress_D(struct DCTStatStruc *pDCTstat, u8 i); -static void mct_initDCT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_DramInit(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_SyncDCTsReady(struct DCTStatStruc *pDCTstat); -static void Get_Trdrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_AfterGetCLT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 mct_SPDCalcWidth(struct MCTStatStruc *pMCTstat,\ - struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_AfterStitchMemory(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 mct_DIMMPresence(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Set_OtherTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Get_Twrwr(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Get_Twrrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Get_TrwtTO(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Get_TrwtWB(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static u8 Check_DqsRcvEn_Diff(struct DCTStatStruc *pDCTstat, u8 dct, - u32 dev, u32 index_reg, u32 index); -static u8 Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat, - u32 dev, u32 index_reg); -static u8 Get_WrDatGross_Diff(struct DCTStatStruc *pDCTstat, u8 dct, - u32 dev, u32 index_reg); -static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat, - u32 dev, u32 index_reg, u32 index); -static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static u16 Get_WrDatGross_MaxMin(struct DCTStatStruc *pDCTstat, u8 dct, - u32 dev, u32 index_reg, u32 index); -static void mct_InitialMCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_init(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void clear_legacy_Mode(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_HTMemMapExt(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void SetCSTriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void SetODTTriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void InitPhyCompensation(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u32 mct_NodePresent_D(void); -static void WaitRoutine_D(u32 time); -static void mct_OtherTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void mct_ResetDataStruct_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -void mct_ClrClToNB_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static u8 CheckNBCOFEarlyArbEn(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -void mct_ClrWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_BeforeDQSTrain_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u32 mct_DisDllShutdownSR(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 DramConfigLo, u8 dct); -static void mct_EnDllShutdownSR(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); - -/*See mctAutoInitMCT header for index relationships to CL and T*/ -static const u16 Table_F_k[] = {00,200,266,333,400,533 }; -static const u8 Table_T_k[] = {0x00,0x50,0x3D,0x30,0x25, 0x18 }; -static const u8 Table_CL2_j[] = {0x04,0x08,0x10,0x20,0x40, 0x80 }; -static const u8 Tab_defTrc_k[] = {0x0,0x41,0x3C,0x3C,0x3A, 0x3A }; -static const u16 Tab_40T_k[] = {00,200,150,120,100,75 }; -static const u8 Tab_BankAddr[] = {0x0,0x08,0x09,0x10,0x0C,0x0D,0x11,0x0E,0x15,0x16,0x0F,0x17}; -static const u8 Tab_tCL_j[] = {0,2,3,4,5}; -static const u8 Tab_1KTfawT_k[] = {00,8,10,13,14,20}; -static const u8 Tab_2KTfawT_k[] = {00,10,14,17,18,24}; -static const u8 Tab_L1CLKDis[] = {8,8,6,4,2,0,8,8}; -static const u8 Tab_M2CLKDis[] = {2,0,8,8,2,0,2,0}; -static const u8 Tab_S1CLKDis[] = {8,0,8,8,8,0,8,0}; -static const u8 Table_Comp_Rise_Slew_20x[] = {7, 3, 2, 2, 0xFF}; -static const u8 Table_Comp_Rise_Slew_15x[] = {7, 7, 3, 2, 0xFF}; -static const u8 Table_Comp_Fall_Slew_20x[] = {7, 5, 3, 2, 0xFF}; -static const u8 Table_Comp_Fall_Slew_15x[] = {7, 7, 5, 3, 0xFF}; - -const u8 Table_DQSRcvEn_Offset[] = {0x00,0x01,0x10,0x11,0x2}; - -void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - /* - * Memory may be mapped contiguously all the way up to 4GB (depending - * on setup options). It is the responsibility of PCI subsystem to - * create an uncacheable IO region below 4GB and to adjust TOP_MEM - * downward prior to any IO mapping or accesses. It is the same - * responsibility of the CPU sub-system prior to accessing LAPIC. - * - * Slot Number is an external convention, and is determined by OEM with - * accompanying silk screening. OEM may choose to use Slot number - * convention which is consistent with DIMM number conventions. - * All AMD engineering - * platforms do. - * - * Run-Time Requirements: - * 1. Complete Hypertransport Bus Configuration - * 2. SMBus Controller Initialized - * 3. Checksummed or Valid NVRAM bits - * 4. MCG_CTL=-1, MC4_CTL_EN = 0 for all CPUs - * 5. MCi_STS from shutdown/warm reset recorded (if desired) prior to - * entry - * 6. All var MTRRs reset to zero - * 7. State of NB_CFG.DisDatMsk set properly on all CPUs - * 8. All CPUs at 2GHz Speed (unless DQS training is not installed). - * 9. All cHT links at max Speed/Width (unless DQS training is not - * installed). - * - * - * Global relationship between index values and item values: - * j CL(j) k F(k) - * -------------------------- - * 0 2.0 - - - * 1 3.0 1 200 MHz - * 2 4.0 2 266 MHz - * 3 5.0 3 333 MHz - * 4 6.0 4 400 MHz - * 5 7.0 5 533 MHz - */ - u8 Node, NodesWmem; - u32 node_sys_base; - -restartinit: - mctInitMemGPIOs_A_D(); /* Set any required GPIOs*/ - NodesWmem = 0; - node_sys_base = 0; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - pDCTstat->Node_ID = Node; - pDCTstat->dev_host = PA_HOST(Node); - pDCTstat->dev_map = PA_MAP(Node); - pDCTstat->dev_dct = PA_DCT(Node); - pDCTstat->dev_nbmisc = PA_NBMISC(Node); - pDCTstat->NodeSysBase = node_sys_base; - - if (mctGet_NVbits(NV_PACK_TYPE) == PT_GR) { - uint32_t dword; - pDCTstat->Dual_Node_Package = 1; - - /* Get the internal node number */ - dword = Get_NB32(pDCTstat->dev_nbmisc, 0xe8); - dword = (dword >> 30) & 0x3; - pDCTstat->Internal_Node_ID = dword; - } else { - pDCTstat->Dual_Node_Package = 0; - } - - print_tx("mctAutoInitMCT_D: mct_init Node ", Node); - mct_init(pMCTstat, pDCTstat); - mctNodeIDDebugPort_D(); - pDCTstat->NodePresent = NodePresent_D(Node); - if (pDCTstat->NodePresent) { /* See if Node is there*/ - print_t("mctAutoInitMCT_D: clear_legacy_Mode\n"); - clear_legacy_Mode(pMCTstat, pDCTstat); - pDCTstat->LogicalCPUID = mctGetLogicalCPUID_D(Node); - - print_t("mctAutoInitMCT_D: mct_InitialMCT_D\n"); - mct_InitialMCT_D(pMCTstat, pDCTstat); - - print_t("mctAutoInitMCT_D: mctSMBhub_Init\n"); - mctSMBhub_Init(Node); /* Switch SMBUS crossbar to proper node*/ - - print_t("mctAutoInitMCT_D: mct_initDCT\n"); - mct_initDCT(pMCTstat, pDCTstat); - if (pDCTstat->ErrCode == SC_FatalErr) { - goto fatalexit; /* any fatal errors?*/ - } else if (pDCTstat->ErrCode < SC_StopError) { - NodesWmem++; - } - } /* if Node present */ - node_sys_base = pDCTstat->NodeSysBase; - node_sys_base += (pDCTstat->NodeSysLimit + 2) & ~0x0F; - } - if (NodesWmem == 0) { - printk(BIOS_DEBUG, "No Nodes?!\n"); - goto fatalexit; - } - - print_t("mctAutoInitMCT_D: SyncDCTsReady_D\n"); - SyncDCTsReady_D(pMCTstat, pDCTstatA); /* Make sure DCTs are ready for accesses.*/ - - print_t("mctAutoInitMCT_D: HTMemMapInit_D\n"); - HTMemMapInit_D(pMCTstat, pDCTstatA); /* Map local memory into system address space.*/ - mctHookAfterHTMap(); - - print_t("mctAutoInitMCT_D: CPUMemTyping_D\n"); - CPUMemTyping_D(pMCTstat, pDCTstatA); /* Map dram into WB/UC CPU cacheability */ - mctHookAfterCPU(); /* Setup external northbridge(s) */ - - print_t("mctAutoInitMCT_D: DQSTiming_D\n"); - DQSTiming_D(pMCTstat, pDCTstatA); /* Get Receiver Enable and DQS signal timing*/ - - print_t("mctAutoInitMCT_D: UMAMemTyping_D\n"); - UMAMemTyping_D(pMCTstat, pDCTstatA); /* Fix up for UMA sizing */ - - print_t("mctAutoInitMCT_D: :OtherTiming\n"); - mct_OtherTiming(pMCTstat, pDCTstatA); - - if (ReconfigureDIMMspare_D(pMCTstat, pDCTstatA)) { /* RESET# if 1st pass of DIMM spare enabled*/ - goto restartinit; - } - - InterleaveNodes_D(pMCTstat, pDCTstatA); - InterleaveChannels_D(pMCTstat, pDCTstatA); - - print_t("mctAutoInitMCT_D: ECCInit_D\n"); - if (ECCInit_D(pMCTstat, pDCTstatA)) { /* Setup ECC control and ECC check-bits*/ - print_t("mctAutoInitMCT_D: MCTMemClr_D\n"); - MCTMemClr_D(pMCTstat,pDCTstatA); - } - - mct_FinalMCT_D(pMCTstat, (pDCTstatA + 0)); // Node 0 - print_tx("mctAutoInitMCT_D Done: Global Status: ", pMCTstat->GStatus); - return; - -fatalexit: - die("mct_d: fatalexit"); -} - - -static u8 ReconfigureDIMMspare_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 ret; - - if (mctGet_NVbits(NV_CS_SpareCTL)) { - if (MCT_DIMM_SPARE_NO_WARM) { - /* Do no warm-reset DIMM spare */ - if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) { - LoadDQSSigTmgRegs_D(pMCTstat, pDCTstatA); - ret = 0; - } else { - mct_ResetDataStruct_D(pMCTstat, pDCTstatA); - pMCTstat->GStatus |= 1 << GSB_EnDIMMSpareNW; - ret = 1; - } - } else { - /* Do warm-reset DIMM spare */ - if (mctGet_NVbits(NV_DQSTrainCTL)) - mctWarmReset_D(); - ret = 0; - } - - - } else { - ret = 0; - } - - return ret; -} - - -static void DQSTiming_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 nv_DQSTrainCTL; - - if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) { - return; - } - nv_DQSTrainCTL = mctGet_NVbits(NV_DQSTrainCTL); - /* FIXME: BOZO- DQS training every time*/ - nv_DQSTrainCTL = 1; - - print_t("DQSTiming_D: mct_BeforeDQSTrain_D:\n"); - mct_BeforeDQSTrain_D(pMCTstat, pDCTstatA); - phyAssistedMemFnceTraining(pMCTstat, pDCTstatA); - - if (nv_DQSTrainCTL) { - mctHookBeforeAnyTraining(pMCTstat, pDCTstatA); - - print_t("DQSTiming_D: TrainReceiverEn_D FirstPass:\n"); - TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass); - - print_t("DQSTiming_D: mct_TrainDQSPos_D\n"); - mct_TrainDQSPos_D(pMCTstat, pDCTstatA); - - // Second Pass never used for Barcelona! - //print_t("DQSTiming_D: TrainReceiverEn_D SecondPass:\n"); - //TrainReceiverEn_D(pMCTstat, pDCTstatA, SecondPass); - - print_t("DQSTiming_D: mctSetEccDQSRcvrEn_D\n"); - mctSetEccDQSRcvrEn_D(pMCTstat, pDCTstatA); - - print_t("DQSTiming_D: TrainMaxReadLatency_D\n"); -//FIXME - currently uses calculated value TrainMaxReadLatency_D(pMCTstat, pDCTstatA); - mctHookAfterAnyTraining(); - mctSaveDQSSigTmg_D(); - - print_t("DQSTiming_D: mct_EndDQSTraining_D\n"); - mct_EndDQSTraining_D(pMCTstat, pDCTstatA); - - print_t("DQSTiming_D: MCTMemClr_D\n"); - MCTMemClr_D(pMCTstat, pDCTstatA); - } else { - mctGetDQSSigTmg_D(); /* get values into data structure */ - LoadDQSSigTmgRegs_D(pMCTstat, pDCTstatA); /* load values into registers.*/ - //mctDoWarmResetMemClr_D(); - MCTMemClr_D(pMCTstat, pDCTstatA); - } -} - - -static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node, Receiver, Channel, Dir, DIMM; - u32 dev; - u32 index_reg; - u32 reg; - u32 index; - u32 val; - - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->DCTSysLimit) { - dev = pDCTstat->dev_dct; - for (Channel = 0;Channel < 2; Channel++) { - /* there are four receiver pairs, - loosely associated with chipselects.*/ - index_reg = 0x98 + Channel * 0x100; - for (Receiver = 0; Receiver < 8; Receiver += 2) { - /* Set Receiver Enable Values */ - mct_SetRcvrEnDly_D(pDCTstat, - 0, /* RcvrEnDly */ - 1, /* FinalValue, From stack */ - Channel, - Receiver, - dev, index_reg, - (Receiver >> 1) * 3 + 0x10, /* Addl_Index */ - 2); /* Pass Second Pass ? */ - - } - } - for (Channel = 0; Channel < 2; Channel++) { - SetEccDQSRcvrEn_D(pDCTstat, Channel); - } - - for (Channel = 0; Channel < 2; Channel++) { - u8 *p; - index_reg = 0x98 + Channel * 0x100; - - /* NOTE: - * when 400, 533, 667, it will support dimm0/1/2/3, - * and set conf for dimm0, hw will copy to dimm1/2/3 - * set for dimm1, hw will copy to dimm3 - * Rev A/B only support DIMM0/1 when 800MHz and above - * + 0x100 to next dimm - * Rev C support DIMM0/1/2/3 when 800MHz and above - * + 0x100 to next dimm - */ - for (DIMM = 0; DIMM < 2; DIMM++) { - if (DIMM == 0) { - index = 0; /* CHA Write Data Timing Low */ - } else { - if (pDCTstat->Speed >= 4) { - index = 0x100 * DIMM; - } else { - break; - } - } - for (Dir = 0; Dir < 2; Dir++) {//RD/WR - p = pDCTstat->persistentData.CH_D_DIR_B_DQS[Channel][DIMM][Dir]; - val = stream_to_int(p); /* CHA Read Data Timing High */ - Set_NB32_index_wait(dev, index_reg, index+1, val); - val = stream_to_int(p+4); /* CHA Write Data Timing High */ - Set_NB32_index_wait(dev, index_reg, index+2, val); - val = *(p+8); /* CHA Write ECC Timing */ - Set_NB32_index_wait(dev, index_reg, index+3, val); - index += 4; - } - } - } - - for (Channel = 0; Channel < 2; Channel++) { - reg = 0x78 + Channel * 0x100; - val = Get_NB32(dev, reg); - val &= ~(0x3ff<<22); - val |= ((u32) pDCTstat->CH_MaxRdLat[Channel] << 22); - val &= ~(1 << DqsRcvEnTrain); - Set_NB32(dev, reg, val); /* program MaxRdLatency to correspond with current delay*/ - } - } - } -} - -#ifdef UNUSED_CODE -static void ResetNBECCstat_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void ResetNBECCstat_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - /* Clear MC4_STS for all Nodes in the system. This is required in some - * circumstances to clear left over garbage from cold reset, shutdown, - * or normal ECC memory conditioning. - */ - - //FIXME: this function depends on pDCTstat Array (with Node id) - Is this really a problem? - - u32 dev; - u8 Node; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - dev = pDCTstat->dev_nbmisc; - /*MCA NB Status Low (alias to MC4_STS[31:0] */ - Set_NB32(dev, 0x48, 0); - /* MCA NB Status High (alias to MC4_STS[63:32] */ - Set_NB32(dev, 0x4C, 0); - } - } -} -#endif - -static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - u32 NextBase, BottomIO; - u8 _MemHoleRemap, DramHoleBase; - u32 HoleSize, DramSelBaseAddr; - - u32 val; - u32 base; - u32 limit; - u32 dev, devx; - struct DCTStatStruc *pDCTstat; - - _MemHoleRemap = mctGet_NVbits(NV_MemHole); - - if (pMCTstat->HoleBase == 0) { - DramHoleBase = mctGet_NVbits(NV_BottomIO); - } else { - DramHoleBase = pMCTstat->HoleBase >> (24-8); - } - - BottomIO = DramHoleBase << (24-8); - - NextBase = 0; - pDCTstat = pDCTstatA + 0; - dev = pDCTstat->dev_map; - - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - devx = pDCTstat->dev_map; - DramSelBaseAddr = 0; - if (!pDCTstat->GangedMode) { - DramSelBaseAddr = pDCTstat->NodeSysLimit - pDCTstat->DCTSysLimit; - /*In unganged mode, we must add DCT0 and DCT1 to DCTSysLimit */ - val = pDCTstat->NodeSysLimit; - if ((val & 0xFF) == 0xFE) { - DramSelBaseAddr++; - val++; - } - pDCTstat->DCTSysLimit = val; - } - - base = pDCTstat->DCTSysBase; - limit = pDCTstat->DCTSysLimit; - if (limit > base) { - base += NextBase; - limit += NextBase; - DramSelBaseAddr += NextBase; - printk(BIOS_DEBUG, " Node: %02x base: %02x limit: %02x BottomIO: %02x\n", Node, base, limit, BottomIO); - - if (_MemHoleRemap) { - if ((base < BottomIO) && (limit >= BottomIO)) { - /* HW Dram Remap */ - pDCTstat->Status |= 1 << SB_HWHole; - pMCTstat->GStatus |= 1 << GSB_HWHole; - pDCTstat->DCTSysBase = base; - pDCTstat->DCTSysLimit = limit; - pDCTstat->DCTHoleBase = BottomIO; - pMCTstat->HoleBase = BottomIO; - HoleSize = _4GB_RJ8 - BottomIO; /* HoleSize[39:8] */ - if ((DramSelBaseAddr > 0) && (DramSelBaseAddr < BottomIO)) - base = DramSelBaseAddr; - val = ((base + HoleSize) >> (24-8)) & 0xFF; - val <<= 8; /* shl 16, rol 24 */ - val |= DramHoleBase << 24; - val |= 1 << DramHoleValid; - Set_NB32(devx, 0xF0, val); /* Dram Hole Address Reg */ - pDCTstat->DCTSysLimit += HoleSize; - base = pDCTstat->DCTSysBase; - limit = pDCTstat->DCTSysLimit; - } else if (base == BottomIO) { - /* SW Node Hoist */ - pMCTstat->GStatus |= 1 << GSB_SpIntRemapHole; - pDCTstat->Status |= 1 << SB_SWNodeHole; - pMCTstat->GStatus |= 1 << GSB_SoftHole; - pMCTstat->HoleBase = base; - limit -= base; - base = _4GB_RJ8; - limit += base; - pDCTstat->DCTSysBase = base; - pDCTstat->DCTSysLimit = limit; - } else { - /* No Remapping. Normal Contiguous mapping */ - pDCTstat->DCTSysBase = base; - pDCTstat->DCTSysLimit = limit; - } - } else { - /*No Remapping. Normal Contiguous mapping*/ - pDCTstat->DCTSysBase = base; - pDCTstat->DCTSysLimit = limit; - } - base |= 3; /* set WE,RE fields*/ - pMCTstat->SysLimit = limit; - } - Set_NB32(dev, 0x40 + (Node << 3), base); /* [Node] + Dram Base 0 */ - - /* if Node limit > 1GB then set it to 1GB boundary for each node */ - if ((mctSetNodeBoundary_D()) && (limit > 0x00400000)) { - limit++; - limit &= 0xFFC00000; - limit--; - } - val = limit & 0xFFFF0000; - val |= Node; - Set_NB32(dev, 0x44 + (Node << 3), val); /* set DstNode */ - - limit = pDCTstat->DCTSysLimit; - if (limit) { - NextBase = (limit & 0xFFFF0000) + 0x10000; - if ((mctSetNodeBoundary_D()) && (NextBase > 0x00400000)) { - NextBase++; - NextBase &= 0xFFC00000; - NextBase--; - } - } - } - - /* Copy dram map from Node 0 to Node 1-7 */ - for (Node = 1; Node < MAX_NODES_SUPPORTED; Node++) { - u32 reg; - pDCTstat = pDCTstatA + Node; - devx = pDCTstat->dev_map; - - if (pDCTstat->NodePresent) { - printk(BIOS_DEBUG, " Copy dram map from Node 0 to Node %02x\n", Node); - reg = 0x40; /*Dram Base 0*/ - do { - val = Get_NB32(dev, reg); - Set_NB32(devx, reg, val); - reg += 4; - } while (reg < 0x80); - } else { - break; /* stop at first absent Node */ - } - } - - /*Copy dram map to F1x120/124*/ - mct_HTMemMapExt(pMCTstat, pDCTstatA); -} - - -void MCTMemClr_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - - /* Initiates a memory clear operation for all node. The mem clr - * is done in parallel. After the memclr is complete, all processors - * status are checked to ensure that memclr has completed. - */ - u8 Node; - struct DCTStatStruc *pDCTstat; - - if (!mctGet_NVbits(NV_DQSTrainCTL)) { - // FIXME: callback to wrapper: mctDoWarmResetMemClr_D - } else { // NV_DQSTrainCTL == 1 - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - DCTMemClr_Init_D(pMCTstat, pDCTstat); - } - } - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - DCTMemClr_Sync_D(pMCTstat, pDCTstat); - } - } - } -} - - -void DCTMemClr_Init_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 val; - u32 dev; - u32 reg; - - /* Initiates a memory clear operation on one node */ - if (pDCTstat->DCTSysLimit) { - dev = pDCTstat->dev_dct; - reg = 0x110; - - do { - val = Get_NB32(dev, reg); - } while (val & (1 << MemClrBusy)); - - val |= (1 << MemClrInit); - Set_NB32(dev, reg, val); - - } -} - - -void MCTMemClrSync_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - /* Ensures that memory clear has completed on all node.*/ - u8 Node; - struct DCTStatStruc *pDCTstat; - - if (!mctGet_NVbits(NV_DQSTrainCTL)) { - // callback to wrapper: mctDoWarmResetMemClr_D - } else { // NV_DQSTrainCTL == 1 - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - DCTMemClr_Sync_D(pMCTstat, pDCTstat); - } - } - } -} - - -static void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 val; - u32 dev = pDCTstat->dev_dct; - u32 reg; - - /* Ensure that a memory clear operation has completed on one node */ - if (pDCTstat->DCTSysLimit) { - reg = 0x110; - - do { - val = Get_NB32(dev, reg); - } while (val & (1 << MemClrBusy)); - - do { - val = Get_NB32(dev, reg); - } while (!(val & (1 << Dr_MemClrStatus))); - } - - /* Implement BKDG Rev 3.62 recommendations */ - val = 0x0FE40F80; - if (!(mctGetLogicalCPUID(0) & AMD_FAM10_LT_D) && mctGet_NVbits(NV_Unganged)) - val |= (0x18 << 2); - else - val |= (0x10 << 2); - val |= MCCH_FlushWrOnStpGnt; // Set for S3 - Set_NB32(dev, 0x11C, val); -} - - -u8 NodePresent_D(u8 Node) -{ - /* - * Determine if a single Hammer Node exists within the network. - */ - - u32 dev; - u32 val; - u32 dword; - u8 ret = 0; - - dev = PA_HOST(Node); /*test device/vendor id at host bridge */ - val = Get_NB32(dev, 0); - dword = mct_NodePresent_D(); /* FIXME: BOZO -11001022h rev for F */ - if (val == dword) { /* AMD Hammer Family CPU HT Configuration */ - if (oemNodePresent_D(Node, &ret)) - goto finish; - /* Node ID register */ - val = Get_NB32(dev, 0x60); - val &= 0x07; - dword = Node; - if (val == dword) /* current nodeID = requested nodeID ? */ - ret = 1; -finish: - ; - } - - return ret; -} - - -static void DCTInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* - * Initialize DRAM on single Athlon 64/Opteron Node. - */ - - u8 stopDCTflag; - u32 val; - - ClearDCT_D(pMCTstat, pDCTstat, dct); - stopDCTflag = 1; /*preload flag with 'disable' */ - if (mct_DIMMPresence(pMCTstat, pDCTstat, dct) < SC_StopError) { - print_t("\t\tDCTInit_D: mct_DIMMPresence Done\n"); - if (mct_SPDCalcWidth(pMCTstat, pDCTstat, dct) < SC_StopError) { - print_t("\t\tDCTInit_D: mct_SPDCalcWidth Done\n"); - if (AutoCycTiming_D(pMCTstat, pDCTstat, dct) < SC_StopError) { - print_t("\t\tDCTInit_D: AutoCycTiming_D Done\n"); - if (AutoConfig_D(pMCTstat, pDCTstat, dct) < SC_StopError) { - print_t("\t\tDCTInit_D: AutoConfig_D Done\n"); - if (PlatformSpec_D(pMCTstat, pDCTstat, dct) < SC_StopError) { - print_t("\t\tDCTInit_D: PlatformSpec_D Done\n"); - stopDCTflag = 0; - if (!(pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW))) { - print_t("\t\tDCTInit_D: StartupDCT_D\n"); - StartupDCT_D(pMCTstat, pDCTstat, dct); /*yeaahhh! */ - } - } - } - } - } - } - if (stopDCTflag) { - u32 reg_off = dct * 0x100; - val = 1<<DisDramInterface; - Set_NB32(pDCTstat->dev_dct, reg_off+0x94, val); - /*To maximize power savings when DisDramInterface = 1b, - all of the MemClkDis bits should also be set.*/ - val = 0xFF000000; - Set_NB32(pDCTstat->dev_dct, reg_off+0x88, val); - } else { - mct_EnDllShutdownSR(pMCTstat, pDCTstat, dct); - } -} - - -static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - /* Wait (and block further access to dram) for all DCTs to be ready, - * by polling all InitDram bits and waiting for possible memory clear - * operations to be complete. Read MemClkFreqVal bit to see if - * the DIMMs are present in this node. - */ - - u8 Node; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - mct_SyncDCTsReady(pDCTstat); - } -} - - -static void StartupDCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Read MemClkFreqVal bit to see if the DIMMs are present in this node. - * If the DIMMs are present then set the DRAM Enable bit for this node. - * - * Setting dram init starts up the DCT state machine, initializes the - * dram devices with MRS commands, and kicks off any - * HW memory clear process that the chip is capable of. The sooner - * that dram init is set for all nodes, the faster the memory system - * initialization can complete. Thus, the init loop is unrolled into - * two loops so as to start the processes for non BSP nodes sooner. - * This procedure will not wait for the process to finish. - * Synchronization is handled elsewhere. - */ - - u32 val; - u32 dev; - u8 byte; - u32 reg; - u32 reg_off = dct * 0x100; - - dev = pDCTstat->dev_dct; - val = Get_NB32(dev, 0x94 + reg_off); - if (val & (1 << MemClkFreqVal)) { - print_t("\t\t\tStartupDCT_D: MemClkFreqVal\n"); - byte = mctGet_NVbits(NV_DQSTrainCTL); - if (byte == 1) { - /* Enable DQSRcvEn training mode */ - print_t("\t\t\tStartupDCT_D: DqsRcvEnTrain set\n"); - reg = 0x78 + reg_off; - val = Get_NB32(dev, reg); - /* Setting this bit forces a 1T window with hard left - * pass/fail edge and a probabilistic right pass/fail - * edge. LEFT edge is referenced for final - * receiver enable position.*/ - val |= 1 << DqsRcvEnTrain; - Set_NB32(dev, reg, val); - } - mctHookBeforeDramInit(); /* generalized Hook */ - print_t("\t\t\tStartupDCT_D: DramInit\n"); - mct_DramInit(pMCTstat, pDCTstat, dct); - AfterDramInit_D(pDCTstat, dct); - mctHookAfterDramInit(); /* generalized Hook*/ - } -} - - -static void ClearDCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 reg_end; - u32 dev = pDCTstat->dev_dct; - u32 reg = 0x40 + 0x100 * dct; - u32 val = 0; - - if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) { - reg_end = 0x78 + 0x100 * dct; - } else { - reg_end = 0xA4 + 0x100 * dct; - } - - while (reg < reg_end) { - Set_NB32(dev, reg, val); - reg += 4; - } - - val = 0; - dev = pDCTstat->dev_map; - reg = 0xF0; - Set_NB32(dev, reg, val); -} - - -static u8 AutoCycTiming_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Initialize DCT Timing registers as per DIMM SPD. - * For primary timing (T, CL) use best case T value. - * For secondary timing params., use most aggressive settings - * of slowest DIMM. - * - * There are three components to determining "maximum frequency": - * SPD component, Bus load component, and "Preset" max frequency - * component. - * - * The SPD component is a function of the min cycle time specified - * by each DIMM, and the interaction of cycle times from all DIMMs - * in conjunction with CAS latency. The SPD component only applies - * when user timing mode is 'Auto'. - * - * The Bus load component is a limiting factor determined by electrical - * characteristics on the bus as a result of varying number of device - * loads. The Bus load component is specific to each platform but may - * also be a function of other factors. The bus load component only - * applies when user timing mode is 'Auto'. - * - * The Preset component is subdivided into three items and is the - * minimum of the set: Silicon revision, user limit setting when user - * timing mode is 'Auto' and memclock mode is 'Limit', OEM build - * specification of the maximum frequency. The Preset component is only - * applies when user timing mode is 'Auto'. - */ - - u8 i; - u8 Twr, Trtp; - u8 Trp, Trrd, Trcd, Tras, Trc, Trfc[4], Rows; - u32 DramTimingLo, DramTimingHi; - u16 Tk40; - u8 Twtr; - u8 LDIMM; - u8 DDR2_1066; - u8 byte; - u32 dword; - u32 dev; - u32 reg; - u32 reg_off; - u32 val; - u16 smbaddr; - - /* Get primary timing (CAS Latency and Cycle Time) */ - if (pDCTstat->Speed == 0) { - mctGet_MaxLoadFreq(pDCTstat); - - /* and Factor in presets (setup options, Si cap, etc.) */ - GetPresetmaxF_D(pMCTstat, pDCTstat); - - /* Go get best T and CL as specified by DIMM mfgs. and OEM */ - SPDGetTCL_D(pMCTstat, pDCTstat, dct); - /* skip callback mctForce800to1067_D */ - pDCTstat->Speed = pDCTstat->DIMMAutoSpeed; - pDCTstat->CASL = pDCTstat->DIMMCASL; - - /* if "manual" memclock mode */ - if (mctGet_NVbits(NV_MCTUSRTMGMODE) == 2) - pDCTstat->Speed = mctGet_NVbits(NV_MemCkVal) + 1; - - } - mct_AfterGetCLT(pMCTstat, pDCTstat, dct); - - /* Gather all DIMM mini-max values for cycle timing data */ - Rows = 0; - Trp = 0; - Trrd = 0; - Trcd = 0; - Trtp = 0; - Tras = 0; - Trc = 0; - Twr = 0; - Twtr = 0; - for (i = 0; i < 4; i++) - Trfc[i] = 0; - - for (i = 0; i< MAX_DIMMS_SUPPORTED; i++) { - LDIMM = i >> 1; - if (pDCTstat->DIMMValid & (1 << i)) { - smbaddr = Get_DIMMAddress_D(pDCTstat, dct + i); - byte = mctRead_SPD(smbaddr, SPD_ROWSZ); - if (Rows < byte) - Rows = byte; /* keep track of largest row sz */ - - byte = mctRead_SPD(smbaddr, SPD_TRP); - if (Trp < byte) - Trp = byte; - - byte = mctRead_SPD(smbaddr, SPD_TRRD); - if (Trrd < byte) - Trrd = byte; - - byte = mctRead_SPD(smbaddr, SPD_TRCD); - if (Trcd < byte) - Trcd = byte; - - byte = mctRead_SPD(smbaddr, SPD_TRTP); - if (Trtp < byte) - Trtp = byte; - - byte = mctRead_SPD(smbaddr, SPD_TWR); - if (Twr < byte) - Twr = byte; - - byte = mctRead_SPD(smbaddr, SPD_TWTR); - if (Twtr < byte) - Twtr = byte; - - val = mctRead_SPD(smbaddr, SPD_TRC); - if ((val == 0) || (val == 0xFF)) { - pDCTstat->ErrStatus |= 1<<SB_NoTrcTrfc; - pDCTstat->ErrCode = SC_VarianceErr; - val = Get_DefTrc_k_D(pDCTstat->Speed); - } else { - byte = mctRead_SPD(smbaddr, SPD_TRCRFC); - if (byte & 0xF0) { - val++; /* round up in case fractional extension is non-zero.*/ - } - } - if (Trc < val) - Trc = val; - - /* dev density = rank size/#devs per rank */ - byte = mctRead_SPD(smbaddr, SPD_BANKSZ); - - val = ((byte >> 5) | (byte << 3)) & 0xFF; - val <<= 2; - - byte = mctRead_SPD(smbaddr, SPD_DEVWIDTH) & 0xFE; /* dev density = 2^(rows+columns+banks) */ - if (byte == 4) { - val >>= 4; - } else if (byte == 8) { - val >>= 3; - } else if (byte == 16) { - val >>= 2; - } - - byte = bsr(val); - - if (Trfc[LDIMM] < byte) - Trfc[LDIMM] = byte; - - byte = mctRead_SPD(smbaddr, SPD_TRAS); - if (Tras < byte) - Tras = byte; - } /* Dimm Present */ - } - - /* Convert DRAM CycleTiming values and store into DCT structure */ - DDR2_1066 = 0; - byte = pDCTstat->Speed; - if (byte == 5) - DDR2_1066 = 1; - Tk40 = Get_40Tk_D(byte); - - /* Notes: - 1. All secondary time values given in SPDs are in binary with units of ns. - 2. Some time values are scaled by four, in order to have least count of 0.25 ns - (more accuracy). JEDEC SPD spec. shows which ones are x1 and x4. - 3. Internally to this SW, cycle time, Tk, is scaled by 10 to affect a - least count of 0.1 ns (more accuracy). - 4. SPD values not scaled are multiplied by 10 and then divided by 10T to find - equivalent minimum number of bus clocks (a remainder causes round-up of clocks). - 5. SPD values that are prescaled by 4 are multiplied by 10 and then divided by 40T to find - equivalent minimum number of bus clocks (a remainder causes round-up of clocks).*/ - - /* Tras */ - dword = Tras * 40; - pDCTstat->DIMMTras = (u16)dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TrasT_1066) - val = Min_TrasT_1066; - else if (val > Max_TrasT_1066) - val = Max_TrasT_1066; - } else { - if (val < Min_TrasT) - val = Min_TrasT; - else if (val > Max_TrasT) - val = Max_TrasT; - } - pDCTstat->Tras = val; - - /* Trp */ - dword = Trp * 10; - pDCTstat->DIMMTrp = dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TrasT_1066) - val = Min_TrpT_1066; - else if (val > Max_TrpT_1066) - val = Max_TrpT_1066; - } else { - if (val < Min_TrpT) - val = Min_TrpT; - else if (val > Max_TrpT) - val = Max_TrpT; - } - pDCTstat->Trp = val; - - /*Trrd*/ - dword = Trrd * 10; - pDCTstat->DIMMTrrd = dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TrrdT_1066) - val = Min_TrrdT_1066; - else if (val > Max_TrrdT_1066) - val = Max_TrrdT_1066; - } else { - if (val < Min_TrrdT) - val = Min_TrrdT; - else if (val > Max_TrrdT) - val = Max_TrrdT; - } - pDCTstat->Trrd = val; - - /* Trcd */ - dword = Trcd * 10; - pDCTstat->DIMMTrcd = dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TrcdT_1066) - val = Min_TrcdT_1066; - else if (val > Max_TrcdT_1066) - val = Max_TrcdT_1066; - } else { - if (val < Min_TrcdT) - val = Min_TrcdT; - else if (val > Max_TrcdT) - val = Max_TrcdT; - } - pDCTstat->Trcd = val; - - /* Trc */ - dword = Trc * 40; - pDCTstat->DIMMTrc = dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TrcT_1066) - val = Min_TrcT_1066; - else if (val > Max_TrcT_1066) - val = Max_TrcT_1066; - } else { - if (val < Min_TrcT) - val = Min_TrcT; - else if (val > Max_TrcT) - val = Max_TrcT; - } - pDCTstat->Trc = val; - - /* Trtp */ - dword = Trtp * 10; - pDCTstat->DIMMTrtp = dword; - val = pDCTstat->Speed; - if (val <= 2) { /* 7.75ns / Speed in ns to get clock # */ - val = 2; /* for DDR400/DDR533 */ - } else { /* Note a speed of 3 will be a Trtp of 3 */ - val = 3; /* for DDR667/DDR800/DDR1066 */ - } - pDCTstat->Trtp = val; - - /* Twr */ - dword = Twr * 10; - pDCTstat->DIMMTwr = dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TwrT_1066) - val = Min_TwrT_1066; - else if (val > Max_TwrT_1066) - val = Max_TwrT_1066; - } else { - if (val < Min_TwrT) - val = Min_TwrT; - else if (val > Max_TwrT) - val = Max_TwrT; - } - pDCTstat->Twr = val; - - /* Twtr */ - dword = Twtr * 10; - pDCTstat->DIMMTwtr = dword; - val = dword / Tk40; - if (dword % Tk40) { /* round up number of busclocks */ - val++; - } - if (DDR2_1066) { - if (val < Min_TwrT_1066) - val = Min_TwtrT_1066; - else if (val > Max_TwtrT_1066) - val = Max_TwtrT_1066; - } else { - if (val < Min_TwtrT) - val = Min_TwtrT; - else if (val > Max_TwtrT) - val = Max_TwtrT; - } - pDCTstat->Twtr = val; - - - /* Trfc0-Trfc3 */ - for (i = 0; i < 4; i++) - pDCTstat->Trfc[i] = Trfc[i]; - - mctAdjustAutoCycTmg_D(); - - /* Program DRAM Timing values */ - DramTimingLo = 0; /* Dram Timing Low init */ - val = pDCTstat->CASL; - val = Tab_tCL_j[val]; - DramTimingLo |= val; - - val = pDCTstat->Trcd; - if (DDR2_1066) - val -= Bias_TrcdT_1066; - else - val -= Bias_TrcdT; - - DramTimingLo |= val << 4; - - val = pDCTstat->Trp; - if (DDR2_1066) - val -= Bias_TrpT_1066; - else { - val -= Bias_TrpT; - val <<= 1; - } - DramTimingLo |= val << 7; - - val = pDCTstat->Trtp; - val -= Bias_TrtpT; - DramTimingLo |= val << 11; - - val = pDCTstat->Tras; - if (DDR2_1066) - val -= Bias_TrasT_1066; - else - val -= Bias_TrasT; - DramTimingLo |= val << 12; - - val = pDCTstat->Trc; - val -= Bias_TrcT; - DramTimingLo |= val << 16; - - if (!DDR2_1066) { - val = pDCTstat->Twr; - val -= Bias_TwrT; - DramTimingLo |= val << 20; - } - - val = pDCTstat->Trrd; - if (DDR2_1066) - val -= Bias_TrrdT_1066; - else - val -= Bias_TrrdT; - DramTimingLo |= val << 22; - - - DramTimingHi = 0; /* Dram Timing Low init */ - val = pDCTstat->Twtr; - if (DDR2_1066) - val -= Bias_TwtrT_1066; - else - val -= Bias_TwtrT; - DramTimingHi |= val << 8; - - val = 2; - DramTimingHi |= val << 16; - - val = 0; - for (i = 4; i > 0; i--) { - val <<= 3; - val |= Trfc[i-1]; - } - DramTimingHi |= val << 20; - - - dev = pDCTstat->dev_dct; - reg_off = 0x100 * dct; - print_tx("AutoCycTiming: DramTimingLo ", DramTimingLo); - print_tx("AutoCycTiming: DramTimingHi ", DramTimingHi); - - Set_NB32(dev, 0x88 + reg_off, DramTimingLo); /*DCT Timing Low*/ - DramTimingHi |=0x0000FC77; - Set_NB32(dev, 0x8c + reg_off, DramTimingHi); /*DCT Timing Hi*/ - - if (DDR2_1066) { - /* Twr */ - dword = pDCTstat->Twr; - dword -= Bias_TwrT_1066; - dword <<= 4; - reg = 0x84 + reg_off; - val = Get_NB32(dev, reg); - val &= 0x8F; - val |= dword; - Set_NB32(dev, reg, val); - } - - print_tx("AutoCycTiming: Status ", pDCTstat->Status); - print_tx("AutoCycTiming: ErrStatus ", pDCTstat->ErrStatus); - print_tx("AutoCycTiming: ErrCode ", pDCTstat->ErrCode); - print_t("AutoCycTiming: Done\n"); - - mctHookAfterAutoCycTmg(); - - return pDCTstat->ErrCode; -} - - -static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Get max frequency from OEM platform definition, from any user - * override (limiting) of max frequency, and from any Si Revision - * Specific information. Return the least of these three in - * DCTStatStruc.PresetmaxFreq. - */ - - u16 proposedFreq; - u16 word; - - /* Get CPU Si Revision defined limit (NPT) */ - proposedFreq = 533; /* Rev F0 programmable max memclock is */ - - /*Get User defined limit if "limit" mode */ - if (mctGet_NVbits(NV_MCTUSRTMGMODE) == 1) { - word = Get_Fk_D(mctGet_NVbits(NV_MemCkVal) + 1); - if (word < proposedFreq) - proposedFreq = word; - - /* Get Platform defined limit */ - word = mctGet_NVbits(NV_MAX_MEMCLK); - if (word < proposedFreq) - proposedFreq = word; - - word = pDCTstat->PresetmaxFreq; - if (word > proposedFreq) - word = proposedFreq; - - pDCTstat->PresetmaxFreq = word; - } -} - - - -static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Find the best T and CL primary timing parameter pair, per Mfg., - * for the given set of DIMMs, and store into DCTStatStruc - * (.DIMMAutoSpeed and .DIMMCASL). See "Global relationship between - * index values and item values" for definition of CAS latency - * index (j) and Frequency index (k). - */ - int i, j, k; - u8 T1min, CL1min; - - /* i={0..7} (std. physical DIMM number) - * j is an integer which enumerates increasing CAS latency. - * k is an integer which enumerates decreasing cycle time. - * CL no. {0,1,2} corresponds to CL X, CL X-.5, or CL X-1 (per individual DIMM) - * Max timing values are per parameter, of all DIMMs, spec'd in ns like the SPD. - */ - - CL1min = 0xFF; - T1min = 0xFF; - for (k = K_MAX; k >= K_MIN; k--) { - for (j = J_MIN; j <= J_MAX; j++) { - if (Sys_Capability_D(pMCTstat, pDCTstat, j, k)) { - /* 1. check to see if DIMMi is populated. - 2. check if DIMMi supports CLj and Tjk */ - for (i = 0; i < MAX_DIMMS_SUPPORTED; i++) { - if (pDCTstat->DIMMValid & (1 << i)) { - if (Dimm_Supports_D(pDCTstat, i, j, k)) - break; - } - } /* while ++i */ - if (i == MAX_DIMMS_SUPPORTED) { - T1min = k; - CL1min = j; - goto got_TCL; - } - } - } /* while ++j */ - } /* while --k */ - -got_TCL: - if (T1min != 0xFF) { - pDCTstat->DIMMCASL = CL1min; /*mfg. optimized */ - pDCTstat->DIMMAutoSpeed = T1min; - print_tx("SPDGetTCL_D: DIMMCASL ", pDCTstat->DIMMCASL); - print_tx("SPDGetTCL_D: DIMMAutoSpeed ", pDCTstat->DIMMAutoSpeed); - - } else { - pDCTstat->DIMMCASL = CL_DEF; /* failsafe values (running in min. mode) */ - pDCTstat->DIMMAutoSpeed = T_DEF; - pDCTstat->ErrStatus |= 1 << SB_DimmMismatchT; - pDCTstat->ErrStatus |= 1 << SB_MinimumMode; - pDCTstat->ErrCode = SC_VarianceErr; - } - print_tx("SPDGetTCL_D: Status ", pDCTstat->Status); - print_tx("SPDGetTCL_D: ErrStatus ", pDCTstat->ErrStatus); - print_tx("SPDGetTCL_D: ErrCode ", pDCTstat->ErrCode); - print_t("SPDGetTCL_D: Done\n"); -} - - -static u8 PlatformSpec_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 dev; - u32 reg; - u32 val; - - mctGet_PS_Cfg_D(pMCTstat, pDCTstat, dct); - - if (pDCTstat->GangedMode) { - mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 1); - } - - if (pDCTstat->_2Tmode == 2) { - dev = pDCTstat->dev_dct; - reg = 0x94 + 0x100 * dct; /* Dram Configuration Hi */ - val = Get_NB32(dev, reg); - val |= 1 << 20; /* 2T CMD mode */ - Set_NB32(dev, reg, val); - } - - mct_PlatformSpec(pMCTstat, pDCTstat, dct); - InitPhyCompensation(pMCTstat, pDCTstat, dct); - mctHookAfterPSCfg(); - return pDCTstat->ErrCode; -} - - -static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 DramControl, DramTimingLo, Status; - u32 DramConfigLo, DramConfigHi, DramConfigMisc, DramConfigMisc2; - u32 val; - u32 reg_off; - u32 dev; - u16 word; - u32 dword; - u8 byte; - - print_tx("AutoConfig_D: DCT: ", dct); - - DramConfigLo = 0; - DramConfigHi = 0; - DramConfigMisc = 0; - DramConfigMisc2 = 0; - - /* set bank addressing and Masks, plus CS pops */ - SPDSetBanks_D(pMCTstat, pDCTstat, dct); - if (pDCTstat->ErrCode == SC_StopError) - goto AutoConfig_exit; - - /* map chip-selects into local address space */ - StitchMemory_D(pMCTstat, pDCTstat, dct); - InterleaveBanks_D(pMCTstat, pDCTstat, dct); - - /* temp image of status (for convenience). RO usage! */ - Status = pDCTstat->Status; - - dev = pDCTstat->dev_dct; - reg_off = 0x100 * dct; - - - /* Build Dram Control Register Value */ - DramConfigMisc2 = Get_NB32 (dev, 0xA8 + reg_off); /* Dram Control*/ - DramControl = Get_NB32 (dev, 0x78 + reg_off); /* Dram Control*/ - - if (mctGet_NVbits(NV_CLKHZAltVidC3)) - DramControl |= 1<<16; - - // FIXME: Add support(skip) for Ax and Cx versions - DramControl |= 5; /* RdPtrInit */ - - - /* Build Dram Config Lo Register Value */ - DramConfigLo |= 1 << 4; /* 75 Ohms ODT */ - if (mctGet_NVbits(NV_MAX_DIMMS) == 8) { - if (pDCTstat->Speed == 3) { - if (pDCTstat->MAdimms[dct] == 4) - DramConfigLo |= 1 << 5; /* 50 Ohms ODT */ - } else if (pDCTstat->Speed == 4) { - if (pDCTstat->MAdimms[dct] != 1) - DramConfigLo |= 1 << 5; /* 50 Ohms ODT */ - } - } else { - // FIXME: Skip for Ax versions - if (pDCTstat->MAdimms[dct] == 4) { - if (pDCTstat->DimmQRPresent != 0) { - if ((pDCTstat->Speed == 3) || (pDCTstat->Speed == 4)) { - DramConfigLo |= 1 << 5; /* 50 Ohms ODT */ - } - } else if (pDCTstat->MAdimms[dct] == 4) { - if (pDCTstat->Speed == 4) { - if (pDCTstat->DimmQRPresent != 0) { - DramConfigLo |= 1 << 5; /* 50 Ohms ODT */ - } - } - } - } else if (pDCTstat->MAdimms[dct] == 2) { - DramConfigLo |= 1 << 5; /* 50 Ohms ODT */ - } - - } - - // FIXME: Skip for Ax versions - /* callback not required - if (!mctParityControl_D()) */ - if (Status & (1 << SB_PARDIMMs)) { - DramConfigLo |= 1 << ParEn; - DramConfigMisc2 |= 1 << ActiveCmdAtRst; - } else { - DramConfigLo &= ~(1 << ParEn); - DramConfigMisc2 &= ~(1 << ActiveCmdAtRst); - } - - if (mctGet_NVbits(NV_BurstLen32)) { - if (!pDCTstat->GangedMode) - DramConfigLo |= 1 << BurstLength32; - } - - if (Status & (1 << SB_128bitmode)) - DramConfigLo |= 1 << Width128; /* 128-bit mode (normal) */ - - word = dct; - dword = X4Dimm; - while (word < 8) { - if (pDCTstat->Dimmx4Present & (1 << word)) - DramConfigLo |= 1 << dword; /* X4Dimm[3:0] */ - word++; - word++; - dword++; - } - - if (!(Status & (1 << SB_Registered))) - DramConfigLo |= 1 << UnBuffDimm; /* Unbuffered DIMMs */ - - if (mctGet_NVbits(NV_ECC_CAP)) - if (Status & (1 << SB_ECCDIMMs)) - if (mctGet_NVbits(NV_ECC)) - DramConfigLo |= 1 << DimmEcEn; - - DramConfigLo = mct_DisDllShutdownSR(pMCTstat, pDCTstat, DramConfigLo, dct); - - /* Build Dram Config Hi Register Value */ - dword = pDCTstat->Speed; - DramConfigHi |= dword - 1; /* get MemClk encoding */ - DramConfigHi |= 1 << MemClkFreqVal; - - if (Status & (1 << SB_Registered)) - if ((pDCTstat->Dimmx4Present != 0) && (pDCTstat->Dimmx8Present != 0)) - /* set only if x8 Registered DIMMs in System*/ - DramConfigHi |= 1 << RDqsEn; - - if (mctGet_NVbits(NV_CKE_PDEN)) { - DramConfigHi |= 1 << 15; /* PowerDownEn */ - if (mctGet_NVbits(NV_CKE_CTL)) - /*Chip Select control of CKE*/ - DramConfigHi |= 1 << 16; - } - - /* Control Bank Swizzle */ - if (0) /* call back not needed mctBankSwizzleControl_D()) */ - DramConfigHi &= ~(1 << BankSwizzleMode); - else - DramConfigHi |= 1 << BankSwizzleMode; /* recommended setting (default) */ - - /* Check for Quadrank DIMM presence */ - if (pDCTstat->DimmQRPresent != 0) { - byte = mctGet_NVbits(NV_4RANKType); - if (byte == 2) - DramConfigHi |= 1 << 17; /* S4 (4-Rank SO-DIMMs) */ - else if (byte == 1) - DramConfigHi |= 1 << 18; /* R4 (4-Rank Registered DIMMs) */ - } - - if (0) /* call back not needed mctOverrideDcqBypMax_D) */ - val = mctGet_NVbits(NV_BYPMAX); - else - val = 0x0f; // recommended setting (default) - DramConfigHi |= val << 24; - - val = pDCTstat->DIMM2Kpage; - if (pDCTstat->GangedMode != 0) { - if (dct != 0) { - val &= 0x55; - } else { - val &= 0xAA; - } - } - if (val) - val = Tab_2KTfawT_k[pDCTstat->Speed]; - else - val = Tab_1KTfawT_k[pDCTstat->Speed]; - - if (pDCTstat->Speed == 5) - val >>= 1; - - val -= Bias_TfawT; - val <<= 28; - DramConfigHi |= val; /* Tfaw for 1K or 2K paged drams */ - - // FIXME: Skip for Ax versions - DramConfigHi |= 1 << DcqArbBypassEn; - - - /* Build MemClkDis Value from Dram Timing Lo and - Dram Config Misc Registers - 1. We will assume that MemClkDis field has been preset prior to this - point. - 2. We will only set MemClkDis bits if a DIMM is NOT present AND if: - NV_AllMemClks <>0 AND SB_DiagClks == 0 */ - - - /* Dram Timing Low (owns Clock Enable bits) */ - DramTimingLo = 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))) { - const u8 *p; - byte = mctGet_NVbits(NV_PACK_TYPE); - if (byte == PT_L1) - p = Tab_L1CLKDis; - else if (byte == PT_M2) - p = Tab_M2CLKDis; - else - p = Tab_S1CLKDis; - - dword = 0; - while (dword < MAX_DIMMS_SUPPORTED) { - val = p[dword]; - print_tx("DramTimingLo: val=", val); - if (!(pDCTstat->DIMMValid & (1 << val))) - /*disable memclk*/ - DramTimingLo |= 1 << (dword+24); - dword++; - } - } - } - - print_tx("AutoConfig_D: DramControl: ", DramControl); - print_tx("AutoConfig_D: DramTimingLo: ", DramTimingLo); - print_tx("AutoConfig_D: DramConfigMisc: ", DramConfigMisc); - print_tx("AutoConfig_D: DramConfigMisc2: ", DramConfigMisc2); - print_tx("AutoConfig_D: DramConfigLo: ", DramConfigLo); - print_tx("AutoConfig_D: DramConfigHi: ", DramConfigHi); - - /* Write Values to the registers */ - Set_NB32(dev, 0x78 + reg_off, DramControl); - Set_NB32(dev, 0x88 + reg_off, DramTimingLo); - Set_NB32(dev, 0xA0 + reg_off, DramConfigMisc); - Set_NB32(dev, 0xA8 + reg_off, DramConfigMisc2); - Set_NB32(dev, 0x90 + reg_off, DramConfigLo); - mct_SetDramConfigHi_D(pDCTstat, dct, DramConfigHi); - mct_ForceAutoPrecharge_D(pDCTstat, dct); - mct_EarlyArbEn_D(pMCTstat, pDCTstat); - mctHookAfterAutoCfg(); - - print_tx("AutoConfig: Status ", pDCTstat->Status); - print_tx("AutoConfig: ErrStatus ", pDCTstat->ErrStatus); - print_tx("AutoConfig: ErrCode ", pDCTstat->ErrCode); - print_t("AutoConfig: Done\n"); -AutoConfig_exit: - return pDCTstat->ErrCode; -} - - -static void SPDSetBanks_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Set bank addressing, program Mask values and build a chip-select - * population map. This routine programs PCI 0:24N:2x80 config register - * and PCI 0:24N:2x60,64,68,6C config registers (CS Mask 0-3). - */ - - u8 ChipSel, Rows, Cols, Ranks, Banks; - u32 BankAddrReg, csMask; - - u32 val; - u32 reg; - u32 dev; - u32 reg_off; - u8 byte; - u16 word; - u32 dword; - u16 smbaddr; - - dev = pDCTstat->dev_dct; - reg_off = 0x100 * dct; - - BankAddrReg = 0; - for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel+=2) { - byte = ChipSel; - if ((pDCTstat->Status & (1 << SB_64MuxedMode)) && ChipSel >=4) - byte -= 3; - - if (pDCTstat->DIMMValid & (1 << byte)) { - smbaddr = Get_DIMMAddress_D(pDCTstat, (ChipSel + dct)); - - byte = mctRead_SPD(smbaddr, SPD_ROWSZ); - Rows = byte & 0x1f; - - byte = mctRead_SPD(smbaddr, SPD_COLSZ); - Cols = byte & 0x1f; - - Banks = mctRead_SPD(smbaddr, SPD_LBANKS); - - byte = mctRead_SPD(smbaddr, SPD_DEVWIDTH); - - byte = mctRead_SPD(smbaddr, SPD_DMBANKS); - Ranks = (byte & 7) + 1; - - /* Configure Bank encoding - * Use a 6-bit key into a lookup table. - * Key (index) = CCCBRR, where CCC is the number of - * Columns minus 9,RR is the number of Rows minus 13, - * and B is the number of banks minus 2. - * See "6-bit Bank Addressing Table" at the end of - * this file.*/ - byte = Cols - 9; /* 9 Cols is smallest dev size */ - byte <<= 3; /* make room for row and bank bits*/ - if (Banks == 8) - byte |= 4; - - /* 13 Rows is smallest dev size */ - byte |= Rows - 13; /* CCCBRR internal encode */ - - for (dword = 0; dword < 12; dword++) { - if (byte == Tab_BankAddr[dword]) - break; - } - - if (dword < 12) { - - /* bit no. of CS field in address mapping reg.*/ - dword <<= (ChipSel << 1); - BankAddrReg |= dword; - - /* Mask value=(2pow(rows+cols+banks+3)-1)>>8, - or 2pow(rows+cols+banks-5)-1*/ - csMask = 0; - - byte = Rows + Cols; /* cl = rows+cols*/ - if (Banks == 8) - byte -= 2; /* 3 banks - 5 */ - else - byte -= 3; /* 2 banks - 5 */ - /* mask size (64-bit rank only) */ - - if (pDCTstat->Status & (1 << SB_128bitmode)) - byte++; /* double mask size if in 128-bit mode*/ - - csMask |= 1 << byte; - csMask--; - - /*set ChipSelect population indicator even bits*/ - pDCTstat->CSPresent |= (1 << ChipSel); - if (Ranks >= 2) - /*set ChipSelect population indicator odd bits*/ - pDCTstat->CSPresent |= 1 << (ChipSel + 1); - - reg = 0x60+(ChipSel << 1) + reg_off; /*Dram CS Mask Register */ - val = csMask; - val &= 0x1FF83FE0; /* Mask out reserved bits.*/ - Set_NB32(dev, reg, val); - } - } else { - if (pDCTstat->DIMMSPDCSE & (1 << ChipSel)) - pDCTstat->CSTestFail |= (1 << ChipSel); - } /* if DIMMValid*/ - } /* while ChipSel*/ - - SetCSTriState(pMCTstat, pDCTstat, dct); - /* SetCKETriState */ - SetODTTriState(pMCTstat, pDCTstat, dct); - - if (pDCTstat->Status & (1 << SB_128bitmode)) { - SetCSTriState(pMCTstat, pDCTstat, 1); /* force dct1) */ - SetODTTriState(pMCTstat, pDCTstat, 1); /* force dct1) */ - } - word = pDCTstat->CSPresent; - mctGetCS_ExcludeMap(); /* mask out specified chip-selects */ - word ^= pDCTstat->CSPresent; - pDCTstat->CSTestFail |= word; /* enable ODT to disabled DIMMs */ - if (!pDCTstat->CSPresent) - pDCTstat->ErrCode = SC_StopError; - - reg = 0x80 + reg_off; /* Bank Addressing Register */ - Set_NB32(dev, reg, BankAddrReg); - - print_tx("SPDSetBanks: Status ", pDCTstat->Status); - print_tx("SPDSetBanks: ErrStatus ", pDCTstat->ErrStatus); - print_tx("SPDSetBanks: ErrCode ", pDCTstat->ErrCode); - print_t("SPDSetBanks: Done\n"); -} - - -static void SPDCalcWidth_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Per SPDs, check the symmetry of DIMM pairs (DIMM on Channel A - * matching with DIMM on Channel B), the overall DIMM population, - * and determine the width mode: 64-bit, 64-bit muxed, 128-bit. - */ - - u8 i; - u8 smbaddr, smbaddr1; - u8 byte, byte1; - - /* Check Symmetry of Channel A and Channel B DIMMs - (must be matched for 128-bit mode).*/ - for (i = 0; i < MAX_DIMMS_SUPPORTED; i += 2) { - if ((pDCTstat->DIMMValid & (1 << i)) && (pDCTstat->DIMMValid & (1<<(i+1)))) { - smbaddr = Get_DIMMAddress_D(pDCTstat, i); - smbaddr1 = Get_DIMMAddress_D(pDCTstat, i+1); - - byte = mctRead_SPD(smbaddr, SPD_ROWSZ) & 0x1f; - byte1 = mctRead_SPD(smbaddr1, SPD_ROWSZ) & 0x1f; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); - break; - } - - byte = mctRead_SPD(smbaddr, SPD_COLSZ) & 0x1f; - byte1 = mctRead_SPD(smbaddr1, SPD_COLSZ) & 0x1f; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); - break; - } - - byte = mctRead_SPD(smbaddr, SPD_BANKSZ); - byte1 = mctRead_SPD(smbaddr1, SPD_BANKSZ); - if (byte != byte1) { - pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); - break; - } - - byte = mctRead_SPD(smbaddr, SPD_DEVWIDTH) & 0x7f; - byte1 = mctRead_SPD(smbaddr1, SPD_DEVWIDTH) & 0x7f; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); - break; - } - - byte = mctRead_SPD(smbaddr, SPD_DMBANKS) & 7; /* #ranks-1 */ - byte1 = mctRead_SPD(smbaddr1, SPD_DMBANKS) & 7; /* #ranks-1 */ - if (byte != byte1) { - pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); - break; - } - - } - } - -} - - -static void StitchMemory_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Requires that Mask values for each bank be programmed first and that - * the chip-select population indicator is correctly set. - */ - - u8 b = 0; - u32 nxtcsBase, curcsBase; - u8 p, q; - u32 BiggestBank; - u8 _DSpareEn; - - u16 word; - u32 dev; - u32 reg; - u32 reg_off; - u32 val; - - - dev = pDCTstat->dev_dct; - reg_off = 0x100 * dct; - - _DSpareEn = 0; - - /* CS Sparing 1 = enabled, 0 = disabled */ - if (mctGet_NVbits(NV_CS_SpareCTL) & 1) { - if (MCT_DIMM_SPARE_NO_WARM) { - /* Do no warm-reset DIMM spare */ - if (pMCTstat->GStatus & 1 << GSB_EnDIMMSpareNW) { - word = pDCTstat->CSPresent; - val = bsf(word); - word &= ~(1<<val); - if (word) - /* Make sure at least two chip-selects are available */ - _DSpareEn = 1; - else - pDCTstat->ErrStatus |= 1 << SB_SpareDis; - } - } else { - if (!mctGet_NVbits(NV_DQSTrainCTL)) { /*DQS Training 1 = enabled, 0 = disabled */ - word = pDCTstat->CSPresent; - val = bsf(word); - word &= ~(1 << val); - if (word) - /* Make sure at least two chip-selects are available */ - _DSpareEn = 1; - else - pDCTstat->ErrStatus |= 1 << SB_SpareDis; - } - } - } - - nxtcsBase = 0; /* Next available cs base ADDR[39:8] */ - for (p = 0; p < MAX_DIMMS_SUPPORTED; p++) { - BiggestBank = 0; - for (q = 0; q < MAX_CS_SUPPORTED; q++) { /* from DIMMS to CS */ - if (pDCTstat->CSPresent & (1 << q)) { /* bank present? */ - reg = 0x40 + (q << 2) + reg_off; /* Base[q] reg.*/ - val = Get_NB32(dev, reg); - if (!(val & 3)) { /* (CSEnable|Spare == 1)bank is enabled already? */ - reg = 0x60 + ((q << 1) & 0xc) + reg_off; /*Mask[q] reg.*/ - val = Get_NB32(dev, reg); - val >>= 19; - val++; - val <<= 19; - if (val > BiggestBank) { - /*Bingo! possibly Map this chip-select next! */ - BiggestBank = val; - b = q; - } - } - } /*if bank present */ - } /* while q */ - if (BiggestBank !=0) { - curcsBase = nxtcsBase; /* curcsBase = nxtcsBase*/ - /* DRAM CS Base b Address Register offset */ - reg = 0x40 + (b << 2) + reg_off; - if (_DSpareEn) { - BiggestBank = 0; - val = 1 << Spare; /* Spare Enable*/ - } else { - val = curcsBase; - val |= 1 << CSEnable; /* Bank Enable */ - } - Set_NB32(dev, reg, val); - if (_DSpareEn) - _DSpareEn = 0; - else - /* let nxtcsBase+=Size[b] */ - nxtcsBase += BiggestBank; - } - - /* bank present but disabled?*/ - if (pDCTstat->CSTestFail & (1 << p)) { - /* DRAM CS Base b Address Register offset */ - reg = (p << 2) + 0x40 + reg_off; - val = 1 << TestFail; - Set_NB32(dev, reg, val); - } - } - - if (nxtcsBase) { - pDCTstat->DCTSysLimit = nxtcsBase - 1; - mct_AfterStitchMemory(pMCTstat, pDCTstat, dct); - } - - print_tx("StitchMemory: Status ", pDCTstat->Status); - print_tx("StitchMemory: ErrStatus ", pDCTstat->ErrStatus); - print_tx("StitchMemory: ErrCode ", pDCTstat->ErrCode); - print_t("StitchMemory: Done\n"); -} - - -static u8 Get_Tk_D(u8 k) -{ - return Table_T_k[k]; -} - - -static u8 Get_CLj_D(u8 j) -{ - return Table_CL2_j[j]; -} - -static u8 Get_DefTrc_k_D(u8 k) -{ - return Tab_defTrc_k[k]; -} - - -static u16 Get_40Tk_D(u8 k) -{ - return Tab_40T_k[k]; /* FIXME: k or k<<1 ?*/ -} - - -static u16 Get_Fk_D(u8 k) -{ - return Table_F_k[k]; /* FIXME: k or k<<1 ? */ -} - - -static u8 Dimm_Supports_D(struct DCTStatStruc *pDCTstat, - u8 i, u8 j, u8 k) -{ - u8 Tk, CLj, CL_i; - u8 ret = 0; - - u32 DIMMi; - u8 byte; - u16 word, wordx; - - DIMMi = Get_DIMMAddress_D(pDCTstat, i); - - CLj = Get_CLj_D(j); - - /* check if DIMMi supports CLj */ - CL_i = mctRead_SPD(DIMMi, SPD_CASLAT); - byte = CL_i & CLj; - if (byte) { - /*find out if its CL X, CLX-1, or CLX-2 */ - word = bsr(byte); /* bit position of CLj */ - wordx = bsr(CL_i); /* bit position of CLX of CLi */ - wordx -= word; /* CL number (CL no. = 0,1, 2, or 3) */ - wordx <<= 3; /* 8 bits per SPD byte index */ - /*get T from SPD byte 9, 23, 25*/ - word = (EncodedTSPD >> wordx) & 0xFF; - Tk = Get_Tk_D(k); - byte = mctRead_SPD(DIMMi, word); /* DIMMi speed */ - if (Tk < byte) { - ret = 1; - } else if (byte == 0) { - pDCTstat->ErrStatus |= 1 << SB_NoCycTime; - ret = 1; - } else { - ret = 0; /* DIMM is capable! */ - } - } else { - ret = 1; - } - return ret; -} - - -static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Check DIMMs present, verify checksum, flag SDRAM type, - * build population indicator bitmaps, and preload bus loading - * of DIMMs into DCTStatStruc. - * MAAload = number of devices on the "A" bus. - * MABload = number of devices on the "B" bus. - * MAAdimms = number of DIMMs on the "A" bus slots. - * MABdimms = number of DIMMs on the "B" bus slots. - * DATAAload = number of ranks on the "A" bus slots. - * DATABload = number of ranks on the "B" bus slots. - */ - - u16 i, j, k; - u8 smbaddr, Index; - u16 Checksum; - u8 SPDCtrl; - u16 RegDIMMPresent, MaxDimms; - u8 devwidth; - u16 DimmSlots; - u8 byte = 0, bytex; - u16 word; - - /* preload data structure with addrs */ - mctGet_DIMMAddr(pDCTstat, pDCTstat->Node_ID); - - DimmSlots = MaxDimms = mctGet_NVbits(NV_MAX_DIMMS); - - SPDCtrl = mctGet_NVbits(NV_SPDCHK_RESTRT); - - RegDIMMPresent = 0; - pDCTstat->DimmQRPresent = 0; - - for (i = 0; i< MAX_DIMMS_SUPPORTED; i++) { - if (i >= MaxDimms) - break; - - if ((pDCTstat->DimmQRPresent & (1 << i)) || (i < DimmSlots)) { - print_tx("\t DIMMPresence: i=", i); - smbaddr = Get_DIMMAddress_D(pDCTstat, i); - print_tx("\t DIMMPresence: smbaddr=", smbaddr); - if (smbaddr) { - Checksum = 0; - for (Index = 0; Index < 64; Index++) { - int status; - status = mctRead_SPD(smbaddr, Index); - if (status < 0) - break; - byte = status & 0xFF; - if (Index < 63) - Checksum += byte; - } - - if (Index == 64) { - pDCTstat->DIMMPresent |= 1 << i; - if ((Checksum & 0xFF) == byte) { - byte = mctRead_SPD(smbaddr, SPD_TYPE); - if (byte == JED_DDR2SDRAM) { - /*Dimm is 'Present'*/ - pDCTstat->DIMMValid |= 1 << i; - } - } else { - pDCTstat->DIMMSPDCSE = 1 << i; - if (SPDCtrl == 0) { - pDCTstat->ErrStatus |= 1 << SB_DIMMChkSum; - pDCTstat->ErrCode = SC_StopError; - } else { - /*if NV_SPDCHK_RESTRT is set to 1, ignore faulty SPD checksum*/ - pDCTstat->ErrStatus |= 1 << SB_DIMMChkSum; - byte = mctRead_SPD(smbaddr, SPD_TYPE); - if (byte == JED_DDR2SDRAM) - pDCTstat->DIMMValid |= 1 << i; - } - } - /* Get module information for SMBIOS */ - if (pDCTstat->DIMMValid & (1 << i)) { - pDCTstat->DimmManufacturerID[i] = 0; - for (k = 0; k < 8; k++) - pDCTstat->DimmManufacturerID[i] |= ((uint64_t)mctRead_SPD(smbaddr, SPD_MANID_START + k)) << (k * 8); - for (k = 0; k < SPD_PARTN_LENGTH; k++) - pDCTstat->DimmPartNumber[i][k] = mctRead_SPD(smbaddr, SPD_PARTN_START + k); - pDCTstat->DimmPartNumber[i][SPD_PARTN_LENGTH] = 0; - pDCTstat->DimmRevisionNumber[i] = 0; - for (k = 0; k < 2; k++) - pDCTstat->DimmRevisionNumber[i] |= ((uint16_t)mctRead_SPD(smbaddr, SPD_REVNO_START + k)) << (k * 8); - pDCTstat->DimmSerialNumber[i] = 0; - for (k = 0; k < 4; k++) - pDCTstat->DimmSerialNumber[i] |= ((uint32_t)mctRead_SPD(smbaddr, SPD_SERIAL_START + k)) << (k * 8); - pDCTstat->DimmRows[i] = mctRead_SPD(smbaddr, SPD_ROWSZ) & 0xf; - pDCTstat->DimmCols[i] = mctRead_SPD(smbaddr, SPD_COLSZ) & 0xf; - pDCTstat->DimmRanks[i] = (mctRead_SPD(smbaddr, SPD_DMBANKS) & 0x7) + 1; - pDCTstat->DimmBanks[i] = mctRead_SPD(smbaddr, SPD_LBANKS); - pDCTstat->DimmWidth[i] = mctRead_SPD(smbaddr, SPD_DEVWIDTH); - } - /* Check module type */ - byte = mctRead_SPD(smbaddr, SPD_DIMMTYPE); - if (byte & JED_REGADCMSK) { - RegDIMMPresent |= 1 << i; - pDCTstat->DimmRegistered[i] = 1; - } else { - pDCTstat->DimmRegistered[i] = 0; - } - /* Check ECC capable */ - byte = mctRead_SPD(smbaddr, SPD_EDCTYPE); - if (byte & JED_ECC) { - /* DIMM is ECC capable */ - pDCTstat->DimmECCPresent |= 1 << i; - } - if (byte & JED_ADRCPAR) { - /* DIMM is ECC capable */ - pDCTstat->DimmPARPresent |= 1 << i; - } - /* Check if x4 device */ - devwidth = mctRead_SPD(smbaddr, SPD_DEVWIDTH) & 0xFE; - if (devwidth == 4) { - /* DIMM is made with x4 or x16 drams */ - pDCTstat->Dimmx4Present |= 1 << i; - } else if (devwidth == 8) { - pDCTstat->Dimmx8Present |= 1 << i; - } else if (devwidth == 16) { - pDCTstat->Dimmx16Present |= 1 << i; - } - /* check page size */ - byte = mctRead_SPD(smbaddr, SPD_COLSZ); - byte &= 0x0F; - word = 1 << byte; - word >>= 3; - word *= devwidth; /* (((2^COLBITS) / 8) * ORG) / 2048 */ - word >>= 11; - if (word) - pDCTstat->DIMM2Kpage |= 1 << i; - - /*Check if SPD diag bit 'analysis probe installed' is set */ - byte = mctRead_SPD(smbaddr, SPD_ATTRIB); - if (byte & JED_PROBEMSK) - pDCTstat->Status |= 1 << SB_DiagClks; - - byte = mctRead_SPD(smbaddr, SPD_DMBANKS); - if (!(byte & (1 << SPDPLBit))) - pDCTstat->DimmPlPresent |= 1 << i; - byte &= 7; - byte++; /* ranks */ - if (byte > 2) { - /* if any DIMMs are QR, we have to make two passes through DIMMs*/ - if (pDCTstat->DimmQRPresent == 0) { - MaxDimms <<= 1; - } - if (i < DimmSlots) { - pDCTstat->DimmQRPresent |= (1 << i) | (1 << (i+4)); - } - byte = 2; /* upper two ranks of QR DIMM will be counted on another DIMM number iteration*/ - } else if (byte == 2) { - pDCTstat->DimmDRPresent |= 1 << i; - } - bytex = devwidth; - if (devwidth == 16) - bytex = 4; - else if (devwidth == 4) - bytex = 16; - - if (byte == 2) - bytex <<= 1; /*double Addr bus load value for dual rank DIMMs*/ - - j = i & (1<<0); - pDCTstat->DATAload[j] += byte; /*number of ranks on DATA bus*/ - pDCTstat->MAload[j] += bytex; /*number of devices on CMD/ADDR bus*/ - pDCTstat->MAdimms[j]++; /*number of DIMMs on A bus */ - /*check for DRAM package Year <= 06*/ - byte = mctRead_SPD(smbaddr, SPD_MANDATEYR); - if (byte < MYEAR06) { - /*Year < 06 and hence Week < 24 of 06 */ - pDCTstat->DimmYr06 |= 1 << i; - pDCTstat->DimmWk2406 |= 1 << i; - } else if (byte == MYEAR06) { - /*Year = 06, check if Week <= 24 */ - pDCTstat->DimmYr06 |= 1 << i; - byte = mctRead_SPD(smbaddr, SPD_MANDATEWK); - if (byte <= MWEEK24) - pDCTstat->DimmWk2406 |= 1 << i; - } - } - } - } - } - print_tx("\t DIMMPresence: DIMMValid=", pDCTstat->DIMMValid); - print_tx("\t DIMMPresence: DIMMPresent=", pDCTstat->DIMMPresent); - print_tx("\t DIMMPresence: RegDIMMPresent=", RegDIMMPresent); - print_tx("\t DIMMPresence: DimmECCPresent=", pDCTstat->DimmECCPresent); - print_tx("\t DIMMPresence: DimmPARPresent=", pDCTstat->DimmPARPresent); - print_tx("\t DIMMPresence: Dimmx4Present=", pDCTstat->Dimmx4Present); - print_tx("\t DIMMPresence: Dimmx8Present=", pDCTstat->Dimmx8Present); - print_tx("\t DIMMPresence: Dimmx16Present=", pDCTstat->Dimmx16Present); - print_tx("\t DIMMPresence: DimmPlPresent=", pDCTstat->DimmPlPresent); - print_tx("\t DIMMPresence: DimmDRPresent=", pDCTstat->DimmDRPresent); - print_tx("\t DIMMPresence: DimmQRPresent=", pDCTstat->DimmQRPresent); - print_tx("\t DIMMPresence: DATAload[0]=", pDCTstat->DATAload[0]); - print_tx("\t DIMMPresence: MAload[0]=", pDCTstat->MAload[0]); - print_tx("\t DIMMPresence: MAdimms[0]=", pDCTstat->MAdimms[0]); - print_tx("\t DIMMPresence: DATAload[1]=", pDCTstat->DATAload[1]); - print_tx("\t DIMMPresence: MAload[1]=", pDCTstat->MAload[1]); - print_tx("\t DIMMPresence: MAdimms[1]=", pDCTstat->MAdimms[1]); - - if (pDCTstat->DIMMValid != 0) { /* If any DIMMs are present...*/ - if (RegDIMMPresent != 0) { - if ((RegDIMMPresent ^ pDCTstat->DIMMValid) !=0) { - /* module type DIMM mismatch (reg'ed, unbuffered) */ - pDCTstat->ErrStatus |= 1 << SB_DimmMismatchM; - pDCTstat->ErrCode = SC_StopError; - } else{ - /* all DIMMs are registered */ - pDCTstat->Status |= 1 << SB_Registered; - } - } - if (pDCTstat->DimmECCPresent != 0) { - if ((pDCTstat->DimmECCPresent ^ pDCTstat->DIMMValid) == 0) { - /* all DIMMs are ECC capable */ - pDCTstat->Status |= 1 << SB_ECCDIMMs; - } - } - if (pDCTstat->DimmPARPresent != 0) { - if ((pDCTstat->DimmPARPresent ^ pDCTstat->DIMMValid) == 0) { - /*all DIMMs are Parity capable */ - pDCTstat->Status |= 1 << SB_PARDIMMs; - } - } - } else { - /* no DIMMs present or no DIMMs that qualified. */ - pDCTstat->ErrStatus |= 1 << SB_NoDimms; - pDCTstat->ErrCode = SC_StopError; - } - - print_tx("\t DIMMPresence: Status ", pDCTstat->Status); - print_tx("\t DIMMPresence: ErrStatus ", pDCTstat->ErrStatus); - print_tx("\t DIMMPresence: ErrCode ", pDCTstat->ErrCode); - print_t("\t DIMMPresence: Done\n"); - - mctHookAfterDIMMpre(); - - return pDCTstat->ErrCode; -} - - -static u8 Sys_Capability_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, int j, int k) -{ - /* Determine if system is capable of operating at given input - * parameters for CL, and T. There are three components to - * determining "maximum frequency" in AUTO mode: SPD component, - * Bus load component, and "Preset" max frequency component. - * This procedure is used to help find the SPD component and relies - * on pre-determination of the bus load component and the Preset - * components. The generalized algorithm for finding maximum - * frequency is structured this way so as to optimize for CAS - * latency (which might get better as a result of reduced frequency). - * See "Global relationship between index values and item values" - * for definition of CAS latency index (j) and Frequency index (k). - */ - u8 freqOK, ClOK; - u8 ret = 0; - - if (Get_Fk_D(k) > pDCTstat->PresetmaxFreq) - freqOK = 0; - else - freqOK = 1; - - /* compare proposed CAS latency with AMD Si capabilities */ - if ((j < J_MIN) || (j > J_MAX)) - ClOK = 0; - else - ClOK = 1; - - if (freqOK && ClOK) - ret = 1; - - return ret; -} - - -static u8 Get_DIMMAddress_D(struct DCTStatStruc *pDCTstat, u8 i) -{ - u8 *p; - - p = pDCTstat->DIMMAddr; - return p[i]; -} - - -static void mct_initDCT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 val; - u8 err_code; - - /* Config. DCT0 for Ganged or unganged mode */ - print_t("\tmct_initDCT: DCTInit_D 0\n"); - DCTInit_D(pMCTstat, pDCTstat, 0); - if (pDCTstat->ErrCode == SC_FatalErr) { - // Do nothing goto exitDCTInit; /* any fatal errors? */ - } else { - /* Configure DCT1 if unganged and enabled*/ - if (!pDCTstat->GangedMode) { - if (pDCTstat->DIMMValidDCT[1] > 0) { - print_t("\tmct_initDCT: DCTInit_D 1\n"); - err_code = pDCTstat->ErrCode; /* save DCT0 errors */ - pDCTstat->ErrCode = 0; - DCTInit_D(pMCTstat, pDCTstat, 1); - if (pDCTstat->ErrCode == 2) /* DCT1 is not Running */ - pDCTstat->ErrCode = err_code; /* Using DCT0 Error code to update pDCTstat.ErrCode */ - } else { - val = 1 << DisDramInterface; - Set_NB32(pDCTstat->dev_dct, 0x100 + 0x94, val); - } - } - } -// exitDCTInit: -} - - -static void mct_DramInit(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - - mct_BeforeDramInit_Prod_D(pMCTstat, pDCTstat); - // FIXME: for rev A: mct_BeforeDramInit_D(pDCTstat, dct); - - /* Disable auto refresh before Dram init when in ganged mode (Erratum 278) */ - if (pDCTstat->LogicalCPUID & (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_BA)) { - if (pDCTstat->GangedMode) { - val = Get_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct)); - val |= 1 << DisAutoRefresh; - Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val); - } - } - - mct_DramInit_Hw_D(pMCTstat, pDCTstat, dct); - - /* Re-enable auto refresh after Dram init when in ganged mode - * to ensure both DCTs are in sync (Erratum 278) - */ - - if (pDCTstat->LogicalCPUID & (AMD_DR_B0 | AMD_DR_B1 | AMD_DR_BA)) { - if (pDCTstat->GangedMode) { - do { - val = Get_NB32(pDCTstat->dev_dct, 0x90 + (0x100 * dct)); - } while (!(val & (1 << InitDram))); - - WaitRoutine_D(50); - - val = Get_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct)); - val &= ~(1 << DisAutoRefresh); - Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val); - val |= 1 << DisAutoRefresh; - Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val); - val &= ~(1 << DisAutoRefresh); - Set_NB32(pDCTstat->dev_dct, 0x8C + (0x100 * dct), val); - } - } -} - - -static u8 mct_setMode(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 byte; - u8 bytex; - u32 val; - u32 reg; - - byte = bytex = pDCTstat->DIMMValid; - bytex &= 0x55; /* CHA DIMM pop */ - pDCTstat->DIMMValidDCT[0] = bytex; - - byte &= 0xAA; /* CHB DIMM popa */ - byte >>= 1; - pDCTstat->DIMMValidDCT[1] = byte; - - if (byte != bytex) { - pDCTstat->ErrStatus &= ~(1 << SB_DimmMismatchO); - } else { - if (mctGet_NVbits(NV_Unganged)) - pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); - - if (!(pDCTstat->ErrStatus & (1 << SB_DimmMismatchO))) { - pDCTstat->GangedMode = 1; - /* valid 128-bit mode population. */ - pDCTstat->Status |= 1 << SB_128bitmode; - reg = 0x110; - val = Get_NB32(pDCTstat->dev_dct, reg); - val |= 1 << DctGangEn; - Set_NB32(pDCTstat->dev_dct, reg, val); - print_tx("setMode: DRAM Controller Select Low Register = ", val); - } - } - return pDCTstat->ErrCode; -} - - -u32 Get_NB32(u32 dev, u32 reg) -{ - return pci_read_config32(dev, reg); -} - - -void Set_NB32(u32 dev, u32 reg, u32 val) -{ - pci_write_config32(dev, reg, val); -} - - -u32 Get_NB32_index(u32 dev, u32 index_reg, u32 index) -{ - u32 dword; - - Set_NB32(dev, index_reg, index); - dword = Get_NB32(dev, index_reg+0x4); - - return dword; -} - -void Set_NB32_index(u32 dev, u32 index_reg, u32 index, u32 data) -{ - Set_NB32(dev, index_reg, index); - Set_NB32(dev, index_reg + 0x4, data); -} - - -u32 Get_NB32_index_wait(u32 dev, u32 index_reg, u32 index) -{ - - u32 dword; - - - index &= ~(1 << DctAccessWrite); - Set_NB32(dev, index_reg, index); - do { - dword = Get_NB32(dev, index_reg); - } while (!(dword & (1 << DctAccessDone))); - dword = Get_NB32(dev, index_reg + 0x4); - - return dword; -} - - -void Set_NB32_index_wait(u32 dev, u32 index_reg, u32 index, u32 data) -{ - u32 dword; - - - Set_NB32(dev, index_reg + 0x4, data); - index |= (1 << DctAccessWrite); - Set_NB32(dev, index_reg, index); - do { - dword = Get_NB32(dev, index_reg); - } while (!(dword & (1 << DctAccessDone))); - -} - - -static u8 mct_PlatformSpec(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Get platform specific config/timing values from the interface layer - * and program them into DCT. - */ - - u32 dev = pDCTstat->dev_dct; - u32 index_reg; - u8 i, i_start, i_end; - - if (pDCTstat->GangedMode) { - SyncSetting(pDCTstat); - i_start = 0; - i_end = 2; - } else { - i_start = dct; - i_end = dct + 1; - } - for (i = i_start; i < i_end; i++) { - index_reg = 0x98 + (i * 0x100); - Set_NB32_index_wait(dev, index_reg, 0x00, pDCTstat->CH_ODC_CTL[i]); /* Channel A Output Driver Compensation Control */ - Set_NB32_index_wait(dev, index_reg, 0x04, pDCTstat->CH_ADDR_TMG[i]); /* Channel A Output Driver Compensation Control */ - } - - return pDCTstat->ErrCode; - -} - - -static void mct_SyncDCTsReady(struct DCTStatStruc *pDCTstat) -{ - u32 dev; - u32 val; - - if (pDCTstat->NodePresent) { - print_tx("mct_SyncDCTsReady: Node ", pDCTstat->Node_ID); - dev = pDCTstat->dev_dct; - - if ((pDCTstat->DIMMValidDCT[0]) || (pDCTstat->DIMMValidDCT[1])) { /* This Node has dram */ - do { - val = Get_NB32(dev, 0x110); - } while (!(val & (1 << DramEnabled))); - print_t("mct_SyncDCTsReady: DramEnabled\n"); - } - } /* Node is present */ -} - - -static void mct_AfterGetCLT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - if (!pDCTstat->GangedMode) { - if (dct == 0) { - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct]; - if (pDCTstat->DIMMValidDCT[dct] == 0) - pDCTstat->ErrCode = SC_StopError; - } else { - pDCTstat->CSPresent = 0; - pDCTstat->CSTestFail = 0; - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct]; - if (pDCTstat->DIMMValidDCT[dct] == 0) - pDCTstat->ErrCode = SC_StopError; - } - } -} - -static u8 mct_SPDCalcWidth(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 ret; - - if (dct == 0) { - SPDCalcWidth_D(pMCTstat, pDCTstat); - ret = mct_setMode(pMCTstat, pDCTstat); - } else { - ret = pDCTstat->ErrCode; - } - - print_tx("SPDCalcWidth: Status ", pDCTstat->Status); - print_tx("SPDCalcWidth: ErrStatus ", pDCTstat->ErrStatus); - print_tx("SPDCalcWidth: ErrCode ", pDCTstat->ErrCode); - print_t("SPDCalcWidth: Done\n"); - - return ret; -} - - -static void mct_AfterStitchMemory(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dword; - u32 dev; - u32 reg; - u8 _MemHoleRemap; - u32 DramHoleBase; - - _MemHoleRemap = mctGet_NVbits(NV_MemHole); - DramHoleBase = mctGet_NVbits(NV_BottomIO); - DramHoleBase <<= 8; - /* Increase hole size so;[31:24]to[31:16] - * it has granularity of 128MB shl eax,8 - * Set 'effective' bottom IOmov DramHoleBase,eax - */ - pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8; - - /* In unganged mode, we must add DCT0 and DCT1 to DCTSysLimit */ - if (!pDCTstat->GangedMode) { - dev = pDCTstat->dev_dct; - pDCTstat->NodeSysLimit += pDCTstat->DCTSysLimit; - /* if DCT0 and DCT1 both exist, set DctSelBaseAddr[47:27] to the top of DCT0 */ - if (dct == 0) { - if (pDCTstat->DIMMValidDCT[1] > 0) { - dword = pDCTstat->DCTSysLimit + 1; - dword += pDCTstat->NodeSysBase; - dword >>= 8; /* scale [39:8] to [47:27],and to F2x110[31:11] */ - if ((dword >= DramHoleBase) && _MemHoleRemap) { - pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8; - val = pMCTstat->HoleBase; - val >>= 16; - val = (((~val) & 0xFF) + 1); - val <<= 8; - dword += val; - } - reg = 0x110; - val = Get_NB32(dev, reg); - val &= 0x7F; - val |= dword; - val |= 3; /* Set F2x110[DctSelHiRngEn], F2x110[DctSelHi] */ - Set_NB32(dev, reg, val); - print_tx("AfterStitch DCT0 and DCT1: DRAM Controller Select Low Register = ", val); - print_tx("AfterStitch DCT0 and DCT1: DRAM Controller Select High Register = ", dword); - - reg = 0x114; - val = dword; - Set_NB32(dev, reg, val); - } - } else { - /* Program the DctSelBaseAddr value to 0 - if DCT 0 is disabled */ - if (pDCTstat->DIMMValidDCT[0] == 0) { - dword = pDCTstat->NodeSysBase; - dword >>= 8; - if ((dword >= DramHoleBase) && _MemHoleRemap) { - pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8; - val = pMCTstat->HoleBase; - val >>= 8; - val &= ~(0xFFFF); - val |= (((~val) & 0xFFFF) + 1); - dword += val; - } - reg = 0x114; - val = dword; - Set_NB32(dev, reg, val); - - reg = 0x110; - val |= 3; /* Set F2x110[DctSelHiRngEn], F2x110[DctSelHi] */ - Set_NB32(dev, reg, val); - print_tx("AfterStitch DCT1 only: DRAM Controller Select Low Register = ", val); - print_tx("AfterStitch DCT1 only: DRAM Controller Select High Register = ", dword); - } - } - } else { - pDCTstat->NodeSysLimit += pDCTstat->DCTSysLimit; - } - print_tx("AfterStitch pDCTstat->NodeSysBase = ", pDCTstat->NodeSysBase); - print_tx("mct_AfterStitchMemory: pDCTstat->NodeSysLimit ", pDCTstat->NodeSysLimit); -} - - -static u8 mct_DIMMPresence(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 ret; - - if (dct == 0) - ret = DIMMPresence_D(pMCTstat, pDCTstat); - else - ret = pDCTstat->ErrCode; - - return ret; -} - - -/* mct_BeforeGetDIMMAddress inline in C */ - - -static void mct_OtherTiming(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) { - if (pDCTstat->DIMMValidDCT[0]) { - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[0]; - Set_OtherTiming(pMCTstat, pDCTstat, 0); - } - if (pDCTstat->DIMMValidDCT[1] && !pDCTstat->GangedMode) { - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[1]; - Set_OtherTiming(pMCTstat, pDCTstat, 1); - } - } /* Node is present*/ - } /* while Node */ -} - - -static void Set_OtherTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 reg; - u32 reg_off = 0x100 * dct; - u32 val; - u32 dword; - u32 dev = pDCTstat->dev_dct; - - Get_Trdrd(pMCTstat, pDCTstat, dct); - Get_Twrwr(pMCTstat, pDCTstat, dct); - Get_Twrrd(pMCTstat, pDCTstat, dct); - Get_TrwtTO(pMCTstat, pDCTstat, dct); - Get_TrwtWB(pMCTstat, pDCTstat); - - reg = 0x8C + reg_off; /* Dram Timing Hi */ - val = Get_NB32(dev, reg); - val &= 0xffff0300; - dword = pDCTstat->TrwtTO; //0x07 - val |= dword << 4; - dword = pDCTstat->Twrrd; //0x03 - val |= dword << 10; - dword = pDCTstat->Twrwr; //0x03 - val |= dword << 12; - dword = pDCTstat->Trdrd; //0x03 - val |= dword << 14; - dword = pDCTstat->TrwtWB; //0x07 - val |= dword; - val = OtherTiming_A_D(pDCTstat, val); - Set_NB32(dev, reg, val); - -} - - -static void Get_Trdrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 Trdrd; - u8 byte; - u32 dword; - u32 val; - u32 index_reg = 0x98 + 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - - if ((pDCTstat->Dimmx4Present != 0) && (pDCTstat->Dimmx8Present != 0)) { - /* mixed (x4 or x8) DIMM types - the largest DqsRcvEnGrossDelay of any DIMM minus the DqsRcvEnGrossDelay - of any other DIMM is equal to the Critical Gross Delay Difference (CGDD) for Trdrd.*/ - byte = Get_DqsRcvEnGross_Diff(pDCTstat, dev, index_reg); - if (byte == 0) - Trdrd = 1; - else - Trdrd = 2; - - } else { - /* - Trdrd with non-mixed DIMM types - RdDqsTime are the same for all DIMMs and DqsRcvEn difference between - any two DIMMs is less than half of a MEMCLK, BIOS should program Trdrd to 0000b, - else BIOS should program Trdrd to 0001b. - - RdDqsTime are the same for all DIMMs - DDR400~DDR667 only use one set register - DDR800 have two set register for DIMM0 and DIMM1 */ - Trdrd = 1; - if (pDCTstat->Speed > 3) { - /* DIMM0+DIMM1 exist */ //NOTE it should be 5 - val = bsf(pDCTstat->DIMMValid); - dword = bsr(pDCTstat->DIMMValid); - if (dword != val && dword != 0) { - /* DCT Read DQS Timing Control - DIMM0 - Low */ - dword = Get_NB32_index_wait(dev, index_reg, 0x05); - /* DCT Read DQS Timing Control - DIMM1 - Low */ - val = Get_NB32_index_wait(dev, index_reg, 0x105); - if (val != dword) - goto Trdrd_1; - - /* DCT Read DQS Timing Control - DIMM0 - High */ - dword = Get_NB32_index_wait(dev, index_reg, 0x06); - /* DCT Read DQS Timing Control - DIMM1 - High */ - val = Get_NB32_index_wait(dev, index_reg, 0x106); - if (val != dword) - goto Trdrd_1; - } - } - - /* DqsRcvEn difference between any two DIMMs is - less than half of a MEMCLK */ - /* DqsRcvEn byte 1,0*/ - if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x10)) - goto Trdrd_1; - /* DqsRcvEn byte 3,2*/ - if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x11)) - goto Trdrd_1; - /* DqsRcvEn byte 5,4*/ - if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x20)) - goto Trdrd_1; - /* DqsRcvEn byte 7,6*/ - if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x21)) - goto Trdrd_1; - /* DqsRcvEn ECC*/ - if (Check_DqsRcvEn_Diff(pDCTstat, dct, dev, index_reg, 0x12)) - goto Trdrd_1; - Trdrd = 0; - Trdrd_1: - ; - } - pDCTstat->Trdrd = Trdrd; - -} - - -static void Get_Twrwr(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 Twrwr = 0; - u32 index_reg = 0x98 + 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - u32 val; - u32 dword; - - /* WrDatGrossDlyByte only use one set register when DDR400~DDR667 - DDR800 have two set register for DIMM0 and DIMM1 */ - if (pDCTstat->Speed > 3) { - val = bsf(pDCTstat->DIMMValid); - dword = bsr(pDCTstat->DIMMValid); - if (dword != val && dword != 0) { - /*the largest WrDatGrossDlyByte of any DIMM minus the - WrDatGrossDlyByte of any other DIMM is equal to CGDD */ - val = Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg); - } - if (val == 0) - Twrwr = 2; - else - Twrwr = 3; - } - pDCTstat->Twrwr = Twrwr; -} - - -static void Get_Twrrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 byte, bytex, val; - u32 index_reg = 0x98 + 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - - /* On any given byte lane, the largest WrDatGrossDlyByte delay of - any DIMM minus the DqsRcvEnGrossDelay delay of any other DIMM is - equal to the Critical Gross Delay Difference (CGDD) for Twrrd.*/ - - /* WrDatGrossDlyByte only use one set register when DDR400~DDR667 - DDR800 have two set register for DIMM0 and DIMM1 */ - if (pDCTstat->Speed > 3) { - val = Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg); - } else { - val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 1); /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM0 */ - pDCTstat->WrDatGrossH = (u8) val; /* low byte = max value */ - } - - Get_DqsRcvEnGross_Diff(pDCTstat, dev, index_reg); - - bytex = pDCTstat->DqsRcvEnGrossL; - byte = pDCTstat->WrDatGrossH; - if (byte > bytex) { - byte -= bytex; - if (byte == 1) - bytex = 1; - else - bytex = 2; - } else { - bytex = 0; - } - pDCTstat->Twrrd = bytex; -} - - -static void Get_TrwtTO(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 byte, bytex; - u32 index_reg = 0x98 + 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - - /* On any given byte lane, the largest WrDatGrossDlyByte delay of - any DIMM minus the DqsRcvEnGrossDelay delay of any other DIMM is - equal to the Critical Gross Delay Difference (CGDD) for TrwtTO. */ - Get_DqsRcvEnGross_Diff(pDCTstat, dev, index_reg); - Get_WrDatGross_Diff(pDCTstat, dct, dev, index_reg); - bytex = pDCTstat->DqsRcvEnGrossL; - byte = pDCTstat->WrDatGrossH; - if (bytex > byte) { - bytex -= byte; - if ((bytex == 1) || (bytex == 2)) - bytex = 3; - else - bytex = 4; - } else { - byte -= bytex; - if ((byte == 0) || (byte == 1)) - bytex = 2; - else - bytex = 1; - } - - pDCTstat->TrwtTO = bytex; -} - - -static void Get_TrwtWB(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* TrwtWB ensures read-to-write data-bus turnaround. - This value should be one more than the programmed TrwtTO.*/ - pDCTstat->TrwtWB = pDCTstat->TrwtTO + 1; -} - - -static u8 Check_DqsRcvEn_Diff(struct DCTStatStruc *pDCTstat, - u8 dct, u32 dev, u32 index_reg, - u32 index) -{ - u8 Smallest_0, Largest_0, Smallest_1, Largest_1; - u8 i; - u32 val; - u8 byte; - u8 ecc_reg = 0; - - Smallest_0 = 0xFF; - Smallest_1 = 0xFF; - Largest_0 = 0; - Largest_1 = 0; - - if (index == 0x12) - ecc_reg = 1; - - for (i = 0; i < 8; i+=2) { - if (pDCTstat->DIMMValid & (1 << i)) { - val = Get_NB32_index_wait(dev, index_reg, index); - byte = val & 0xFF; - if (byte < Smallest_0) - Smallest_0 = byte; - if (byte > Largest_0) - Largest_0 = byte; - if (!(ecc_reg)) { - byte = (val >> 16) & 0xFF; - if (byte < Smallest_1) - Smallest_1 = byte; - if (byte > Largest_1) - Largest_1 = byte; - } - } - index += 3; - } /* while ++i */ - - /* check if total DqsRcvEn delay difference between any - two DIMMs is less than half of a MEMCLK */ - if ((Largest_0 - Smallest_0) > 31) - return 1; - if (!(ecc_reg)) - if ((Largest_1 - Smallest_1) > 31) - return 1; - return 0; -} - - -static u8 Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat, - u32 dev, u32 index_reg) -{ - u8 Smallest, Largest; - u32 val; - u8 byte, bytex; - - /* The largest DqsRcvEnGrossDelay of any DIMM minus the - DqsRcvEnGrossDelay of any other DIMM is equal to the Critical - Gross Delay Difference (CGDD) */ - /* DqsRcvEn byte 1,0 */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x10); - Largest = val & 0xFF; - Smallest = (val >> 8) & 0xFF; - - /* DqsRcvEn byte 3,2 */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x11); - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - - /* DqsRcvEn byte 5,4 */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x20); - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - - /* DqsRcvEn byte 7,6 */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x21); - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - - if (pDCTstat->DimmECCPresent> 0) { - /*DqsRcvEn Ecc */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, index_reg, 0x12); - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - } - - pDCTstat->DqsRcvEnGrossL = Largest; - return Largest - Smallest; -} - - -static u8 Get_WrDatGross_Diff(struct DCTStatStruc *pDCTstat, - u8 dct, u32 dev, u32 index_reg) -{ - u8 Smallest, Largest; - u32 val; - u8 byte, bytex; - - /* The largest WrDatGrossDlyByte of any DIMM minus the - WrDatGrossDlyByte of any other DIMM is equal to CGDD */ - val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x01); /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM0 */ - Largest = val & 0xFF; - Smallest = (val >> 8) & 0xFF; - val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x101); /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM1 */ - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - - // FIXME: Add Cx support. - - pDCTstat->WrDatGrossH = Largest; - return Largest - Smallest; -} - -static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat, - u32 dev, u32 index_reg, - u32 index) -{ - u8 Smallest, Largest; - u8 i; - u8 byte; - u32 val; - u16 word; - u8 ecc_reg = 0; - - Smallest = 7; - Largest = 0; - - if (index == 0x12) - ecc_reg = 1; - - for (i = 0; i < 8; i+=2) { - if (pDCTstat->DIMMValid & (1 << i)) { - val = Get_NB32_index_wait(dev, index_reg, index); - val &= 0x00E000E0; - byte = (val >> 5) & 0xFF; - if (byte < Smallest) - Smallest = byte; - if (byte > Largest) - Largest = byte; - if (!(ecc_reg)) { - byte = (val >> (16 + 5)) & 0xFF; - if (byte < Smallest) - Smallest = byte; - if (byte > Largest) - Largest = byte; - } - } - index += 3; - } /* while ++i */ - - word = Smallest; - word <<= 8; - word |= Largest; - - return word; -} - -static u16 Get_WrDatGross_MaxMin(struct DCTStatStruc *pDCTstat, - u8 dct, u32 dev, u32 index_reg, - u32 index) -{ - u8 Smallest, Largest; - u8 i, j; - u32 val; - u8 byte; - u16 word; - - Smallest = 3; - Largest = 0; - for (i = 0; i < 2; i++) { - val = Get_NB32_index_wait(dev, index_reg, index); - val &= 0x60606060; - val >>= 5; - for (j = 0; j < 4; j++) { - byte = val & 0xFF; - if (byte < Smallest) - Smallest = byte; - if (byte > Largest) - Largest = byte; - val >>= 8; - } /* while ++j */ - index++; - } /*while ++i*/ - - if (pDCTstat->DimmECCPresent > 0) { - index++; - val = Get_NB32_index_wait(dev, index_reg, index); - val &= 0x00000060; - val >>= 5; - byte = val & 0xFF; - if (byte < Smallest) - Smallest = byte; - if (byte > Largest) - Largest = byte; - } - - word = Smallest; - word <<= 8; - word |= Largest; - - return word; -} - - - -static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - print_t("\tmct_FinalMCT_D: Clr Cl, Wb\n"); - - - /* ClrClToNB_D postponed until we're done executing from ROM */ - mct_ClrWbEnhWsbDis_D(pMCTstat, pDCTstat); -} - - -static void mct_InitialMCT_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) -{ - print_t("\tmct_InitialMCT_D: Set Cl, Wb\n"); - mct_SetClToNB_D(pMCTstat, pDCTstat); - mct_SetWbEnhWsbDis_D(pMCTstat, pDCTstat); -} - - -static u32 mct_NodePresent_D(void) -{ - u32 val; - val = 0x12001022; - return val; -} - - -static void mct_init(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 lo, hi; - u32 addr; - - pDCTstat->GangedMode = 0; - pDCTstat->DRPresent = 1; - - /* enable extend PCI configuration access */ - addr = NB_CFG_MSR; - _RDMSR(addr, &lo, &hi); - if (hi & (1 << (46-32))) { - pDCTstat->Status |= 1 << SB_ExtConfig; - } else { - hi |= 1 << (46-32); - _WRMSR(addr, lo, hi); - } -} - - -static void clear_legacy_Mode(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 reg; - u32 val; - u32 dev = pDCTstat->dev_dct; - - /* Clear Legacy BIOS Mode bit */ - reg = 0x94; - val = Get_NB32(dev, reg); - val &= ~(1<<LegacyBiosMode); - Set_NB32(dev, reg, val); -} - - -static void mct_HTMemMapExt(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - u32 Drambase, Dramlimit; - u32 val; - u32 reg; - u32 dev; - u32 devx; - u32 dword; - struct DCTStatStruc *pDCTstat; - - pDCTstat = pDCTstatA + 0; - dev = pDCTstat->dev_map; - - /* Copy dram map from F1x40/44,F1x48/4c, - to F1x120/124(Node0),F1x120/124(Node1),...*/ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - devx = pDCTstat->dev_map; - - /* get base/limit from Node0 */ - reg = 0x40 + (Node << 3); /* Node0/Dram Base 0 */ - val = Get_NB32(dev, reg); - Drambase = val >> (16 + 3); - - reg = 0x44 + (Node << 3); /* Node0/Dram Base 0 */ - val = Get_NB32(dev, reg); - Dramlimit = val >> (16 + 3); - - /* set base/limit to F1x120/124 per Node */ - if (pDCTstat->NodePresent) { - reg = 0x120; /* F1x120,DramBase[47:27] */ - val = Get_NB32(devx, reg); - val &= 0xFFE00000; - val |= Drambase; - Set_NB32(devx, reg, val); - - reg = 0x124; - val = Get_NB32(devx, reg); - val &= 0xFFE00000; - val |= Dramlimit; - Set_NB32(devx, reg, val); - - if (pMCTstat->GStatus & (1 << GSB_HWHole)) { - reg = 0xF0; - val = Get_NB32(devx, reg); - val |= (1 << DramMemHoistValid); - val &= ~(0xFF << 24); - dword = (pMCTstat->HoleBase >> (24 - 8)) & 0xFF; - dword <<= 24; - val |= dword; - Set_NB32(devx, reg, val); - } - - } - } -} - -static void SetCSTriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dev = pDCTstat->dev_dct; - u32 index_reg = 0x98 + 0x100 * dct; - u8 cs; - u32 index; - u16 word; - - /* Tri-state unused chipselects when motherboard - termination is available */ - - // FIXME: skip for Ax - - word = pDCTstat->CSPresent; - if (pDCTstat->Status & (1 << SB_Registered)) { - for (cs = 0; cs < 8; cs++) { - if (word & (1 << cs)) { - if (!(cs & 1)) - word |= 1 << (cs + 1); - } - } - } - word = (~word) & 0xFF; - index = 0x0c; - val = Get_NB32_index_wait(dev, index_reg, index); - val |= word; - Set_NB32_index_wait(dev, index_reg, index, val); -} - - -#ifdef UNUSED_CODE -static void SetCKETriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dev; - u32 index_reg = 0x98 + 0x100 * dct; - u8 cs; - u32 index; - u16 word; - - /* Tri-state unused CKEs when motherboard termination is available */ - - // FIXME: skip for Ax - - dev = pDCTstat->dev_dct; - word = 0x101; - for (cs = 0; cs < 8; cs++) { - if (pDCTstat->CSPresent & (1 << cs)) { - if (!(cs & 1)) - word &= 0xFF00; - else - word &= 0x00FF; - } - } - - index = 0x0c; - val = Get_NB32_index_wait(dev, index_reg, index); - if ((word & 0x00FF) == 1) - val |= 1 << 12; - else - val &= ~(1 << 12); - - if ((word >> 8) == 1) - val |= 1 << 13; - else - val &= ~(1 << 13); - - Set_NB32_index_wait(dev, index_reg, index, val); -} -#endif - -static void SetODTTriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dev; - u32 index_reg = 0x98 + 0x100 * dct; - u8 cs; - u32 index; - u8 odt; - u8 max_dimms; - - // FIXME: skip for Ax - - dev = pDCTstat->dev_dct; - - /* Tri-state unused ODTs when motherboard termination is available */ - max_dimms = (u8) mctGet_NVbits(NV_MAX_DIMMS); - odt = 0x0F; /* tristate all the pins then clear the used ones. */ - - for (cs = 0; cs < 8; cs += 2) { - if (pDCTstat->CSPresent & (1 << cs)) { - odt &= ~(1 << (cs / 2)); - - /* if quad-rank capable platform clear additional pins */ - if (max_dimms != MAX_CS_SUPPORTED) { - if (pDCTstat->CSPresent & (1 << (cs + 1))) - odt &= ~(4 << (cs / 2)); - } - } - } - - index = 0x0C; - val = Get_NB32_index_wait(dev, index_reg, index); - val |= (odt << 8); - Set_NB32_index_wait(dev, index_reg, index, val); - -} - - -static void InitPhyCompensation(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 i; - u32 index_reg = 0x98 + 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - u32 val; - u32 valx = 0; - u32 dword; - const u8 *p; - - val = Get_NB32_index_wait(dev, index_reg, 0x00); - dword = 0; - for (i = 0; i < 6; i++) { - switch (i) { - case 0: - case 4: - p = Table_Comp_Rise_Slew_15x; - valx = p[(val >> 16) & 3]; - break; - case 1: - case 5: - p = Table_Comp_Fall_Slew_15x; - valx = p[(val >> 16) & 3]; - break; - case 2: - p = Table_Comp_Rise_Slew_20x; - valx = p[(val >> 8) & 3]; - break; - case 3: - p = Table_Comp_Fall_Slew_20x; - valx = p[(val >> 8) & 3]; - break; - - } - dword |= valx << (5 * i); - } - - /* Override/Exception */ - if (!pDCTstat->GangedMode) { - i = 0; /* use i for the dct setting required */ - if (pDCTstat->MAdimms[0] < 4) - i = 1; - if (((pDCTstat->Speed == 2) || (pDCTstat->Speed == 3)) && (pDCTstat->MAdimms[i] == 4)) { - dword &= 0xF18FFF18; - index_reg = 0x98; /* force dct = 0 */ - } - } - - Set_NB32_index_wait(dev, index_reg, 0x0a, dword); -} - - -static void WaitRoutine_D(u32 time) -{ - while (time) { - _EXECFENCE; - time--; - } -} - - -static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 reg; - u32 val; - u32 dev = pDCTstat->dev_dct; - - /* GhEnhancement #18429 modified by askar: For low NB CLK : - * Memclk ratio, the DCT may need to arbitrate early to avoid - * unnecessary bubbles. - * bit 19 of F2x[1,0]78 Dram Control Register, set this bit only when - * NB CLK : Memclk ratio is between 3:1 (inclusive) to 4:5 (inclusive) - */ - - reg = 0x78; - val = Get_NB32(dev, reg); - - //FIXME: check for Cx - if (CheckNBCOFEarlyArbEn(pMCTstat, pDCTstat)) - val |= (1 << EarlyArbEn); - - Set_NB32(dev, reg, val); - -} - - -static u8 CheckNBCOFEarlyArbEn(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 reg; - u32 val; - u32 tmp; - u32 rem; - u32 dev = pDCTstat->dev_dct; - u32 hi, lo; - u8 NbDid = 0; - - /* Check if NB COF >= 4*Memclk, if it is not, return a fatal error - */ - - /* 3*(Fn2xD4[NBFid]+4)/(2^NbDid)/(3+Fn2x94[MemClkFreq]) */ - _RDMSR(MSR_COFVID_STS, &lo, &hi); - if (lo & (1 << 22)) - NbDid |= 1; - - - reg = 0x94; - val = Get_NB32(dev, reg); - if (!(val & (1 << MemClkFreqVal))) - val = Get_NB32(dev, reg * 0x100); /* get the DCT1 value */ - - val &= 0x07; - val += 3; - if (NbDid) - val <<= 1; - tmp = val; - - dev = pDCTstat->dev_nbmisc; - reg = 0xD4; - val = Get_NB32(dev, reg); - val &= 0x1F; - val += 3; - val *= 3; - val = val / tmp; - rem = val % tmp; - tmp >>= 1; - - // Yes this could be nicer but this was how the asm was.... - if (val < 3) { /* NClk:MemClk < 3:1 */ - return 0; - } else if (val > 4) { /* NClk:MemClk >= 5:1 */ - return 0; - } else if ((val == 4) && (rem > tmp)) { /* NClk:MemClk > 4.5:1 */ - return 0; - } else { - return 1; /* 3:1 <= NClk:MemClk <= 4.5:1*/ - } -} - - -static void mct_ResetDataStruct_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - struct DCTStatStruc *pDCTstat; - - /* Initialize Data structures by clearing all entries to 0 */ - memset(pMCTstat, 0x00, sizeof(*pMCTstat)); - - for (Node = 0; Node < 8; Node++) { - pDCTstat = pDCTstatA + Node; - - /* Clear all entries except persistentData */ - memset(pDCTstat, 0x00, sizeof(*pDCTstat) - sizeof(pDCTstat->persistentData)); - } -} - - -static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 i; - u32 reg_off; - u32 dev = pDCTstat->dev_dct; - - // FIXME: skip for Ax - if ((pDCTstat->Speed == 3) || (pDCTstat->Speed == 2)) { // MemClkFreq = 667MHz or 533MHz - for (i = 0; i < 2; i++) { - reg_off = 0x100 * i; - Set_NB32(dev, 0x98 + reg_off, 0x0D000030); - Set_NB32(dev, 0x9C + reg_off, 0x00000806); - Set_NB32(dev, 0x98 + reg_off, 0x4D040F30); - } - } -} - - -void mct_AdjustDelayRange_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 *dqs_pos) -{ - // FIXME: Skip for Ax - if ((pDCTstat->Speed == 3) || (pDCTstat->Speed == 2)) { // MemClkFreq = 667MHz or 533MHz - *dqs_pos = 32; - } -} - -static u32 mct_DisDllShutdownSR(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 DramConfigLo, u8 dct) -{ - u32 reg_off = 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - - /* Write 0000_07D0h to register F2x[1, 0]98_x4D0FE006 */ - if (pDCTstat->LogicalCPUID & (AMD_DA_C2 | AMD_RB_C3)) { - Set_NB32(dev, 0x9C + reg_off, 0x7D0); - Set_NB32(dev, 0x98 + reg_off, 0x4D0FE006); - Set_NB32(dev, 0x9C + reg_off, 0x190); - Set_NB32(dev, 0x98 + reg_off, 0x4D0FE007); - } - - return DramConfigLo | /* DisDllShutdownSR */ 1 << 27; -} - -static void mct_EnDllShutdownSR(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 reg_off = 0x100 * dct; - u32 dev = pDCTstat->dev_dct, val; - - /* Write 0000_07D0h to register F2x[1, 0]98_x4D0FE006 */ - if (pDCTstat->LogicalCPUID & (AMD_DA_C2 | AMD_RB_C3)) { - Set_NB32(dev, 0x9C + reg_off, 0x1C); - Set_NB32(dev, 0x98 + reg_off, 0x4D0FE006); - Set_NB32(dev, 0x9C + reg_off, 0x13D); - Set_NB32(dev, 0x98 + reg_off, 0x4D0FE007); - - val = Get_NB32(dev, 0x90 + reg_off); - val &= ~(1 << 27/* DisDllShutdownSR */); - Set_NB32(dev, 0x90 + reg_off, val); - } -} - -void mct_SetClToNB_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 lo, hi; - u32 msr; - - // FIXME: Maybe check the CPUID? - not for now. - // pDCTstat->LogicalCPUID; - - msr = BU_CFG2_MSR; - _RDMSR(msr, &lo, &hi); - lo |= 1 << ClLinesToNbDis; - _WRMSR(msr, lo, hi); -} - - -void mct_ClrClToNB_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - - u32 lo, hi; - u32 msr; - - // FIXME: Maybe check the CPUID? - not for now. - // pDCTstat->LogicalCPUID; - - msr = BU_CFG2_MSR; - _RDMSR(msr, &lo, &hi); - if (!pDCTstat->ClToNB_flag) - lo &= ~(1 << ClLinesToNbDis); - _WRMSR(msr, lo, hi); - -} - - -void mct_SetWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 lo, hi; - u32 msr; - - // FIXME: Maybe check the CPUID? - not for now. - // pDCTstat->LogicalCPUID; - - msr = BU_CFG_MSR; - _RDMSR(msr, &lo, &hi); - hi |= (1 << WbEnhWsbDis_D); - _WRMSR(msr, lo, hi); -} - - -void mct_ClrWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 lo, hi; - u32 msr; - - // FIXME: Maybe check the CPUID? - not for now. - // pDCTstat->LogicalCPUID; - - msr = BU_CFG_MSR; - _RDMSR(msr, &lo, &hi); - hi &= ~(1 << WbEnhWsbDis_D); - _WRMSR(msr, lo, hi); -} - - -void mct_SetDramConfigHi_D(struct DCTStatStruc *pDCTstat, u32 dct, - u32 DramConfigHi) -{ - /* Bug#15114: Comp. update interrupted by Freq. change can cause - * subsequent update to be invalid during any MemClk frequency change: - * Solution: From the bug report: - * 1. A software-initiated frequency change should be wrapped into the - * following sequence : - * a) Disable Compensation (F2[1, 0]9C_x08[30]) - * b) Reset the Begin Compensation bit (D3CMP->COMP_CONFIG[0]) in - * all the compensation engines - * c) Do frequency change - * d) Enable Compensation (F2[1, 0]9C_x08[30]) - * 2. A software-initiated Disable Compensation should always be - * followed by step b) of the above steps. - * Silicon Status: Fixed In Rev B0 - * - * Errata#177: DRAM Phy Automatic Compensation Updates May Be Invalid - * Solution: BIOS should disable the phy automatic compensation prior - * to initiating a memory clock frequency change as follows: - * 1. Disable PhyAutoComp by writing 1'b1 to F2x[1, 0]9C_x08[30] - * 2. Reset the Begin Compensation bits by writing 32'h0 to - * F2x[1, 0]9C_x4D004F00 - * 3. Perform frequency change - * 4. Enable PhyAutoComp by writing 1'b0 to F2x[1, 0]9C_08[30] - * In addition, any time software disables the automatic phy - * compensation it should reset the begin compensation bit per step 2. - * Silicon Status: Fixed in DR-B0 - */ - - u32 dev = pDCTstat->dev_dct; - u32 index_reg = 0x98 + 0x100 * dct; - u32 index; - - u32 val; - - index = 0x08; - val = Get_NB32_index_wait(dev, index_reg, index); - Set_NB32_index_wait(dev, index_reg, index, val | (1 << DisAutoComp)); - - //FIXME: check for Bx Cx CPU - // if Ax mct_SetDramConfigHi_Samp_D - - /* errata#177 */ - index = 0x4D014F00; /* F2x[1, 0]9C_x[D0FFFFF:D000000] DRAM Phy Debug Registers */ - index |= 1 << DctAccessWrite; - val = 0; - Set_NB32_index_wait(dev, index_reg, index, val); - - Set_NB32(dev, 0x94 + 0x100 * dct, DramConfigHi); - - index = 0x08; - val = Get_NB32_index_wait(dev, index_reg, index); - Set_NB32_index_wait(dev, index_reg, index, val & (~(1 << DisAutoComp))); -} - -static void mct_BeforeDQSTrain_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - struct DCTStatStruc *pDCTstat; - - /* Errata 178 - * - * 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. - * Solution: At least, set WrDqs fine delay to be 0 for DDR2 training. - */ - - for (Node = 0; Node < 8; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - mct_BeforeDQSTrain_Samp_D(pMCTstat, pDCTstat); - mct_ResetDLL_D(pMCTstat, pDCTstat, 0); - mct_ResetDLL_D(pMCTstat, pDCTstat, 1); - } - } -} - -static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 Receiver; - u32 dev = pDCTstat->dev_dct; - u32 reg_off = 0x100 * dct; - u32 addr; - u32 lo, hi; - u8 wrap32dis = 0; - u8 valid = 0; - - /* Skip reset DLL for B3 */ - if (pDCTstat->LogicalCPUID & AMD_DR_B3) { - return; - } - - 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 32bit mode */ - _WRMSR(addr, lo, hi); - - - pDCTstat->Channel = dct; - Receiver = mct_InitReceiver_D(pDCTstat, dct); - /* there are four receiver pairs, loosely associated with chipselects.*/ - for (; Receiver < 8; Receiver += 2) { - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, Receiver)) { - addr = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, dct, Receiver, &valid); - if (valid) { - mct_Read1LTestPattern_D(pMCTstat, pDCTstat, addr); /* cache fills */ - - /* Write 0000_8000h to register F2x[1,0]9C_xD080F0C */ - Set_NB32_index_wait(dev, 0x98 + reg_off, 0x4D080F0C, 0x00008000); - mct_Wait(80); /* wait >= 300ns */ - - /* Write 0000_0000h to register F2x[1,0]9C_xD080F0C */ - Set_NB32_index_wait(dev, 0x98 + reg_off, 0x4D080F0C, 0x00000000); - mct_Wait(800); /* wait >= 2us */ - break; - } - } - } - if (!wrap32dis) { - addr = HWCR_MSR; - _RDMSR(addr, &lo, &hi); - lo &= ~(1<<17); /* restore HWCR.wrap32dis */ - _WRMSR(addr, lo, hi); - } -} - - -void mct_EnableDatIntlv_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 dev = pDCTstat->dev_dct; - u32 val; - - /* Enable F2x110[DctDatIntlv] */ - // Call back not required mctHookBeforeDatIntlv_D() - // FIXME Skip for Ax - if (!pDCTstat->GangedMode) { - val = Get_NB32(dev, 0x110); - val |= 1 << 5; // DctDatIntlv - Set_NB32(dev, 0x110, val); - - // FIXME Skip for Cx - dev = pDCTstat->dev_nbmisc; - val = Get_NB32(dev, 0x8C); // NB Configuration Hi - val |= 1 << (36-32); // DisDatMask - Set_NB32(dev, 0x8C, val); - } -} - -#ifdef UNUSED_CODE -static void mct_SetupSync_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* set F2x78[ChSetupSync] when F2x[1, 0]9C_x04[AddrCmdSetup, CsOdtSetup, - * CkeSetup] setups for one DCT are all 0s and at least one of the setups, - * F2x[1, 0]9C_x04[AddrCmdSetup, CsOdtSetup, CkeSetup], of the other - * controller is 1 - */ - u32 cha, chb; - u32 dev = pDCTstat->dev_dct; - u32 val; - - cha = pDCTstat->CH_ADDR_TMG[0] & 0x0202020; - chb = pDCTstat->CH_ADDR_TMG[1] & 0x0202020; - - if ((cha != chb) && ((cha == 0) || (chb == 0))) { - val = Get_NB32(dev, 0x78); - val |= ChSetupSync; - Set_NB32(dev, 0x78, val); - } -} -#endif - -static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct) { - - u32 val; - u32 reg_off = 0x100 * dct; - u32 dev = pDCTstat->dev_dct; - - if (pDCTstat->LogicalCPUID & (AMD_DR_B2 | AMD_DR_B3)) { - mct_Wait(10000); /* Wait 50 us*/ - val = Get_NB32(dev, 0x110); - if (val & (1 << DramEnabled)) { - /* If 50 us expires while DramEnable =0 then do the following */ - val = Get_NB32(dev, 0x90 + reg_off); - val &= ~(1 << Width128); /* Program Width128 = 0 */ - Set_NB32(dev, 0x90 + reg_off, val); - - val = Get_NB32_index_wait(dev, 0x98 + reg_off, 0x05); /* Perform dummy CSR read to F2x09C_x05 */ - - if (pDCTstat->GangedMode) { - val = Get_NB32(dev, 0x90 + reg_off); - val |= 1 << Width128; /* Program Width128 = 0 */ - Set_NB32(dev, 0x90 + reg_off, val); - } - } - } -} - - -/* ========================================================== - * 6-bit Bank Addressing Table - * RR = rows-13 binary - * B = Banks-2 binary - * CCC = Columns-9 binary - * ========================================================== - * DCT CCCBRR Rows Banks Columns 64-bit CS Size - * Encoding - * 0000 000000 13 2 9 128MB - * 0001 001000 13 2 10 256MB - * 0010 001001 14 2 10 512MB - * 0011 010000 13 2 11 512MB - * 0100 001100 13 3 10 512MB - * 0101 001101 14 3 10 1GB - * 0110 010001 14 2 11 1GB - * 0111 001110 15 3 10 2GB - * 1000 010101 14 3 11 2GB - * 1001 010110 15 3 11 4GB - * 1010 001111 16 3 10 4GB - * 1011 010111 16 3 11 8GB - */ diff --git a/src/northbridge/amd/amdmct/mct/mct_d.h b/src/northbridge/amd/amdmct/mct/mct_d.h deleted file mode 100644 index b985137987..0000000000 --- a/src/northbridge/amd/amdmct/mct/mct_d.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdmct/mct/mct_d_gcc.c b/src/northbridge/amd/amdmct/mct/mct_d_gcc.c deleted file mode 100644 index d826fed96d..0000000000 --- a/src/northbridge/amd/amdmct/mct/mct_d_gcc.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdmct/mct/mct_d_gcc.h b/src/northbridge/amd/amdmct/mct/mct_d_gcc.h deleted file mode 100644 index 993aa21d74..0000000000 --- a/src/northbridge/amd/amdmct/mct/mct_d_gcc.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdmct/mct/mctardk3.c b/src/northbridge/amd/amdmct/mct/mctardk3.c deleted file mode 100644 index c36ba8ea7a..0000000000 --- a/src/northbridge/amd/amdmct/mct/mctardk3.c +++ /dev/null @@ -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; - } -} diff --git a/src/northbridge/amd/amdmct/mct/mctardk4.c b/src/northbridge/amd/amdmct/mct/mctardk4.c deleted file mode 100644 index c700593740..0000000000 --- a/src/northbridge/amd/amdmct/mct/mctardk4.c +++ /dev/null @@ -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); - } -} diff --git a/src/northbridge/amd/amdmct/mct/mctchi_d.c b/src/northbridge/amd/amdmct/mct/mctchi_d.c deleted file mode 100644 index d2acc15118..0000000000 --- a/src/northbridge/amd/amdmct/mct/mctchi_d.c +++ /dev/null @@ -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"); -} diff --git a/src/northbridge/amd/amdmct/mct/mctcsi_d.c b/src/northbridge/amd/amdmct/mct/mctcsi_d.c deleted file mode 100644 index 6a19788ab3..0000000000 --- a/src/northbridge/amd/amdmct/mct/mctcsi_d.c +++ /dev/null @@ -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"); -} diff --git a/src/northbridge/amd/amdmct/mct/mctdqs_d.c b/src/northbridge/amd/amdmct/mct/mctdqs_d.c deleted file mode 100644 index 2e52a39619..0000000000 --- a/src/northbridge/amd/amdmct/mct/mctdqs_d.c +++ /dev/null @@ -1,1207 +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 <console/console.h> -#include <cpu/x86/cr.h> -#include <cpu/amd/msr.h> -#include <cpu/amd/mtrr.h> - -#include "mct_d.h" - -static void CalcEccDQSPos_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u16 like, - u8 scale, u8 ChipSel); -static void GetDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel); -static u8 MiddleDQS_D(u8 min, u8 max); -static void TrainReadDQS_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 cs_start); -static void TrainWriteDQS_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 cs_start); -static void WriteDQSTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo); -static void WriteL18TestPattern_D(struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo); -static void WriteL9TestPattern_D(struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo); -static u8 CompareDQSTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 addr_lo); -static void FlushDQSTestPattern_D(struct DCTStatStruc *pDCTstat, - u32 addr_lo); -static void ReadDQSTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo); -static void mct_SetDQSDelayCSR_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 ChipSel); -static void mct_SetDQSDelayAllCSR_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 cs_start); -static void SetupDqsPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 *buffer); - -void print_debug_dqs(const char *str, u32 val, u8 level) -{ -#if DQS_TRAIN_DEBUG > 0 - if (DQS_TRAIN_DEBUG >= level) { - printk(BIOS_DEBUG, "%s%x\n", str, val); - } -#endif -} - -void print_debug_dqs_pair(const char *str, u32 val, const char *str2, u32 val2, u8 level) -{ -#if DQS_TRAIN_DEBUG > 0 - if (DQS_TRAIN_DEBUG >= level) { - printk(BIOS_DEBUG, "%s%08x%s%08x\n", str, val, str2, val2); - } -#endif -} - -/*Warning: These must be located so they do not cross a logical 16-bit segment boundary!*/ -static const u32 TestPatternJD1a_D[] = { - 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF, /* QW0-1, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW2-3, ALL-EVEN */ - 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF, /* QW4-5, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW6-7, ALL-EVEN */ - 0xFeFeFeFe,0xFeFeFeFe,0x01010101,0x01010101, /* QW0-1, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0x01010101,0x01010101, /* QW2-3, DQ0-ODD */ - 0x01010101,0x01010101,0xFeFeFeFe,0xFeFeFeFe, /* QW4-5, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0x01010101,0x01010101, /* QW6-7, DQ0-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW0-1, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, /* QW2-3, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0x02020202,0x02020202, /* QW4-5, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW6-7, DQ1-ODD */ - 0x04040404,0x04040404,0xfBfBfBfB,0xfBfBfBfB, /* QW0-1, DQ2-ODD */ - 0x04040404,0x04040404,0x04040404,0x04040404, /* QW2-3, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW4-5, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW6-7, DQ2-ODD */ - 0x08080808,0x08080808,0xF7F7F7F7,0xF7F7F7F7, /* QW0-1, DQ3-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW2-3, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0x08080808,0x08080808, /* QW4-5, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW6-7, DQ3-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW0-1, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0x10101010,0x10101010, /* QW2-3, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW4-5, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0x10101010,0x10101010, /* QW6-7, DQ4-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW0-1, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0x20202020,0x20202020, /* QW2-3, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW4-5, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW6-7, DQ5-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW0-1, DQ6-ODD */ - 0x40404040,0x40404040,0xBfBfBfBf,0xBfBfBfBf, /* QW2-3, DQ6-ODD */ - 0x40404040,0x40404040,0xBfBfBfBf,0xBfBfBfBf, /* QW4-5, DQ6-ODD */ - 0x40404040,0x40404040,0xBfBfBfBf,0xBfBfBfBf, /* QW6-7, DQ6-ODD */ - 0x80808080,0x80808080,0x7F7F7F7F,0x7F7F7F7F, /* QW0-1, DQ7-ODD */ - 0x80808080,0x80808080,0x7F7F7F7F,0x7F7F7F7F, /* QW2-3, DQ7-ODD */ - 0x80808080,0x80808080,0x7F7F7F7F,0x7F7F7F7F, /* QW4-5, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080 /* QW6-7, DQ7-ODD */ -}; -static const u32 TestPatternJD1b_D[] = { - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW0,CHA-B, ALL-EVEN */ - 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, /* QW1,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW2,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW3,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW4,CHA-B, ALL-EVEN */ - 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, /* QW5,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW6,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW7,CHA-B, ALL-EVEN */ - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, /* QW0,CHA-B, DQ0-ODD */ - 0x01010101,0x01010101,0x01010101,0x01010101, /* QW1,CHA-B, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, /* QW2,CHA-B, DQ0-ODD */ - 0x01010101,0x01010101,0x01010101,0x01010101, /* QW3,CHA-B, DQ0-ODD */ - 0x01010101,0x01010101,0x01010101,0x01010101, /* QW4,CHA-B, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, /* QW5,CHA-B, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, /* QW6,CHA-B, DQ0-ODD */ - 0x01010101,0x01010101,0x01010101,0x01010101, /* QW7,CHA-B, DQ0-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW0,CHA-B, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW1,CHA-B, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, /* QW2,CHA-B, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, /* QW3,CHA-B, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, /* QW4,CHA-B, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW5,CHA-B, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW6,CHA-B, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW7,CHA-B, DQ1-ODD */ - 0x04040404,0x04040404,0x04040404,0x04040404, /* QW0,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW1,CHA-B, DQ2-ODD */ - 0x04040404,0x04040404,0x04040404,0x04040404, /* QW2,CHA-B, DQ2-ODD */ - 0x04040404,0x04040404,0x04040404,0x04040404, /* QW3,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW4,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW5,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW6,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW7,CHA-B, DQ2-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW0,CHA-B, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW1,CHA-B, DQ3-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW2,CHA-B, DQ3-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW3,CHA-B, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW4,CHA-B, DQ3-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW5,CHA-B, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW6,CHA-B, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW7,CHA-B, DQ3-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW0,CHA-B, DQ4-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW1,CHA-B, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW2,CHA-B, DQ4-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW3,CHA-B, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW4,CHA-B, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW5,CHA-B, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW6,CHA-B, DQ4-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW7,CHA-B, DQ4-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW0,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW1,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW2,CHA-B, DQ5-ODD */ - 0x20202020,0x20202020,0x20202020,0x20202020, /* QW3,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW4,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW5,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW6,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW7,CHA-B, DQ5-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW0,CHA-B, DQ6-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW1,CHA-B, DQ6-ODD */ - 0x40404040,0x40404040,0x40404040,0x40404040, /* QW2,CHA-B, DQ6-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW3,CHA-B, DQ6-ODD */ - 0x40404040,0x40404040,0x40404040,0x40404040, /* QW4,CHA-B, DQ6-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW5,CHA-B, DQ6-ODD */ - 0x40404040,0x40404040,0x40404040,0x40404040, /* QW6,CHA-B, DQ6-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW7,CHA-B, DQ6-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080, /* QW0,CHA-B, DQ7-ODD */ - 0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F, /* QW1,CHA-B, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080, /* QW2,CHA-B, DQ7-ODD */ - 0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F, /* QW3,CHA-B, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080, /* QW4,CHA-B, DQ7-ODD */ - 0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F, /* QW5,CHA-B, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080, /* QW6,CHA-B, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080 /* QW7,CHA-B, DQ7-ODD */ -}; - -void TrainReceiverEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, u8 Pass) -{ - u8 Node; - struct DCTStatStruc *pDCTstat; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - -/*FIXME: needed? if (!pDCTstat->NodePresent) - break; -*/ - if (pDCTstat->DCTSysLimit) { - mct_TrainRcvrEn_D(pMCTstat, pDCTstat, Pass); - } - } -} - - -static void SetEccDQSRdWrPos_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel) -{ - u8 channel; - u8 direction; - - for (channel = 0; channel < 2; channel++) { - for (direction = 0; direction < 2; direction++) { - pDCTstat->Channel = channel; /* Channel A or B */ - pDCTstat->Direction = direction; /* Read or write */ - CalcEccDQSPos_D(pMCTstat, pDCTstat, pDCTstat->CH_EccDQSLike[channel], pDCTstat->CH_EccDQSScale[channel], ChipSel); - print_debug_dqs_pair("\t\tSetEccDQSRdWrPos: channel ", channel, direction == DQS_READDIR? " R dqs_delay":" W dqs_delay", pDCTstat->DQSDelay, 2); - pDCTstat->ByteLane = 8; - StoreDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel); - mct_SetDQSDelayCSR_D(pMCTstat, pDCTstat, ChipSel); - } - } -} - - - -static void CalcEccDQSPos_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u16 like, u8 scale, u8 ChipSel) -{ - u8 DQSDelay0, DQSDelay1; - u16 DQSDelay; - - pDCTstat->ByteLane = like & 0xff; - GetDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel); - DQSDelay0 = pDCTstat->DQSDelay; - - pDCTstat->ByteLane = (like >> 8) & 0xff; - GetDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel); - DQSDelay1 = pDCTstat->DQSDelay; - - if (DQSDelay0 > DQSDelay1) { - DQSDelay = DQSDelay0 - DQSDelay1; - } else { - DQSDelay = DQSDelay1 - DQSDelay0; - } - - DQSDelay = DQSDelay * (~scale); - - DQSDelay += 0x80; // round it - - DQSDelay >>= 8; // /256 - - if (DQSDelay0 > DQSDelay1) { - DQSDelay = DQSDelay1 - DQSDelay; - } else { - DQSDelay += DQSDelay1; - } - - pDCTstat->DQSDelay = (u8)DQSDelay; -} - - -static void TrainDQSRdWrPos_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 cs_start) -{ - u32 Errors; - u8 Channel, DQSWrDelay; - u8 _DisableDramECC = 0; - u32 PatternBuffer[292]; - u8 _Wrap32Dis = 0, _SSE2 = 0; - u8 dqsWrDelay_end; - - u32 addr; - CRx_TYPE cr4; - u32 lo, hi; - - print_debug_dqs("\nTrainDQSRdWrPos: Node_ID ", pDCTstat->Node_ID, 0); - cr4 = read_cr4(); - if (cr4 & (1<<9)) { - _SSE2 = 1; - } - cr4 |= (1<<9); /* OSFXSR enable SSE2 */ - write_cr4(cr4); - - addr = HWCR_MSR; - _RDMSR(addr, &lo, &hi); - if (lo & (1<<17)) { - _Wrap32Dis = 1; - } - lo |= (1<<17); /* HWCR.wrap32dis */ - _WRMSR(addr, lo, hi); /* allow 64-bit memory references in real mode */ - - /* Disable ECC correction of reads on the dram bus. */ - _DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat); - - SetupDqsPattern_D(pMCTstat, pDCTstat, PatternBuffer); - - /* mct_BeforeTrainDQSRdWrPos_D */ - dqsWrDelay_end = 0x20; - - Errors = 0; - for (Channel = 0; Channel < 2; Channel++) { - print_debug_dqs("\tTrainDQSRdWrPos: 1 Channel ",Channel, 1); - pDCTstat->Channel = Channel; - - if (pDCTstat->DIMMValidDCT[Channel] == 0) /* mct_BeforeTrainDQSRdWrPos_D */ - continue; - - for (DQSWrDelay = 0; DQSWrDelay < dqsWrDelay_end; DQSWrDelay++) { - pDCTstat->DQSDelay = DQSWrDelay; - pDCTstat->Direction = DQS_WRITEDIR; - mct_SetDQSDelayAllCSR_D(pMCTstat, pDCTstat, cs_start); - - print_debug_dqs("\t\tTrainDQSRdWrPos: 21 DQSWrDelay ", DQSWrDelay, 2); - TrainReadDQS_D(pMCTstat, pDCTstat, cs_start); - - print_debug_dqs("\t\tTrainDQSRdWrPos: 22 TrainErrors ",pDCTstat->TrainErrors, 2); - if (pDCTstat->TrainErrors == 0) { - break; - } - Errors |= pDCTstat->TrainErrors; - } - if (DQSWrDelay < dqsWrDelay_end) { - Errors = 0; - - print_debug_dqs("\tTrainDQSRdWrPos: 231 DQSWrDelay ", DQSWrDelay, 1); - TrainWriteDQS_D(pMCTstat, pDCTstat, cs_start); - } - print_debug_dqs("\tTrainDQSRdWrPos: 232 Errors ", Errors, 1); - pDCTstat->ErrStatus |= Errors; - } - -#if DQS_TRAIN_DEBUG > 0 - { - u8 val; - u8 i; - u8 Channel, Receiver, Dir; - u8 *p; - - for (Dir = 0; Dir < 2; Dir++) { - if (Dir == 0) { - printk(BIOS_DEBUG, "TrainDQSRdWrPos: CH_D_DIR_B_DQS WR:\n"); - } else { - printk(BIOS_DEBUG, "TrainDQSRdWrPos: CH_D_DIR_B_DQS RD:\n"); - } - for (Channel = 0; Channel < 2; Channel++) { - printk(BIOS_DEBUG, "Channel: %02x\n", Channel); - for (Receiver = cs_start; Receiver < (cs_start + 2); Receiver += 2) { - printk(BIOS_DEBUG, "\t\tReceiver: %02x: ", Receiver); - p = pDCTstat->persistentData.CH_D_DIR_B_DQS[Channel][Receiver >> 1][Dir]; - for (i = 0; i < 8; i++) { - val = p[i]; - printk(BIOS_DEBUG, "%02x ", val); - } - printk(BIOS_DEBUG, "\n"); - } - } - } - - } -#endif - - 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); - } - - print_tx("TrainDQSRdWrPos: Status ", pDCTstat->Status); - print_tx("TrainDQSRdWrPos: TrainErrors ", pDCTstat->TrainErrors); - print_tx("TrainDQSRdWrPos: ErrStatus ", pDCTstat->ErrStatus); - print_tx("TrainDQSRdWrPos: ErrCode ", pDCTstat->ErrCode); - print_t("TrainDQSRdWrPos: Done\n"); -} - - -static void SetupDqsPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 *buffer) -{ - /* 1. Set the Pattern type (0 or 1) in DCTStatstruc.Pattern - * 2. Copy the pattern from ROM to Cache, aligning on 16 byte boundary - * 3. Set the ptr to Cacheable copy in DCTStatstruc.PtrPatternBufA - */ - - u32 *buf; - u16 i; - - buf = (u32 *)(((u32)buffer + 0x10) & (0xfffffff0)); - if (pDCTstat->Status & (1 << SB_128bitmode)) { - pDCTstat->Pattern = 1; /* 18 cache lines, alternating qwords */ - for (i = 0; i < 16*18; i++) - buf[i] = TestPatternJD1b_D[i]; - } else { - pDCTstat->Pattern = 0; /* 9 cache lines, sequential qwords */ - for (i = 0; i < 16*9; i++) - buf[i] = TestPatternJD1a_D[i]; - } - pDCTstat->PtrPatternBufA = (u32)buf; -} - - -static void TrainDQSPos_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 cs_start) -{ - u32 Errors; - u8 ChipSel, DQSDelay; - u8 RnkDlySeqPassMin,RnkDlySeqPassMax, RnkDlyFilterMin, RnkDlyFilterMax; - u8 LastTest; - u32 TestAddr; - u8 ByteLane; - u8 MutualCSPassW[64]; - u8 BanksPresent; - u8 dqsDelay_end; - u8 tmp, valid; - - - /* MutualCSPassW: each byte represents a bitmap of pass/fail per - * ByteLane. The indext within MutualCSPassW is the delay value - * given the results. - */ - - - print_debug_dqs("\t\t\tTrainDQSPos begin ", 0, 3); - - Errors = 0; - BanksPresent = 0; - - if (pDCTstat->Direction == DQS_READDIR) { - dqsDelay_end = 64; - mct_AdjustDelayRange_D(pMCTstat, pDCTstat, &dqsDelay_end); - } else { - dqsDelay_end = 32; - } - - /* Bitmapped status per delay setting, 0xff = All positions - * passing (1= PASS). Set the entire array. - */ - for (DQSDelay = 0; DQSDelay < 64; DQSDelay++) { - MutualCSPassW[DQSDelay] = 0xFF; - } - - for (ChipSel = cs_start; ChipSel < (cs_start + 2); ChipSel++) { /* logical register chipselects 0..7 */ - print_debug_dqs("\t\t\t\tTrainDQSPos: 11 ChipSel ", ChipSel, 4); - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, pDCTstat->Channel, ChipSel)) { - print_debug_dqs("\t\t\t\tmct_RcvrRankEnabled_D CS not enabled ", ChipSel, 4); - continue; - } - - BanksPresent = 1; /* flag for at least one bank is present */ - TestAddr = mct_GetMCTSysAddr_D(pMCTstat, pDCTstat, pDCTstat->Channel, ChipSel, &valid); - if (!valid) { - print_debug_dqs("\t\t\t\tAddress not supported on current CS ", TestAddr, 4); - continue; - } - - print_debug_dqs("\t\t\t\tTrainDQSPos: 12 TestAddr ", TestAddr, 4); - SetUpperFSbase(TestAddr); /* fs:eax = far ptr to target */ - - if (pDCTstat->Direction == DQS_READDIR) { - print_debug_dqs("\t\t\t\tTrainDQSPos: 13 for read ", 0, 4); - WriteDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8); - } - - for (DQSDelay = 0; DQSDelay < dqsDelay_end; DQSDelay++) { - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 141 DQSDelay ", DQSDelay, 5); - if (MutualCSPassW[DQSDelay] == 0) - continue; //skip current delay value if other chipselects have failed all 8 bytelanes - pDCTstat->DQSDelay = DQSDelay; - mct_SetDQSDelayAllCSR_D(pMCTstat, pDCTstat, cs_start); - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 142 MutualCSPassW ", MutualCSPassW[DQSDelay], 5); - - if (pDCTstat->Direction == DQS_WRITEDIR) { - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 143 for write", 0, 5); - WriteDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8); - } - - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 144 Pattern ", pDCTstat->Pattern, 5); - ReadDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8); - /* print_debug_dqs("\t\t\t\t\tTrainDQSPos: 145 MutualCSPassW ", MutualCSPassW[DQSDelay], 5); */ - tmp = CompareDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8); /* 0 = fail, 1 = pass */ - - if (mct_checkFenceHoleAdjust_D(pMCTstat, pDCTstat, DQSDelay, ChipSel, &tmp)) { - goto skipLocMiddle; - } - - MutualCSPassW[DQSDelay] &= tmp; - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 146\tMutualCSPassW ", MutualCSPassW[DQSDelay], 5); - - SetTargetWTIO_D(TestAddr); - FlushDQSTestPattern_D(pDCTstat, TestAddr << 8); - ResetTargetWTIO_D(); - } - - } - - if (BanksPresent) { - for (ByteLane = 0; ByteLane < 8; ByteLane++) { - print_debug_dqs("\t\t\t\tTrainDQSPos: 31 ByteLane ",ByteLane, 4); - pDCTstat->ByteLane = ByteLane; - LastTest = DQS_FAIL; /* Analyze the results */ - RnkDlySeqPassMin = 0; - RnkDlySeqPassMax = 0; - RnkDlyFilterMax = 0; - RnkDlyFilterMin = 0; - for (DQSDelay = 0; DQSDelay < dqsDelay_end; DQSDelay++) { - if (MutualCSPassW[DQSDelay] & (1 << ByteLane)) { - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 321 DQSDelay ", DQSDelay, 5); - print_debug_dqs("\t\t\t\t\tTrainDQSPos: 322 MutualCSPassW ", MutualCSPassW[DQSDelay], 5); - - RnkDlySeqPassMax = DQSDelay; - if (LastTest == DQS_FAIL) { - RnkDlySeqPassMin = DQSDelay; //start sequential run - } - if ((RnkDlySeqPassMax - RnkDlySeqPassMin)>(RnkDlyFilterMax-RnkDlyFilterMin)) { - RnkDlyFilterMin = RnkDlySeqPassMin; - RnkDlyFilterMax = RnkDlySeqPassMax; - } - LastTest = DQS_PASS; - } else { - LastTest = DQS_FAIL; - } - } - print_debug_dqs("\t\t\t\tTrainDQSPos: 33 RnkDlySeqPassMax ", RnkDlySeqPassMax, 4); - if (RnkDlySeqPassMax == 0) { - Errors |= 1 << SB_NODQSPOS; /* no passing window */ - } else { - print_debug_dqs_pair("\t\t\t\tTrainDQSPos: 34 RnkDlyFilter: ", RnkDlyFilterMin, " ", RnkDlyFilterMax, 4); - if (((RnkDlyFilterMax - RnkDlyFilterMin) < MIN_DQS_WNDW)) { - Errors |= 1 << SB_SMALLDQS; - } else { - u8 middle_dqs; - /* mctEngDQSwindow_Save_D Not required for arrays */ - middle_dqs = MiddleDQS_D(RnkDlyFilterMin, RnkDlyFilterMax); - pDCTstat->DQSDelay = middle_dqs; - mct_SetDQSDelayCSR_D(pMCTstat, pDCTstat, cs_start); /* load the register with the value */ - StoreDQSDatStrucVal_D(pMCTstat, pDCTstat, cs_start); /* store the value into the data structure */ - print_debug_dqs("\t\t\t\tTrainDQSPos: 42 middle_dqs : ",middle_dqs, 4); - } - } - } - } -skipLocMiddle: - pDCTstat->TrainErrors = Errors; - - print_debug_dqs("\t\t\tTrainDQSPos: Errors ", Errors, 3); - -} - - -void StoreDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel) -{ - /* Store the DQSDelay value, found during a training sweep, into the DCT - * status structure for this node - */ - - - /* When 400, 533, 667, it will support dimm0/1/2/3, - * and set conf for dimm0, hw will copy to dimm1/2/3 - * set for dimm1, hw will copy to dimm3 - * Rev A/B only support DIMM0/1 when 800MHz and above + 0x100 to next dimm - * Rev C support DIMM0/1/2/3 when 800MHz and above + 0x100 to next dimm - */ - - /* FindDQSDatDimmVal_D is not required since we use an array */ - u8 dn = 0; - - if (pDCTstat->Status & (1 << SB_Over400MHz)) - dn = ChipSel>>1; /* if odd or even logical DIMM */ - - pDCTstat->persistentData.CH_D_DIR_B_DQS[pDCTstat->Channel][dn][pDCTstat->Direction][pDCTstat->ByteLane] = - pDCTstat->DQSDelay; -} - - -static void GetDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel) -{ - u8 dn = 0; - - - /* When 400, 533, 667, it will support dimm0/1/2/3, - * and set conf for dimm0, hw will copy to dimm1/2/3 - * set for dimm1, hw will copy to dimm3 - * Rev A/B only support DIMM0/1 when 800MHz and above + 0x100 to next dimm - * Rev C support DIMM0/1/2/3 when 800MHz and above + 0x100 to next dimm - */ - - /* FindDQSDatDimmVal_D is not required since we use an array */ - if (pDCTstat->Status & (1<<SB_Over400MHz)) - dn = ChipSel >> 1; /*if odd or even logical DIMM */ - - pDCTstat->DQSDelay = - pDCTstat->persistentData.CH_D_DIR_B_DQS[pDCTstat->Channel][dn][pDCTstat->Direction][pDCTstat->ByteLane]; -} - - -/* FindDQSDatDimmVal_D is not required since we use an array */ - - -static u8 MiddleDQS_D(u8 min, u8 max) -{ - u8 size; - size = max-min; - if (size % 2) - size++; // round up if the size isn't even. - return (min + (size >> 1)); -} - - -static void TrainReadDQS_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 cs_start) -{ - print_debug_dqs("\t\tTrainReadPos ", 0, 2); - pDCTstat->Direction = DQS_READDIR; - TrainDQSPos_D(pMCTstat, pDCTstat, cs_start); -} - - -static void TrainWriteDQS_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 cs_start) -{ - pDCTstat->Direction = DQS_WRITEDIR; - print_debug_dqs("\t\tTrainWritePos", 0, 2); - TrainDQSPos_D(pMCTstat, pDCTstat, cs_start); -} - - -void proc_IOCLFLUSH_D(u32 addr_hi) -{ - SetTargetWTIO_D(addr_hi); - proc_CLFLUSH(addr_hi); - ResetTargetWTIO_D(); -} - - -static u8 ChipSelPresent_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 ChipSel) -{ - u32 val; - u32 reg; - u32 dev = pDCTstat->dev_dct; - u32 reg_off; - u8 ret = 0; - - if (!pDCTstat->GangedMode) { - reg_off = 0x100 * Channel; - } else { - reg_off = 0; - } - - if (ChipSel < MAX_CS_SUPPORTED) { - reg = 0x40 + (ChipSel << 2) + reg_off; - val = Get_NB32(dev, reg); - if (val & (1 << 0)) - ret = 1; - } - - return ret; -} - - -/* proc_CLFLUSH_D located in mct_gcc.h */ - - -static void WriteDQSTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo) -{ - /* Write a pattern of 72 bit times (per DQ), to test dram functionality. - * The pattern is a stress pattern which exercises both ISI and - * crosstalk. The number of cache lines to fill is dependent on DCT - * width mode and burstlength. - * Mode BL Lines Pattern no. - * ----+---+------------------- - * 64 4 9 0 - * 64 8 9 0 - * 64M 4 9 0 - * 64M 8 9 0 - * 128 4 18 1 - * 128 8 N/A - - */ - - if (pDCTstat->Pattern == 0) - WriteL9TestPattern_D(pDCTstat, TestAddr_lo); - else - WriteL18TestPattern_D(pDCTstat, TestAddr_lo); -} - - -static void WriteL18TestPattern_D(struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo) -{ - u8 *buf; - - buf = (u8 *)pDCTstat->PtrPatternBufA; - WriteLNTestPattern(TestAddr_lo, buf, 18); - -} - - -static void WriteL9TestPattern_D(struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo) -{ - u8 *buf; - - buf = (u8 *)pDCTstat->PtrPatternBufA; - WriteLNTestPattern(TestAddr_lo, buf, 9); -} - - - -static u8 CompareDQSTestPattern_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u32 addr_lo) -{ - /* Compare a pattern of 72 bit times (per DQ), to test dram functionality. - * The pattern is a stress pattern which exercises both ISI and - * crosstalk. The number of cache lines to fill is dependent on DCT - * width mode and burstlength. - * Mode BL Lines Pattern no. - * ----+---+------------------- - * 64 4 9 0 - * 64 8 9 0 - * 64M 4 9 0 - * 64M 8 9 0 - * 128 4 18 1 - * 128 8 N/A - - */ - - u32 *test_buf; - u8 bitmap; - u8 bytelane; - u8 i; - u32 value; - u8 j; - u32 value_test; - u8 pattern, channel; - - pattern = pDCTstat->Pattern; - channel = pDCTstat->Channel; - test_buf = (u32 *)pDCTstat->PtrPatternBufA; - - if (pattern && channel) { - addr_lo += 8; //second channel - test_buf += 2; - } - - bytelane = 0; /* bytelane counter */ - bitmap = 0xFF; /* bytelane test bitmap, 1 = pass */ - for (i = 0; i < (9 * 64 / 4); i++) { /* sizeof testpattern. /4 due to next loop */ - value = read32_fs(addr_lo); - value_test = *test_buf; - - print_debug_dqs_pair("\t\t\t\t\t\ttest_buf = ", (u32)test_buf, " value = ", value_test, 7); - print_debug_dqs_pair("\t\t\t\t\t\ttaddr_lo = ", addr_lo, " value = ", value, 7); - - for (j = 0; j < (4 * 8); j += 8) { /* go through a 32bit data, on 1 byte step. */ - if (((value >> j) & 0xff) != ((value_test >> j) & 0xff)) { - bitmap &= ~(1 << bytelane); - } - - bytelane++; - bytelane &= 0x7; - } - - print_debug_dqs("\t\t\t\t\t\tbitmap = ", bitmap, 7); - - if (!bitmap) - break; - - if (bytelane == 0) { - if (pattern == 1) { //dual channel - addr_lo += 8; //skip over other channel's data - test_buf += 2; - } - } - addr_lo += 4; - test_buf += 1; - } - - return bitmap; -} - - -static void FlushDQSTestPattern_D(struct DCTStatStruc *pDCTstat, - u32 addr_lo) -{ - /* Flush functions in mct_gcc.h */ - if (pDCTstat->Pattern == 0) { - FlushDQSTestPattern_L9(addr_lo); - } else { - FlushDQSTestPattern_L18(addr_lo); - } -} - -void SetTargetWTIO_D(u32 TestAddr) -{ - u32 lo, hi; - hi = TestAddr >> 24; - lo = TestAddr << 8; - _WRMSR(MTRR_IORR0_BASE, lo, hi); /* IORR0 Base */ - hi = 0xFF; - lo = 0xFC000800; /* 64MB Mask */ - _WRMSR(MTRR_IORR0_MASK, lo, hi); /* IORR0 Mask */ -} - - -void ResetTargetWTIO_D(void) -{ - u32 lo, hi; - - hi = 0; - lo = 0; - _WRMSR(MTRR_IORR0_MASK, lo, hi); // IORR0 Mask -} - - -static void ReadDQSTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo) -{ - /* Read a pattern of 72 bit times (per DQ), to test dram functionality. - * The pattern is a stress pattern which exercises both ISI and - * crosstalk. The number of cache lines to fill is dependent on DCT - * width mode and burstlength. - * Mode BL Lines Pattern no. - * ----+---+------------------- - * 64 4 9 0 - * 64 8 9 0 - * 64M 4 9 0 - * 64M 8 9 0 - * 128 4 18 1 - * 128 8 N/A - - */ - if (pDCTstat->Pattern == 0) - ReadL9TestPattern(TestAddr_lo); - else - ReadL18TestPattern(TestAddr_lo); - _MFENCE; -} - - -u32 SetUpperFSbase(u32 addr_hi) -{ - /* Set the upper 32-bits of the Base address, 4GB aligned) for the - * FS selector. - */ - - u32 lo, hi; - u32 addr; - lo = 0; - hi = addr_hi>>24; - addr = FS_Base; - _WRMSR(addr, lo, hi); - return addr_hi << 8; -} - - -void ResetDCTWrPtr_D(u32 dev, u32 index_reg, u32 index) -{ - u32 val; - - val = Get_NB32_index_wait(dev, index_reg, index); - Set_NB32_index_wait(dev, index_reg, index, val); -} - - -/* mctEngDQSwindow_Save_D not required with arrays */ - - -void mct_TrainDQSPos_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - u8 ChipSel; - struct DCTStatStruc *pDCTstat; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - if (pDCTstat->DCTSysLimit) { - /* when DCT speed >= 400MHz, we only support 2 DIMMs - * and we have two sets registers for DIMM0 and DIMM1 so - * here we must traning DQSRd/WrPos for DIMM0 and DIMM1 - */ - if (pDCTstat->Speed >= 4) { - pDCTstat->Status |= (1 << SB_Over400MHz); - } - for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel += 2) { - TrainDQSRdWrPos_D(pMCTstat, pDCTstat, ChipSel); - SetEccDQSRdWrPos_D(pMCTstat, pDCTstat, ChipSel); - } - } - } -} - - -/* mct_BeforeTrainDQSRdWrPos_D - * Function is inline. - */ - -u8 mct_DisableDimmEccEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 _DisableDramECC = 0; - u32 val; - u32 reg; - u32 dev; - - /*Disable ECC correction of reads on the dram bus. */ - - dev = pDCTstat->dev_dct; - reg = 0x90; - val = Get_NB32(dev, reg); - if (val & (1<<DimmEcEn)) { - _DisableDramECC |= 0x01; - val &= ~(1<<DimmEcEn); - Set_NB32(dev, reg, val); - } - if (!pDCTstat->GangedMode) { - reg = 0x190; - val = Get_NB32(dev, reg); - if (val & (1<<DimmEcEn)) { - _DisableDramECC |= 0x02; - val &= ~(1<<DimmEcEn); - Set_NB32(dev, reg, val); - } - } - return _DisableDramECC; -} - - - -void mct_EnableDimmEccEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 _DisableDramECC) -{ - - u32 val; - u32 reg; - u32 dev; - - /* Enable ECC correction if it was previously disabled */ - - dev = pDCTstat->dev_dct; - - if ((_DisableDramECC & 0x01) == 0x01) { - reg = 0x90; - val = Get_NB32(dev, reg); - val |= (1<<DimmEcEn); - Set_NB32(dev, reg, val); - } - if ((_DisableDramECC & 0x02) == 0x02) { - reg = 0x190; - val = Get_NB32(dev, reg); - val |= (1<<DimmEcEn); - Set_NB32(dev, reg, val); - } -} - - -static void mct_SetDQSDelayCSR_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel) -{ - u8 ByteLane; - u32 val; - u32 index_reg = 0x98 + 0x100 * pDCTstat->Channel; - u8 shift; - u32 dqs_delay = (u32)pDCTstat->DQSDelay; - u32 dev = pDCTstat->dev_dct; - u32 index; - - ByteLane = pDCTstat->ByteLane; - - /* Channel is offset */ - if (ByteLane < 4) { - index = 1; - } else if (ByteLane <8) { - index = 2; - } else { - index = 3; - } - - if (pDCTstat->Direction == DQS_READDIR) { - index += 4; - } - - /* get the proper register index */ - shift = ByteLane % 4; - shift <<= 3; /* get bit position of bytelane, 8 bit */ - - if (pDCTstat->Status & (1 << SB_Over400MHz)) { - index += (ChipSel >> 1) * 0x100; /* if logical DIMM1/DIMM3 */ - } - - val = Get_NB32_index_wait(dev, index_reg, index); - val &= ~(0x7f << shift); - val |= (dqs_delay << shift); - Set_NB32_index_wait(dev, index_reg, index, val); -} - - -static void mct_SetDQSDelayAllCSR_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 cs_start) -{ - u8 ByteLane; - u8 ChipSel = cs_start; - - - for (ChipSel = cs_start; ChipSel < (cs_start + 2); ChipSel++) { - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, pDCTstat->Channel, ChipSel)) { - for (ByteLane = 0; ByteLane < 8; ByteLane++) { - pDCTstat->ByteLane = ByteLane; - mct_SetDQSDelayCSR_D(pMCTstat, pDCTstat, ChipSel); - } - } - } -} - - -u8 mct_RcvrRankEnabled_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 ChipSel) -{ - u8 ret; - - ret = ChipSelPresent_D(pMCTstat, pDCTstat, Channel, ChipSel); - return ret; -} - - -u32 mct_GetRcvrSysAddr_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 channel, u8 receiver, u8 *valid) -{ - return mct_GetMCTSysAddr_D(pMCTstat, pDCTstat, channel, receiver, valid); -} - - -u32 mct_GetMCTSysAddr_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 receiver, u8 *valid) -{ - u32 val; - u32 reg_off = 0; - u32 reg; - u32 dword; - u32 dev = pDCTstat->dev_dct; - - *valid = 0; - - - if (!pDCTstat->GangedMode) { - reg_off = 0x100 * Channel; - } - - /* get the local base addr of the chipselect */ - reg = 0x40 + (receiver << 2) + reg_off; - val = Get_NB32(dev, reg); - - val &= ~0x0F; - - /* unganged mode DCT0+DCT1, sys addr of DCT1 = node - * base+DctSelBaseAddr+local ca base*/ - if ((Channel) && (pDCTstat->GangedMode == 0) && (pDCTstat->DIMMValidDCT[0] > 0)) { - reg = 0x110; - dword = Get_NB32(dev, reg); - dword &= 0xfffff800; - dword <<= 8; /* scale [47:27] of F2x110[31:11] to [39:8]*/ - val += dword; - - /* if DCTSelBaseAddr < Hole, and eax > HoleBase, then add Hole size to test address */ - if ((val >= pDCTstat->DCTHoleBase) && (pDCTstat->DCTHoleBase > dword)) { - dword = (~(pDCTstat->DCTHoleBase >> (24 - 8)) + 1) & 0xFF; - dword <<= (24 - 8); - val += dword; - } - } else { - /* sys addr = node base+local cs base */ - val += pDCTstat->DCTSysBase; - - /* New stuff */ - if (pDCTstat->DCTHoleBase && (val >= pDCTstat->DCTHoleBase)) { - val -= pDCTstat->DCTSysBase; - dword = Get_NB32(pDCTstat->dev_map, 0xF0); /* get Hole Offset */ - val += (dword & 0x0000ff00) << (24-8-8); - } - } - - /* New stuff */ - val += ((1 << 21) >> 8); /* Add 2MB offset to avoid compat area */ - if (val >= MCT_TRNG_KEEPOUT_START) { - while (val < MCT_TRNG_KEEPOUT_END) - val += (1 << (15-8)); /* add 32K */ - } - - /* Add a node seed */ - val += (((1 * pDCTstat->Node_ID) << 20) >> 8); /* Add 1MB per node to avoid aliases */ - - /* HW remap disabled? */ - if (!(pDCTstat->Status & (1 << SB_HWHole))) { - if (!(pDCTstat->Status & (1 << SB_SWNodeHole))) { - /* SW memhole disabled */ - u32 lo, hi; - _RDMSR(TOP_MEM, &lo, &hi); - lo >>= 8; - if ((val >= lo) && (val < _4GB_RJ8)) { - val = 0; - *valid = 0; - goto exitGetAddr; - } else { - *valid = 1; - goto exitGetAddrWNoError; - } - } else { - *valid = 1; - goto exitGetAddrWNoError; - } - } else { - *valid = 1; - goto exitGetAddrWNoError; - } - -exitGetAddrWNoError: - - /* Skip if Address is in UMA region */ - dword = pMCTstat->Sub4GCacheTop; - dword >>= 8; - if (dword != 0) { - if ((val >= dword) && (val < _4GB_RJ8)) { - val = 0; - *valid = 0; - } else { - *valid = 1; - } - } - print_debug_dqs("mct_GetMCTSysAddr_D: receiver ", receiver, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: Channel ", Channel, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: base_addr ", val, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: valid ", *valid, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: status ", pDCTstat->Status, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: HoleBase ", pDCTstat->DCTHoleBase, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: Cachetop ", pMCTstat->Sub4GCacheTop, 2); - -exitGetAddr: - return val; -} - - -void mct_Write1LTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 TestAddr, u8 pattern) -{ - - u8 *buf; - - /* Issue the stream of writes. When F2x11C[MctWrLimit] is reached - * (or when F2x11C[FlushWr] is set again), all the writes are written - * to DRAM. - */ - - SetUpperFSbase(TestAddr); - - if (pattern) - buf = (u8 *)pDCTstat->PtrPatternBufB; - else - buf = (u8 *)pDCTstat->PtrPatternBufA; - - WriteLNTestPattern(TestAddr << 8, buf, 1); -} - - -void mct_Read1LTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 addr) -{ - /* BIOS issues the remaining (Ntrain - 2) reads after checking that - * F2x11C[PrefDramTrainMode] is cleared. These reads must be to - * consecutive cache lines (i.e., 64 bytes apart) and must not cross - * a naturally aligned 4KB boundary. These reads hit the prefetches and - * read the data from the prefetch buffer. - */ - - /* get data from DIMM */ - SetUpperFSbase(addr); - - /* 1st move causes read fill (to exclusive or shared)*/ - read32_fs(addr << 8); -} diff --git a/src/northbridge/amd/amdmct/mct/mctecc_d.c b/src/northbridge/amd/amdmct/mct/mctecc_d.c deleted file mode 100644 index 8eb7bf54b7..0000000000 --- a/src/northbridge/amd/amdmct/mct/mctecc_d.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdmct/mct/mctgr.c b/src/northbridge/amd/amdmct/mct/mctgr.c deleted file mode 100644 index 41a479b21e..0000000000 --- a/src/northbridge/amd/amdmct/mct/mctgr.c +++ /dev/null @@ -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); - } -} diff --git a/src/northbridge/amd/amdmct/mct/mcthdi.c b/src/northbridge/amd/amdmct/mct/mcthdi.c deleted file mode 100644 index b67282ef60..0000000000 --- a/src/northbridge/amd/amdmct/mct/mcthdi.c +++ /dev/null @@ -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); -} diff --git a/src/northbridge/amd/amdmct/mct/mctmtr_d.c b/src/northbridge/amd/amdmct/mct/mctmtr_d.c deleted file mode 100644 index 883ab651cc..0000000000 --- a/src/northbridge/amd/amdmct/mct/mctmtr_d.c +++ /dev/null @@ -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; - } -} diff --git a/src/northbridge/amd/amdmct/mct/mctndi_d.c b/src/northbridge/amd/amdmct/mct/mctndi_d.c deleted file mode 100644 index 3f09f4a472..0000000000 --- a/src/northbridge/amd/amdmct/mct/mctndi_d.c +++ /dev/null @@ -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"); -} diff --git a/src/northbridge/amd/amdmct/mct/mctpro_d.c b/src/northbridge/amd/amdmct/mct/mctpro_d.c deleted file mode 100644 index 83937330f8..0000000000 --- a/src/northbridge/amd/amdmct/mct/mctpro_d.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdmct/mct/mctsrc.c b/src/northbridge/amd/amdmct/mct/mctsrc.c deleted file mode 100644 index 406547e0f8..0000000000 --- a/src/northbridge/amd/amdmct/mct/mctsrc.c +++ /dev/null @@ -1,1090 +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; 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. - */ - -#include <console/console.h> -#include <cpu/x86/cr.h> -#include <cpu/amd/msr.h> - -#include "mct_d.h" - -/****************************************************************************** - Description: Receiver En and DQS Timing Training feature for DDR 2 MCT -******************************************************************************/ - -static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Pass); -static u8 mct_SavePassRcvEnDly_D(struct DCTStatStruc *pDCTstat, - u8 rcvrEnDly, u8 Channel, - u8 receiver, u8 Pass); -static u8 mct_CompareTestPatternQW0_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 addr, u8 channel, - u8 pattern, u8 Pass); -static void mct_InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Channel); -static void CalcEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Channel); -static void mct_SetFinalRcvrEnDly_D(struct DCTStatStruc *pDCTstat, - u8 RcvrEnDly, u8 where, - u8 Channel, u8 Receiver, - u32 dev, u32 index_reg, - u8 Addl_Index, u8 Pass); -static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u8 DQSRcvEnDly); -static void fenceDynTraining_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_DisableDQSRcvEn_D(struct DCTStatStruc *pDCTstat); - -/* Warning: These must be located so they do not cross a logical 16-bit - segment boundary! */ -const u32 TestPattern0_D[] = { - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, -}; -const u32 TestPattern1_D[] = { - 0x55555555, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0x55555555, 0x55555555, -}; -const u32 TestPattern2_D[] = { - 0x12345678, 0x87654321, 0x23456789, 0x98765432, - 0x59385824, 0x30496724, 0x24490795, 0x99938733, - 0x40385642, 0x38465245, 0x29432163, 0x05067894, - 0x12349045, 0x98723467, 0x12387634, 0x34587623, -}; - -static void SetupRcvrPattern(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 *buffer, u8 pass) -{ - /* - * 1. Copy the alpha and Beta patterns from ROM to Cache, - * aligning on 16 byte boundary - * 2. Set the ptr to DCTStatstruc.PtrPatternBufA for Alpha - * 3. Set the ptr to DCTStatstruc.PtrPatternBufB for Beta - */ - - u32 *buf_a; - u32 *buf_b; - u32 *p_A; - u32 *p_B; - u8 i; - - buf_a = (u32 *)(((u32)buffer + 0x10) & (0xfffffff0)); - buf_b = buf_a + 32; //?? - p_A = (u32 *)SetupDqsPattern_1PassB(pass); - p_B = (u32 *)SetupDqsPattern_1PassA(pass); - - for (i = 0; i < 16; i++) { - buf_a[i] = p_A[i]; - buf_b[i] = p_B[i]; - } - - pDCTstat->PtrPatternBufA = (u32)buf_a; - pDCTstat->PtrPatternBufB = (u32)buf_b; -} - - -void mct_TrainRcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Pass) -{ - if (mct_checkNumberOfDqsRcvEn_1Pass(Pass)) - dqsTrainRcvrEn_SW(pMCTstat, pDCTstat, Pass); -} - - -static void dqsTrainRcvrEn_SW(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Pass) -{ - u8 Channel, RcvrEnDly, RcvrEnDlyRmin; - u8 Test0, Test1, CurrTest, CurrTestSide0, CurrTestSide1; - u8 CTLRMaxDelay, _2Ranks, PatternA, PatternB; - u8 Addl_Index = 0; - u8 Receiver; - u8 _DisableDramECC = 0, _Wrap32Dis = 0, _SSE2 = 0; - u8 RcvrEnDlyLimit, Final_Value, MaxDelay_CH[2]; - u32 TestAddr0, TestAddr1, TestAddr0B, TestAddr1B; - u32 PatternBuffer[64+4]; /* FIXME: need increase 8? */ - u32 Errors; - - u32 val; - u32 reg; - u32 dev; - u32 index_reg; - u32 ch_start, ch_end, ch; - u32 msr; - CRx_TYPE cr4; - u32 lo, hi; - - u8 valid; - u32 tmp; - u8 LastTest; - - print_debug_dqs("\nTrainRcvEn: Node", pDCTstat->Node_ID, 0); - print_debug_dqs("TrainRcvEn: Pass", Pass, 0); - - - dev = pDCTstat->dev_dct; - ch_start = 0; - if (!pDCTstat->GangedMode) { - ch_end = 2; - } else { - ch_end = 1; - } - - for (ch = ch_start; ch < ch_end; ch++) { - reg = 0x78 + (0x100 * ch); - val = Get_NB32(dev, reg); - val &= ~(0x3ff << 22); - val |= (0x0c8 << 22); /* Max Rd Lat */ - Set_NB32(dev, reg, val); - } - - Final_Value = 1; - if (Pass == FirstPass) { - mct_InitDQSPos4RcvrEn_D(pMCTstat, pDCTstat); - } else { - pDCTstat->DimmTrainFail = 0; - pDCTstat->CSTrainFail = ~pDCTstat->CSPresent; - } - print_t("TrainRcvrEn: 1\n"); - - cr4 = read_cr4(); - if (cr4 & (1 << 9)) { /* save the old value */ - _SSE2 = 1; - } - cr4 |= (1 << 9); /* OSFXSR enable SSE2 */ - write_cr4(cr4); - print_t("TrainRcvrEn: 2\n"); - - msr = HWCR_MSR; - _RDMSR(msr, &lo, &hi); - //FIXME: Why use SSEDIS - if (lo & (1 << 17)) { /* save the old value */ - _Wrap32Dis = 1; - } - lo |= (1 << 17); /* HWCR.wrap32dis */ - lo &= ~(1 << 15); /* SSEDIS */ - _WRMSR(msr, lo, hi); /* Setting wrap32dis allows 64-bit memory references in real mode */ - print_t("TrainRcvrEn: 3\n"); - - _DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat); - - - if (pDCTstat->Speed == 1) { - pDCTstat->T1000 = 5000; /* get the T1000 figure (cycle time (ns)*1K */ - } else if (pDCTstat->Speed == 2) { - pDCTstat->T1000 = 3759; - } else if (pDCTstat->Speed == 3) { - pDCTstat->T1000 = 3003; - } else if (pDCTstat->Speed == 4) { - pDCTstat->T1000 = 2500; - } else if (pDCTstat->Speed == 5) { - pDCTstat->T1000 = 1876; - } else { - pDCTstat->T1000 = 0; - } - - SetupRcvrPattern(pMCTstat, pDCTstat, PatternBuffer, Pass); - print_t("TrainRcvrEn: 4\n"); - - Errors = 0; - dev = pDCTstat->dev_dct; - CTLRMaxDelay = 0; - - for (Channel = 0; Channel < 2; Channel++) { - print_debug_dqs("\tTrainRcvEn51: Node ", pDCTstat->Node_ID, 1); - print_debug_dqs("\tTrainRcvEn51: Channel ", Channel, 1); - pDCTstat->Channel = Channel; - - MaxDelay_CH[Channel] = 0; - index_reg = 0x98 + 0x100 * Channel; - - Receiver = mct_InitReceiver_D(pDCTstat, Channel); - /* There are four receiver pairs, loosely associated with chipselects. */ - for (; Receiver < 8; Receiver += 2) { - Addl_Index = (Receiver >> 1) * 3 + 0x10; - LastTest = DQS_FAIL; - - /* mct_ModifyIndex_D */ - RcvrEnDlyRmin = RcvrEnDlyLimit = 0xff; - - print_debug_dqs("\t\tTrainRcvEnd52: index ", Addl_Index, 2); - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver)) { - print_t("\t\t\tRank not enabled_D\n"); - continue; - } - - TestAddr0 = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, Channel, Receiver, &valid); - if (!valid) { /* Address not supported on current CS */ - print_t("\t\t\tAddress not supported on current CS\n"); - continue; - } - - TestAddr0B = TestAddr0 + (BigPagex8_RJ8 << 3); - - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver+1)) { - TestAddr1 = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, Channel, Receiver+1, &valid); - if (!valid) { /* Address not supported on current CS */ - print_t("\t\t\tAddress not supported on current CS+1\n"); - continue; - } - TestAddr1B = TestAddr1 + (BigPagex8_RJ8 << 3); - _2Ranks = 1; - } else { - _2Ranks = TestAddr1 = TestAddr1B = 0; - } - - print_debug_dqs("\t\tTrainRcvEn53: TestAddr0 ", TestAddr0, 2); - print_debug_dqs("\t\tTrainRcvEn53: TestAddr0B ", TestAddr0B, 2); - print_debug_dqs("\t\tTrainRcvEn53: TestAddr1 ", TestAddr1, 2); - print_debug_dqs("\t\tTrainRcvEn53: TestAddr1B ", TestAddr1B, 2); - - /* - * Get starting RcvrEnDly value - */ - RcvrEnDly = mct_Get_Start_RcvrEnDly_1Pass(Pass); - - /* mct_GetInitFlag_D*/ - if (Pass == FirstPass) { - pDCTstat->DqsRcvEn_Pass = 0; - } else { - pDCTstat->DqsRcvEn_Pass = 0xFF; - } - pDCTstat->DqsRcvEn_Saved = 0; - - - while (RcvrEnDly < RcvrEnDlyLimit) { /* sweep Delay value here */ - print_debug_dqs("\t\t\tTrainRcvEn541: RcvrEnDly ", RcvrEnDly, 3); - - /* callback not required - if (mct_AdjustDelay_D(pDCTstat, RcvrEnDly)) - goto skipDly; - */ - - /* Odd steps get another pattern such that even - and odd steps alternate. The pointers to the - patterns will be swaped at the end of the loop - so that they correspond. */ - if (RcvrEnDly & 1) { - PatternA = 1; - PatternB = 0; - } else { - /* Even step */ - PatternA = 0; - PatternB = 1; - } - - mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr0, PatternA); /* rank 0 of DIMM, testpattern 0 */ - mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr0B, PatternB); /* rank 0 of DIMM, testpattern 1 */ - if (_2Ranks) { - mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr1, PatternA); /*rank 1 of DIMM, testpattern 0 */ - mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr1B, PatternB); /*rank 1 of DIMM, testpattern 1 */ - } - - mct_SetRcvrEnDly_D(pDCTstat, RcvrEnDly, 0, Channel, Receiver, dev, index_reg, Addl_Index, Pass); - - CurrTest = DQS_FAIL; - CurrTestSide0 = DQS_FAIL; - CurrTestSide1 = DQS_FAIL; - - mct_Read1LTestPattern_D(pMCTstat, pDCTstat, TestAddr0); /*cache fills */ - Test0 = mct_CompareTestPatternQW0_D(pMCTstat, pDCTstat, TestAddr0, Channel, PatternA, Pass);/* ROM vs cache compare */ - proc_IOCLFLUSH_D(TestAddr0); - ResetDCTWrPtr_D(dev, index_reg, Addl_Index); - - print_debug_dqs("\t\t\tTrainRcvEn542: Test0 result ", Test0, 3); - - // != 0x00 mean pass - - if (Test0 == DQS_PASS) { - mct_Read1LTestPattern_D(pMCTstat, pDCTstat, TestAddr0B); /*cache fills */ - /* ROM vs cache compare */ - Test1 = mct_CompareTestPatternQW0_D(pMCTstat, pDCTstat, TestAddr0B, Channel, PatternB, Pass); - proc_IOCLFLUSH_D(TestAddr0B); - ResetDCTWrPtr_D(dev, index_reg, Addl_Index); - - print_debug_dqs("\t\t\tTrainRcvEn543: Test1 result ", Test1, 3); - - if (Test1 == DQS_PASS) { - CurrTestSide0 = DQS_PASS; - } - } - if (_2Ranks) { - mct_Read1LTestPattern_D(pMCTstat, pDCTstat, TestAddr1); /*cache fills */ - /* ROM vs cache compare */ - Test0 = mct_CompareTestPatternQW0_D(pMCTstat, pDCTstat, TestAddr1, Channel, PatternA, Pass); - proc_IOCLFLUSH_D(TestAddr1); - ResetDCTWrPtr_D(dev, index_reg, Addl_Index); - - print_debug_dqs("\t\t\tTrainRcvEn544: Test0 result ", Test0, 3); - - if (Test0 == DQS_PASS) { - mct_Read1LTestPattern_D(pMCTstat, pDCTstat, TestAddr1B); /*cache fills */ - /* ROM vs cache compare */ - Test1 = mct_CompareTestPatternQW0_D(pMCTstat, pDCTstat, TestAddr1B, Channel, PatternB, Pass); - proc_IOCLFLUSH_D(TestAddr1B); - ResetDCTWrPtr_D(dev, index_reg, Addl_Index); - - print_debug_dqs("\t\t\tTrainRcvEn545: Test1 result ", Test1, 3); - if (Test1 == DQS_PASS) { - CurrTestSide1 = DQS_PASS; - } - } - } - - if (_2Ranks) { - if ((CurrTestSide0 == DQS_PASS) && (CurrTestSide1 == DQS_PASS)) { - CurrTest = DQS_PASS; - } - } else if (CurrTestSide0 == DQS_PASS) { - CurrTest = DQS_PASS; - } - - - /* record first pass DqsRcvEn to stack */ - valid = mct_SavePassRcvEnDly_D(pDCTstat, RcvrEnDly, Channel, Receiver, Pass); - - /* Break(1:RevF,2:DR) or not(0) FIXME: This comment deosn't make sense */ - if (valid == 2 || (LastTest == DQS_FAIL && valid == 1)) { - RcvrEnDlyRmin = RcvrEnDly; - break; - } - - LastTest = CurrTest; - - /* swap the rank 0 pointers */ - tmp = TestAddr0; - TestAddr0 = TestAddr0B; - TestAddr0B = tmp; - - /* swap the rank 1 pointers */ - tmp = TestAddr1; - TestAddr1 = TestAddr1B; - TestAddr1B = tmp; - - print_debug_dqs("\t\t\tTrainRcvEn56: RcvrEnDly ", RcvrEnDly, 3); - - RcvrEnDly++; - - } /* while RcvrEnDly */ - - print_debug_dqs("\t\tTrainRcvEn61: RcvrEnDly ", RcvrEnDly, 2); - print_debug_dqs("\t\tTrainRcvEn61: RcvrEnDlyRmin ", RcvrEnDlyRmin, 3); - print_debug_dqs("\t\tTrainRcvEn61: RcvrEnDlyLimit ", RcvrEnDlyLimit, 3); - if (RcvrEnDlyRmin == RcvrEnDlyLimit) { - /* no passing window */ - pDCTstat->ErrStatus |= 1 << SB_NORCVREN; - Errors |= 1 << SB_NORCVREN; - pDCTstat->ErrCode = SC_FatalErr; - } - - if (RcvrEnDly > (RcvrEnDlyLimit - 1)) { - /* passing window too narrow, too far delayed*/ - pDCTstat->ErrStatus |= 1 << SB_SmallRCVR; - Errors |= 1 << SB_SmallRCVR; - pDCTstat->ErrCode = SC_FatalErr; - RcvrEnDly = RcvrEnDlyLimit - 1; - pDCTstat->CSTrainFail |= 1 << Receiver; - pDCTstat->DimmTrainFail |= 1 << (Receiver + Channel); - } - - // CHB_D0_B0_RCVRDLY set in mct_Average_RcvrEnDly_Pass - mct_Average_RcvrEnDly_Pass(pDCTstat, RcvrEnDly, RcvrEnDlyLimit, Channel, Receiver, Pass); - - mct_SetFinalRcvrEnDly_D(pDCTstat, RcvrEnDly, Final_Value, Channel, Receiver, dev, index_reg, Addl_Index, Pass); - - if (pDCTstat->ErrStatus & (1 << SB_SmallRCVR)) { - Errors |= 1 << SB_SmallRCVR; - } - - RcvrEnDly += Pass1MemClkDly; - if (RcvrEnDly > CTLRMaxDelay) { - CTLRMaxDelay = RcvrEnDly; - } - - } /* while Receiver */ - - MaxDelay_CH[Channel] = CTLRMaxDelay; - } /* for Channel */ - - CTLRMaxDelay = MaxDelay_CH[0]; - if (MaxDelay_CH[1] > CTLRMaxDelay) - CTLRMaxDelay = MaxDelay_CH[1]; - - for (Channel = 0; Channel < 2; Channel++) { - mct_SetMaxLatency_D(pDCTstat, Channel, CTLRMaxDelay); /* program Ch A/B MaxAsyncLat to correspond with max delay */ - } - - ResetDCTWrPtr_D(dev, index_reg, Addl_Index); - - if (_DisableDramECC) { - mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC); - } - - if (Pass == FirstPass) { - /*Disable DQSRcvrEn training mode */ - print_t("TrainRcvrEn: mct_DisableDQSRcvEn_D\n"); - mct_DisableDQSRcvEn_D(pDCTstat); - } - - if (!_Wrap32Dis) { - msr = HWCR_MSR; - _RDMSR(msr, &lo, &hi); - lo &= ~(1<<17); /* restore HWCR.wrap32dis */ - _WRMSR(msr, 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, "TrainRcvrEn: CH_MaxRdLat:\n"); - for (Channel = 0; Channel < 2; Channel++) { - printk(BIOS_DEBUG, "Channel: %02x: %02x\n", Channel, pDCTstat->CH_MaxRdLat[Channel]); - } - } -#endif - -#if DQS_TRAIN_DEBUG > 0 - { - u8 val; - u8 Channel, Receiver; - u8 i; - u8 *p; - - printk(BIOS_DEBUG, "TrainRcvrEn: CH_D_B_RCVRDLY:\n"); - for (Channel = 0; Channel < 2; Channel++) { - printk(BIOS_DEBUG, "Channel: %02x\n", Channel); - for (Receiver = 0; Receiver < 8; Receiver+=2) { - printk(BIOS_DEBUG, "\t\tReceiver: %02x: ", Receiver); - p = pDCTstat->persistentData.CH_D_B_RCVRDLY[Channel][Receiver>>1]; - for (i = 0; i < 8; i++) { - val = p[i]; - printk(BIOS_DEBUG, "%02x ", val); - } - printk(BIOS_DEBUG, "\n"); - } - } - } -#endif - - print_tx("TrainRcvrEn: Status ", pDCTstat->Status); - print_tx("TrainRcvrEn: ErrStatus ", pDCTstat->ErrStatus); - print_tx("TrainRcvrEn: ErrCode ", pDCTstat->ErrCode); - print_t("TrainRcvrEn: Done\n"); -} - - -u8 mct_InitReceiver_D(struct DCTStatStruc *pDCTstat, u8 dct) -{ - if (pDCTstat->DIMMValidDCT[dct] == 0) { - return 8; - } else { - return 0; - } -} - - -static void mct_SetFinalRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u8 RcvrEnDly, u8 where, u8 Channel, u8 Receiver, u32 dev, u32 index_reg, u8 Addl_Index, u8 Pass/*, u8 *p*/) -{ - /* - * Program final DqsRcvEnDly to additional index for DQS receiver - * enabled delay - */ - mct_SetRcvrEnDly_D(pDCTstat, RcvrEnDly, where, Channel, Receiver, dev, index_reg, Addl_Index, Pass); -} - - -static void mct_DisableDQSRcvEn_D(struct DCTStatStruc *pDCTstat) -{ - u8 ch_end, ch; - u32 reg; - u32 dev; - u32 val; - - dev = pDCTstat->dev_dct; - if (pDCTstat->GangedMode) { - ch_end = 1; - } else { - ch_end = 2; - } - - for (ch = 0; ch < ch_end; ch++) { - reg = 0x78 + 0x100 * ch; - val = Get_NB32(dev, reg); - val &= ~(1 << DqsRcvEnTrain); - Set_NB32(dev, reg, val); - } -} - - -/* mct_ModifyIndex_D - * Function only used once so it was inlined. - */ - - -/* mct_GetInitFlag_D - * Function only used once so it was inlined. - */ - - -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) -{ - u32 index; - u8 i; - u8 *p; - u32 val; - - if (RcvrEnDly == 0xFE) { - /*set the boudary flag */ - pDCTstat->Status |= 1 << SB_DQSRcvLimit; - } - - /* DimmOffset not needed for CH_D_B_RCVRDLY array */ - - - for (i = 0; i < 8; i++) { - if (FinalValue) { - /*calculate dimm offset */ - p = pDCTstat->persistentData.CH_D_B_RCVRDLY[Channel][Receiver >> 1]; - RcvrEnDly = p[i]; - } - - /* if flag = 0, set DqsRcvEn value to reg. */ - /* get the register index from table */ - index = Table_DQSRcvEn_Offset[i >> 1]; - index += Addl_Index; /* DIMMx DqsRcvEn byte0 */ - val = Get_NB32_index_wait(dev, index_reg, index); - if (i & 1) { - /* odd byte lane */ - val &= ~(0xFF << 16); - val |= (RcvrEnDly << 16); - } else { - /* even byte lane */ - val &= ~0xFF; - val |= RcvrEnDly; - } - Set_NB32_index_wait(dev, index_reg, index, val); - } - -} - -static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u8 DQSRcvEnDly) -{ - u32 dev; - u32 reg; - u16 SubTotal; - u32 index_reg; - u32 reg_off; - u32 val; - u32 valx; - - if (pDCTstat->GangedMode) - Channel = 0; - - dev = pDCTstat->dev_dct; - reg_off = 0x100 * Channel; - index_reg = 0x98 + reg_off; - - /* 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 */ - - /* Add 5.5 to the sub-total. 5.5 represents part of the - * processor specific constant delay value in the DRAM - * clock domain. - */ - SubTotal <<= 1; /*scale 1/2 MemClk to 1/4 MemClk */ - SubTotal += 11; /*add 5.5 1/2MemClk */ - - /* 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; - - val = Get_NB32(pDCTstat->dev_nbmisc, 0xD4); - SubTotal *= ((val & 0x1f) + 4) * 3; - - SubTotal /= valx; - if (SubTotal % valx) { /* round up */ - SubTotal++; - } - - /* Add 5 NCLKs to the sub-total. 5 represents part of the - * processor specific constant value in the northbridge - * clock domain. - */ - SubTotal += 5; - - pDCTstat->CH_MaxRdLat[Channel] = SubTotal; - if (pDCTstat->GangedMode) { - pDCTstat->CH_MaxRdLat[1] = SubTotal; - } - - /* Program the F2x[1, 0]78[MaxRdLatency] register with - * the total delay value (in NCLKs). - */ - - reg = 0x78 + reg_off; - val = Get_NB32(dev, reg); - val &= ~(0x3ff << 22); - val |= (SubTotal & 0x3ff) << 22; - - /* program MaxRdLatency to correspond with current delay */ - Set_NB32(dev, reg, val); -} - - -static u8 mct_SavePassRcvEnDly_D(struct DCTStatStruc *pDCTstat, - u8 rcvrEnDly, u8 Channel, - u8 receiver, u8 Pass) -{ - u8 i; - u8 mask_Saved, mask_Pass; - u8 *p; - - /* calculate dimm offset - * not needed for CH_D_B_RCVRDLY array - */ - - /* cmp if there has new DqsRcvEnDly to be recorded */ - mask_Pass = pDCTstat->DqsRcvEn_Pass; - - if (Pass == SecondPass) { - mask_Pass = ~mask_Pass; - } - - mask_Saved = pDCTstat->DqsRcvEn_Saved; - if (mask_Pass != mask_Saved) { - - /* find desired stack offset according to channel/dimm/byte */ - if (Pass == SecondPass) { - // FIXME: SecondPass is never used for Barcelona p = pDCTstat->persistentData.CH_D_B_RCVRDLY_1[Channel][receiver>>1]; - p = 0; // Keep the compiler happy. - } else { - mask_Saved &= mask_Pass; - p = pDCTstat->persistentData.CH_D_B_RCVRDLY[Channel][receiver>>1]; - } - for (i = 0; i < 8; i++) { - /* cmp per byte lane */ - if (mask_Pass & (1 << i)) { - if (!(mask_Saved & (1 << i))) { - /* save RcvEnDly to stack, according to - the related Dimm/byte lane */ - p[i] = (u8)rcvrEnDly; - mask_Saved |= 1 << i; - } - } - } - pDCTstat->DqsRcvEn_Saved = mask_Saved; - } - return mct_SaveRcvEnDly_D_1Pass(pDCTstat, Pass); -} - - -static u8 mct_CompareTestPatternQW0_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 addr, u8 channel, - u8 pattern, u8 Pass) -{ - /* 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. - */ - - u8 *test_buf; - u8 i; - u8 result; - u8 value; - - - if (Pass == FirstPass) { - if (pattern == 1) { - test_buf = (u8 *)TestPattern1_D; - } else { - test_buf = (u8 *)TestPattern0_D; - } - } else { // Second Pass - test_buf = (u8 *)TestPattern2_D; - } - - SetUpperFSbase(addr); - addr <<= 8; - - if ((pDCTstat->Status & (1<<SB_128bitmode)) && channel) { - addr += 8; /* second channel */ - test_buf += 8; - } - - print_debug_dqs_pair("\t\t\t\t\t\t test_buf = ", (u32)test_buf, " | addr_lo = ", addr, 4); - for (i = 0; i < 8; i++) { - value = read32_fs(addr); - print_debug_dqs_pair("\t\t\t\t\t\t\t\t ", test_buf[i], " | ", value, 4); - - if (value == test_buf[i]) { - pDCTstat->DqsRcvEn_Pass |= (1<<i); - } else { - pDCTstat->DqsRcvEn_Pass &= ~(1<<i); - } - } - - result = DQS_FAIL; - - if (Pass == FirstPass) { - /* if first pass, at least one byte lane pass - * ,then DQS_PASS = 1 and will set to related reg. - */ - if (pDCTstat->DqsRcvEn_Pass != 0) { - result = DQS_PASS; - } else { - result = DQS_FAIL; - } - - } else { - /* if second pass, at least one byte lane fail - * ,then DQS_FAIL = 1 and will set to related reg. - */ - if (pDCTstat->DqsRcvEn_Pass != 0xFF) { - result = DQS_FAIL; - } else { - result = DQS_PASS; - } - } - - /* if second pass, we can't find the fail until FFh, - * then let it fail to save the final delay - */ - if ((Pass == SecondPass) && (pDCTstat->Status & (1 << SB_DQSRcvLimit))) { - result = DQS_FAIL; - pDCTstat->DqsRcvEn_Pass = 0; - } - - /* second pass needs to be inverted - * FIXME? this could be inverted in the above code to start with... - */ - if (Pass == SecondPass) { - if (result == DQS_PASS) { - result = DQS_FAIL; - } else if (result == DQS_FAIL) { /* FIXME: doesn't need to be else if */ - result = DQS_PASS; - } - } - - - return result; -} - - - -static void mct_InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Initialize the DQS Positions in preparation for - * Receiver Enable Training. - * Write Position is 1/2 Memclock Delay - * Read Position is 1/2 Memclock Delay - */ - u8 i; - for (i = 0; i < 2; i++) { - InitDQSPos4RcvrEn_D(pMCTstat, pDCTstat, i); - } -} - - -static void InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Channel) -{ - /* Initialize the DQS Positions in preparation for - * Receiver Enable Training. - * Write Position is no Delay - * Read Position is 1/2 Memclock Delay - */ - - u8 i, j; - u32 dword; - u8 dn = 2; // TODO: Rev C could be 4 - u32 dev = pDCTstat->dev_dct; - u32 index_reg = 0x98 + 0x100 * Channel; - - - // FIXME: add Cx support - dword = 0x00000000; - for (i = 1; i <= 3; i++) { - for (j = 0; j < dn; j++) - /* DIMM0 Write Data Timing Low */ - /* DIMM0 Write ECC Timing */ - Set_NB32_index_wait(dev, index_reg, i + 0x100 * j, dword); - } - - /* errata #180 */ - dword = 0x2f2f2f2f; - for (i = 5; i <= 6; i++) { - for (j = 0; j < dn; j++) - /* DIMM0 Read DQS Timing Control Low */ - Set_NB32_index_wait(dev, index_reg, i + 0x100 * j, dword); - } - - dword = 0x0000002f; - for (j = 0; j < dn; j++) - /* DIMM0 Read DQS ECC Timing Control */ - Set_NB32_index_wait(dev, index_reg, 7 + 0x100 * j, dword); -} - - -void SetEccDQSRcvrEn_D(struct DCTStatStruc *pDCTstat, u8 Channel) -{ - u32 dev; - u32 index_reg; - u32 index; - u8 ChipSel; - u8 *p; - u32 val; - - dev = pDCTstat->dev_dct; - index_reg = 0x98 + Channel * 0x100; - index = 0x12; - p = pDCTstat->persistentData.CH_D_BC_RCVRDLY[Channel]; - print_debug_dqs("\t\tSetEccDQSRcvrPos: Channel ", Channel, 2); - for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel += 2) { - val = p[ChipSel>>1]; - Set_NB32_index_wait(dev, index_reg, index, val); - print_debug_dqs_pair("\t\tSetEccDQSRcvrPos: ChipSel ", - ChipSel, " rcvr_delay ", val, 2); - index += 3; - } -} - - -static void CalcEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Channel) -{ - u8 ChipSel; - u16 EccDQSLike; - u8 EccDQSScale; - u32 val, val0, val1; - - EccDQSLike = pDCTstat->CH_EccDQSLike[Channel]; - EccDQSScale = pDCTstat->CH_EccDQSScale[Channel]; - - for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel += 2) { - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, ChipSel)) { - u8 *p; - p = pDCTstat->persistentData.CH_D_B_RCVRDLY[Channel][ChipSel>>1]; - - /* DQS Delay Value of Data Bytelane - * most like ECC byte lane */ - val0 = p[EccDQSLike & 0x07]; - /* DQS Delay Value of Data Bytelane - * 2nd most like ECC byte lane */ - val1 = p[(EccDQSLike>>8) & 0x07]; - - if (val0 > val1) { - val = val0 - val1; - } else { - val = val1 - val0; - } - - val *= ~EccDQSScale; - val >>= 8; // /256 - - if (val0 > val1) { - val -= val1; - } else { - val += val0; - } - - pDCTstat->persistentData.CH_D_BC_RCVRDLY[Channel][ChipSel>>1] = val; - } - } - SetEccDQSRcvrEn_D(pDCTstat, Channel); -} - -void mctSetEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - u8 i; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - if (!pDCTstat->NodePresent) - break; - if (pDCTstat->DCTSysLimit) { - for (i = 0; i < 2; i++) - CalcEccDQSRcvrEn_D(pMCTstat, pDCTstat, i); - } - } -} - - -void phyAssistedMemFnceTraining(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - - u8 Node = 0; - struct DCTStatStruc *pDCTstat; - - // FIXME: skip for Ax - while (Node < MAX_NODES_SUPPORTED) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->DCTSysLimit) { - fenceDynTraining_D(pMCTstat, pDCTstat, 0); - fenceDynTraining_D(pMCTstat, pDCTstat, 1); - } - Node++; - } -} - - -static void fenceDynTraining_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u16 avRecValue; - u32 val; - u32 dev; - u32 index_reg = 0x98 + 0x100 * dct; - u32 index; - - /* BIOS first programs a seed value to the phase recovery engine - * (recommended 19) registers. - * Dram Phase Recovery Control Register (F2x[1,0]9C_x[51:50] and - * F2x[1,0]9C_x52.) . - */ - - dev = pDCTstat->dev_dct; - for (index = 0x50; index <= 0x52; index ++) { - val = (FenceTrnFinDlySeed & 0x1F); - if (index != 0x52) { - val |= val << 8 | val << 16 | val << 24; - } - Set_NB32_index_wait(dev, index_reg, index, val); - } - - - /* Set F2x[1,0]9C_x08[PhyFenceTrEn]=1. */ - val = Get_NB32_index_wait(dev, index_reg, 0x08); - val |= 1 << PhyFenceTrEn; - Set_NB32_index_wait(dev, index_reg, 0x08, val); - - /* Wait 200 MEMCLKs. */ - mct_Wait(50000); /* wait 200us */ - - /* Clear F2x[1,0]9C_x08[PhyFenceTrEn]=0. */ - val = Get_NB32_index_wait(dev, index_reg, 0x08); - val &= ~(1 << PhyFenceTrEn); - Set_NB32_index_wait(dev, index_reg, 0x08, val); - - /* BIOS reads the phase recovery engine registers - * F2x[1,0]9C_x[51:50] and F2x[1,0]9C_x52. */ - avRecValue = 0; - for (index = 0x50; index <= 0x52; index ++) { - val = Get_NB32_index_wait(dev, index_reg, index); - avRecValue += val & 0x7F; - if (index != 0x52) { - avRecValue += (val >> 8) & 0x7F; - avRecValue += (val >> 16) & 0x7F; - avRecValue += (val >> 24) & 0x7F; - } - } - - val = avRecValue / 9; - if (avRecValue % 9) - val++; - avRecValue = val; - - /* Write the (averaged value -8) to F2x[1,0]9C_x0C[PhyFence]. */ - avRecValue -= 8; - val = Get_NB32_index_wait(dev, index_reg, 0x0C); - val &= ~(0x1F << 16); - val |= (avRecValue & 0x1F) << 16; - Set_NB32_index_wait(dev, index_reg, 0x0C, val); - - /* Rewrite F2x[1,0]9C_x04-DRAM Address/Command Timing Control Register - * delays (both channels). */ - val = Get_NB32_index_wait(dev, index_reg, 0x04); - Set_NB32_index_wait(dev, index_reg, 0x04, val); -} - - -void mct_Wait(u32 cycles) -{ - u32 saved; - u32 hi, lo, msr; - - /* Wait # of 50ns cycles - This seems like a hack to me... */ - - cycles <<= 3; /* x8 (number of 1.25ns ticks) */ - - msr = 0x10; /* TSC */ - _RDMSR(msr, &lo, &hi); - saved = lo; - do { - _RDMSR(msr, &lo, &hi); - } while (lo - saved < cycles); -} diff --git a/src/northbridge/amd/amdmct/mct/mctsrc1p.c b/src/northbridge/amd/amdmct/mct/mctsrc1p.c deleted file mode 100644 index 8ae60253ab..0000000000 --- a/src/northbridge/amd/amdmct/mct/mctsrc1p.c +++ /dev/null @@ -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); -} diff --git a/src/northbridge/amd/amdmct/mct/mctsrc2p.c b/src/northbridge/amd/amdmct/mct/mctsrc2p.c deleted file mode 100644 index ab278e9199..0000000000 --- a/src/northbridge/amd/amdmct/mct/mctsrc2p.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdmct/mct/mcttmrl.c b/src/northbridge/amd/amdmct/mct/mcttmrl.c deleted file mode 100644 index 6ec4d648d8..0000000000 --- a/src/northbridge/amd/amdmct/mct/mcttmrl.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/Makefile.inc b/src/northbridge/amd/amdmct/mct_ddr3/Makefile.inc deleted file mode 100644 index 65c146a662..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/Makefile.inc +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c deleted file mode 100644 index fa8c71447b..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +++ /dev/null @@ -1,8220 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2015-2017 Raptor Engineering, LLC - * 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. - */ - -/* Description: Main memory controller system configuration for DDR 3 */ - -/* KNOWN ISSUES - ERRATA - * - * Trtp is not calculated correctly when the controller is in 64-bit mode, it - * is 1 busclock off. No fix planned. The controller is not ordinarily in - * 64-bit mode. - * - * 32 Byte burst not supported. No fix planned. The controller is not - * ordinarily in 64-bit mode. - * - * Trc precision does not use extra Jedec defined fractional component. - * InsteadTrc (course) is rounded up to nearest 1 ns. - * - * Mini and Micro DIMM not supported. Only RDIMM, UDIMM, SO-DIMM defined types - * supported. - */ - -#include <console/console.h> -#include <northbridge/amd/amdfam10/debug.h> -#include <northbridge/amd/amdfam10/raminit.h> -#include <northbridge/amd/amdfam10/amdfam10.h> -#include <southbridge/amd/common/reset.h> -#include <cpu/x86/msr.h> -#include <cpu/amd/msr.h> -#include <cpu/x86/mtrr.h> -#include <device/pci_ops.h> -#include <arch/acpi.h> -#include <string.h> -#include <types.h> -#include <device/dram/ddr3.h> - -#include "s3utils.h" -#include "mct_d_gcc.h" -#include "mct_d.h" - -static u8 ReconfigureDIMMspare_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void DQSTiming_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, - uint8_t allow_config_restore); -static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void ClearDCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 AutoCycTiming_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void SPDSetBanks_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void StitchMemory_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u16 Get_Fk_D(u8 k); -static u8 Get_DIMMAddress_D(struct DCTStatStruc *pDCTstat, u8 i); -static void mct_preInitDCT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_initDCT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_DramInit(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_SyncDCTsReady(struct DCTStatStruc *pDCTstat); -static void Get_Trdrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_AfterGetCLT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 mct_SPDCalcWidth(struct MCTStatStruc *pMCTstat,\ - struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_AfterStitchMemory(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u8 mct_DIMMPresence(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Set_OtherTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Get_Twrwr(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Get_Twrrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Get_TrwtTO(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void Get_TrwtWB(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat, - u32 dev, uint8_t dct, u32 index_reg); -static void Get_WrDatGross_Diff(struct DCTStatStruc *pDCTstat, u8 dct, - u32 dev, u32 index_reg); -static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat, - u32 dev, uint8_t dct, u32 index_reg, u32 index); -static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static u16 Get_WrDatGross_MaxMin(struct DCTStatStruc *pDCTstat, u8 dct, - u32 dev, u32 index_reg, u32 index); -static void mct_InitialMCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_init(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void clear_legacy_Mode(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_HTMemMapExt(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void SetCSTriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void SetCKETriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void SetODTTriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void InitDDRPhy(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u32 mct_NodePresent_D(void); -static void mct_OtherTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void mct_ResetDataStruct_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_ProgramODT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -void mct_ClrClToNB_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static u8 CheckNBCOFEarlyArbEn(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -void mct_ClrWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void mct_BeforeDQSTrain_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA); -static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct); -static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static u32 mct_DisDllShutdownSR(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 DramConfigLo, u8 dct); -static void mct_EnDllShutdownSR(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -void ChangeMemClk(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); - -static u8 Get_Latency_Diff(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -static void SyncSetting(struct DCTStatStruc *pDCTstat); -static uint8_t crcCheck(struct DCTStatStruc *pDCTstat, uint8_t dimm); - -uint8_t is_ecc_enabled(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); - -/*See mctAutoInitMCT header for index relationships to CL and T*/ -static const u16 Table_F_k[] = {00,200,266,333,400,533 }; -static const u8 Tab_BankAddr[] = {0x3F,0x01,0x09,0x3F,0x3F,0x11,0x0A,0x19,0x12,0x1A,0x21,0x22,0x23}; -const u8 Table_DQSRcvEn_Offset[] = {0x00,0x01,0x10,0x11,0x2}; - -/**************************************************************************** - Describe how platform maps MemClk pins to logical DIMMs. The MemClk pins - are identified based on BKDG definition of Fn2x88[MemClkDis] bitmap. - AGESA will base on this value to disable unused MemClk to save power. - - If MEMCLK_MAPPING or MEMCLK_MAPPING contains all zeroes, AGESA will use - default MemClkDis setting based on package type. - - Example: - BKDG definition of Fn2x88[MemClkDis] bitmap for AM3 package is like below: - Bit AM3/S1g3 pin name - 0 M[B,A]_CLK_H/L[0] - 1 M[B,A]_CLK_H/L[1] - 2 M[B,A]_CLK_H/L[2] - 3 M[B,A]_CLK_H/L[3] - 4 M[B,A]_CLK_H/L[4] - 5 M[B,A]_CLK_H/L[5] - 6 M[B,A]_CLK_H/L[6] - 7 M[B,A]_CLK_H/L[7] - - And platform has the following routing: - CS0 M[B,A]_CLK_H/L[4] - CS1 M[B,A]_CLK_H/L[2] - CS2 M[B,A]_CLK_H/L[3] - CS3 M[B,A]_CLK_H/L[5] - - Then: - ; CS0 CS1 CS2 CS3 CS4 CS5 CS6 CS7 - MEMCLK_MAPPING EQU 00010000b, 00000100b, 00001000b, 00100000b, 00000000b, 00000000b, 00000000b, 00000000b -*/ - -/* ========================================================================================== - * Set up clock pin to DIMM mappings, - * NOTE: If you are not sure about the pin mappings, you can keep all MemClk signals active, - * just set all entries in the relevant table(s) to 0xff. - * ========================================================================================== - */ -static const u8 Tab_L1CLKDis[] = {0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04}; -static const u8 Tab_AM3CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; -static const u8 Tab_S1CLKDis[] = {0xA2, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -/* C32: Enable CS0 - CS3 clocks (DIMM0 - DIMM1) */ -static const u8 Tab_C32CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; - -/* G34: Enable CS0 - CS3 clocks (DIMM0 - DIMM1) */ -static const u8 Tab_G34CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; - -/* FM2: Enable all the clocks for the dimms */ -static const u8 Tab_FM2CLKDis[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}; - -static const u8 Tab_ManualCLKDis[]= {0x10, 0x04, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00}; -/* ========================================================================================== */ - -static const u8 Table_Comp_Rise_Slew_20x[] = {7, 3, 2, 2, 0xFF}; -static const u8 Table_Comp_Rise_Slew_15x[] = {7, 7, 3, 2, 0xFF}; -static const u8 Table_Comp_Fall_Slew_20x[] = {7, 5, 3, 2, 0xFF}; -static const u8 Table_Comp_Fall_Slew_15x[] = {7, 7, 5, 3, 0xFF}; - -uint8_t dct_ddr_voltage_index(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t dimm; - uint8_t ddr_voltage_index = 0; - - /* If no DIMMs are present on this DCT, report 1.5V operation and skip checking the hardware */ - if (pDCTstat->DIMMValidDCT[dct] == 0) - return 0x1; - - /* Find current DDR supply voltage for this DCT */ - for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) { - if (pDCTstat->DIMMValidDCT[dct] & (1 << dimm)) - ddr_voltage_index |= pDCTstat->DimmConfiguredVoltage[dimm]; - } - if (ddr_voltage_index > 0x7) { - printk(BIOS_DEBUG, "%s: Insufficient DDR supply voltage indicated! Configuring processor for 1.25V operation, but this attempt may fail...\n", __func__); - ddr_voltage_index = 0x4; - } - if (ddr_voltage_index == 0x0) { - printk(BIOS_DEBUG, "%s: No DDR supply voltage indicated! Configuring processor for 1.5V operation, but this attempt may fail...\n", __func__); - ddr_voltage_index = 0x1; - } - - return ddr_voltage_index; -} - -static uint16_t fam15h_mhz_to_memclk_config(uint16_t freq) -{ - 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 iter; - - /* Compute the index value for the given frequency */ - for (iter = 0; iter <= 0x16; iter++) { - if (fam15h_freq_tab[iter] == freq) { - freq = iter; - break; - } - } - if (freq == 0) - freq = 0x4; - - return freq; -} - -static uint16_t fam10h_mhz_to_memclk_config(uint16_t freq) -{ - uint16_t fam10h_freq_tab[] = {0, 0, 0, 400, 533, 667, 800}; - uint16_t iter; - - /* Compute the index value for the given frequency */ - for (iter = 0; iter <= 0x6; iter++) { - if (fam10h_freq_tab[iter] == freq) { - freq = iter; - break; - } - } - if (freq == 0) - freq = 0x3; - - return freq; -} - -static inline uint8_t is_model10_1f(void) -{ - uint8_t model101f = 0; - uint32_t family; - - family = cpuid_eax(0x80000001); - family = ((family & 0x0ff000) >> 12); - - if (family >= 0x10 && family <= 0x1f) - /* Model 0x10 to 0x1f */ - model101f = 1; - - return model101f; -} - -uint8_t is_ecc_enabled(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) -{ - uint8_t ecc_enabled = 1; - - if (!pMCTstat->try_ecc) - ecc_enabled = 0; - - if (pDCTstat->NodePresent && (pDCTstat->DIMMValidDCT[0] || pDCTstat->DIMMValidDCT[1])) - if (!(pDCTstat->Status & (1 << SB_ECCDIMMs))) - ecc_enabled = 0; - - return !!ecc_enabled; -} - -uint8_t get_available_lane_count(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) -{ - if (is_ecc_enabled(pMCTstat, pDCTstat)) - return 9; - else - return 8; -} - -uint16_t mhz_to_memclk_config(uint16_t freq) -{ - if (is_fam15h()) - return fam15h_mhz_to_memclk_config(freq); - else - return fam10h_mhz_to_memclk_config(freq) + 1; -} - -uint32_t fam10h_address_timing_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - uint8_t package_type; - uint32_t calibration_code = 0; - - package_type = mctGet_NVbits(NV_PACK_TYPE); - uint16_t MemClkFreq = (Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x7) + 1; - - /* Obtain number of DIMMs on channel */ - uint8_t dimm_count = pDCTstat->MAdimms[dct]; - uint8_t rank_count_dimm0; - uint8_t rank_count_dimm1; - - if (package_type == PT_GR) { - /* Socket G34 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam10h BKDG Rev. 3.62 section 2.8.9.5.8 Tables 60 - 61 */ - if (MaxDimmsInstallable == 1) { - if (MemClkFreq == 0x4) { - /* DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0x5) { - /* DDR3-1066 */ - calibration_code = 0x003c3c3c; - } else if (MemClkFreq == 0x6) { - /* DDR3-1333 */ - calibration_code = 0x003a3a3a; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - if (MemClkFreq == 0x4) { - /* DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0x5) { - /* DDR3-1066 */ - calibration_code = 0x003c3c3c; - } else if (MemClkFreq == 0x6) { - /* DDR3-1333 */ - calibration_code = 0x003a3a3a; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - if (MemClkFreq == 0x4) { - /* DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0x5) { - /* DDR3-1066 */ - calibration_code = 0x003a3c3a; - } else if (MemClkFreq == 0x6) { - /* DDR3-1333 */ - calibration_code = 0x00383a38; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else { - /* UDIMM */ - /* Fam10h BKDG Rev. 3.62 section 2.8.9.5.8 Table 56 */ - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-800 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x003b0000; - } else if (MemClkFreq == 0x5) { - /* DDR3-1066 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x00380000; - } else if (MemClkFreq == 0x6) { - /* DDR3-1333 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x00360000; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-800 */ - calibration_code = 0x00390039; - } else if (MemClkFreq == 0x5) { - /* DDR3-1066 */ - calibration_code = 0x00350037; - } else if (MemClkFreq == 0x6) { - /* DDR3-1333 */ - calibration_code = 0x00000035; - } - } - } - } else { - /* TODO - * Other socket support unimplemented - */ - } - - return calibration_code; -} - -static uint32_t fam15h_phy_predriver_calibration_code(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t drive_strength) -{ - uint8_t lrdimm = 0; - uint8_t package_type; - uint8_t ddr_voltage_index; - uint32_t calibration_code = 0; - uint16_t MemClkFreq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f; - - ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct); - package_type = mctGet_NVbits(NV_PACK_TYPE); - - if (!lrdimm) { - /* Not an LRDIMM */ - if ((package_type == PT_M2) || (package_type == PT_GR)) { - /* Socket AM3 or G34 */ - if (ddr_voltage_index & 0x4) { - /* 1.25V */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 43 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0xb6d; - else if (drive_strength == 0x2) - calibration_code = 0x924; - else if (drive_strength == 0x3) - calibration_code = 0x6db; - } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0xfff; - else if (drive_strength == 0x2) - calibration_code = 0xdb6; - else if (drive_strength == 0x3) - calibration_code = 0x924; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0xfff; - else if (drive_strength == 0x2) - calibration_code = 0xfff; - else if (drive_strength == 0x3) - calibration_code = 0xfff; - } - } else if (ddr_voltage_index & 0x2) { - /* 1.35V */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 42 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0x924; - else if (drive_strength == 0x2) - calibration_code = 0x6db; - else if (drive_strength == 0x3) - calibration_code = 0x492; - } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0xdb6; - else if (drive_strength == 0x2) - calibration_code = 0xbd6; - else if (drive_strength == 0x3) - calibration_code = 0x6db; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0xfff; - else if (drive_strength == 0x2) - calibration_code = 0xfff; - else if (drive_strength == 0x3) - calibration_code = 0xdb6; - } - } else if (ddr_voltage_index & 0x1) { - /* 1.5V */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 41 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (drive_strength == 0x0) - calibration_code = 0xb6d; - else if (drive_strength == 0x1) - calibration_code = 0x6db; - else if (drive_strength == 0x2) - calibration_code = 0x492; - else if (drive_strength == 0x3) - calibration_code = 0x492; - } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0x924; - else if (drive_strength == 0x2) - calibration_code = 0x6db; - else if (drive_strength == 0x3) - calibration_code = 0x6db; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0xfff; - else if (drive_strength == 0x2) - calibration_code = 0xfff; - else if (drive_strength == 0x3) - calibration_code = 0xb6d; - } - } - } else if (package_type == PT_C3) { - /* Socket C32 */ - if (ddr_voltage_index & 0x4) { - /* 1.25V */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 46 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0xb6d; - else if (drive_strength == 0x2) - calibration_code = 0x924; - else if (drive_strength == 0x3) - calibration_code = 0x6db; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0xfff; - else if (drive_strength == 0x2) - calibration_code = 0xdb6; - else if (drive_strength == 0x3) - calibration_code = 0x924; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - if (drive_strength == 0x0) - calibration_code = 0xb6d; - else if (drive_strength == 0x1) - calibration_code = 0x6db; - else if (drive_strength == 0x2) - calibration_code = 0x492; - else if (drive_strength == 0x3) - calibration_code = 0x492; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0xfff; - else if (drive_strength == 0x2) - calibration_code = 0xfff; - else if (drive_strength == 0x3) - calibration_code = 0xfff; - } - } else if (ddr_voltage_index & 0x2) { - /* 1.35V */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 45 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0x924; - else if (drive_strength == 0x2) - calibration_code = 0x6db; - else if (drive_strength == 0x3) - calibration_code = 0x492; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0xdb6; - else if (drive_strength == 0x2) - calibration_code = 0xb6d; - else if (drive_strength == 0x3) - calibration_code = 0x6db; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0x924; - else if (drive_strength == 0x2) - calibration_code = 0x6db; - else if (drive_strength == 0x3) - calibration_code = 0x492; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0xfff; - else if (drive_strength == 0x2) - calibration_code = 0xfff; - else if (drive_strength == 0x3) - calibration_code = 0xdb6; - } - } else if (ddr_voltage_index & 0x1) { - /* 1.5V */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 44 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (drive_strength == 0x0) - calibration_code = 0xb6d; - else if (drive_strength == 0x1) - calibration_code = 0x6db; - else if (drive_strength == 0x2) - calibration_code = 0x492; - else if (drive_strength == 0x3) - calibration_code = 0x492; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0x924; - else if (drive_strength == 0x2) - calibration_code = 0x6db; - else if (drive_strength == 0x3) - calibration_code = 0x6db; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - if (drive_strength == 0x0) - calibration_code = 0xb6d; - else if (drive_strength == 0x1) - calibration_code = 0x6db; - else if (drive_strength == 0x2) - calibration_code = 0x492; - else if (drive_strength == 0x3) - calibration_code = 0x492; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (drive_strength == 0x0) - calibration_code = 0xfff; - else if (drive_strength == 0x1) - calibration_code = 0xfff; - else if (drive_strength == 0x2) - calibration_code = 0xfff; - else if (drive_strength == 0x3) - calibration_code = 0xb6d; - } - } - } else if (package_type == PT_FM2) { - /* Socket FM2 */ - if (ddr_voltage_index & 0x1) { - /* 1.5V */ - /* Fam15h BKDG Rev. 3.12 section 2.9.5.4.4 Table 22 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0xb24; - } else if (MemClkFreq >= 0xa) { - /* DDR3-1066 or higher */ - calibration_code = 0xff6; - } - } - } - } else { - /* LRDIMM */ - - /* TODO - * Implement LRDIMM support - * See Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Tables 47 - 49 - */ - } - - return calibration_code; -} - -static uint32_t fam15h_phy_predriver_cmd_addr_calibration_code(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t drive_strength) -{ - uint8_t ddr_voltage_index; - uint32_t calibration_code = 0; - uint16_t MemClkFreq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f; - - ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct); - - if (ddr_voltage_index & 0x4) { - /* 1.25V */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 52 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (drive_strength == 0x0) - calibration_code = 0x492; - else if (drive_strength == 0x1) - calibration_code = 0x492; - else if (drive_strength == 0x2) - calibration_code = 0x492; - else if (drive_strength == 0x3) - calibration_code = 0x492; - } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (drive_strength == 0x0) - calibration_code = 0xdad; - else if (drive_strength == 0x1) - calibration_code = 0x924; - else if (drive_strength == 0x2) - calibration_code = 0x6db; - else if (drive_strength == 0x3) - calibration_code = 0x492; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (drive_strength == 0x0) - calibration_code = 0xff6; - else if (drive_strength == 0x1) - calibration_code = 0xdad; - else if (drive_strength == 0x2) - calibration_code = 0xb64; - else if (drive_strength == 0x3) - calibration_code = 0xb64; - } - } else if (ddr_voltage_index & 0x2) { - /* 1.35V */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 51 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (drive_strength == 0x0) - calibration_code = 0x492; - else if (drive_strength == 0x1) - calibration_code = 0x492; - else if (drive_strength == 0x2) - calibration_code = 0x492; - else if (drive_strength == 0x3) - calibration_code = 0x492; - } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (drive_strength == 0x0) - calibration_code = 0x924; - else if (drive_strength == 0x1) - calibration_code = 0x6db; - else if (drive_strength == 0x2) - calibration_code = 0x6db; - else if (drive_strength == 0x3) - calibration_code = 0x6db; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (drive_strength == 0x0) - calibration_code = 0xb6d; - else if (drive_strength == 0x1) - calibration_code = 0xb6d; - else if (drive_strength == 0x2) - calibration_code = 0x924; - else if (drive_strength == 0x3) - calibration_code = 0x924; - } - } else if (ddr_voltage_index & 0x1) { - /* 1.5V */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 50 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (drive_strength == 0x0) - calibration_code = 0x492; - else if (drive_strength == 0x1) - calibration_code = 0x492; - else if (drive_strength == 0x2) - calibration_code = 0x492; - else if (drive_strength == 0x3) - calibration_code = 0x492; - } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (drive_strength == 0x0) - calibration_code = 0x6db; - else if (drive_strength == 0x1) - calibration_code = 0x6db; - else if (drive_strength == 0x2) - calibration_code = 0x6db; - else if (drive_strength == 0x3) - calibration_code = 0x6db; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (drive_strength == 0x0) - calibration_code = 0xb6d; - else if (drive_strength == 0x1) - calibration_code = 0xb6d; - else if (drive_strength == 0x2) - calibration_code = 0xb6d; - else if (drive_strength == 0x3) - calibration_code = 0xb6d; - } - } - - return calibration_code; -} - -static uint32_t fam15h_phy_predriver_clk_calibration_code(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t drive_strength) -{ - uint8_t ddr_voltage_index; - uint32_t calibration_code = 0; - uint16_t MemClkFreq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f; - - ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct); - - if (ddr_voltage_index & 0x4) { - /* 1.25V */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 55 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (drive_strength == 0x0) - calibration_code = 0xdad; - else if (drive_strength == 0x1) - calibration_code = 0xdad; - else if (drive_strength == 0x2) - calibration_code = 0x924; - else if (drive_strength == 0x3) - calibration_code = 0x924; - } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (drive_strength == 0x0) - calibration_code = 0xff6; - else if (drive_strength == 0x1) - calibration_code = 0xff6; - else if (drive_strength == 0x2) - calibration_code = 0xff6; - else if (drive_strength == 0x3) - calibration_code = 0xff6; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (drive_strength == 0x0) - calibration_code = 0xff6; - else if (drive_strength == 0x1) - calibration_code = 0xff6; - else if (drive_strength == 0x2) - calibration_code = 0xff6; - else if (drive_strength == 0x3) - calibration_code = 0xff6; - } - } else if (ddr_voltage_index & 0x2) { - /* 1.35V */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 54 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (drive_strength == 0x0) - calibration_code = 0xdad; - else if (drive_strength == 0x1) - calibration_code = 0xdad; - else if (drive_strength == 0x2) - calibration_code = 0x924; - else if (drive_strength == 0x3) - calibration_code = 0x924; - } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (drive_strength == 0x0) - calibration_code = 0xff6; - else if (drive_strength == 0x1) - calibration_code = 0xff6; - else if (drive_strength == 0x2) - calibration_code = 0xff6; - else if (drive_strength == 0x3) - calibration_code = 0xdad; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (drive_strength == 0x0) - calibration_code = 0xff6; - else if (drive_strength == 0x1) - calibration_code = 0xff6; - else if (drive_strength == 0x2) - calibration_code = 0xff6; - else if (drive_strength == 0x3) - calibration_code = 0xdad; - } - } else if (ddr_voltage_index & 0x1) { - /* 1.5V */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 53 */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (drive_strength == 0x0) - calibration_code = 0x924; - else if (drive_strength == 0x1) - calibration_code = 0x924; - else if (drive_strength == 0x2) - calibration_code = 0x924; - else if (drive_strength == 0x3) - calibration_code = 0x924; - } else if ((MemClkFreq == 0xa) || (MemClkFreq == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (drive_strength == 0x0) - calibration_code = 0xff6; - else if (drive_strength == 0x1) - calibration_code = 0xff6; - else if (drive_strength == 0x2) - calibration_code = 0xff6; - else if (drive_strength == 0x3) - calibration_code = 0xb6d; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (drive_strength == 0x0) - calibration_code = 0xff6; - else if (drive_strength == 0x1) - calibration_code = 0xff6; - else if (drive_strength == 0x2) - calibration_code = 0xff6; - else if (drive_strength == 0x3) - calibration_code = 0xff6; - } - } - - return calibration_code; -} - -uint32_t fam15h_output_driver_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - uint8_t package_type; - uint32_t calibration_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]; - uint8_t rank_count_dimm0; - uint8_t rank_count_dimm1; - - if (package_type == PT_GR) { - /* Socket G34 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 74 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x00112222; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x10112222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x20112222; - } else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) { - /* DDR3-1333 - DDR3-1600 */ - calibration_code = 0x30112222; - } else if (MemClkFreq == 0x16) { - /* DDR3-1866 */ - calibration_code = 0x30332222; - } - - if (rank_count_dimm0 == 4) { - calibration_code &= ~(0xff << 16); - calibration_code |= 0x22 << 16; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (dimm_count == 1) { - /* 1 DIMM detected */ - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x00112222; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x10112222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x20112222; - } else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) { - /* DDR3-1333 - DDR3-1600 */ - calibration_code = 0x30112222; - } - - if ((rank_count_dimm0 == 4) || (rank_count_dimm1 == 4)) { - calibration_code &= ~(0xff << 16); - calibration_code |= 0x22 << 16; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x10222222; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x20222222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x30222222; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x30222222; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - calibration_code = 0x30222222; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - /* TODO - * LRDIMM support unimplemented - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 73 */ - if (MaxDimmsInstallable == 1) { - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x00112222; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x10112222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x20112222; - } else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) { - /* DDR3-1333 - DDR3-1600 */ - calibration_code = 0x30112222; - } else if (MemClkFreq == 0x16) { - /* DDR3-1866 */ - calibration_code = 0x30332222; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x00112222; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x10112222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x20112222; - } else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) { - /* DDR3-1333 - DDR3-1600 */ - calibration_code = 0x30112222; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x10222222; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x20222222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x30222222; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x30222222; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - calibration_code = 0x30222222; - else - calibration_code = 0x30112222; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_C3) { - /* Socket C32 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 77 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x00112222; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x10112222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x20112222; - } else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) { - /* DDR3-1333 - DDR3-1600 */ - calibration_code = 0x30112222; - } - - if (rank_count_dimm0 == 4) { - calibration_code &= ~(0xff << 16); - calibration_code |= 0x22 << 16; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (dimm_count == 1) { - /* 1 DIMM detected */ - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x00112222; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x10112222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x20112222; - } else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) { - /* DDR3-1333 - DDR3-1600 */ - calibration_code = 0x30112222; - } - - if ((rank_count_dimm0 == 4) || (rank_count_dimm1 == 4)) { - calibration_code &= ~(0xff << 16); - calibration_code |= 0x22 << 16; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x10222222; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x20222222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x30222222; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x30222222; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - calibration_code = 0x30222222; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - /* TODO - * LRDIMM support unimplemented - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 73 */ - if (MaxDimmsInstallable == 1) { - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x00112222; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x10112222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x20112222; - } else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) { - /* DDR3-1333 - DDR3-1600 */ - calibration_code = 0x30112222; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x00112222; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x10112222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x20112222; - } else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) { - /* DDR3-1333 - DDR3-1600 */ - calibration_code = 0x30112222; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x10222222; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x20222222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x30222222; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x30222222; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - calibration_code = 0x30222222; - else - calibration_code = 0x30112222; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_FM2) { - /* Socket FM2 */ - /* Assume UDIMM */ - /* Fam15h Model10h BKDG Rev. 3.12 section 2.9.5.6.6 Table 32 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x00112222; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x10112222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x20112222; - } else if (MemClkFreq >= 0xe) { - /* DDR3-1333 or higher */ - calibration_code = 0x30112222; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (dimm_count == 1) { - /* 1 DIMM detected */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 or DDR3-800 */ - calibration_code = 0x00112222; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x10112222; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x20112222; - } else if (MemClkFreq >= 0x12) { - /* DDR3-1600 or higher */ - calibration_code = 0x30112222; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x10222322; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x20222322; - } else if (MemClkFreq >= 0xa) { - /* DDR3-1066 or higher */ - calibration_code = 0x30222322; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else { - /* TODO - * Other socket support unimplemented - */ - } - - return calibration_code; -} - -uint32_t fam15h_address_timing_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - uint8_t package_type; - uint32_t calibration_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]; - uint8_t rank_count_dimm0; - uint8_t rank_count_dimm1; - - if (package_type == PT_GR) { - /* Socket G34 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 74 */ - if (MaxDimmsInstallable == 1) { - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x003c3c3c; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x003a3a3a; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - calibration_code = 0x00393939; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x00393c39; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00373a37; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - calibration_code = 0x00363936; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x003a3c3a; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00383a38; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - calibration_code = 0x00353935; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - /* TODO - * LRDIMM support unimplemented - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 76 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x003b0000; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x003b0000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x00383837; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00363635; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00353533; - else - calibration_code = 0x00003533; - } else if (MemClkFreq == 0x16) { - /* DDR3-1866 */ - calibration_code = 0x00333330; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x003b0000; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x003b0000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x00383837; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00363635; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00353533; - else - calibration_code = 0x00003533; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x00390039; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x00390039; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x003a3a3a; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00003939; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - calibration_code = 0x00003738; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_C3) { - /* Socket C32 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 77 */ - if (MaxDimmsInstallable == 1) { - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x003c3c3c; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x003a3a3a; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - calibration_code = 0x00393939; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x00393c39; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00373a37; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - calibration_code = 0x00363936; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 - DDR3-800 */ - calibration_code = 0x00000000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x003a3c3a; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00383a38; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - calibration_code = 0x00353935; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - /* TODO - * LRDIMM support unimplemented - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 76 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x003b0000; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x003b0000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x00383837; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00363635; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00353533; - else - calibration_code = 0x00003533; - } else if (MemClkFreq == 0x16) { - /* DDR3-1866 */ - calibration_code = 0x00333330; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x003b0000; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x003b0000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x00383837; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00363635; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00353533; - else - calibration_code = 0x00003533; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (MemClkFreq == 0x4) { - /* DDR3-667 */ - calibration_code = 0x00390039; - } else if (MemClkFreq == 0x6) { - /* DDR3-800 */ - calibration_code = 0x00390039; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x003a3a3a; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00003939; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - calibration_code = 0x00003738; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_FM2) { - /* Socket FM2 */ - /* Assume UDIMM */ - /* Fam15h Model10h BKDG Rev. 3.12 section 2.9.5.6.6 Table 32 */ - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 or DDR3-800 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x003b0000; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x00380000; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - if (rank_count_dimm0 == 1) - calibration_code = 0x00000000; - else - calibration_code = 0x00360000; - } else if (MemClkFreq >= 0x12) { - /* DDR3-1600 or higher */ - calibration_code = 0x00000000; - } - - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)) { - /* DDR3-667 or DDR3-800 */ - calibration_code = 0x00390039; - } else if (MemClkFreq == 0xa) { - /* DDR3-1066 */ - calibration_code = 0x00350037; - } else if (MemClkFreq == 0xe) { - /* DDR3-1333 */ - calibration_code = 0x00000035; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - calibration_code = 0x0000002b; - } else if (MemClkFreq > 0x12) { - /* DDR3-1866 or greater */ - calibration_code = 0x00000031; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else { - /* TODO - * Other socket support unimplemented - */ - } - - return calibration_code; -} - -uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - uint8_t package_type; - uint32_t slow_access = 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]; - uint8_t rank_count_dimm0; - uint8_t rank_count_dimm1; - - if (package_type == PT_GR) { - /* Socket G34 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 74 */ - slow_access = 0; - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 75 */ - slow_access = 0; - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 73 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6) - || (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) { - /* DDR3-667 - DDR3-1333 */ - slow_access = 0; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (rank_count_dimm0 == 1) - slow_access = 0; - else - slow_access = 1; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6) - || (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) { - /* DDR3-667 - DDR3-1333 */ - slow_access = 0; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - if (rank_count_dimm0 == 1) - slow_access = 0; - else - slow_access = 1; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6) - || (MemClkFreq == 0xa)) { - /* DDR3-667 - DDR3-1066 */ - slow_access = 0; - } else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) { - /* DDR3-1333 - DDR3-1600 */ - slow_access = 1; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_C3) { - /* Socket C32 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 77 */ - slow_access = 0; - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 78 */ - slow_access = 0; - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 76 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6) - || (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) { - /* DDR3-667 - DDR3-1333 */ - slow_access = 0; - } else if ((MemClkFreq == 0x12) || (MemClkFreq == 0x16)) { - /* DDR3-1600 - DDR3-1866 */ - if (rank_count_dimm0 == 1) - slow_access = 0; - else - slow_access = 1; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6) - || (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) { - /* DDR3-667 - DDR3-1333 */ - slow_access = 0; - } else if (MemClkFreq == 0x12) { - /* DDR3-1600 */ - if (rank_count_dimm0 == 1) - slow_access = 0; - else - slow_access = 1; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6) - || (MemClkFreq == 0xa)) { - /* DDR3-667 - DDR3-1066 */ - slow_access = 0; - } else if ((MemClkFreq == 0xe) || (MemClkFreq == 0x12)) { - /* DDR3-1333 - DDR3-1600 */ - slow_access = 1; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_FM2) { - /* Socket FM2 */ - /* UDIMM */ - /* Fam15h Model10 BKDG Rev. 3.12 section 2.9.5.6.6 Table 32 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6) - || (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) { - /* DDR3-667 - DDR3-1333 */ - slow_access = 0; - } else if (MemClkFreq >= 0x12) { - /* DDR3-1600 or higher */ - if (rank_count_dimm0 == 1) - slow_access = 0; - else - slow_access = 1; - } - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6) - || (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) { - /* DDR3-667 - DDR3-1333 */ - slow_access = 0; - } else if (MemClkFreq >= 0x12) { - /* DDR3-1600 or higher */ - if (rank_count_dimm0 == 1) - slow_access = 0; - else - slow_access = 1; - } - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6) - || (MemClkFreq == 0xa)) { - /* DDR3-667 - DDR3-1066 */ - slow_access = 0; - } else if (MemClkFreq >= 0xe) { - /* DDR3-1333 or higher */ - slow_access = 1; - } - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else { - /* TODO - * Other socket support unimplemented - */ - } - - return slow_access; -} - -static uint8_t fam15h_odt_tristate_enable_code(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - uint8_t package_type; - uint8_t odt_tristate_code = 0; - - package_type = mctGet_NVbits(NV_PACK_TYPE); - - /* Obtain number of DIMMs on channel */ - uint8_t dimm_count = pDCTstat->MAdimms[dct]; - uint8_t rank_count_dimm0; - uint8_t rank_count_dimm1; - - if (package_type == PT_GR) { - /* Socket G34 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 104 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - odt_tristate_code = 0xe; - else - odt_tristate_code = 0xa; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm1 == 1) - odt_tristate_code = 0xd; - else - odt_tristate_code = 0x5; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0xc; - else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 >= 2)) - odt_tristate_code = 0x4; - else if ((rank_count_dimm0 >= 2) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0x8; - else - odt_tristate_code = 0x0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - - /* TODO - * Implement LRDIMM support - * See Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 105 - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 103 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - odt_tristate_code = 0xe; - else - odt_tristate_code = 0xa; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - odt_tristate_code = 0xd; - else - odt_tristate_code = 0x5; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0xc; - else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 2)) - odt_tristate_code = 0x4; - else if ((rank_count_dimm0 == 2) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0x8; - else - odt_tristate_code = 0x0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_C3) { - /* Socket C32 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 107 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - odt_tristate_code = 0xe; - else - odt_tristate_code = 0xa; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm1 == 1) - odt_tristate_code = 0xd; - else - odt_tristate_code = 0x5; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0xc; - else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 >= 2)) - odt_tristate_code = 0x4; - else if ((rank_count_dimm0 >= 2) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0x8; - else - odt_tristate_code = 0x0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - - /* TODO - * Implement LRDIMM support - * See Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 108 - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 106 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - odt_tristate_code = 0xe; - else - odt_tristate_code = 0xa; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - odt_tristate_code = 0xd; - else - odt_tristate_code = 0x5; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0xc; - else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 2)) - odt_tristate_code = 0x4; - else if ((rank_count_dimm0 == 2) && (rank_count_dimm1 == 1)) - odt_tristate_code = 0x8; - else - odt_tristate_code = 0x0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_FM2) { - /* Socket FM2 */ - /* UDIMM */ - odt_tristate_code = 0x0; - } else { - /* TODO - * Other socket support unimplemented - */ - } - - return odt_tristate_code; -} - -static uint8_t fam15h_cs_tristate_enable_code(struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - uint8_t package_type; - uint8_t cs_tristate_code = 0; - - package_type = mctGet_NVbits(NV_PACK_TYPE); - - /* Obtain number of DIMMs on channel */ - uint8_t dimm_count = pDCTstat->MAdimms[dct]; - uint8_t rank_count_dimm0; - uint8_t rank_count_dimm1; - - if (package_type == PT_GR) { - /* Socket G34 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 104 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 < 4) - cs_tristate_code = 0xfc; - else - cs_tristate_code = 0xcc; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm1 < 4) - cs_tristate_code = 0xf3; - else - cs_tristate_code = 0x33; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - cs_tristate_code = 0xf0; - else if ((rank_count_dimm0 < 4) && (rank_count_dimm1 == 4)) - cs_tristate_code = 0x30; - else if ((rank_count_dimm0 == 4) && (rank_count_dimm1 < 4)) - cs_tristate_code = 0xc0; - else - cs_tristate_code = 0x0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - - /* TODO - * Implement LRDIMM support - * See Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 105 - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 103 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - cs_tristate_code = 0xfe; - else - cs_tristate_code = 0xfc; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - cs_tristate_code = 0xfb; - else - cs_tristate_code = 0xf3; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - cs_tristate_code = 0xfa; - else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 2)) - cs_tristate_code = 0xf2; - else if ((rank_count_dimm0 == 2) && (rank_count_dimm1 == 1)) - cs_tristate_code = 0xf8; - else - cs_tristate_code = 0xf0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_C3) { - /* Socket C32 */ - if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 107 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 < 4) - cs_tristate_code = 0xfc; - else - cs_tristate_code = 0xcc; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm1 < 4) - cs_tristate_code = 0xf3; - else - cs_tristate_code = 0x33; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - cs_tristate_code = 0xf0; - else if ((rank_count_dimm0 < 4) && (rank_count_dimm1 == 4)) - cs_tristate_code = 0x30; - else if ((rank_count_dimm0 == 4) && (rank_count_dimm1 < 4)) - cs_tristate_code = 0xc0; - else - cs_tristate_code = 0x0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - - /* TODO - * Implement LRDIMM support - * See Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 108 - */ - } else { - /* UDIMM */ - /* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 106 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - cs_tristate_code = 0xfe; - else - cs_tristate_code = 0xfc; - } else if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if (rank_count_dimm0 == 1) - cs_tristate_code = 0xfb; - else - cs_tristate_code = 0xf3; - } else if (dimm_count == 2) { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1)) - cs_tristate_code = 0xfa; - else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 2)) - cs_tristate_code = 0xf2; - else if ((rank_count_dimm0 == 2) && (rank_count_dimm1 == 1)) - cs_tristate_code = 0xf8; - else - cs_tristate_code = 0xf0; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } - } else if (package_type == PT_FM2) { - /* Socket FM2 */ - /* UDIMM */ - cs_tristate_code = 0x0; - } else { - /* TODO - * Other socket support unimplemented - */ - } - - return cs_tristate_code; -} - -void set_2t_configuration(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - uint32_t dev; - uint32_t reg; - uint32_t dword; - - uint8_t enable_slow_access_mode = 0; - dev = pDCTstat->dev_dct; - - if (is_fam15h()) { - if (pDCTstat->_2Tmode) - enable_slow_access_mode = 1; - } else { - if (pDCTstat->_2Tmode == 2) - enable_slow_access_mode = 1; - } - - reg = 0x94; /* DRAM Configuration High */ - dword = Get_NB32_DCT(dev, dct, reg); - if (enable_slow_access_mode) - dword |= (0x1 << 20); /* Set 2T CMD mode */ - else - dword &= ~(0x1 << 20); /* Clear 2T CMD mode */ - Set_NB32_DCT(dev, dct, reg, dword); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -void precise_ndelay_fam15(struct MCTStatStruc *pMCTstat, uint32_t nanoseconds) { - msr_t tsc_msr; - uint64_t cycle_count = (((uint64_t)pMCTstat->TSCFreq) * nanoseconds) / 1000; - uint64_t start_timestamp; - uint64_t current_timestamp; - - tsc_msr = rdmsr(TSC_MSR); - start_timestamp = (((uint64_t)tsc_msr.hi) << 32) | tsc_msr.lo; - do { - tsc_msr = rdmsr(TSC_MSR); - current_timestamp = (((uint64_t)tsc_msr.hi) << 32) | tsc_msr.lo; - } while ((current_timestamp - start_timestamp) < cycle_count); -} - -void precise_memclk_delay_fam15(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, uint32_t clocks) { - uint16_t memclk_freq; - uint32_t delay_ns; - 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}; - - memclk_freq = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f; - - if (fam15h_freq_tab[memclk_freq] == 0) { - printk(BIOS_DEBUG, "ERROR: precise_memclk_delay_fam15 for DCT %d (delay %d clocks) failed to obtain valid memory frequency!" - " (pDCTstat: %p pDCTstat->dev_dct: %08x memclk_freq: %02x)\n", dct, clocks, pDCTstat, pDCTstat->dev_dct, memclk_freq); - } - delay_ns = (((uint64_t)clocks * 1000) / fam15h_freq_tab[memclk_freq]); - precise_ndelay_fam15(pMCTstat, delay_ns); -} - -static void read_spd_bytes(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dimm) -{ - uint8_t addr; - uint16_t byte; - - addr = Get_DIMMAddress_D(pDCTstat, dimm); - pDCTstat->spd_data.spd_address[dimm] = addr; - - for (byte = 0; byte < 256; byte++) { - pDCTstat->spd_data.spd_bytes[dimm][byte] = mctRead_SPD(addr, byte); - } -} - -#ifdef DEBUG_DIMM_SPD -static void dump_spd_bytes(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dimm) -{ - uint16_t byte; - - printk(BIOS_DEBUG, "SPD dump for DIMM %d\n ", dimm); - for (byte = 0; byte < 16; byte++) { - printk(BIOS_DEBUG, "%02x ", byte); - } - for (byte = 0; byte < 256; byte++) { - if ((byte & 0xf) == 0x0) { - printk(BIOS_DEBUG, "\n%02x ", byte >> 4); - } - printk(BIOS_DEBUG, "%02x ", pDCTstat->spd_data.spd_bytes[dimm][byte]); - } - printk(BIOS_DEBUG, "\n"); -} -#endif - -static void set_up_cc6_storage_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t num_nodes) -{ - uint8_t interleaved; - uint8_t destination_node; - int8_t range; - int8_t max_range; - uint8_t max_node; - uint64_t max_range_limit; - uint8_t byte; - uint32_t dword; - uint32_t dword2; - uint64_t qword; - - interleaved = 0; - if (pMCTstat->GStatus & (1 << GSB_NodeIntlv)) - interleaved = 1; - - printk(BIOS_INFO, - "%s: Initializing CC6 DRAM storage area for node %d" - " (interleaved: %d)\n", - __func__, pDCTstat->Node_ID, interleaved); - - /* Find highest DRAM range (DramLimitAddr) */ - max_node = 0; - max_range = -1; - max_range_limit = 0; - for (range = 0; range < 8; range++) { - dword = Get_NB32(pDCTstat->dev_map, 0x40 + (range * 0x8)); - if (!(dword & 0x3)) - continue; - - dword = Get_NB32(pDCTstat->dev_map, 0x44 + (range * 0x8)); - dword2 = Get_NB32(pDCTstat->dev_map, 0x144 + (range * 0x8)); - qword = 0xffffff; - qword |= ((((uint64_t)dword) >> 16) & 0xffff) << 24; - qword |= (((uint64_t)dword2) & 0xff) << 40; - - if (qword > max_range_limit) { - max_range = range; - max_range_limit = qword; - max_node = dword & 0x7; - } - } - - if (max_range >= 0) { - printk(BIOS_INFO, - "%s:\toriginal (node %d) max_range_limit: %16llx DRAM" - " limit: %16llx\n", - __func__, max_node, max_range_limit, - (((uint64_t)(Get_NB32(pDCTstat->dev_map, 0x124) - & 0x1fffff)) << 27) | 0x7ffffff); - - if (interleaved) - /* Move upper limit down by 16M * the number of nodes */ - max_range_limit -= (0x1000000ULL * num_nodes); - else - /* Move upper limit down by 16M */ - max_range_limit -= 0x1000000ULL; - - printk(BIOS_INFO, "%s:\tnew max_range_limit: %16llx\n", - __func__, max_range_limit); - - /* Disable the range */ - dword = Get_NB32(pDCTstat->dev_map, 0x40 + (max_range * 0x8)); - byte = dword & 0x3; - dword &= ~(0x3); - Set_NB32(pDCTstat->dev_map, 0x40 + (max_range * 0x8), dword); - - /* Store modified range */ - dword = Get_NB32(pDCTstat->dev_map, 0x44 + (max_range * 0x8)); - dword &= ~(0xffff << 16); /* DramLimit[39:24] = max_range_limit[39:24] */ - dword |= ((max_range_limit >> 24) & 0xffff) << 16; - Set_NB32(pDCTstat->dev_map, 0x44 + (max_range * 0x8), dword); - - dword = Get_NB32(pDCTstat->dev_map, 0x144 + (max_range * 0x8)); - dword &= ~0xff; /* DramLimit[47:40] = max_range_limit[47:40] */ - dword |= (max_range_limit >> 40) & 0xff; - Set_NB32(pDCTstat->dev_map, 0x144 + (max_range * 0x8), dword); - - /* Reenable the range */ - dword = Get_NB32(pDCTstat->dev_map, 0x40 + (max_range * 0x8)); - dword |= byte; - Set_NB32(pDCTstat->dev_map, 0x40 + (max_range * 0x8), dword); - } - - /* Determine save state destination node */ - if (interleaved) - destination_node = Get_NB32(pDCTstat->dev_host, 0x60) & 0x7; - else - destination_node = max_node; - - /* Set save state destination node */ - dword = Get_NB32(pDCTstat->dev_link, 0x128); - dword &= ~(0x3f << 12); /* CoreSaveStateDestNode = destination_node */ - dword |= (destination_node & 0x3f) << 12; - Set_NB32(pDCTstat->dev_link, 0x128, dword); - - printk(BIOS_INFO, "%s:\tTarget node: %d\n", __func__, destination_node); - - printk(BIOS_INFO, "%s:\tDone\n", __func__); -} - -static void lock_dram_config(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - uint32_t dword; - - dword = Get_NB32(pDCTstat->dev_dct, 0x118); - dword |= 0x1 << 19; /* LockDramCfg = 1 */ - Set_NB32(pDCTstat->dev_dct, 0x118, dword); -} - -static void set_cc6_save_enable(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t enable) -{ - uint32_t dword; - - dword = Get_NB32(pDCTstat->dev_dct, 0x118); - dword &= ~(0x1 << 18); /* CC6SaveEn = enable */ - dword |= (enable & 0x1) << 18; - Set_NB32(pDCTstat->dev_dct, 0x118, dword); -} - -void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - /* - * Memory may be mapped contiguously all the way up to 4GB (depending on setup - * options). It is the responsibility of PCI subsystem to create an uncacheable - * IO region below 4GB and to adjust TOP_MEM downward prior to any IO mapping or - * accesses. It is the same responsibility of the CPU sub-system prior to - * accessing LAPIC. - * - * Slot Number is an external convention, and is determined by OEM with accompanying - * silk screening. OEM may choose to use Slot number convention which is consistent - * with DIMM number conventions. All AMD engineering platforms do. - * - * Build Requirements: - * 1. MCT_SEG0_START and MCT_SEG0_END macros to begin and end the code segment, - * defined in mcti.inc. - * - * Run-Time Requirements: - * 1. Complete Hypertransport Bus Configuration - * 2. SMBus Controller Initialized - * 1. BSP in Big Real Mode - * 2. Stack at SS:SP, located somewhere between A000:0000 and F000:FFFF - * 3. Checksummed or Valid NVRAM bits - * 4. MCG_CTL = -1, MC4_CTL_EN = 0 for all CPUs - * 5. MCi_STS from shutdown/warm reset recorded (if desired) prior to entry - * 6. All var MTRRs reset to zero - * 7. State of NB_CFG.DisDatMsk set properly on all CPUs - * 8. All CPUs at 2GHz Speed (unless DQS training is not installed). - * 9. All cHT links at max Speed/Width (unless DQS training is not installed). - * - * - * Global relationship between index values and item values: - * - * pDCTstat.CASL pDCTstat.Speed - * j CL(j) k F(k) - * -------------------------- - * 0 2.0 - - - * 1 3.0 1 200 MHz - * 2 4.0 2 266 MHz - * 3 5.0 3 333 MHz - * 4 6.0 4 400 MHz - * 5 7.0 5 533 MHz - * 6 8.0 6 667 MHz - * 7 9.0 7 800 MHz - */ - u8 Node, NodesWmem; - u32 node_sys_base; - uint8_t dimm; - uint8_t nvram; - uint8_t enable_cc6; - uint8_t ecc_enabled; - uint8_t allow_config_restore; - - uint8_t s3resume = acpi_is_wakeup_s3(); - -restartinit: - - if (!mctGet_NVbits(NV_ECC_CAP) || !mctGet_NVbits(NV_ECC)) - pMCTstat->try_ecc = 0; - else - pMCTstat->try_ecc = 1; - - mctInitMemGPIOs_A_D(); /* Set any required GPIOs*/ - if (s3resume) { - printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_ForceNBPState0_En_Fam15\n"); - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - mct_ForceNBPState0_En_Fam15(pMCTstat, pDCTstat); - } - -#if CONFIG(HAVE_ACPI_RESUME) - printk(BIOS_DEBUG, "mctAutoInitMCT_D: Restoring DCT configuration from NVRAM\n"); - if (restore_mct_information_from_nvram(0) != 0) - printk(BIOS_CRIT, "%s: ERROR: Unable to restore DCT configuration from NVRAM\n", __func__); - pMCTstat->GStatus |= 1 << GSB_ConfigRestored; -#endif - - if (is_fam15h()) { - printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_ForceNBPState0_Dis_Fam15\n"); - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - mct_ForceNBPState0_Dis_Fam15(pMCTstat, pDCTstat); - } - } - } else { - NodesWmem = 0; - node_sys_base = 0; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - /* Zero out data structures to avoid false detection of DIMMs */ - memset(pDCTstat, 0, sizeof(struct DCTStatStruc)); - - /* Initialize data structures */ - pDCTstat->Node_ID = Node; - pDCTstat->dev_host = PA_HOST(Node); - pDCTstat->dev_map = PA_MAP(Node); - pDCTstat->dev_dct = PA_DCT(Node); - pDCTstat->dev_nbmisc = PA_NBMISC(Node); - pDCTstat->dev_link = PA_LINK(Node); - pDCTstat->dev_nbctl = PA_NBCTL(Node); - pDCTstat->NodeSysBase = node_sys_base; - - if (mctGet_NVbits(NV_PACK_TYPE) == PT_GR) { - uint32_t dword; - pDCTstat->Dual_Node_Package = 1; - - /* Get the internal node number */ - dword = Get_NB32(pDCTstat->dev_nbmisc, 0xe8); - dword = (dword >> 30) & 0x3; - pDCTstat->Internal_Node_ID = dword; - } else { - pDCTstat->Dual_Node_Package = 0; - } - - printk(BIOS_DEBUG, "%s: mct_init Node %d\n", __func__, Node); - mct_init(pMCTstat, pDCTstat); - mctNodeIDDebugPort_D(); - pDCTstat->NodePresent = NodePresent_D(Node); - if (pDCTstat->NodePresent) { - pDCTstat->LogicalCPUID = mctGetLogicalCPUID_D(Node); - - printk(BIOS_DEBUG, "%s: mct_InitialMCT_D\n", __func__); - mct_InitialMCT_D(pMCTstat, pDCTstat); - - printk(BIOS_DEBUG, "%s: mctSMBhub_Init\n", __func__); - mctSMBhub_Init(Node); /* Switch SMBUS crossbar to proper node */ - - printk(BIOS_DEBUG, "%s: mct_preInitDCT\n", __func__); - mct_preInitDCT(pMCTstat, pDCTstat); - } - node_sys_base = pDCTstat->NodeSysBase; - node_sys_base += (pDCTstat->NodeSysLimit + 2) & ~0x0F; - } - - /* If the boot fails make sure training is attempted after reset */ - nvram = 0; - set_option("allow_spd_nvram_cache_restore", &nvram); - -#if CONFIG(DIMM_VOLTAGE_SET_SUPPORT) - printk(BIOS_DEBUG, "%s: DIMMSetVoltage\n", __func__); - DIMMSetVoltages(pMCTstat, pDCTstatA); /* Set the DIMM voltages (mainboard specific) */ -#endif - if (!CONFIG(DIMM_VOLTAGE_SET_SUPPORT)) { - /* Assume 1.5V operation */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (!pDCTstat->NodePresent) - continue; - - for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) { - if (pDCTstat->DIMMValid & (1 << dimm)) - pDCTstat->DimmConfiguredVoltage[dimm] = 0x1; - } - } - } - - /* If DIMM configuration has not changed since last boot restore training values */ - allow_config_restore = 1; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) - if (!pDCTstat->spd_data.nvram_spd_match) - allow_config_restore = 0; - } - - /* FIXME - * Stability issues have arisen on multiple Family 15h systems - * when configuration restoration is enabled. In all cases these - * stability issues resolved by allowing the RAM to go through a - * full training cycle. - * - * Debug and reenable this! - */ - allow_config_restore = 0; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - printk(BIOS_DEBUG, "%s: mctSMBhub_Init\n", __func__); - mctSMBhub_Init(Node); /* Switch SMBUS crossbar to proper node*/ - - printk(BIOS_DEBUG, "%s: mct_initDCT\n", __func__); - mct_initDCT(pMCTstat, pDCTstat); - if (pDCTstat->ErrCode == SC_FatalErr) { - goto fatalexit; /* any fatal errors?*/ - } else if (pDCTstat->ErrCode < SC_StopError) { - NodesWmem++; - } - } - } - if (NodesWmem == 0) { - printk(BIOS_ALERT, "Unable to detect valid memory on any nodes. Halting!\n"); - goto fatalexit; - } - - printk(BIOS_DEBUG, "mctAutoInitMCT_D: SyncDCTsReady_D\n"); - SyncDCTsReady_D(pMCTstat, pDCTstatA); /* Make sure DCTs are ready for accesses.*/ - - printk(BIOS_DEBUG, "mctAutoInitMCT_D: HTMemMapInit_D\n"); - HTMemMapInit_D(pMCTstat, pDCTstatA); /* Map local memory into system address space.*/ - mctHookAfterHTMap(); - - if (!is_fam15h()) { - printk(BIOS_DEBUG, "mctAutoInitMCT_D: CPUMemTyping_D\n"); - CPUMemTyping_D(pMCTstat, pDCTstatA); /* Map dram into WB/UC CPU cacheability */ - } - - printk(BIOS_DEBUG, "mctAutoInitMCT_D: mctHookAfterCPU\n"); - mctHookAfterCPU(); /* Setup external northbridge(s) */ - - /* FIXME - * Previous training values should only be used if the current desired - * speed is the same as the speed used in the previous boot. - * How to get the desired speed at this point in the code? - */ - - printk(BIOS_DEBUG, "mctAutoInitMCT_D: DQSTiming_D\n"); - DQSTiming_D(pMCTstat, pDCTstatA, allow_config_restore); /* Get Receiver Enable and DQS signal timing*/ - - if (!is_fam15h()) { - printk(BIOS_DEBUG, "mctAutoInitMCT_D: UMAMemTyping_D\n"); - UMAMemTyping_D(pMCTstat, pDCTstatA); /* Fix up for UMA sizing */ - } - - if (!allow_config_restore) { - printk(BIOS_DEBUG, "mctAutoInitMCT_D: :OtherTiming\n"); - mct_OtherTiming(pMCTstat, pDCTstatA); - } - - if (ReconfigureDIMMspare_D(pMCTstat, pDCTstatA)) { /* RESET# if 1st pass of DIMM spare enabled*/ - goto restartinit; - } - - InterleaveNodes_D(pMCTstat, pDCTstatA); - InterleaveChannels_D(pMCTstat, pDCTstatA); - - ecc_enabled = 1; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) - if (!is_ecc_enabled(pMCTstat, pDCTstat)) - ecc_enabled = 0; - } - - if (ecc_enabled) { - printk(BIOS_DEBUG, "mctAutoInitMCT_D: ECCInit_D\n"); - if (!ECCInit_D(pMCTstat, pDCTstatA)) { /* Setup ECC control and ECC check-bits*/ - /* Memory was not cleared during ECC setup */ - /* mctDoWarmResetMemClr_D(); */ - printk(BIOS_DEBUG, "mctAutoInitMCT_D: MCTMemClr_D\n"); - MCTMemClr_D(pMCTstat,pDCTstatA); - } - } - - if (is_fam15h()) { - printk(BIOS_DEBUG, "mctAutoInitMCT_D: CPUMemTyping_D\n"); - CPUMemTyping_D(pMCTstat, pDCTstatA); /* Map dram into WB/UC CPU cacheability */ - - printk(BIOS_DEBUG, "mctAutoInitMCT_D: UMAMemTyping_D\n"); - UMAMemTyping_D(pMCTstat, pDCTstatA); /* Fix up for UMA sizing */ - - printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_ForceNBPState0_Dis_Fam15\n"); - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - mct_ForceNBPState0_Dis_Fam15(pMCTstat, pDCTstat); - } - } - - if (is_fam15h()) { - enable_cc6 = 0; - if (get_option(&nvram, "cpu_cc6_state") == CB_SUCCESS) - enable_cc6 = !!nvram; - - if (enable_cc6) { - uint8_t num_nodes; - - num_nodes = 0; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) - num_nodes++; - } - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) - set_up_cc6_storage_fam15(pMCTstat, pDCTstat, num_nodes); - } - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - set_cc6_save_enable(pMCTstat, pDCTstat, 1); - lock_dram_config(pMCTstat, pDCTstat); - } - } - } - } - - mct_FinalMCT_D(pMCTstat, pDCTstatA); - printk(BIOS_DEBUG, "mctAutoInitMCT_D Done: Global Status: %x\n", pMCTstat->GStatus); - } - - return; - -fatalexit: - die("mct_d: fatalexit"); -} - -void initialize_mca(uint8_t bsp, uint8_t suppress_errors) { - uint8_t node; - uint32_t mc4_status_high; - uint32_t mc4_status_low; - - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - if (bsp && (node > 0)) - break; - - mc4_status_high = pci_read_config32(PCI_DEV(0, 0x18 + node, 3), 0x4c); - mc4_status_low = pci_read_config32(PCI_DEV(0, 0x18 + node, 3), 0x48); - if ((mc4_status_high & (0x1 << 31)) && (mc4_status_high != 0xffffffff)) { - if (!suppress_errors) - printk(BIOS_WARNING, "WARNING: 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(PCI_DEV(0, 0x18 + node, 3), 0x48, 0x0); - pci_write_config32(PCI_DEV(0, 0x18 + node, 3), 0x4c, 0x0); - } - } -} - -static u8 ReconfigureDIMMspare_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 ret; - - if (mctGet_NVbits(NV_CS_SpareCTL)) { - if (MCT_DIMM_SPARE_NO_WARM) { - /* Do no warm-reset DIMM spare */ - if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) { - LoadDQSSigTmgRegs_D(pMCTstat, pDCTstatA); - ret = 0; - } else { - mct_ResetDataStruct_D(pMCTstat, pDCTstatA); - pMCTstat->GStatus |= 1 << GSB_EnDIMMSpareNW; - ret = 1; - } - } else { - /* Do warm-reset DIMM spare */ - if (mctGet_NVbits(NV_DQSTrainCTL)) - mctWarmReset_D(); - ret = 0; - } - } else { - ret = 0; - } - - return ret; -} - -/* Enable or disable phy-assisted training mode - * Phy-assisted training mode applies to the follow DRAM training procedures: - * Write Levelization Training (2.10.5.8.1) - * DQS Receiver Enable Training (2.10.5.8.2) - */ -void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t enable) -{ - uint8_t index; - uint32_t dword; - uint32_t index_reg = 0x98; - uint32_t dev = pDCTstat->dev_dct; - - if (enable) { - /* Enable training mode */ - dword = Get_NB32_DCT(dev, dct, 0x78); /* DRAM Control */ - dword &= ~(0x1 << 17); /* AddrCmdTriEn = 0 */ - Set_NB32_DCT(dev, dct, 0x78, dword); /* DRAM Control */ - - dword = Get_NB32_DCT(dev, dct, 0x8c); /* DRAM Timing High */ - dword |= (0x1 << 18); /* DisAutoRefresh = 1 */ - Set_NB32_DCT(dev, dct, 0x8c, dword); /* DRAM Timing High */ - - dword = Get_NB32_DCT(dev, dct, 0x94); /* DRAM Configuration High */ - dword &= ~(0xf << 24); /* DcqBypassMax = 0 */ - dword &= ~(0x1 << 22); /* BankSwizzleMode = 0 */ - dword &= ~(0x1 << 15); /* PowerDownEn = 0 */ - dword &= ~(0x3 << 10); /* ZqcsInterval = 0 */ - Set_NB32_DCT(dev, dct, 0x94, dword); /* DRAM Configuration High */ - - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000d); - dword &= ~(0xf << 16); /* RxMaxDurDllNoLock = 0 */ - dword &= ~(0xf); /* TxMaxDurDllNoLock = 0 */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000d, dword); - - for (index = 0; index < 0x9; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0010 | (index << 8)); - dword &= ~(0x1 << 12); /* EnRxPadStandby = 0 */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0010 | (index << 8), dword); - } - - dword = Get_NB32_DCT(dev, dct, 0xa4); /* DRAM Controller Temperature Throttle */ - dword &= ~(0x1 << 11); /* BwCapEn = 0 */ - dword &= ~(0x1 << 8); /* ODTSEn = 0 */ - Set_NB32_DCT(dev, dct, 0xa4, dword); /* DRAM Controller Temperature Throttle */ - - dword = Get_NB32_DCT(dev, dct, 0x110); /* DRAM Controller Select Low */ - dword &= ~(0x1 << 2); /* DctSelIntLvEn = 0 */ - Set_NB32_DCT(dev, dct, 0x110, dword); /* DRAM Controller Select Low */ - - dword = Get_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x58); /* Scrub Rate Control */ - dword &= ~(0x1f << 24); /* L3Scrub = 0 */ - dword &= ~(0x1f); /* DramScrub = 0 */ - Set_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x58, dword); /* Scrub Rate Control */ - - dword = Get_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x5c); /* DRAM Scrub Address Low */ - dword &= ~(0x1); /* ScrubReDirEn = 0 */ - Set_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x5c, dword); /* DRAM Scrub Address Low */ - - dword = Get_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x1b8); /* L3 Control 1 */ - dword |= (0x1 << 4); /* L3ScrbRedirDis = 1 */ - Set_NB32_DCT(pDCTstat->dev_nbmisc, dct, 0x1b8, dword); /* L3 Control 1 */ - - /* Fam15h BKDG section 2.10.5.5.1 */ - dword = Get_NB32_DCT(dev, dct, 0x218); /* DRAM Timing 5 */ - dword &= ~(0xf << 24); /* TrdrdSdSc = 0xb */ - dword |= (0xb << 24); - dword &= ~(0xf << 16); /* TrdrdSdDc = 0xb */ - dword |= (0xb << 16); - dword &= ~(0xf); /* TrdrdDd = 0xb */ - dword |= 0xb; - Set_NB32_DCT(dev, dct, 0x218, dword); /* DRAM Timing 5 */ - - /* Fam15h BKDG section 2.10.5.5.2 */ - dword = Get_NB32_DCT(dev, dct, 0x214); /* DRAM Timing 4 */ - dword &= ~(0xf << 16); /* TwrwrSdSc = 0xb */ - dword |= (0xb << 16); - dword &= ~(0xf << 8); /* TwrwrSdDc = 0xb */ - dword |= (0xb << 8); - dword &= ~(0xf); /* TwrwrDd = 0xb */ - dword |= 0xb; - Set_NB32_DCT(dev, dct, 0x214, dword); /* DRAM Timing 4 */ - - /* Fam15h BKDG section 2.10.5.5.3 */ - dword = Get_NB32_DCT(dev, dct, 0x218); /* DRAM Timing 5 */ - dword &= ~(0xf << 8); /* Twrrd = 0xb */ - dword |= (0xb << 8); - Set_NB32_DCT(dev, dct, 0x218, dword); /* DRAM Timing 5 */ - - /* Fam15h BKDG section 2.10.5.5.4 */ - dword = Get_NB32_DCT(dev, dct, 0x21c); /* DRAM Timing 6 */ - dword &= ~(0x1f << 8); /* TrwtTO = 0x16 */ - dword |= (0x16 << 8); - dword &= ~(0x1f << 16); /* TrwtWB = TrwtTO + 1 */ - dword |= ((((dword >> 8) & 0x1f) + 1) << 16); - Set_NB32_DCT(dev, dct, 0x21c, dword); /* DRAM Timing 6 */ - } else { - /* Disable training mode */ - uint8_t lane; - uint8_t dimm; - int16_t max_cdd_we_delta; - int16_t cdd_trwtto_we_delta; - uint8_t receiver; - uint8_t lane_count; - uint8_t x4_present = 0; - uint8_t x8_present = 0; - uint8_t memclk_index; - uint8_t interleave_channels = 0; - uint16_t trdrdsddc; - uint16_t trdrddd; - uint16_t cdd_trdrddd; - uint16_t twrwrsddc; - uint16_t twrwrdd; - uint16_t cdd_twrwrdd; - uint16_t twrrd; - uint16_t cdd_twrrd; - uint16_t cdd_trwtto; - uint16_t trwtto; - uint8_t first_dimm; - uint16_t delay; - uint16_t delay2; - uint8_t min_value; - uint8_t write_early; - uint8_t read_odt_delay; - uint8_t write_odt_delay; - uint8_t buffer_data_delay; - int16_t latency_difference; - uint16_t difference; - uint16_t current_total_delay_1[MAX_BYTE_LANES]; - uint16_t current_total_delay_2[MAX_BYTE_LANES]; - uint8_t ddr_voltage_index; - uint8_t max_dimms_installable; - - /* FIXME - * This should be platform configurable - */ - uint8_t dimm_event_l_pin_support = 0; - - ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct); - max_dimms_installable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - if (pDCTstat->Dimmx4Present & ((dct)?0xaa:0x55)) - x4_present = 1; - if (pDCTstat->Dimmx8Present & ((dct)?0xaa:0x55)) - x8_present = 1; - memclk_index = Get_NB32_DCT(dev, dct, 0x94) & 0x1f; - - if (pDCTstat->DIMMValidDCT[0] && pDCTstat->DIMMValidDCT[1] && mctGet_NVbits(NV_Unganged)) - interleave_channels = 1; - - dword = Get_NB32_DCT(dev, dct, 0x240); - delay = (dword >> 4) & 0xf; - if (delay > 6) - read_odt_delay = delay - 6; - else - read_odt_delay = 0; - delay = (dword >> 12) & 0x7; - if (delay > 6) - write_odt_delay = delay - 6; - else - write_odt_delay = 0; - - dword = (Get_NB32_DCT(dev, dct, 0xa8) >> 24) & 0x3; - write_early = dword / 2; - - latency_difference = Get_NB32_DCT(dev, dct, 0x200) & 0x1f; - dword = Get_NB32_DCT(dev, dct, 0x20c) & 0x1f; - latency_difference -= dword; - - if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - - /* TODO - * Implement LRDIMM support - * See Fam15h BKDG Rev. 3.14 section 2.10.5.5 - */ - } else { - buffer_data_delay = 0; - } - - /* TODO: - * Adjust trdrdsddc if four-rank DIMMs are installed per - * section 2.10.5.5.1 of the Family 15h BKDG. - * cdd_trdrdsddc will also need to be calculated in that process. - */ - trdrdsddc = 3; - - /* Calculate the Critical Delay Difference for TrdrdDd */ - cdd_trdrddd = 0; - first_dimm = 1; - for (receiver = 0; receiver < 8; receiver += 2) { - dimm = (receiver >> 1); - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, receiver)) - continue; - - read_dqs_receiver_enable_control_registers(current_total_delay_2, dev, dct, dimm, index_reg); - - if (first_dimm) { - memcpy(current_total_delay_1, current_total_delay_2, sizeof(current_total_delay_1)); - first_dimm = 0; - } - - for (lane = 0; lane < lane_count; lane++) { - if (current_total_delay_1[lane] > current_total_delay_2[lane]) - difference = current_total_delay_1[lane] - current_total_delay_2[lane]; - else - difference = current_total_delay_2[lane] - current_total_delay_1[lane]; - - if (difference > cdd_trdrddd) - cdd_trdrddd = difference; - } - } - - /* Convert the difference to MEMCLKs */ - cdd_trdrddd = (((cdd_trdrddd + (1 << 6) - 1) >> 6) & 0xf); - - /* Calculate Trdrddd */ - delay = (read_odt_delay + 3) * 2; - delay2 = cdd_trdrddd + 7; - if (delay2 > delay) - delay = delay2; - trdrddd = (delay + 1) / 2; /* + 1 is equivalent to ceiling function here */ - if (trdrdsddc > trdrddd) - trdrddd = trdrdsddc; - - /* TODO: - * Adjust twrwrsddc if four-rank DIMMs are installed per - * section 2.10.5.5.1 of the Family 15h BKDG. - * cdd_twrwrsddc will also need to be calculated in that process. - */ - twrwrsddc = 4; - - /* Calculate the Critical Delay Difference for TwrwrDd */ - cdd_twrwrdd = 0; - first_dimm = 1; - for (receiver = 0; receiver < 8; receiver += 2) { - dimm = (receiver >> 1); - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, receiver)) - continue; - - read_dqs_write_timing_control_registers(current_total_delay_2, dev, dct, dimm, index_reg); - - if (first_dimm) { - memcpy(current_total_delay_1, current_total_delay_2, sizeof(current_total_delay_1)); - first_dimm = 0; - } - - for (lane = 0; lane < lane_count; lane++) { - if (current_total_delay_1[lane] > current_total_delay_2[lane]) - difference = current_total_delay_1[lane] - current_total_delay_2[lane]; - else - difference = current_total_delay_2[lane] - current_total_delay_1[lane]; - - if (difference > cdd_twrwrdd) - cdd_twrwrdd = difference; - } - } - - /* Convert the difference to MEMCLKs */ - cdd_twrwrdd = (((cdd_twrwrdd + (1 << 6) - 1) >> 6) & 0xf); - - /* Calculate Twrwrdd */ - delay = (write_odt_delay + 3) * 2; - delay2 = cdd_twrwrdd + 7; - if (delay2 > delay) - delay = delay2; - twrwrdd = (delay + 1) / 2; /* + 1 is equivalent to ceiling function here */ - if (twrwrsddc > twrwrdd) - twrwrdd = twrwrsddc; - - dword = Get_NB32_DCT(dev, dct, 0x78); /* DRAM Control */ - dword |= (0x1 << 17); /* AddrCmdTriEn = 1 */ - Set_NB32_DCT(dev, dct, 0x78, dword); /* DRAM Control */ - - dword = Get_NB32_DCT(dev, dct, 0x8c); /* DRAM Timing High */ - dword &= ~(0x1 << 18); /* DisAutoRefresh = 0 */ - Set_NB32_DCT(dev, dct, 0x8c, dword); /* DRAM Timing High */ - - /* Configure power saving options */ - dword = Get_NB32_DCT(dev, dct, 0xa8); /* Dram Miscellaneous 2 */ - dword |= (0x1 << 22); /* PrtlChPDEnhEn = 0x1 */ - dword |= (0x1 << 21); /* AggrPDEn = 0x1 */ - Set_NB32_DCT(dev, dct, 0xa8, dword); /* Dram Miscellaneous 2 */ - - /* Configure partial power down delay */ - dword = Get_NB32(dev, 0x244); /* DRAM Controller Miscellaneous 3 */ - dword &= ~0xf; /* PrtlChPDDynDly = 0x2 */ - dword |= 0x2; - Set_NB32(dev, 0x244, dword); /* DRAM Controller Miscellaneous 3 */ - - /* Configure power save delays */ - delay = 0xa; - delay2 = 0x3; - - /* Family 15h BKDG Table 214 */ - if ((pDCTstat->Status & (1 << SB_Registered)) - || (pDCTstat->Status & (1 << SB_LoadReduced))) { - if (memclk_index <= 0x6) { - if (ddr_voltage_index < 0x4) - /* 1.5 or 1.35V */ - delay2 = 0x3; - else - /* 1.25V */ - delay2 = 0x4; - } - else if ((memclk_index == 0xa) - || (memclk_index == 0xe)) - delay2 = 0x4; - else if (memclk_index == 0x12) - delay2 = 0x5; - else if (memclk_index == 0x16) - delay2 = 0x6; - } else { - if (memclk_index <= 0x6) - delay2 = 0x3; - else if ((memclk_index == 0xa) - || (memclk_index == 0xe)) - delay2 = 0x4; - else if (memclk_index == 0x12) - delay2 = 0x5; - else if (memclk_index == 0x16) - delay2 = 0x6; - } - - /* Family 15h BKDG Table 215 */ - if (memclk_index <= 0x6) - delay = 0xa; - else if (memclk_index == 0xa) - delay = 0xd; - else if (memclk_index == 0xe) - delay = 0x10; - else if (memclk_index == 0x12) - delay = 0x14; - else if (memclk_index == 0x16) - delay = 0x17; - - dword = Get_NB32_DCT(dev, dct, 0x248); /* Dram Power Management 0 */ - dword &= ~(0x3f << 24); /* AggrPDDelay = 0x0 */ - dword &= ~(0x3f << 16); /* PchgPDEnDelay = 0x1 */ - dword |= (0x1 << 16); - dword &= ~(0x1f << 8); /* Txpdll = delay */ - dword |= ((delay & 0x1f) << 8); - dword &= ~0xf; /* Txp = delay2 */ - dword |= delay2 & 0xf; - Set_NB32_DCT(dev, dct, 0x248, dword); /* Dram Power Management 0 */ - - /* Family 15h BKDG Table 216 */ - if (memclk_index <= 0x6) { - delay = 0x5; - delay2 = 0x3; - } else if (memclk_index == 0xa) { - delay = 0x6; - delay2 = 0x3; - } else if (memclk_index == 0xe) { - delay = 0x7; - delay2 = 0x4; - } else if (memclk_index == 0x12) { - delay = 0x8; - delay2 = 0x4; - } else if (memclk_index == 0x16) { - delay = 0xa; - delay2 = 0x5; - } - - dword = Get_NB32_DCT(dev, dct, 0x24c); /* Dram Power Management 1 */ - dword &= ~(0x3f << 24); /* Tcksrx = delay */ - dword |= ((delay & 0x3f) << 24); - dword &= ~(0x3f << 16); /* Tcksre = delay */ - dword |= ((delay & 0x3f) << 16); - dword &= ~(0x3f << 8); /* Tckesr = delay2 + 1 */ - dword |= (((delay2 + 1) & 0x3f) << 8); - dword &= ~0xf; /* Tpd = delay2 */ - dword |= delay2 & 0xf; - Set_NB32_DCT(dev, dct, 0x24c, dword); /* Dram Power Management 1 */ - - dword = Get_NB32_DCT(dev, dct, 0x94); /* DRAM Configuration High */ - dword |= (0xf << 24); /* DcqBypassMax = 0xf */ - dword |= (0x1 << 22); /* BankSwizzleMode = 1 */ - dword |= (0x1 << 15); /* PowerDownEn = 1 */ - dword &= ~(0x3 << 10); /* ZqcsInterval = 0x2 */ - dword |= (0x2 << 10); - Set_NB32_DCT(dev, dct, 0x94, dword); /* DRAM Configuration High */ - - if (x4_present && x8_present) { - /* Mixed channel of 4x and 8x DIMMs */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000d); - dword &= ~(0x3 << 24); /* RxDLLWakeupTime = 0 */ - dword &= ~(0x7 << 20); /* RxCPUpdPeriod = 0 */ - dword &= ~(0xf << 16); /* RxMaxDurDllNoLock = 0 */ - dword &= ~(0x3 << 8); /* TxDLLWakeupTime = 0 */ - dword &= ~(0x7 << 4); /* TxCPUpdPeriod = 0 */ - dword &= ~(0xf); /* TxMaxDurDllNoLock = 0 */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000d, dword); - } else { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000d); - dword &= ~(0x3 << 24); /* RxDLLWakeupTime = 3 */ - dword |= (0x3 << 24); - dword &= ~(0x7 << 20); /* RxCPUpdPeriod = 3 */ - dword |= (0x3 << 20); - dword &= ~(0xf << 16); /* RxMaxDurDllNoLock = 7 */ - dword |= (0x7 << 16); - dword &= ~(0x3 << 8); /* TxDLLWakeupTime = 3 */ - dword |= (0x3 << 8); - dword &= ~(0x7 << 4); /* TxCPUpdPeriod = 3 */ - dword |= (0x3 << 4); - dword &= ~(0xf); /* TxMaxDurDllNoLock = 7 */ - dword |= 0x7; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000d, dword); - } - - if ((memclk_index <= 0x12) && (x4_present != x8_present)) { - /* MemClkFreq <= 800MHz - * Not a mixed channel of x4 and x8 DIMMs - */ - for (index = 0; index < 0x9; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0010 | (index << 8)); - dword |= (0x1 << 12); /* EnRxPadStandby = 1 */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0010 | (index << 8), dword); - } - } else { - for (index = 0; index < 0x9; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0010 | (index << 8)); - dword &= ~(0x1 << 12); /* EnRxPadStandby = 0 */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0010 | (index << 8), dword); - } - } - - /* Calculate the Critical Delay Difference for Twrrd */ - cdd_twrrd = 0; - for (receiver = 0; receiver < 8; receiver += 2) { - dimm = (receiver >> 1); - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, receiver)) - continue; - - read_dqs_write_timing_control_registers(current_total_delay_1, dev, dct, dimm, index_reg); - read_dqs_receiver_enable_control_registers(current_total_delay_2, dev, dct, dimm, index_reg); - - for (lane = 0; lane < lane_count; lane++) { - if (current_total_delay_1[lane] > current_total_delay_2[lane]) - difference = current_total_delay_1[lane] - current_total_delay_2[lane]; - else - difference = current_total_delay_2[lane] - current_total_delay_1[lane]; - - if (difference > cdd_twrrd) - cdd_twrrd = difference; - } - } - - /* Convert the difference to MEMCLKs */ - cdd_twrrd = (((cdd_twrrd + (1 << 6) - 1) >> 6) & 0xf); - - /* Fam15h BKDG section 2.10.5.5.3 */ - if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* LRDIMM */ - - /* TODO - * Implement LRDIMM support - * See Fam15h BKDG Rev. 3.14 section 2.10.5.5 - */ - twrrd = 0xb; - } else { - max_cdd_we_delta = (((int16_t)cdd_twrrd + 1 - ((int16_t)write_early * 2)) + 1) / 2; - if (max_cdd_we_delta < 0) - max_cdd_we_delta = 0; - if (((uint16_t)max_cdd_we_delta) > write_odt_delay) - dword = max_cdd_we_delta; - else - dword = write_odt_delay; - dword += 3; - if (latency_difference < dword) { - dword -= latency_difference; - if (dword < 1) - twrrd = 1; - else - twrrd = dword; - } else { - twrrd = 1; - } - } - - /* Calculate the Critical Delay Difference for TrwtTO */ - cdd_trwtto = 0; - for (receiver = 0; receiver < 8; receiver += 2) { - dimm = (receiver >> 1); - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, receiver)) - continue; - - read_dqs_receiver_enable_control_registers(current_total_delay_1, dev, dct, dimm, index_reg); - read_dqs_write_timing_control_registers(current_total_delay_2, dev, dct, dimm, index_reg); - - for (lane = 0; lane < lane_count; lane++) { - if (current_total_delay_1[lane] > current_total_delay_2[lane]) - difference = current_total_delay_1[lane] - current_total_delay_2[lane]; - else - difference = current_total_delay_2[lane] - current_total_delay_1[lane]; - - if (difference > cdd_trwtto) - cdd_trwtto = difference; - } - } - - /* Convert the difference to MEMCLKs */ - cdd_trwtto = (((cdd_trwtto + (1 << 6) - 1) >> 6) & 0xf); - - /* Fam15h BKDG section 2.10.5.5.4 */ - if (max_dimms_installable == 1) - min_value = 0; - else - min_value = read_odt_delay + buffer_data_delay; - cdd_trwtto_we_delta = (((int16_t)cdd_trwtto - 1 + ((int16_t)write_early * 2)) + 1) / 2; - cdd_trwtto_we_delta += latency_difference + 3; - if (cdd_trwtto_we_delta < 0) - cdd_trwtto_we_delta = 0; - if ((cdd_trwtto_we_delta) > min_value) - trwtto = cdd_trwtto_we_delta; - else - trwtto = min_value; - - dword = Get_NB32_DCT(dev, dct, 0xa4); /* DRAM Controller Temperature Throttle */ - dword &= ~(0x1 << 11); /* BwCapEn = 0 */ - dword &= ~(0x1 << 8); /* ODTSEn = dimm_event_l_pin_support */ - dword |= (dimm_event_l_pin_support & 0x1) << 8; - Set_NB32_DCT(dev, dct, 0xa4, dword); /* DRAM Controller Temperature Throttle */ - - dword = Get_NB32_DCT(dev, dct, 0x110); /* DRAM Controller Select Low */ - dword &= ~(0x1 << 2); /* DctSelIntLvEn = interleave_channels */ - dword |= (interleave_channels & 0x1) << 2; - dword |= (0x3 << 6); /* DctSelIntLvAddr = 0x3 */ - Set_NB32_DCT(dev, dct, 0x110, dword); /* DRAM Controller Select Low */ - - /* NOTE - * ECC-related setup is performed as part of ECCInit_D and must not be located here, - * otherwise semi-random lockups will occur due to misconfigured scrubbing hardware! - */ - - /* Fam15h BKDG section 2.10.5.5.2 */ - dword = Get_NB32_DCT(dev, dct, 0x214); /* DRAM Timing 4 */ - dword &= ~(0xf << 16); /* TwrwrSdSc = 0x1 */ - dword |= (0x1 << 16); - dword &= ~(0xf << 8); /* TwrwrSdDc = twrwrsddc */ - dword |= ((twrwrsddc & 0xf) << 8); - dword &= ~(0xf); /* TwrwrDd = twrwrdd */ - dword |= (twrwrdd & 0xf); - Set_NB32_DCT(dev, dct, 0x214, dword); /* DRAM Timing 4 */ - - /* Fam15h BKDG section 2.10.5.5.3 */ - dword = Get_NB32_DCT(dev, dct, 0x218); /* DRAM Timing 5 */ - dword &= ~(0xf << 24); /* TrdrdSdSc = 0x1 */ - dword |= (0x1 << 24); - dword &= ~(0xf << 16); /* TrdrdSdDc = trdrdsddc */ - dword |= ((trdrdsddc & 0xf) << 16); - dword &= ~(0xf << 8); /* Twrrd = twrrd */ - dword |= ((twrrd & 0xf) << 8); - dword &= ~(0xf); /* TrdrdDd = trdrddd */ - dword |= (trdrddd & 0xf); - Set_NB32_DCT(dev, dct, 0x218, dword); /* DRAM Timing 5 */ - - /* Fam15h BKDG section 2.10.5.5.4 */ - dword = Get_NB32_DCT(dev, dct, 0x21c); /* DRAM Timing 6 */ - dword &= ~(0x1f << 8); /* TrwtTO = trwtto */ - dword |= ((trwtto & 0x1f) << 8); - dword &= ~(0x1f << 16); /* TrwtWB = TrwtTO + 1 */ - dword |= ((((dword >> 8) & 0x1f) + 1) << 16); - Set_NB32_DCT(dev, dct, 0x21c, dword); /* DRAM Timing 6 */ - - /* Enable prefetchers */ - dword = Get_NB32(dev, 0x11c); /* Memory Controller Configuration High */ - dword &= ~(0x1 << 13); /* PrefIoDis = 0 */ - dword &= ~(0x1 << 12); /* PrefCpuDis = 0 */ - Set_NB32(dev, 0x11c, dword); /* Memory Controller Configuration High */ - } -} - -static void exit_training_mode_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - uint8_t node; - uint8_t dct; - - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + node; - - if (pDCTstat->NodePresent) - for (dct = 0; dct < 2; dct++) - fam15EnableTrainingMode(pMCTstat, pDCTstat, dct, 0); - } -} - -static void DQSTiming_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, uint8_t allow_config_restore) -{ - uint8_t Node; - u8 nv_DQSTrainCTL; - uint8_t retry_requested; - - if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) { - return; - } - - /* Set initial TCWL offset to zero */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - uint8_t dct; - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - for (dct = 0; dct < 2; dct++) - pDCTstat->tcwl_delay[dct] = 0; - } - -retry_dqs_training_and_levelization: - nv_DQSTrainCTL = !allow_config_restore; - - mct_BeforeDQSTrain_D(pMCTstat, pDCTstatA); - phyAssistedMemFnceTraining(pMCTstat, pDCTstatA, -1); - - if (is_fam15h()) { - struct DCTStatStruc *pDCTstat; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - if (pDCTstat->NodePresent) { - if (pDCTstat->DIMMValidDCT[0]) - InitPhyCompensation(pMCTstat, pDCTstat, 0); - if (pDCTstat->DIMMValidDCT[1]) - InitPhyCompensation(pMCTstat, pDCTstat, 1); - } - } - } - - mctHookBeforeAnyTraining(pMCTstat, pDCTstatA); - if (!is_fam15h()) { - /* TODO: should be in mctHookBeforeAnyTraining */ - _WRMSR(MTRR_FIX_4K_E0000, 0x04040404, 0x04040404); - _WRMSR(MTRR_FIX_4K_E8000, 0x04040404, 0x04040404); - _WRMSR(MTRR_FIX_4K_F0000, 0x04040404, 0x04040404); - _WRMSR(MTRR_FIX_4K_F8000, 0x04040404, 0x04040404); - } - - if (nv_DQSTrainCTL) { - mct_WriteLevelization_HW(pMCTstat, pDCTstatA, FirstPass); - - if (is_fam15h()) { - /* Receiver Enable Training Pass 1 */ - TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass); - } - - mct_WriteLevelization_HW(pMCTstat, pDCTstatA, SecondPass); - - if (is_fam15h()) { - - /* TODO: - * Determine why running TrainReceiverEn_D in SecondPass - * mode yields less stable training values than when run - * in FirstPass mode as in the HACK below. - */ - TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass); - } else { - TrainReceiverEn_D(pMCTstat, pDCTstatA, FirstPass); - } - - mct_TrainDQSPos_D(pMCTstat, pDCTstatA); - - /* Determine if DQS training requested a retrain attempt */ - retry_requested = 0; - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - if (pDCTstat->TrainErrors & (1 << SB_FatalError)) { - printk(BIOS_ERR, "DIMM training FAILED! Restarting system..."); - soft_reset(); - } - if (pDCTstat->TrainErrors & (1 << SB_RetryConfigTrain)) { - retry_requested = 1; - - /* Clear previous errors */ - pDCTstat->TrainErrors &= ~(1 << SB_RetryConfigTrain); - pDCTstat->TrainErrors &= ~(1 << SB_NODQSPOS); - pDCTstat->ErrStatus &= ~(1 << SB_RetryConfigTrain); - pDCTstat->ErrStatus &= ~(1 << SB_NODQSPOS); - } - } - } - - /* Retry training and levelization if requested */ - if (retry_requested) { - printk(BIOS_DEBUG, "%s: Restarting training on algorithm request\n", __func__); - /* Reset frequency to minimum */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - if (pDCTstat->NodePresent) { - uint8_t original_target_freq = pDCTstat->TargetFreq; - uint8_t original_auto_speed = pDCTstat->DIMMAutoSpeed; - pDCTstat->TargetFreq = mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK)); - pDCTstat->Speed = pDCTstat->DIMMAutoSpeed = pDCTstat->TargetFreq; - SetTargetFreq(pMCTstat, pDCTstatA, Node); - pDCTstat->TargetFreq = original_target_freq; - pDCTstat->DIMMAutoSpeed = original_auto_speed; - } - } - /* Apply any DIMM timing changes */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - if (pDCTstat->NodePresent) { - AutoCycTiming_D(pMCTstat, pDCTstat, 0); - if (!pDCTstat->GangedMode) - if (pDCTstat->DIMMValidDCT[1] > 0) - AutoCycTiming_D(pMCTstat, pDCTstat, 1); - } - } - goto retry_dqs_training_and_levelization; - } - - TrainMaxRdLatency_En_D(pMCTstat, pDCTstatA); - - if (is_fam15h()) - exit_training_mode_fam15(pMCTstat, pDCTstatA); - else - mctSetEccDQSRcvrEn_D(pMCTstat, pDCTstatA); - } else { - mct_WriteLevelization_HW(pMCTstat, pDCTstatA, FirstPass); - - mct_WriteLevelization_HW(pMCTstat, pDCTstatA, SecondPass); - -#if CONFIG(HAVE_ACPI_RESUME) - printk(BIOS_DEBUG, "mctAutoInitMCT_D: Restoring DIMM training configuration from NVRAM\n"); - if (restore_mct_information_from_nvram(1) != 0) - printk(BIOS_CRIT, "%s: ERROR: Unable to restore DCT configuration from NVRAM\n", __func__); -#endif - - if (is_fam15h()) - exit_training_mode_fam15(pMCTstat, pDCTstatA); - - pMCTstat->GStatus |= 1 << GSB_ConfigRestored; - } - - if (is_fam15h()) { - struct DCTStatStruc *pDCTstat; - - /* Switch DCT control register to DCT 0 per Erratum 505 */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - if (pDCTstat->NodePresent) { - fam15h_switch_dct(pDCTstat->dev_map, 0); - } - } - } - - /* FIXME - currently uses calculated value TrainMaxReadLatency_D(pMCTstat, pDCTstatA); */ - mctHookAfterAnyTraining(); -} - -static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node, Receiver, Channel, Dir, DIMM; - u32 dev; - u32 index_reg; - u32 reg; - u32 index; - u32 val; - u8 ByteLane; - u8 txdqs; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->DCTSysLimit) { - dev = pDCTstat->dev_dct; - for (Channel = 0;Channel < 2; Channel++) { - /* there are four receiver pairs, - loosely associated with chipselects.*/ - index_reg = 0x98; - for (Receiver = 0; Receiver < 8; Receiver += 2) { - /* Set Receiver Enable Values */ - mct_SetRcvrEnDly_D(pDCTstat, - 0, /* RcvrEnDly */ - 1, /* FinalValue, From stack */ - Channel, - Receiver, - dev, index_reg, - (Receiver >> 1) * 3 + 0x10, /* Addl_Index */ - 2); /* Pass Second Pass ? */ - /* Restore Write levelization training data */ - for (ByteLane = 0; ByteLane < 9; ByteLane ++) { - txdqs = pDCTstat->persistentData.CH_D_B_TxDqs[Channel][Receiver >> 1][ByteLane]; - index = Table_DQSRcvEn_Offset[ByteLane >> 1]; - index += (Receiver >> 1) * 3 + 0x10 + 0x20; /* Addl_Index */ - val = Get_NB32_index_wait_DCT(dev, Channel, 0x98, index); - if (ByteLane & 1) { /* odd byte lane */ - val &= ~(0xFF << 16); - val |= txdqs << 16; - } else { - val &= ~0xFF; - val |= txdqs; - } - Set_NB32_index_wait_DCT(dev, Channel, 0x98, index, val); - } - } - } - for (Channel = 0; Channel < 2; Channel++) { - SetEccDQSRcvrEn_D(pDCTstat, Channel); - } - - for (Channel = 0; Channel < 2; Channel++) { - u8 *p; - index_reg = 0x98; - - /* NOTE: - * when 400, 533, 667, it will support dimm0/1/2/3, - * and set conf for dimm0, hw will copy to dimm1/2/3 - * set for dimm1, hw will copy to dimm3 - * Rev A/B only support DIMM0/1 when 800MHz and above - * + 0x100 to next dimm - * Rev C support DIMM0/1/2/3 when 800MHz and above - * + 0x100 to next dimm - */ - for (DIMM = 0; DIMM < 4; DIMM++) { - if (DIMM == 0) { - index = 0; /* CHA Write Data Timing Low */ - } else { - if (pDCTstat->Speed >= mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) { - index = 0x100 * DIMM; - } else { - break; - } - } - for (Dir = 0; Dir < 2; Dir++) {/* RD/WR */ - p = pDCTstat->CH_D_DIR_B_DQS[Channel][DIMM][Dir]; - val = stream_to_int(p); /* CHA Read Data Timing High */ - Set_NB32_index_wait_DCT(dev, Channel, index_reg, index+1, val); - val = stream_to_int(p+4); /* CHA Write Data Timing High */ - Set_NB32_index_wait_DCT(dev, Channel, index_reg, index+2, val); - val = *(p+8); /* CHA Write ECC Timing */ - Set_NB32_index_wait_DCT(dev, Channel, index_reg, index+3, val); - index += 4; - } - } - } - - for (Channel = 0; Channel < 2; Channel++) { - reg = 0x78; - val = Get_NB32_DCT(dev, Channel, reg); - val &= ~(0x3ff<<22); - val |= ((u32) pDCTstat->CH_MaxRdLat[Channel][0] << 22); - val &= ~(1<<DqsRcvEnTrain); - Set_NB32_DCT(dev, Channel, reg, val); /* program MaxRdLatency to correspond with current delay*/ - } - } - } -} - -static void HTMemMapInit_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - u32 NextBase, BottomIO; - u8 _MemHoleRemap, DramHoleBase; - u32 HoleSize, DramSelBaseAddr; - - u32 val; - u32 base; - u32 limit; - u32 dev, devx; - struct DCTStatStruc *pDCTstat; - - _MemHoleRemap = mctGet_NVbits(NV_MemHole); - - if (pMCTstat->HoleBase == 0) { - DramHoleBase = mctGet_NVbits(NV_BottomIO); - } else { - DramHoleBase = pMCTstat->HoleBase >> (24-8); - } - - BottomIO = DramHoleBase << (24-8); - - NextBase = 0; - pDCTstat = pDCTstatA + 0; - dev = pDCTstat->dev_map; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - devx = pDCTstat->dev_map; - DramSelBaseAddr = 0; - if (!pDCTstat->GangedMode) { - DramSelBaseAddr = pDCTstat->NodeSysLimit - pDCTstat->DCTSysLimit; - /*In unganged mode, we must add DCT0 and DCT1 to DCTSysLimit */ - val = pDCTstat->NodeSysLimit; - if ((val & 0xFF) == 0xFE) { - DramSelBaseAddr++; - val++; - } - pDCTstat->DCTSysLimit = val; - } - - base = pDCTstat->DCTSysBase; - limit = pDCTstat->DCTSysLimit; - if (limit > base) { - base += NextBase; - limit += NextBase; - DramSelBaseAddr += NextBase; - printk(BIOS_DEBUG, " Node: %02x base: %02x limit: %02x BottomIO: %02x\n", Node, base, limit, BottomIO); - - if (_MemHoleRemap) { - if ((base < BottomIO) && (limit >= BottomIO)) { - /* HW Dram Remap */ - pDCTstat->Status |= 1 << SB_HWHole; - pMCTstat->GStatus |= 1 << GSB_HWHole; - pDCTstat->DCTSysBase = base; - pDCTstat->DCTSysLimit = limit; - pDCTstat->DCTHoleBase = BottomIO; - pMCTstat->HoleBase = BottomIO; - HoleSize = _4GB_RJ8 - BottomIO; /* HoleSize[39:8] */ - if ((DramSelBaseAddr > 0) && (DramSelBaseAddr < BottomIO)) - base = DramSelBaseAddr; - val = ((base + HoleSize) >> (24-8)) & 0xFF; - val <<= 8; /* shl 16, rol 24 */ - val |= DramHoleBase << 24; - val |= 1 << DramHoleValid; - Set_NB32(devx, 0xF0, val); /* Dram Hole Address Reg */ - pDCTstat->DCTSysLimit += HoleSize; - base = pDCTstat->DCTSysBase; - limit = pDCTstat->DCTSysLimit; - } else if (base == BottomIO) { - /* SW Node Hoist */ - pMCTstat->GStatus |= 1<<GSB_SpIntRemapHole; - pDCTstat->Status |= 1<<SB_SWNodeHole; - pMCTstat->GStatus |= 1<<GSB_SoftHole; - pMCTstat->HoleBase = base; - limit -= base; - base = _4GB_RJ8; - limit += base; - pDCTstat->DCTSysBase = base; - pDCTstat->DCTSysLimit = limit; - } else { - /* No Remapping. Normal Contiguous mapping */ - pDCTstat->DCTSysBase = base; - pDCTstat->DCTSysLimit = limit; - } - } else { - /*No Remapping. Normal Contiguous mapping*/ - pDCTstat->DCTSysBase = base; - pDCTstat->DCTSysLimit = limit; - } - base |= 3; /* set WE,RE fields*/ - pMCTstat->SysLimit = limit; - } - Set_NB32(dev, 0x40 + (Node << 3), base); /* [Node] + Dram Base 0 */ - - val = limit & 0xFFFF0000; - val |= Node; - Set_NB32(dev, 0x44 + (Node << 3), val); /* set DstNode */ - - printk(BIOS_DEBUG, " Node: %02x base: %02x limit: %02x\n", Node, base, limit); - limit = pDCTstat->DCTSysLimit; - if (limit) { - NextBase = (limit & 0xFFFF0000) + 0x10000; - } - } - - /* Copy dram map from Node 0 to Node 1-7 */ - for (Node = 1; Node < MAX_NODES_SUPPORTED; Node++) { - u32 reg; - pDCTstat = pDCTstatA + Node; - devx = pDCTstat->dev_map; - - if (pDCTstat->NodePresent) { - printk(BIOS_DEBUG, " Copy dram map from Node 0 to Node %02x\n", Node); - reg = 0x40; /*Dram Base 0*/ - do { - val = Get_NB32(dev, reg); - Set_NB32(devx, reg, val); - reg += 4; - } while (reg < 0x80); - } else { - break; /* stop at first absent Node */ - } - } - - /*Copy dram map to F1x120/124*/ - mct_HTMemMapExt(pMCTstat, pDCTstatA); -} - -void MCTMemClr_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - - /* Initiates a memory clear operation for all node. The mem clr - * is done in parallel. After the memclr is complete, all processors - * status are checked to ensure that memclr has completed. - */ - u8 Node; - uint32_t dword; - struct DCTStatStruc *pDCTstat; - - if (!mctGet_NVbits(NV_DQSTrainCTL)) { - /* FIXME: callback to wrapper: mctDoWarmResetMemClr_D */ - } else { /* NV_DQSTrainCTL == 1 */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - DCTMemClr_Init_D(pMCTstat, pDCTstat); - } - } - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - DCTMemClr_Sync_D(pMCTstat, pDCTstat); - } - } - } - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - /* Enable prefetchers */ - dword = Get_NB32(pDCTstat->dev_dct, 0x11c); /* Memory Controller Configuration High */ - dword &= ~(0x1 << 13); /* PrefIoDis = 0 */ - dword &= ~(0x1 << 12); /* PrefCpuDis = 0 */ - Set_NB32(pDCTstat->dev_dct, 0x11c, dword); /* Memory Controller Configuration High */ - } -} - -void DCTMemClr_Init_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 val; - u32 dev; - uint32_t dword; - - /* Initiates a memory clear operation on one node */ - if (pDCTstat->DCTSysLimit) { - dev = pDCTstat->dev_dct; - - /* Disable prefetchers */ - dword = Get_NB32(dev, 0x11c); /* Memory Controller Configuration High */ - dword |= 0x1 << 13; /* PrefIoDis = 1 */ - dword |= 0x1 << 12; /* PrefCpuDis = 1 */ - Set_NB32(dev, 0x11c, dword); /* Memory Controller Configuration High */ - - do { - val = Get_NB32(dev, 0x110); - } while (val & (1 << MemClrBusy)); - - val |= (1 << MemClrInit); - Set_NB32(dev, 0x110, val); - } -} - -void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - uint32_t dword; - uint32_t dev = pDCTstat->dev_dct; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - /* Ensure that a memory clear operation has completed on one node */ - if (pDCTstat->DCTSysLimit) { - printk(BIOS_DEBUG, "%s: Waiting for memory clear to complete", __func__); - do { - dword = Get_NB32(dev, 0x110); - - printk(BIOS_DEBUG, "."); - } while (dword & (1 << MemClrBusy)); - - printk(BIOS_DEBUG, "\n"); - do { - printk(BIOS_DEBUG, "."); - dword = Get_NB32(dev, 0x110); - } while (!(dword & (1 << Dr_MemClrStatus))); - printk(BIOS_DEBUG, "\n"); - } - - /* Enable prefetchers */ - dword = Get_NB32(dev, 0x11c); /* Memory Controller Configuration High */ - dword &= ~(0x1 << 13); /* PrefIoDis = 0 */ - dword &= ~(0x1 << 12); /* PrefCpuDis = 0 */ - Set_NB32(dev, 0x11c, dword); /* Memory Controller Configuration High */ - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -u8 NodePresent_D(u8 Node) -{ - /* - * Determine if a single Hammer Node exists within the network. - */ - u32 dev; - u32 val; - u32 dword; - u8 ret = 0; - - dev = PA_HOST(Node); /*test device/vendor id at host bridge */ - val = Get_NB32(dev, 0); - dword = mct_NodePresent_D(); /* FIXME: BOZO -11001022h rev for F */ - if (val == dword) { /* AMD Hammer Family CPU HT Configuration */ - if (oemNodePresent_D(Node, &ret)) - goto finish; - /* Node ID register */ - val = Get_NB32(dev, 0x60); - val &= 0x07; - dword = Node; - if (val == dword) /* current nodeID = requested nodeID ? */ - ret = 1; - } -finish: - return ret; -} - -static void DCTPreInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* - * Run DCT pre-initialization tasks - */ - uint32_t dword; - - /* Reset DCT registers */ - ClearDCT_D(pMCTstat, pDCTstat, dct); - pDCTstat->stopDCT[dct] = 1; /* preload flag with 'disable' */ - - if (!is_fam15h()) { - /* Enable DDR3 support */ - dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94); - dword |= 1 << Ddr3Mode; - Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x94, dword); - } - - /* Read the SPD information into the data structures */ - if (mct_DIMMPresence(pMCTstat, pDCTstat, dct) < SC_StopError) { - printk(BIOS_DEBUG, "\t\tDCTPreInit_D: mct_DIMMPresence Done\n"); - } -} - -static void DCTInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* - * Initialize DRAM on single Athlon 64/Opteron Node. - */ - uint32_t dword; - - if (!is_fam15h()) { - /* (Re)-enable DDR3 support */ - dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94); - dword |= 1 << Ddr3Mode; - Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x94, dword); - } - - if (mct_SPDCalcWidth(pMCTstat, pDCTstat, dct) < SC_StopError) { - printk(BIOS_DEBUG, "\t\tDCTInit_D: mct_SPDCalcWidth Done\n"); - if (AutoCycTiming_D(pMCTstat, pDCTstat, dct) < SC_StopError) { - printk(BIOS_DEBUG, "\t\tDCTInit_D: AutoCycTiming_D Done\n"); - - /* SkewMemClk must be set before MemClkFreqVal is set - * This relies on DCTInit_D being called for DCT 1 after - * it has already been called for DCT 0... - */ - if (is_fam15h()) { - /* Set memory clock skew if needed */ - if (dct == 1) { - if (!pDCTstat->stopDCT[0]) { - printk(BIOS_DEBUG, "\t\tDCTInit_D: enabling intra-channel clock skew\n"); - dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe00a); - dword |= (0x1 << 4); /* SkewMemClk = 1 */ - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe00a, dword); - } - } - } - - if (AutoConfig_D(pMCTstat, pDCTstat, dct) < SC_StopError) { - printk(BIOS_DEBUG, "\t\tDCTInit_D: AutoConfig_D Done\n"); - if (PlatformSpec_D(pMCTstat, pDCTstat, dct) < SC_StopError) { - printk(BIOS_DEBUG, "\t\tDCTInit_D: PlatformSpec_D Done\n"); - pDCTstat->stopDCT[dct] = 0; - } - } - } - } -} - -static void DCTFinalInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct) -{ - uint32_t dword; - - /* Finalize DRAM init on a single node */ - if (!pDCTstat->stopDCT[dct]) { - if (!(pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW))) { - printk(BIOS_DEBUG, "\t\tDCTFinalInit_D: StartupDCT_D Start\n"); - StartupDCT_D(pMCTstat, pDCTstat, dct); - printk(BIOS_DEBUG, "\t\tDCTFinalInit_D: StartupDCT_D Done\n"); - } - } - - if (pDCTstat->stopDCT[dct]) { - dword = 1 << DisDramInterface; - Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x94, dword); - - dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x90); - dword &= ~(1 << ParEn); - Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x90, dword); - - /* To maximize power savings when DisDramInterface = 1b, - * all of the MemClkDis bits should also be set. - */ - Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x88, 0xff000000); - } else { - mct_EnDllShutdownSR(pMCTstat, pDCTstat, dct); - } -} - -static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - /* Wait (and block further access to dram) for all DCTs to be ready, - * by polling all InitDram bits and waiting for possible memory clear - * operations to be complete. Read MemClkFreqVal bit to see if - * the DIMMs are present in this node. - */ - u8 Node; - u32 val; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - mct_SyncDCTsReady(pDCTstat); - } - - if (!is_fam15h()) { - /* v6.1.3 */ - /* re-enable phy compensation engine when dram init is completed on all nodes. */ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - if (pDCTstat->NodePresent) { - if (pDCTstat->DIMMValidDCT[0] > 0 || pDCTstat->DIMMValidDCT[1] > 0) { - /* re-enable phy compensation engine when dram init on both DCTs is completed. */ - val = Get_NB32_index_wait(pDCTstat->dev_dct, 0x98, 0x8); - val &= ~(1 << DisAutoComp); - Set_NB32_index_wait(pDCTstat->dev_dct, 0x98, 0x8, val); - } - } - } - } - - /* wait 750us before any memory access can be made. */ - mct_Wait(15000); -} - -void StartupDCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Read MemClkFreqVal bit to see if the DIMMs are present in this node. - * If the DIMMs are present then set the DRAM Enable bit for this node. - * - * Setting dram init starts up the DCT state machine, initializes the - * dram devices with MRS commands, and kicks off any - * HW memory clear process that the chip is capable of. The sooner - * that dram init is set for all nodes, the faster the memory system - * initialization can complete. Thus, the init loop is unrolled into - * two loops so as to start the processes for non BSP nodes sooner. - * This procedure will not wait for the process to finish. - * Synchronization is handled elsewhere. - */ - u32 val; - u32 dev; - - dev = pDCTstat->dev_dct; - val = Get_NB32_DCT(dev, dct, 0x94); - if (val & (1<<MemClkFreqVal)) { - mctHookBeforeDramInit(); /* generalized Hook */ - if (!(pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW))) - mct_DramInit(pMCTstat, pDCTstat, dct); - AfterDramInit_D(pDCTstat, dct); - mctHookAfterDramInit(); /* generalized Hook*/ - } -} - -static void ClearDCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 reg_end; - u32 dev = pDCTstat->dev_dct; - u32 reg = 0x40; - u32 val = 0; - - if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) { - reg_end = 0x78; - } else { - reg_end = 0xA4; - } - - while (reg < reg_end) { - if ((reg & 0xFF) == 0x84) { - if (is_fam15h()) { - val = Get_NB32_DCT(dev, dct, reg); - val &= ~(0x1 << 23); /* Clear PchgPDModeSel */ - val &= ~0x3; /* Clear BurstCtrl */ - } - } - if ((reg & 0xFF) == 0x90) { - if (pDCTstat->LogicalCPUID & AMD_DR_Dx) { - val = Get_NB32_DCT(dev, dct, reg); /* get DRAMConfigLow */ - val |= 0x08000000; /* preserve value of DisDllShutdownSR for only Rev.D */ - } - } - Set_NB32_DCT(dev, dct, reg, val); - val = 0; - reg += 4; - } - - val = 0; - dev = pDCTstat->dev_map; - reg = 0xF0; - Set_NB32(dev, reg, val); -} - -void SPD2ndTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 i; - u16 Twr, Trtp; - u16 Trp, Trrd, Trcd, Tras, Trc; - u8 Trfc[4]; - u16 Tfaw; - u16 Tcwl; /* Fam15h only */ - u32 DramTimingLo, DramTimingHi; - u8 tCK16x; - u16 Twtr; - uint8_t Etr[2]; - u8 LDIMM; - u8 MTB16x; - u8 byte; - u32 dword; - u32 dev; - u32 val; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - /* Gather all DIMM mini-max values for cycle timing data */ - Trp = 0; - Trrd = 0; - Trcd = 0; - Trtp = 0; - Tras = 0; - Trc = 0; - Twr = 0; - Twtr = 0; - for (i = 0; i < 2; i++) - Etr[i] = 0; - for (i = 0; i < 4; i++) - Trfc[i] = 0; - Tfaw = 0; - - for (i = 0; i< MAX_DIMMS_SUPPORTED; i++) { - LDIMM = i >> 1; - if (pDCTstat->DIMMValid & (1 << i)) { - val = pDCTstat->spd_data.spd_bytes[dct + i][SPD_MTBDivisor]; /* MTB = Dividend/Divisor */ - MTB16x = ((pDCTstat->spd_data.spd_bytes[dct + i][SPD_MTBDividend] & 0xff) << 4); - MTB16x /= val; /* transfer to MTB*16 */ - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tRPmin]; - val = byte * MTB16x; - if (Trp < val) - Trp = val; - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tRRDmin]; - val = byte * MTB16x; - if (Trrd < val) - Trrd = val; - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tRCDmin]; - val = byte * MTB16x; - if (Trcd < val) - Trcd = val; - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tRTPmin]; - val = byte * MTB16x; - if (Trtp < val) - Trtp = val; - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tWRmin]; - val = byte * MTB16x; - if (Twr < val) - Twr = val; - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tWTRmin]; - val = byte * MTB16x; - if (Twtr < val) - Twtr = val; - - val = pDCTstat->spd_data.spd_bytes[dct + i][SPD_Upper_tRAS_tRC] & 0xff; - val >>= 4; - val <<= 8; - val |= pDCTstat->spd_data.spd_bytes[dct + i][SPD_tRCmin] & 0xff; - val *= MTB16x; - if (Trc < val) - Trc = val; - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_Density] & 0xf; - if (Trfc[LDIMM] < byte) - Trfc[LDIMM] = byte; - - val = pDCTstat->spd_data.spd_bytes[dct + i][SPD_Upper_tRAS_tRC] & 0xf; - val <<= 8; - val |= (pDCTstat->spd_data.spd_bytes[dct + i][SPD_tRASmin] & 0xff); - val *= MTB16x; - if (Tras < val) - Tras = val; - - val = pDCTstat->spd_data.spd_bytes[dct + i][SPD_Upper_tFAW] & 0xf; - val <<= 8; - val |= pDCTstat->spd_data.spd_bytes[dct + i][SPD_tFAWmin] & 0xff; - val *= MTB16x; - if (Tfaw < val) - Tfaw = val; - - /* Determine if the DIMMs on this channel support 95°C ETR */ - if (pDCTstat->spd_data.spd_bytes[dct + i][SPD_Thermal] & 0x1) - Etr[dct] = 1; - } /* Dimm Present */ - } - - /* Convert DRAM CycleTiming values and store into DCT structure */ - byte = pDCTstat->DIMMAutoSpeed; - if (is_fam15h()) { - if (byte == 0x16) - tCK16x = 17; - else if (byte == 0x12) - tCK16x = 20; - else if (byte == 0xe) - tCK16x = 24; - else if (byte == 0xa) - tCK16x = 30; - else if (byte == 0x6) - tCK16x = 40; - else - tCK16x = 48; - } else { - if (byte == 7) - tCK16x = 20; - else if (byte == 6) - tCK16x = 24; - else if (byte == 5) - tCK16x = 30; - else - tCK16x = 40; - } - - /* Notes: - 1. All secondary time values given in SPDs are in binary with units of ns. - 2. Some time values are scaled by 16, in order to have least count of 0.25 ns - (more accuracy). JEDEC SPD spec. shows which ones are x1 and x4. - 3. Internally to this SW, cycle time, tCK16x, is scaled by 16 to match time values - */ - - /* Tras */ - pDCTstat->DIMMTras = (u16)Tras; - val = Tras / tCK16x; - if (Tras % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TrasT) - val = Min_TrasT; - else if (val > Max_TrasT) - val = Max_TrasT; - pDCTstat->Tras = val; - - /* Trp */ - pDCTstat->DIMMTrp = Trp; - val = Trp / tCK16x; - if (Trp % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TrpT) - val = Min_TrpT; - else if (val > Max_TrpT) - val = Max_TrpT; - pDCTstat->Trp = val; - - /* Trrd */ - pDCTstat->DIMMTrrd = Trrd; - val = Trrd / tCK16x; - if (Trrd % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TrrdT) - val = Min_TrrdT; - else if (val > Max_TrrdT) - val = Max_TrrdT; - pDCTstat->Trrd = val; - - /* Trcd */ - pDCTstat->DIMMTrcd = Trcd; - val = Trcd / tCK16x; - if (Trcd % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TrcdT) - val = Min_TrcdT; - else if (val > Max_TrcdT) - val = Max_TrcdT; - pDCTstat->Trcd = val; - - /* Trc */ - pDCTstat->DIMMTrc = Trc; - val = Trc / tCK16x; - if (Trc % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TrcT) - val = Min_TrcT; - else if (val > Max_TrcT) - val = Max_TrcT; - pDCTstat->Trc = val; - - /* Trtp */ - pDCTstat->DIMMTrtp = Trtp; - val = Trtp / tCK16x; - if (Trtp % tCK16x) { - val ++; - } - if (val < Min_TrtpT) - val = Min_TrtpT; - else if (val > Max_TrtpT) - val = Max_TrtpT; - pDCTstat->Trtp = val; - - /* Twr */ - pDCTstat->DIMMTwr = Twr; - val = Twr / tCK16x; - if (Twr % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TwrT) - val = Min_TwrT; - else if (val > Max_TwrT) - val = Max_TwrT; - pDCTstat->Twr = val; - - /* Twtr */ - pDCTstat->DIMMTwtr = Twtr; - val = Twtr / tCK16x; - if (Twtr % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TwtrT) - val = Min_TwtrT; - else if (val > Max_TwtrT) - val = Max_TwtrT; - pDCTstat->Twtr = val; - - /* Trfc0-Trfc3 */ - for (i = 0; i < 4; i++) - pDCTstat->Trfc[i] = Trfc[i]; - - /* Tfaw */ - pDCTstat->DIMMTfaw = Tfaw; - val = Tfaw / tCK16x; - if (Tfaw % tCK16x) { /* round up number of busclocks */ - val++; - } - if (val < Min_TfawT) - val = Min_TfawT; - else if (val > Max_TfawT) - val = Max_TfawT; - pDCTstat->Tfaw = val; - - mctAdjustAutoCycTmg_D(); - - if (is_fam15h()) { - /* Compute Tcwl (Fam15h BKDG v3.14 Table 203) */ - if (pDCTstat->Speed <= 0x6) - Tcwl = 0x5; - else if (pDCTstat->Speed == 0xa) - Tcwl = 0x6; - else if (pDCTstat->Speed == 0xe) - Tcwl = 0x7; - else if (pDCTstat->Speed == 0x12) - Tcwl = 0x8; - else if (pDCTstat->Speed == 0x16) - Tcwl = 0x9; - else - Tcwl = 0x5; /* Power-on default */ - - /* Apply offset */ - Tcwl += pDCTstat->tcwl_delay[dct]; - } - - /* Program DRAM Timing values */ - if (is_fam15h()) { - dev = pDCTstat->dev_dct; - - dword = Get_NB32_DCT(dev, dct, 0x8c); /* DRAM Timing High */ - if (Etr[dct]) - val = 3; /* Tref = 3.9us */ - else - val = 2; /* Tref = 7.8us */ - dword &= ~(0x3 << 16); - dword |= (val & 0x3) << 16; - Set_NB32_DCT(dev, dct, 0x8c, dword); /* DRAM Timing High */ - - dword = Get_NB32_DCT(dev, dct, 0x200); /* DRAM Timing 0 */ - dword &= ~(0x3f1f1f1f); - dword |= (pDCTstat->Tras & 0x3f) << 24; /* Tras */ - val = pDCTstat->Trp; - val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val); - dword |= (val & 0x1f) << 16; /* Trp */ - dword |= (pDCTstat->Trcd & 0x1f) << 8; /* Trcd */ - dword |= (pDCTstat->CASL & 0x1f); /* Tcl */ - Set_NB32_DCT(dev, dct, 0x200, dword); /* DRAM Timing 0 */ - - dword = Get_NB32_DCT(dev, dct, 0x204); /* DRAM Timing 1 */ - dword &= ~(0x0f3f0f3f); - dword |= (pDCTstat->Trtp & 0xf) << 24; /* Trtp */ - if (pDCTstat->Tfaw != 0) { - val = pDCTstat->Tfaw; - val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val); - if ((val > 0x5) && (val < 0x2b)) - dword |= (val & 0x3f) << 16; /* FourActWindow */ - } - dword |= (pDCTstat->Trrd & 0xf) << 8; /* Trrd */ - dword |= (pDCTstat->Trc & 0x3f); /* Trc */ - Set_NB32_DCT(dev, dct, 0x204, dword); /* DRAM Timing 1 */ - - /* Trfc0-Trfc3 */ - for (i = 0; i < 4; i++) - if (pDCTstat->Trfc[i] == 0x0) - pDCTstat->Trfc[i] = 0x1; - dword = Get_NB32_DCT(dev, dct, 0x208); /* DRAM Timing 2 */ - dword &= ~(0x07070707); - dword |= (pDCTstat->Trfc[3] & 0x7) << 24; /* Trfc3 */ - dword |= (pDCTstat->Trfc[2] & 0x7) << 16; /* Trfc2 */ - dword |= (pDCTstat->Trfc[1] & 0x7) << 8; /* Trfc1 */ - dword |= (pDCTstat->Trfc[0] & 0x7); /* Trfc0 */ - Set_NB32_DCT(dev, dct, 0x208, dword); /* DRAM Timing 2 */ - - dword = Get_NB32_DCT(dev, dct, 0x20c); /* DRAM Timing 3 */ - dword &= ~(0x00000f00); - dword |= (pDCTstat->Twtr & 0xf) << 8; /* Twtr */ - dword &= ~(0x0000001f); - dword |= (Tcwl & 0x1f); /* Tcwl */ - Set_NB32_DCT(dev, dct, 0x20c, dword); /* DRAM Timing 3 */ - - dword = Get_NB32_DCT(dev, dct, 0x22c); /* DRAM Timing 10 */ - dword &= ~(0x0000001f); - dword |= (pDCTstat->Twr & 0x1f); /* Twr */ - Set_NB32_DCT(dev, dct, 0x22c, dword); /* DRAM Timing 10 */ - - if (pDCTstat->Speed > mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) { - /* Enable phy-assisted training mode */ - fam15EnableTrainingMode(pMCTstat, pDCTstat, dct, 1); - } - - /* Other setup (not training specific) */ - dword = Get_NB32_DCT(dev, dct, 0x90); /* DRAM Configuration Low */ - dword &= ~(0x1 << 23); /* ForceAutoPchg = 0 */ - dword &= ~(0x1 << 20); /* DynPageCloseEn = 0 */ - Set_NB32_DCT(dev, dct, 0x90, dword); /* DRAM Configuration Low */ - - Set_NB32_DCT(dev, dct, 0x228, 0x14141414); /* DRAM Timing 9 */ - } else { - DramTimingLo = 0; /* Dram Timing Low init */ - val = pDCTstat->CASL - 4; /* pDCTstat.CASL to reg. definition */ - DramTimingLo |= val; - - val = pDCTstat->Trcd - Bias_TrcdT; - DramTimingLo |= val<<4; - - val = pDCTstat->Trp - Bias_TrpT; - val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val); - DramTimingLo |= val<<7; - - val = pDCTstat->Trtp - Bias_TrtpT; - DramTimingLo |= val<<10; - - val = pDCTstat->Tras - Bias_TrasT; - DramTimingLo |= val<<12; - - val = pDCTstat->Trc - Bias_TrcT; - DramTimingLo |= val<<16; - - val = pDCTstat->Trrd - Bias_TrrdT; - DramTimingLo |= val<<22; - - DramTimingHi = 0; /* Dram Timing High init */ - val = pDCTstat->Twtr - Bias_TwtrT; - DramTimingHi |= val<<8; - - val = 2; /* Tref = 7.8us */ - DramTimingHi |= val<<16; - - val = 0; - for (i = 4; i > 0; i--) { - val <<= 3; - val |= Trfc[i-1]; - } - DramTimingHi |= val << 20; - - dev = pDCTstat->dev_dct; - /* Twr */ - val = pDCTstat->Twr; - if (val == 10) - val = 9; - else if (val == 12) - val = 10; - val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val); - val -= Bias_TwrT; - val <<= 4; - dword = Get_NB32_DCT(dev, dct, 0x84); - dword &= ~0x70; - dword |= val; - Set_NB32_DCT(dev, dct, 0x84, dword); - - /* Tfaw */ - val = pDCTstat->Tfaw; - val = mct_AdjustSPDTimings(pMCTstat, pDCTstat, val); - val -= Bias_TfawT; - val >>= 1; - val <<= 28; - dword = Get_NB32_DCT(dev, dct, 0x94); - dword &= ~0xf0000000; - dword |= val; - Set_NB32_DCT(dev, dct, 0x94, dword); - - /* dev = pDCTstat->dev_dct; */ - - if (pDCTstat->Speed > mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) { - val = Get_NB32_DCT(dev, dct, 0x88); - val &= 0xFF000000; - DramTimingLo |= val; - } - Set_NB32_DCT(dev, dct, 0x88, DramTimingLo); /*DCT Timing Low*/ - - if (pDCTstat->Speed > mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) { - DramTimingHi |= 1 << DisAutoRefresh; - } - DramTimingHi |= 0x000018FF; - Set_NB32_DCT(dev, dct, 0x8c, DramTimingHi); /*DCT Timing Hi*/ - } - - /* dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2)); */ - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static u8 AutoCycTiming_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - /* Initialize DCT Timing registers as per DIMM SPD. - * For primary timing (T, CL) use best case T value. - * For secondary timing params., use most aggressive settings - * of slowest DIMM. - * - * There are three components to determining "maximum frequency": - * SPD component, Bus load component, and "Preset" max frequency - * component. - * - * The SPD component is a function of the min cycle time specified - * by each DIMM, and the interaction of cycle times from all DIMMs - * in conjunction with CAS latency. The SPD component only applies - * when user timing mode is 'Auto'. - * - * The Bus load component is a limiting factor determined by electrical - * characteristics on the bus as a result of varying number of device - * loads. The Bus load component is specific to each platform but may - * also be a function of other factors. The bus load component only - * applies when user timing mode is 'Auto'. - * - * The Preset component is subdivided into three items and is - * the minimum of the set: Silicon revision, user limit - * setting when user timing mode is 'Auto' and memclock mode - * is 'Limit', OEM build specification of the maximum - * frequency. The Preset component is only applies when user - * timing mode is 'Auto'. - */ - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - /* Get primary timing (CAS Latency and Cycle Time) */ - if (pDCTstat->Speed == 0) { - mctGet_MaxLoadFreq(pDCTstat); - - /* and Factor in presets (setup options, Si cap, etc.) */ - GetPresetmaxF_D(pMCTstat, pDCTstat); - - /* Go get best T and CL as specified by DIMM mfgs. and OEM */ - SPDGetTCL_D(pMCTstat, pDCTstat, dct); - - /* skip callback mctForce800to1067_D */ - pDCTstat->Speed = pDCTstat->DIMMAutoSpeed; - pDCTstat->CASL = pDCTstat->DIMMCASL; - - } - mct_AfterGetCLT(pMCTstat, pDCTstat, dct); - - SPD2ndTiming(pMCTstat, pDCTstat, dct); - - printk(BIOS_DEBUG, "AutoCycTiming: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "AutoCycTiming: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "AutoCycTiming: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "AutoCycTiming: Done\n\n"); - - mctHookAfterAutoCycTmg(); - - return pDCTstat->ErrCode; -} - -static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Get max frequency from OEM platform definition, from any user - * override (limiting) of max frequency, and from any Si Revision - * Specific information. Return the least of these three in - * DCTStatStruc.PresetmaxFreq. - */ - /* TODO: Set the proper max frequency in wrappers/mcti_d.c. */ - u16 proposedFreq; - u16 word; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - /* Get CPU Si Revision defined limit (NPT) */ - if (is_fam15h()) - proposedFreq = 933; - else - proposedFreq = 800; /* Rev F0 programmable max memclock is */ - - /*Get User defined limit if "limit" mode */ - if (mctGet_NVbits(NV_MCTUSRTMGMODE) == 1) { - word = Get_Fk_D(mctGet_NVbits(NV_MemCkVal) + 1); - if (word < proposedFreq) - proposedFreq = word; - - /* Get Platform defined limit */ - word = mctGet_NVbits(NV_MAX_MEMCLK); - if (word < proposedFreq) - proposedFreq = word; - - word = pDCTstat->PresetmaxFreq; - if (word > proposedFreq) - word = proposedFreq; - - pDCTstat->PresetmaxFreq = word; - } - /* Check F3xE8[DdrMaxRate] for maximum DRAM data rate support */ - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - /* Find the best T and CL primary timing parameter pair, per Mfg., - * for the given set of DIMMs, and store into DCTStatStruc - * (.DIMMAutoSpeed and .DIMMCASL). See "Global relationship between - * index values and item values" for definition of CAS latency - * index (j) and Frequency index (k). - */ - u8 i, CASLatLow, CASLatHigh; - u16 tAAmin16x; - u8 MTB16x; - u16 tCKmin16x; - u16 tCKproposed16x; - u8 CLactual, CLdesired, CLT_Fail; - uint16_t min_frequency_tck16x; - - u8 byte = 0, bytex = 0; - - CASLatLow = 0xFF; - CASLatHigh = 0xFF; - tAAmin16x = 0; - tCKmin16x = 0; - CLT_Fail = 0; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - if (is_fam15h()) { - uint16_t minimum_frequency_mhz = mctGet_NVbits(NV_MIN_MEMCLK); - if (minimum_frequency_mhz == 0) - minimum_frequency_mhz = 333; - min_frequency_tck16x = 16000 / minimum_frequency_mhz; - } else { - min_frequency_tck16x = 40; - } - - for (i = 0; i < MAX_DIMMS_SUPPORTED; i++) { - if (pDCTstat->DIMMValid & (1 << i)) { - /* Step 1: Determine the common set of supported CAS Latency - * values for all modules on the memory channel using the CAS - * Latencies Supported in SPD bytes 14 and 15. - */ - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_CASLow]; - CASLatLow &= byte; - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_CASHigh]; - CASLatHigh &= byte; - /* Step 2: Determine tAAmin(all) which is the largest tAAmin - value for all modules on the memory channel (SPD byte 16). */ - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_MTBDivisor]; - - MTB16x = ((pDCTstat->spd_data.spd_bytes[dct + i][SPD_MTBDividend] & 0xFF)<<4); - MTB16x /= byte; /* transfer to MTB*16 */ - - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tAAmin]; - if (tAAmin16x < byte * MTB16x) - tAAmin16x = byte * MTB16x; - /* Step 3: Determine tCKmin(all) which is the largest tCKmin - value for all modules on the memory channel (SPD byte 12). */ - byte = pDCTstat->spd_data.spd_bytes[dct + i][SPD_tCKmin]; - - if (tCKmin16x < byte * MTB16x) - tCKmin16x = byte * MTB16x; - } - } - /* calculate tCKproposed16x (proposed clock period in ns * 16) */ - tCKproposed16x = 16000 / pDCTstat->PresetmaxFreq; - if (tCKmin16x > tCKproposed16x) - tCKproposed16x = tCKmin16x; - - /* TODO: get user manual tCK16x(Freq.) and overwrite current tCKproposed16x if manual. */ - if (is_fam15h()) { - if (tCKproposed16x == 17) - pDCTstat->TargetFreq = 0x16; - else if (tCKproposed16x <= 20) { - pDCTstat->TargetFreq = 0x12; - tCKproposed16x = 20; - } else if (tCKproposed16x <= 24) { - pDCTstat->TargetFreq = 0xe; - tCKproposed16x = 24; - } else if (tCKproposed16x <= 30) { - pDCTstat->TargetFreq = 0xa; - tCKproposed16x = 30; - } else if (tCKproposed16x <= 40) { - pDCTstat->TargetFreq = 0x6; - tCKproposed16x = 40; - } else { - pDCTstat->TargetFreq = 0x4; - tCKproposed16x = 48; - } - } else { - if (tCKproposed16x == 20) - pDCTstat->TargetFreq = 7; - else if (tCKproposed16x <= 24) { - pDCTstat->TargetFreq = 6; - tCKproposed16x = 24; - } else if (tCKproposed16x <= 30) { - pDCTstat->TargetFreq = 5; - tCKproposed16x = 30; - } else { - pDCTstat->TargetFreq = 4; - tCKproposed16x = 40; - } - } - /* Running through this loop twice: - - First time find tCL at target frequency - - Second time find tCL at 400MHz */ - - for (;;) { - CLT_Fail = 0; - /* Step 4: For a proposed tCK value (tCKproposed) between tCKmin(all) and tCKmax, - determine the desired CAS Latency. If tCKproposed is not a standard JEDEC - value (2.5, 1.875, 1.5, or 1.25 ns) then tCKproposed must be adjusted to the - next lower standard tCK value for calculating CLdesired. - CLdesired = ceiling (tAAmin(all) / tCKproposed) - where tAAmin is defined in Byte 16. The ceiling function requires that the - quotient be rounded up always. */ - CLdesired = tAAmin16x / tCKproposed16x; - if (tAAmin16x % tCKproposed16x) - CLdesired ++; - /* Step 5: Chose an actual CAS Latency (CLactual) that is greather than or equal - to CLdesired and is supported by all modules on the memory channel as - determined in step 1. If no such value exists, choose a higher tCKproposed - value and repeat steps 4 and 5 until a solution is found. */ - for (i = 0, CLactual = 4; i < 15; i++, CLactual++) { - if ((CASLatHigh << 8 | CASLatLow) & (1 << i)) { - if (CLdesired <= CLactual) - break; - } - } - if (i == 15) - CLT_Fail = 1; - /* Step 6: Once the calculation of CLactual is completed, the BIOS must also - verify that this CAS Latency value does not exceed tAAmax, which is 20 ns - for all DDR3 speed grades, by multiplying CLactual times tCKproposed. If - not, choose a lower CL value and repeat steps 5 and 6 until a solution is found. */ - if (CLactual * tCKproposed16x > 320) - CLT_Fail = 1; - /* get CL and T */ - if (!CLT_Fail) { - bytex = CLactual; - if (is_fam15h()) { - if (tCKproposed16x == 17) - byte = 0x16; - else if (tCKproposed16x == 20) - byte = 0x12; - else if (tCKproposed16x == 24) - byte = 0xe; - else if (tCKproposed16x == 30) - byte = 0xa; - else if (tCKproposed16x == 40) - byte = 0x6; - else - byte = 0x4; - } else { - if (tCKproposed16x == 20) - byte = 7; - else if (tCKproposed16x == 24) - byte = 6; - else if (tCKproposed16x == 30) - byte = 5; - else - byte = 4; - } - } else { - /* mctHookManualCLOverride */ - /* TODO: */ - } - - if (tCKproposed16x != min_frequency_tck16x) { - if (pMCTstat->GStatus & (1 << GSB_EnDIMMSpareNW)) { - pDCTstat->DIMMAutoSpeed = byte; - pDCTstat->DIMMCASL = bytex; - break; - } else { - pDCTstat->TargetCASL = bytex; - tCKproposed16x = min_frequency_tck16x; - } - } else { - pDCTstat->DIMMAutoSpeed = byte; - pDCTstat->DIMMCASL = bytex; - break; - } - } - - printk(BIOS_DEBUG, "SPDGetTCL_D: DIMMCASL %x\n", pDCTstat->DIMMCASL); - printk(BIOS_DEBUG, "SPDGetTCL_D: DIMMAutoSpeed %x\n", pDCTstat->DIMMAutoSpeed); - - printk(BIOS_DEBUG, "SPDGetTCL_D: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "SPDGetTCL_D: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "SPDGetTCL_D: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "SPDGetTCL_D: Done\n\n"); -} - -u8 PlatformSpec_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - if (!is_fam15h()) { - mctGet_PS_Cfg_D(pMCTstat, pDCTstat, dct); - - if (pDCTstat->GangedMode == 1) { - mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 1); - mct_BeforePlatformSpec(pMCTstat, pDCTstat, 1); - } - - set_2t_configuration(pMCTstat, pDCTstat, dct); - - mct_BeforePlatformSpec(pMCTstat, pDCTstat, dct); - mct_PlatformSpec(pMCTstat, pDCTstat, dct); - if (pDCTstat->DIMMAutoSpeed == mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) - InitPhyCompensation(pMCTstat, pDCTstat, dct); - } - mctHookAfterPSCfg(); - - return pDCTstat->ErrCode; -} - -static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 DramControl, DramTimingLo, Status; - u32 DramConfigLo, DramConfigHi, DramConfigMisc, DramConfigMisc2; - u32 val; - u32 dev; - u16 word; - u32 dword; - u8 byte; - uint32_t offset; - - DramConfigLo = 0; - DramConfigHi = 0; - DramConfigMisc = 0; - DramConfigMisc2 = 0; - - /* set bank addressing and Masks, plus CS pops */ - SPDSetBanks_D(pMCTstat, pDCTstat, dct); - if (pDCTstat->ErrCode == SC_StopError) - goto AutoConfig_exit; - - /* map chip-selects into local address space */ - StitchMemory_D(pMCTstat, pDCTstat, dct); - InterleaveBanks_D(pMCTstat, pDCTstat, dct); - - /* temp image of status (for convenience). RO usage! */ - Status = pDCTstat->Status; - - dev = pDCTstat->dev_dct; - - /* Build Dram Control Register Value */ - DramConfigMisc2 = Get_NB32_DCT(dev, dct, 0xa8); /* Dram Miscellaneous 2 */ - DramControl = Get_NB32_DCT(dev, dct, 0x78); /* Dram Control */ - - /* FIXME: Skip mct_checkForDxSupport */ - /* REV_CALL mct_DoRdPtrInit if not Dx */ - if (pDCTstat->LogicalCPUID & AMD_DR_Bx) - val = 5; - else - val = 6; - DramControl &= ~0xFF; - DramControl |= val; /* RdPtrInit = 6 for Cx CPU */ - - if (mctGet_NVbits(NV_CLKHZAltVidC3)) - DramControl |= 1<<16; /* check */ - - DramControl |= 0x00002A00; - - /* FIXME: Skip for Ax versions */ - /* callback not required - if (!mctParityControl_D()) */ - if (Status & (1 << SB_128bitmode)) - DramConfigLo |= 1 << Width128; /* 128-bit mode (normal) */ - - word = dct; - dword = X4Dimm; - while (word < 8) { - if (pDCTstat->Dimmx4Present & (1 << word)) - DramConfigLo |= 1 << dword; /* X4Dimm[3:0] */ - word++; - word++; - dword++; - } - - if (Status & (1 << SB_Registered)) { - /* Registered DIMMs */ - if (!is_fam15h()) { - DramConfigLo |= 1 << ParEn; - } - } else { - /* Unbuffered DIMMs */ - DramConfigLo |= 1 << UnBuffDimm; - } - - if (mctGet_NVbits(NV_ECC_CAP)) - if (Status & (1 << SB_ECCDIMMs)) - if (mctGet_NVbits(NV_ECC)) - DramConfigLo |= 1 << DimmEcEn; - - DramConfigLo = mct_DisDllShutdownSR(pMCTstat, pDCTstat, DramConfigLo, dct); - - /* Build Dram Config Hi Register Value */ - if (is_fam15h()) - offset = 0x0; - else - offset = 0x1; - dword = pDCTstat->Speed; - DramConfigHi |= dword - offset; /* get MemClk encoding */ - DramConfigHi |= 1 << MemClkFreqVal; - - if (!is_fam15h()) - if (Status & (1 << SB_Registered)) - if ((pDCTstat->Dimmx4Present != 0) && (pDCTstat->Dimmx8Present != 0)) - /* set only if x8 Registered DIMMs in System*/ - DramConfigHi |= 1 << RDqsEn; - - if (pDCTstat->LogicalCPUID & AMD_FAM15_ALL) { - DramConfigLo |= 1 << 25; /* PendRefPaybackS3En = 1 */ - DramConfigLo |= 1 << 24; /* StagRefEn = 1 */ - DramConfigHi |= 1 << 16; /* PowerDownMode = 1 */ - } else { - if (mctGet_NVbits(NV_CKE_CTL)) - /*Chip Select control of CKE*/ - DramConfigHi |= 1 << 16; - } - - if (!is_fam15h()) { - /* Control Bank Swizzle */ - if (0) /* call back not needed mctBankSwizzleControl_D()) */ - DramConfigHi &= ~(1 << BankSwizzleMode); - else - DramConfigHi |= 1 << BankSwizzleMode; /* recommended setting (default) */ - } - - /* Check for Quadrank DIMM presence */ - if (pDCTstat->DimmQRPresent != 0) { - byte = mctGet_NVbits(NV_4RANKType); - if (byte == 2) - DramConfigHi |= 1 << 17; /* S4 (4-Rank SO-DIMMs) */ - else if (byte == 1) - DramConfigHi |= 1 << 18; /* R4 (4-Rank Registered DIMMs) */ - } - - if (0) /* call back not needed mctOverrideDcqBypMax_D) */ - val = mctGet_NVbits(NV_BYPMAX); - else - val = 0x0f; /* recommended setting (default) */ - DramConfigHi |= val << 24; - - if (pDCTstat->LogicalCPUID & (AMD_DR_Dx | AMD_DR_Cx | AMD_DR_Bx | AMD_FAM15_ALL)) - DramConfigHi |= 1 << DcqArbBypassEn; - - /* Build MemClkDis Value from Dram Timing Lo and - Dram Config Misc Registers - 1. We will assume that MemClkDis field has been preset prior to this - point. - 2. We will only set MemClkDis bits if a DIMM is NOT present AND if: - NV_AllMemClks <>0 AND SB_DiagClks == 0 */ - - /* Dram Timing Low (owns Clock Enable bits) */ - DramTimingLo = Get_NB32_DCT(dev, dct, 0x88); - if (mctGet_NVbits(NV_AllMemClks) == 0) { - /* Special Jedec SPD diagnostic bit - "enable all clocks" */ - if (!(pDCTstat->Status & (1<<SB_DiagClks))) { - const u8 *p; - p = Tab_ManualCLKDis; - - byte = mctGet_NVbits(NV_PACK_TYPE); - if (byte == PT_L1) - p = Tab_L1CLKDis; - else if (byte == PT_M2 || byte == PT_AS) - p = Tab_AM3CLKDis; - else if (byte == PT_C3) - p = Tab_C32CLKDis; - else if (byte == PT_GR) - p = Tab_G34CLKDis; - else if (byte == PT_FM2) - p = Tab_FM2CLKDis; - else - p = Tab_S1CLKDis; - - dword = 0; - byte = 0xFF; - while (dword < MAX_CS_SUPPORTED) { - if (pDCTstat->CSPresent & (1<<dword)) { - /* re-enable clocks for the enabled CS */ - val = p[dword]; - byte &= ~val; - } - dword++; - } - DramTimingLo &= ~(0xff << 24); - DramTimingLo |= byte << 24; - } - } - - DramConfigMisc2 = mct_SetDramConfigMisc2(pDCTstat, dct, DramConfigMisc2, DramControl); - - printk(BIOS_DEBUG, "AutoConfig_D: DramControl: %08x\n", DramControl); - printk(BIOS_DEBUG, "AutoConfig_D: DramTimingLo: %08x\n", DramTimingLo); - printk(BIOS_DEBUG, "AutoConfig_D: DramConfigMisc: %08x\n", DramConfigMisc); - printk(BIOS_DEBUG, "AutoConfig_D: DramConfigMisc2: %08x\n", DramConfigMisc2); - printk(BIOS_DEBUG, "AutoConfig_D: DramConfigLo: %08x\n", DramConfigLo); - printk(BIOS_DEBUG, "AutoConfig_D: DramConfigHi: %08x\n", DramConfigHi); - - /* Write Values to the registers */ - Set_NB32_DCT(dev, dct, 0x78, DramControl); - Set_NB32_DCT(dev, dct, 0x88, DramTimingLo); - Set_NB32_DCT(dev, dct, 0xa0, DramConfigMisc); - Set_NB32_DCT(dev, dct, 0xa8, DramConfigMisc2); - Set_NB32_DCT(dev, dct, 0x90, DramConfigLo); - ProgDramMRSReg_D(pMCTstat, pDCTstat, dct); - - if (is_fam15h()) - InitDDRPhy(pMCTstat, pDCTstat, dct); - - /* Write the DRAM Configuration High register, including memory frequency change */ - dword = Get_NB32_DCT(dev, dct, 0x94); - DramConfigHi |= dword; - mct_SetDramConfigHi_D(pMCTstat, pDCTstat, dct, DramConfigHi); - mct_EarlyArbEn_D(pMCTstat, pDCTstat, dct); - mctHookAfterAutoCfg(); - - /* dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2)); */ - - printk(BIOS_DEBUG, "AutoConfig: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "AutoConfig: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "AutoConfig: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "AutoConfig: Done\n\n"); - -AutoConfig_exit: - return pDCTstat->ErrCode; -} - -static void SPDSetBanks_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Set bank addressing, program Mask values and build a chip-select - * population map. This routine programs PCI 0:24N:2x80 config register - * and PCI 0:24N:2x60,64,68,6C config registers (CS Mask 0-3). - */ - u8 ChipSel, Rows, Cols, Ranks, Banks; - u32 BankAddrReg, csMask; - - u32 val; - u32 reg; - u32 dev; - u8 byte; - u16 word; - u32 dword; - - dev = pDCTstat->dev_dct; - - BankAddrReg = 0; - for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel+=2) { - byte = ChipSel; - if ((pDCTstat->Status & (1 << SB_64MuxedMode)) && ChipSel >=4) - byte -= 3; - - if (pDCTstat->DIMMValid & (1<<byte)) { - byte = pDCTstat->spd_data.spd_bytes[ChipSel + dct][SPD_Addressing]; - Rows = (byte >> 3) & 0x7; /* Rows:0b = 12-bit,... */ - Cols = byte & 0x7; /* Cols:0b = 9-bit,... */ - - byte = pDCTstat->spd_data.spd_bytes[ChipSel + dct][SPD_Density]; - Banks = (byte >> 4) & 7; /* Banks:0b = 3-bit,... */ - - byte = pDCTstat->spd_data.spd_bytes[ChipSel + dct][SPD_Organization]; - Ranks = ((byte >> 3) & 7) + 1; - - /* Configure Bank encoding - * Use a 6-bit key into a lookup table. - * Key (index) = RRRBCC, where CC is the number of Columns minus 9, - * RRR is the number of Rows minus 12, and B is the number of banks - * minus 3. - */ - byte = Cols; - if (Banks == 1) - byte |= 4; - - byte |= Rows << 3; /* RRRBCC internal encode */ - - for (dword = 0; dword < 13; dword++) { - if (byte == Tab_BankAddr[dword]) - break; - } - - if (dword > 12) - continue; - - /* bit no. of CS field in address mapping reg.*/ - dword <<= (ChipSel<<1); - BankAddrReg |= dword; - - /* Mask value=(2pow(rows+cols+banks+3)-1)>>8, - or 2pow(rows+cols+banks-5)-1*/ - csMask = 0; - - byte = Rows + Cols; /* cl = rows+cols*/ - byte += 21; /* row:12+col:9 */ - byte -= 2; /* 3 banks - 5 */ - - if (pDCTstat->Status & (1 << SB_128bitmode)) - byte++; /* double mask size if in 128-bit mode*/ - - csMask |= 1 << byte; - csMask--; - - /*set ChipSelect population indicator even bits*/ - pDCTstat->CSPresent |= (1<<ChipSel); - if (Ranks >= 2) - /*set ChipSelect population indicator odd bits*/ - pDCTstat->CSPresent |= 1 << (ChipSel + 1); - - reg = 0x60+(ChipSel<<1); /*Dram CS Mask Register */ - val = csMask; - val &= 0x1FF83FE0; /* Mask out reserved bits.*/ - Set_NB32_DCT(dev, dct, reg, val); - } else { - if (pDCTstat->DIMMSPDCSE & (1<<ChipSel)) - pDCTstat->CSTestFail |= (1<<ChipSel); - } /* if DIMMValid*/ - } /* while ChipSel*/ - - SetCSTriState(pMCTstat, pDCTstat, dct); - SetCKETriState(pMCTstat, pDCTstat, dct); - SetODTTriState(pMCTstat, pDCTstat, dct); - - if (pDCTstat->Status & (1 << SB_128bitmode)) { - SetCSTriState(pMCTstat, pDCTstat, 1); /* force dct1) */ - SetCKETriState(pMCTstat, pDCTstat, 1); /* force dct1) */ - SetODTTriState(pMCTstat, pDCTstat, 1); /* force dct1) */ - } - - word = pDCTstat->CSPresent; - mctGetCS_ExcludeMap(); /* mask out specified chip-selects */ - word ^= pDCTstat->CSPresent; - pDCTstat->CSTestFail |= word; /* enable ODT to disabled DIMMs */ - if (!pDCTstat->CSPresent) - pDCTstat->ErrCode = SC_StopError; - - reg = 0x80; /* Bank Addressing Register */ - Set_NB32_DCT(dev, dct, reg, BankAddrReg); - - pDCTstat->CSPresent_DCT[dct] = pDCTstat->CSPresent; - /* dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2)); */ - - printk(BIOS_DEBUG, "SPDSetBanks: CSPresent %x\n", pDCTstat->CSPresent_DCT[dct]); - printk(BIOS_DEBUG, "SPDSetBanks: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "SPDSetBanks: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "SPDSetBanks: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "SPDSetBanks: Done\n\n"); -} - -static void SPDCalcWidth_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Per SPDs, check the symmetry of DIMM pairs (DIMM on Channel A - * matching with DIMM on Channel B), the overall DIMM population, - * and determine the width mode: 64-bit, 64-bit muxed, 128-bit. - */ - u8 i; - u8 byte, byte1; - - /* Check Symmetry of Channel A and Channel B DIMMs - (must be matched for 128-bit mode).*/ - for (i = 0; i < MAX_DIMMS_SUPPORTED; i += 2) { - if ((pDCTstat->DIMMValid & (1 << i)) && (pDCTstat->DIMMValid & (1<<(i+1)))) { - byte = pDCTstat->spd_data.spd_bytes[i][SPD_Addressing] & 0x7; - byte1 = pDCTstat->spd_data.spd_bytes[i + 1][SPD_Addressing] & 0x7; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO); - break; - } - - byte = pDCTstat->spd_data.spd_bytes[i][SPD_Density] & 0x0f; - byte1 = pDCTstat->spd_data.spd_bytes[i + 1][SPD_Density] & 0x0f; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO); - break; - } - - byte = pDCTstat->spd_data.spd_bytes[i][SPD_Organization] & 0x7; - byte1 = pDCTstat->spd_data.spd_bytes[i + 1][SPD_Organization] & 0x7; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO); - break; - } - - byte = (pDCTstat->spd_data.spd_bytes[i][SPD_Organization] >> 3) & 0x7; - byte1 = (pDCTstat->spd_data.spd_bytes[i + 1][SPD_Organization] >> 3) & 0x7; - if (byte != byte1) { - pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO); - break; - } - - byte = pDCTstat->spd_data.spd_bytes[i][SPD_DMBANKS] & 7; /* #ranks-1 */ - byte1 = pDCTstat->spd_data.spd_bytes[i + 1][SPD_DMBANKS] & 7; /* #ranks-1 */ - if (byte != byte1) { - pDCTstat->ErrStatus |= (1<<SB_DimmMismatchO); - break; - } - - } - } - -} - -static void StitchMemory_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Requires that Mask values for each bank be programmed first and that - * the chip-select population indicator is correctly set. - */ - u8 b = 0; - u32 nxtcsBase, curcsBase; - u8 p, q; - u32 BiggestBank; - u8 _DSpareEn; - - u16 word; - u32 dev; - u32 reg; - u32 val; - - dev = pDCTstat->dev_dct; - - _DSpareEn = 0; - - /* CS Sparing 1 = enabled, 0 = disabled */ - if (mctGet_NVbits(NV_CS_SpareCTL) & 1) { - if (MCT_DIMM_SPARE_NO_WARM) { - /* Do no warm-reset DIMM spare */ - if (pMCTstat->GStatus & 1 << GSB_EnDIMMSpareNW) { - word = pDCTstat->CSPresent; - val = bsf(word); - word &= ~(1<<val); - if (word) - /* Make sure at least two chip-selects are available */ - _DSpareEn = 1; - else - pDCTstat->ErrStatus |= 1 << SB_SpareDis; - } - } else { - if (!mctGet_NVbits(NV_DQSTrainCTL)) { /*DQS Training 1 = enabled, 0 = disabled */ - word = pDCTstat->CSPresent; - val = bsf(word); - word &= ~(1 << val); - if (word) - /* Make sure at least two chip-selects are available */ - _DSpareEn = 1; - else - pDCTstat->ErrStatus |= 1 << SB_SpareDis; - } - } - } - - nxtcsBase = 0; /* Next available cs base ADDR[39:8] */ - for (p = 0; p < MAX_DIMMS_SUPPORTED; p++) { - BiggestBank = 0; - for (q = 0; q < MAX_CS_SUPPORTED; q++) { /* from DIMMS to CS */ - if (pDCTstat->CSPresent & (1 << q)) { /* bank present? */ - reg = 0x40 + (q << 2); /* Base[q] reg.*/ - val = Get_NB32_DCT(dev, dct, reg); - if (!(val & 3)) { /* (CSEnable|Spare == 1)bank is enabled already? */ - reg = 0x60 + (q << 1); /*Mask[q] reg.*/ - val = Get_NB32_DCT(dev, dct, reg); - val >>= 19; - val++; - val <<= 19; - if (val > BiggestBank) { - /*Bingo! possibly Map this chip-select next! */ - BiggestBank = val; - b = q; - } - } - } /*if bank present */ - } /* while q */ - if (BiggestBank !=0) { - curcsBase = nxtcsBase; /* curcsBase = nxtcsBase*/ - /* DRAM CS Base b Address Register offset */ - reg = 0x40 + (b << 2); - if (_DSpareEn) { - BiggestBank = 0; - val = 1 << Spare; /* Spare Enable*/ - } else { - val = curcsBase; - val |= 1 << CSEnable; /* Bank Enable */ - } - if (((reg - 0x40) >> 2) & 1) { - if (!(pDCTstat->Status & (1 << SB_Registered))) { - u16 dimValid; - dimValid = pDCTstat->DIMMValid; - if (dct & 1) - dimValid <<= 1; - if ((dimValid & pDCTstat->MirrPresU_NumRegR) != 0) { - val |= 1 << onDimmMirror; - } - } - } - Set_NB32_DCT(dev, dct, reg, val); - if (_DSpareEn) - _DSpareEn = 0; - else - /* let nxtcsBase+=Size[b] */ - nxtcsBase += BiggestBank; - } - - /* bank present but disabled?*/ - if (pDCTstat->CSTestFail & (1 << p)) { - /* DRAM CS Base b Address Register offset */ - reg = (p << 2) + 0x40; - val = 1 << TestFail; - Set_NB32_DCT(dev, dct, reg, val); - } - } - - if (nxtcsBase) { - pDCTstat->DCTSysLimit = nxtcsBase - 1; - mct_AfterStitchMemory(pMCTstat, pDCTstat, dct); - } - - /* dump_pci_device(PCI_DEV(0, 0x18+pDCTstat->Node_ID, 2)); */ - - printk(BIOS_DEBUG, "StitchMemory: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "StitchMemory: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "StitchMemory: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "StitchMemory: Done\n\n"); -} - -static u16 Get_Fk_D(u8 k) -{ - return Table_F_k[k]; /* FIXME: k or k<<1 ? */ -} - -static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Check DIMMs present, verify checksum, flag SDRAM type, - * build population indicator bitmaps, and preload bus loading - * of DIMMs into DCTStatStruc. - * MAAload = number of devices on the "A" bus. - * MABload = number of devices on the "B" bus. - * MAAdimms = number of DIMMs on the "A" bus slots. - * MABdimms = number of DIMMs on the "B" bus slots. - * DATAAload = number of ranks on the "A" bus slots. - * DATABload = number of ranks on the "B" bus slots. - */ - u16 i, j, k; - u8 smbaddr; - u8 SPDCtrl; - u16 RegDIMMPresent, LRDIMMPresent, MaxDimms; - u8 devwidth; - u16 DimmSlots; - u8 byte = 0, bytex; - uint8_t crc_status; - - /* preload data structure with addrs */ - mctGet_DIMMAddr(pDCTstat, pDCTstat->Node_ID); - - DimmSlots = MaxDimms = mctGet_NVbits(NV_MAX_DIMMS); - - SPDCtrl = mctGet_NVbits(NV_SPDCHK_RESTRT); - - RegDIMMPresent = 0; - LRDIMMPresent = 0; - pDCTstat->DimmQRPresent = 0; - - for (i = 0; i < MAX_DIMMS_SUPPORTED; i++) { - if (i >= MaxDimms) - break; - - if ((pDCTstat->DimmQRPresent & (1 << i)) || (i < DimmSlots)) { - int status; - smbaddr = Get_DIMMAddress_D(pDCTstat, i); - status = mctRead_SPD(smbaddr, SPD_ByteUse); - if (status >= 0) { - /* Verify result */ - status = mctRead_SPD(smbaddr, SPD_ByteUse); - } - if (status >= 0) { /* SPD access is ok */ - pDCTstat->DIMMPresent |= 1 << i; - read_spd_bytes(pMCTstat, pDCTstat, i); -#ifdef DEBUG_DIMM_SPD - dump_spd_bytes(pMCTstat, pDCTstat, i); -#endif - crc_status = crcCheck(pDCTstat, i); - if (!crc_status) { - /* Try again in case there was a transient glitch */ - read_spd_bytes(pMCTstat, pDCTstat, i); - crc_status = crcCheck(pDCTstat, i); - } - if ((crc_status) || (SPDCtrl == 2)) { /* CRC is OK */ - byte = pDCTstat->spd_data.spd_bytes[i][SPD_TYPE]; - if (byte == JED_DDR3SDRAM) { - /*Dimm is 'Present'*/ - pDCTstat->DIMMValid |= 1 << i; - } - } else { - printk(BIOS_WARNING, "Node %d DIMM %d: SPD checksum invalid\n", pDCTstat->Node_ID, i); - pDCTstat->DIMMSPDCSE = 1 << i; - if (SPDCtrl == 0) { - pDCTstat->ErrStatus |= 1 << SB_DIMMChkSum; - pDCTstat->ErrCode = SC_StopError; - } else { - /*if NV_SPDCHK_RESTRT is set to 1, ignore faulty SPD checksum*/ - pDCTstat->ErrStatus |= 1<<SB_DIMMChkSum; - byte = pDCTstat->spd_data.spd_bytes[i][SPD_TYPE]; - if (byte == JED_DDR3SDRAM) - pDCTstat->DIMMValid |= 1 << i; - } - } - - /* Zero DIMM SPD data cache if DIMM not present / valid */ - if (!(pDCTstat->DIMMValid & (1 << i))) - memset(pDCTstat->spd_data.spd_bytes[i], 0, sizeof(pDCTstat->spd_data.spd_bytes[i])); - - /* Get module information for SMBIOS */ - if (pDCTstat->DIMMValid & (1 << i)) { - pDCTstat->DimmManufacturerID[i] = 0; - for (k = 0; k < 8; k++) - pDCTstat->DimmManufacturerID[i] |= ((uint64_t)pDCTstat->spd_data.spd_bytes[i][SPD_MANID_START + k]) << (k * 8); - for (k = 0; k < SPD_PARTN_LENGTH; k++) - pDCTstat->DimmPartNumber[i][k] = pDCTstat->spd_data.spd_bytes[i][SPD_PARTN_START + k]; - pDCTstat->DimmPartNumber[i][SPD_PARTN_LENGTH] = 0; - pDCTstat->DimmRevisionNumber[i] = 0; - for (k = 0; k < 2; k++) - pDCTstat->DimmRevisionNumber[i] |= ((uint16_t)pDCTstat->spd_data.spd_bytes[i][SPD_REVNO_START + k]) << (k * 8); - pDCTstat->DimmSerialNumber[i] = 0; - for (k = 0; k < 4; k++) - pDCTstat->DimmSerialNumber[i] |= ((uint32_t)pDCTstat->spd_data.spd_bytes[i][SPD_SERIAL_START + k]) << (k * 8); - pDCTstat->DimmRows[i] = (pDCTstat->spd_data.spd_bytes[i][SPD_Addressing] & 0x38) >> 3; - pDCTstat->DimmCols[i] = pDCTstat->spd_data.spd_bytes[i][SPD_Addressing] & 0x7; - pDCTstat->DimmRanks[i] = ((pDCTstat->spd_data.spd_bytes[i][SPD_Organization] & 0x38) >> 3) + 1; - pDCTstat->DimmBanks[i] = 1ULL << (((pDCTstat->spd_data.spd_bytes[i][SPD_Density] & 0x70) >> 4) + 3); - pDCTstat->DimmWidth[i] = 1ULL << ((pDCTstat->spd_data.spd_bytes[i][SPD_BusWidth] & 0x7) + 3); - pDCTstat->DimmChipSize[i] = 1ULL << ((pDCTstat->spd_data.spd_bytes[i][SPD_Density] & 0xf) + 28); - pDCTstat->DimmChipWidth[i] = 1ULL << ((pDCTstat->spd_data.spd_bytes[i][SPD_Organization] & 0x7) + 2); - } - /* Check supported voltage(s) */ - pDCTstat->DimmSupportedVoltages[i] = pDCTstat->spd_data.spd_bytes[i][SPD_Voltage] & 0x7; - pDCTstat->DimmSupportedVoltages[i] ^= 0x1; /* Invert LSB to convert from SPD format to internal bitmap format */ - /* Check module type */ - byte = pDCTstat->spd_data.spd_bytes[i][SPD_DIMMTYPE] & 0x7; - if (byte == JED_RDIMM || byte == JED_MiniRDIMM) { - RegDIMMPresent |= 1 << i; - pDCTstat->DimmRegistered[i] = 1; - } else { - pDCTstat->DimmRegistered[i] = 0; - } - if (byte == JED_LRDIMM) { - LRDIMMPresent |= 1 << i; - pDCTstat->DimmLoadReduced[i] = 1; - } else { - pDCTstat->DimmLoadReduced[i] = 0; - } - /* Check ECC capable */ - byte = pDCTstat->spd_data.spd_bytes[i][SPD_BusWidth]; - if (byte & JED_ECC) { - /* DIMM is ECC capable */ - pDCTstat->DimmECCPresent |= 1 << i; - } - /* Check if x4 device */ - devwidth = pDCTstat->spd_data.spd_bytes[i][SPD_Organization] & 0x7; /* 0:x4,1:x8,2:x16 */ - if (devwidth == 0) { - /* DIMM is made with x4 or x16 drams */ - pDCTstat->Dimmx4Present |= 1 << i; - } else if (devwidth == 1) { - pDCTstat->Dimmx8Present |= 1 << i; - } else if (devwidth == 2) { - pDCTstat->Dimmx16Present |= 1 << i; - } - - byte = (pDCTstat->spd_data.spd_bytes[i][SPD_Organization] >> 3); - byte &= 7; - if (byte == 3) { /* 4ranks */ - /* if any DIMMs are QR, we have to make two passes through DIMMs*/ - if (pDCTstat->DimmQRPresent == 0) { - MaxDimms <<= 1; - } - if (i < DimmSlots) { - pDCTstat->DimmQRPresent |= (1 << i) | (1 << (i+4)); - } else { - pDCTstat->MAdimms[i & 1] --; - } - byte = 1; /* upper two ranks of QR DIMM will be counted on another DIMM number iteration*/ - } else if (byte == 1) { /* 2ranks */ - pDCTstat->DimmDRPresent |= 1 << i; - } - bytex = devwidth; - if (devwidth == 0) - bytex = 16; - else if (devwidth == 1) - bytex = 8; - else if (devwidth == 2) - bytex = 4; - - byte++; /* al+1 = rank# */ - if (byte == 2) - bytex <<= 1; /*double Addr bus load value for dual rank DIMMs*/ - - j = i & (1<<0); - pDCTstat->DATAload[j] += byte; /*number of ranks on DATA bus*/ - pDCTstat->MAload[j] += bytex; /*number of devices on CMD/ADDR bus*/ - pDCTstat->MAdimms[j]++; /*number of DIMMs on A bus */ - - /* check address mirror support for unbuffered dimm */ - /* check number of registers on a dimm for registered dimm */ - byte = pDCTstat->spd_data.spd_bytes[i][SPD_AddressMirror]; - if (RegDIMMPresent & (1 << i)) { - if ((byte & 3) > 1) - pDCTstat->MirrPresU_NumRegR |= 1 << i; - } else { - if ((byte & 1) == 1) - pDCTstat->MirrPresU_NumRegR |= 1 << i; - } - /* Get byte62: Reference Raw Card information. We dont need it now. */ - /* byte = pDCTstat->spd_data.spd_bytes[i][SPD_RefRawCard]; */ - /* Get Byte65/66 for register manufacture ID code */ - if ((0x97 == pDCTstat->spd_data.spd_bytes[i][SPD_RegManufactureID_H]) && - (0x80 == pDCTstat->spd_data.spd_bytes[i][SPD_RegManufactureID_L])) { - if (0x16 == pDCTstat->spd_data.spd_bytes[i][SPD_RegManRevID]) - pDCTstat->RegMan2Present |= 1 << i; - else - pDCTstat->RegMan1Present |= 1 << i; - } - /* Get control word value for RC3 */ - byte = pDCTstat->spd_data.spd_bytes[i][70]; - pDCTstat->CtrlWrd3 |= ((byte >> 4) & 0xf) << (i << 2); /* RC3 = SPD byte 70 [7:4] */ - /* Get control word values for RC4 and RC5 */ - byte = pDCTstat->spd_data.spd_bytes[i][71]; - pDCTstat->CtrlWrd4 |= (byte & 0xf) << (i << 2); /* RC4 = SPD byte 71 [3:0] */ - pDCTstat->CtrlWrd5 |= ((byte >> 4) & 0xf) << (i << 2); /* RC5 = SPD byte 71 [7:4] */ - } - } - } - printk(BIOS_DEBUG, "\t DIMMPresence: DIMMValid=%x\n", pDCTstat->DIMMValid); - printk(BIOS_DEBUG, "\t DIMMPresence: DIMMPresent=%x\n", pDCTstat->DIMMPresent); - printk(BIOS_DEBUG, "\t DIMMPresence: RegDIMMPresent=%x\n", RegDIMMPresent); - printk(BIOS_DEBUG, "\t DIMMPresence: LRDIMMPresent=%x\n", LRDIMMPresent); - printk(BIOS_DEBUG, "\t DIMMPresence: DimmECCPresent=%x\n", pDCTstat->DimmECCPresent); - printk(BIOS_DEBUG, "\t DIMMPresence: DimmPARPresent=%x\n", pDCTstat->DimmPARPresent); - printk(BIOS_DEBUG, "\t DIMMPresence: Dimmx4Present=%x\n", pDCTstat->Dimmx4Present); - printk(BIOS_DEBUG, "\t DIMMPresence: Dimmx8Present=%x\n", pDCTstat->Dimmx8Present); - printk(BIOS_DEBUG, "\t DIMMPresence: Dimmx16Present=%x\n", pDCTstat->Dimmx16Present); - printk(BIOS_DEBUG, "\t DIMMPresence: DimmPlPresent=%x\n", pDCTstat->DimmPlPresent); - printk(BIOS_DEBUG, "\t DIMMPresence: DimmDRPresent=%x\n", pDCTstat->DimmDRPresent); - printk(BIOS_DEBUG, "\t DIMMPresence: DimmQRPresent=%x\n", pDCTstat->DimmQRPresent); - printk(BIOS_DEBUG, "\t DIMMPresence: DATAload[0]=%x\n", pDCTstat->DATAload[0]); - printk(BIOS_DEBUG, "\t DIMMPresence: MAload[0]=%x\n", pDCTstat->MAload[0]); - printk(BIOS_DEBUG, "\t DIMMPresence: MAdimms[0]=%x\n", pDCTstat->MAdimms[0]); - printk(BIOS_DEBUG, "\t DIMMPresence: DATAload[1]=%x\n", pDCTstat->DATAload[1]); - printk(BIOS_DEBUG, "\t DIMMPresence: MAload[1]=%x\n", pDCTstat->MAload[1]); - printk(BIOS_DEBUG, "\t DIMMPresence: MAdimms[1]=%x\n", pDCTstat->MAdimms[1]); - - if (pDCTstat->DIMMValid != 0) { /* If any DIMMs are present...*/ - if (RegDIMMPresent != 0) { - if ((RegDIMMPresent ^ pDCTstat->DIMMValid) !=0) { - /* module type DIMM mismatch (reg'ed, unbuffered) */ - pDCTstat->ErrStatus |= 1<<SB_DimmMismatchM; - pDCTstat->ErrCode = SC_StopError; - } else{ - /* all DIMMs are registered */ - pDCTstat->Status |= 1<<SB_Registered; - } - } - if (LRDIMMPresent != 0) { - if ((LRDIMMPresent ^ pDCTstat->DIMMValid) !=0) { - /* module type DIMM mismatch (reg'ed, unbuffered) */ - pDCTstat->ErrStatus |= 1<<SB_DimmMismatchM; - pDCTstat->ErrCode = SC_StopError; - } else{ - /* all DIMMs are registered */ - pDCTstat->Status |= 1<<SB_LoadReduced; - } - } - if (pDCTstat->DimmECCPresent != 0) { - if ((pDCTstat->DimmECCPresent ^ pDCTstat->DIMMValid) == 0) { - /* all DIMMs are ECC capable */ - pDCTstat->Status |= 1<<SB_ECCDIMMs; - } - } - if (pDCTstat->DimmPARPresent != 0) { - if ((pDCTstat->DimmPARPresent ^ pDCTstat->DIMMValid) == 0) { - /*all DIMMs are Parity capable */ - pDCTstat->Status |= 1<<SB_PARDIMMs; - } - } - } else { - /* no DIMMs present or no DIMMs that qualified. */ - pDCTstat->ErrStatus |= 1<<SB_NoDimms; - pDCTstat->ErrCode = SC_StopError; - } - - printk(BIOS_DEBUG, "\t DIMMPresence: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "\t DIMMPresence: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "\t DIMMPresence: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "\t DIMMPresence: Done\n\n"); - - mctHookAfterDIMMpre(); - - return pDCTstat->ErrCode; -} - -static u8 Get_DIMMAddress_D(struct DCTStatStruc *pDCTstat, u8 i) -{ - u8 *p; - - p = pDCTstat->DIMMAddr; - /* mct_BeforeGetDIMMAddress(); */ - return p[i]; -} - -static void mct_preInitDCT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 err_code; - uint8_t nvram; - uint8_t allow_config_restore; - - /* Preconfigure DCT0 */ - DCTPreInit_D(pMCTstat, pDCTstat, 0); - - /* Configure DCT1 if unganged and enabled*/ - if (!pDCTstat->GangedMode) { - if (pDCTstat->DIMMValidDCT[1] > 0) { - err_code = pDCTstat->ErrCode; /* save DCT0 errors */ - pDCTstat->ErrCode = 0; - DCTPreInit_D(pMCTstat, pDCTstat, 1); - if (pDCTstat->ErrCode == 2) /* DCT1 is not Running */ - pDCTstat->ErrCode = err_code; /* Using DCT0 Error code to update pDCTstat.ErrCode */ - } - } - -#if CONFIG(HAVE_ACPI_RESUME) - calculate_and_store_spd_hashes(pMCTstat, pDCTstat); - - if (load_spd_hashes_from_nvram(pMCTstat, pDCTstat) < 0) { - pDCTstat->spd_data.nvram_spd_match = 0; - } else { - compare_nvram_spd_hashes(pMCTstat, pDCTstat); - } -#else - pDCTstat->spd_data.nvram_spd_match = 0; -#endif - - /* Check to see if restoration of SPD data from NVRAM is allowed */ - allow_config_restore = 0; - if (get_option(&nvram, "allow_spd_nvram_cache_restore") == CB_SUCCESS) - allow_config_restore = !!nvram; - -#if CONFIG(HAVE_ACPI_RESUME) - if (pMCTstat->nvram_checksum != calculate_nvram_mct_hash()) - allow_config_restore = 0; -#else - allow_config_restore = 0; -#endif - - if (!allow_config_restore) - pDCTstat->spd_data.nvram_spd_match = 0; -} - -static void mct_initDCT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 val; - u8 err_code; - - /* Config. DCT0 for Ganged or unganged mode */ - DCTInit_D(pMCTstat, pDCTstat, 0); - DCTFinalInit_D(pMCTstat, pDCTstat, 0); - if (pDCTstat->ErrCode == SC_FatalErr) { - /* Do nothing goto exitDCTInit; any fatal errors? */ - } else { - /* Configure DCT1 if unganged and enabled */ - if (!pDCTstat->GangedMode) { - if (pDCTstat->DIMMValidDCT[1] > 0) { - err_code = pDCTstat->ErrCode; /* save DCT0 errors */ - pDCTstat->ErrCode = 0; - DCTInit_D(pMCTstat, pDCTstat, 1); - DCTFinalInit_D(pMCTstat, pDCTstat, 1); - if (pDCTstat->ErrCode == 2) /* DCT1 is not Running */ - pDCTstat->ErrCode = err_code; /* Using DCT0 Error code to update pDCTstat.ErrCode */ - } else { - val = 1 << DisDramInterface; - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val); - - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - val &= ~(1 << ParEn); - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, val); - - /* To maximize power savings when DisDramInterface = 1b, - * all of the MemClkDis bits should also be set. - */ - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x88, 0xff000000); - } - } - } -} - -static void mct_DramInit(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - mct_BeforeDramInit_Prod_D(pMCTstat, pDCTstat, dct); - mct_DramInit_Sw_D(pMCTstat, pDCTstat, dct); - /* mct_DramInit_Hw_D(pMCTstat, pDCTstat, dct); */ -} - -static u8 mct_setMode(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 byte; - u8 bytex; - u32 val; - u32 reg; - - byte = bytex = pDCTstat->DIMMValid; - bytex &= 0x55; /* CHA DIMM pop */ - pDCTstat->DIMMValidDCT[0] = bytex; - - byte &= 0xAA; /* CHB DIMM popa */ - byte >>= 1; - pDCTstat->DIMMValidDCT[1] = byte; - - if (byte != bytex) { - pDCTstat->ErrStatus &= ~(1 << SB_DimmMismatchO); - } else { - byte = mctGet_NVbits(NV_Unganged); - if (byte) - pDCTstat->ErrStatus |= (1 << SB_DimmMismatchO); /* Set temp. to avoid setting of ganged mode */ - - if ((!(pDCTstat->ErrStatus & (1 << SB_DimmMismatchO))) && (pDCTstat->LogicalCPUID & AMD_FAM10_ALL)) { - /* Ganged channel mode not supported on Family 15h or higher */ - pDCTstat->GangedMode = 1; - /* valid 128-bit mode population. */ - pDCTstat->Status |= 1 << SB_128bitmode; - reg = 0x110; - val = Get_NB32(pDCTstat->dev_dct, reg); - val |= 1 << DctGangEn; - Set_NB32(pDCTstat->dev_dct, reg, val); - } - if (byte) /* NV_Unganged */ - pDCTstat->ErrStatus &= ~(1 << SB_DimmMismatchO); /* Clear so that there is no DIMM mismatch error */ - } - - return pDCTstat->ErrCode; -} - -u32 Get_NB32(u32 dev, u32 reg) -{ - return pci_read_config32(dev, reg); -} - -void Set_NB32(u32 dev, u32 reg, u32 val) -{ - pci_write_config32(dev, reg, val); -} - - -u32 Get_NB32_index(u32 dev, u32 index_reg, u32 index) -{ - u32 dword; - - Set_NB32(dev, index_reg, index); - dword = Get_NB32(dev, index_reg+0x4); - - return dword; -} - -void Set_NB32_index(u32 dev, u32 index_reg, u32 index, u32 data) -{ - Set_NB32(dev, index_reg, index); - Set_NB32(dev, index_reg + 0x4, data); -} - -u32 Get_NB32_index_wait(u32 dev, u32 index_reg, u32 index) -{ - u32 dword; - - index &= ~(1 << DctAccessWrite); - Set_NB32(dev, index_reg, index); - do { - dword = Get_NB32(dev, index_reg); - } while (!(dword & (1 << DctAccessDone))); - dword = Get_NB32(dev, index_reg + 0x4); - - return dword; -} - -void Set_NB32_index_wait(u32 dev, u32 index_reg, u32 index, u32 data) -{ - u32 dword; - - Set_NB32(dev, index_reg + 0x4, data); - index |= (1 << DctAccessWrite); - Set_NB32(dev, index_reg, index); - do { - dword = Get_NB32(dev, index_reg); - } while (!(dword & (1 << DctAccessDone))); - -} - -u8 mct_BeforePlatformSpec(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - /* mct_checkForCxDxSupport_D */ - if (pDCTstat->LogicalCPUID & AMD_DR_GT_Bx) { - /* Family 10h Errata 322: Address and Command Fine Delay Values May Be Incorrect */ - /* 1. Write 00000000h to F2x[1,0]9C_xD08E000 */ - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, 0x98, 0x0D08E000, 0); - /* 2. If DRAM Configuration Register[MemClkFreq] (F2x[1,0]94[2:0]) is - greater than or equal to 011b (DDR-800 and higher), - then write 00000080h to F2x[1,0]9C_xD02E001, - else write 00000090h to F2x[1,0]9C_xD02E001. */ - if (pDCTstat->Speed >= mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, 0x98, 0x0D02E001, 0x80); - else - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, 0x98, 0x0D02E001, 0x90); - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); - - return pDCTstat->ErrCode; -} - -u8 mct_PlatformSpec(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - /* Get platform specific config/timing values from the interface layer - * and program them into DCT. - */ - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - u32 dev = pDCTstat->dev_dct; - u32 index_reg; - u8 i, i_start, i_end; - - if (pDCTstat->GangedMode) { - SyncSetting(pDCTstat); - /* mct_SetupSync_D */ - i_start = 0; - i_end = 2; - } else { - i_start = dct; - i_end = dct + 1; - } - for (i = i_start; i < i_end; i++) { - index_reg = 0x98; - Set_NB32_index_wait_DCT(dev, i, index_reg, 0x00, pDCTstat->CH_ODC_CTL[i]); /* Channel A/B Output Driver Compensation Control */ - Set_NB32_index_wait_DCT(dev, i, index_reg, 0x04, pDCTstat->CH_ADDR_TMG[i]); /* Channel A/B Output Driver Compensation Control */ - printk(BIOS_SPEW, "Programmed DCT %d timing/termination pattern %08x %08x\n", dct, pDCTstat->CH_ADDR_TMG[i], pDCTstat->CH_ODC_CTL[i]); - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); - - return pDCTstat->ErrCode; -} - -static void mct_SyncDCTsReady(struct DCTStatStruc *pDCTstat) -{ - u32 dev; - u32 val; - - if (pDCTstat->NodePresent) { - dev = pDCTstat->dev_dct; - - if ((pDCTstat->DIMMValidDCT[0]) || (pDCTstat->DIMMValidDCT[1])) { - /* This Node has DRAM */ - do { - val = Get_NB32(dev, 0x110); - } while (!(val & (1 << DramEnabled))); - } - } /* Node is present */ -} - -static void mct_AfterGetCLT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - if (!pDCTstat->GangedMode) { - if (dct == 0) { - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct]; - if (pDCTstat->DIMMValidDCT[dct] == 0) - pDCTstat->ErrCode = SC_StopError; - } else { - pDCTstat->CSPresent = 0; - pDCTstat->CSTestFail = 0; - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[dct]; - if (pDCTstat->DIMMValidDCT[dct] == 0) - pDCTstat->ErrCode = SC_StopError; - } - } -} - -static u8 mct_SPDCalcWidth(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 ret; - u32 val; - - if (dct == 0) { - SPDCalcWidth_D(pMCTstat, pDCTstat); - ret = mct_setMode(pMCTstat, pDCTstat); - } else { - ret = pDCTstat->ErrCode; - } - - if (pDCTstat->DIMMValidDCT[0] == 0) { - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94); - val |= 1 << DisDramInterface; - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, val); - - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90); - val &= ~(1 << ParEn); - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, val); - } - if (pDCTstat->DIMMValidDCT[1] == 0) { - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94); - val |= 1 << DisDramInterface; - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val); - - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - val &= ~(1 << ParEn); - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, val); - } - - printk(BIOS_DEBUG, "SPDCalcWidth: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "SPDCalcWidth: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "SPDCalcWidth: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "SPDCalcWidth: Done\n"); - /* Disable dram interface before DRAM init */ - - return ret; -} - -static void mct_AfterStitchMemory(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dword; - u32 dev; - u32 reg; - u8 _MemHoleRemap; - u32 DramHoleBase; - - _MemHoleRemap = mctGet_NVbits(NV_MemHole); - DramHoleBase = mctGet_NVbits(NV_BottomIO); - DramHoleBase <<= 8; - /* Increase hole size so;[31:24]to[31:16] - * it has granularity of 128MB shl eax,8 - * Set 'effective' bottom IOmov DramHoleBase,eax - */ - pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8; - - /* In unganged mode, we must add DCT0 and DCT1 to DCTSysLimit */ - if (!pDCTstat->GangedMode) { - dev = pDCTstat->dev_dct; - pDCTstat->NodeSysLimit += pDCTstat->DCTSysLimit; - /* if DCT0 and DCT1 both exist, set DctSelBaseAddr[47:27] to the top of DCT0 */ - if (dct == 0) { - if (pDCTstat->DIMMValidDCT[1] > 0) { - dword = pDCTstat->DCTSysLimit + 1; - dword += pDCTstat->NodeSysBase; - dword >>= 8; /* scale [39:8] to [47:27],and to F2x110[31:11] */ - if ((dword >= DramHoleBase) && _MemHoleRemap) { - pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8; - val = pMCTstat->HoleBase; - val >>= 16; - val = (((~val) & 0xFF) + 1); - val <<= 8; - dword += val; - } - reg = 0x110; - val = Get_NB32(dev, reg); - val &= 0x7F; - val |= dword; - val |= 3; /* Set F2x110[DctSelHiRngEn], F2x110[DctSelHi] */ - Set_NB32(dev, reg, val); - - reg = 0x114; - val = dword; - Set_NB32(dev, reg, val); - } - } else { - /* Program the DctSelBaseAddr value to 0 - if DCT 0 is disabled */ - if (pDCTstat->DIMMValidDCT[0] == 0) { - dword = pDCTstat->NodeSysBase; - dword >>= 8; - if ((dword >= DramHoleBase) && _MemHoleRemap) { - pMCTstat->HoleBase = (DramHoleBase & 0xFFFFF800) << 8; - val = pMCTstat->HoleBase; - val >>= 8; - val &= ~(0xFFFF); - val |= (((~val) & 0xFFFF) + 1); - dword += val; - } - reg = 0x114; - val = dword; - Set_NB32(dev, reg, val); - - reg = 0x110; - val |= 3; /* Set F2x110[DctSelHiRngEn], F2x110[DctSelHi] */ - Set_NB32(dev, reg, val); - } - } - } else { - pDCTstat->NodeSysLimit += pDCTstat->DCTSysLimit; - } - printk(BIOS_DEBUG, "AfterStitch pDCTstat->NodeSysBase = %x\n", pDCTstat->NodeSysBase); - printk(BIOS_DEBUG, "mct_AfterStitchMemory: pDCTstat->NodeSysLimit = %x\n", pDCTstat->NodeSysLimit); -} - -static u8 mct_DIMMPresence(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 ret; - - if (dct == 0) - ret = DIMMPresence_D(pMCTstat, pDCTstat); - else - ret = pDCTstat->ErrCode; - - return ret; -} - -/* mct_BeforeGetDIMMAddress inline in C */ - -static void mct_OtherTiming(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) { - if (pDCTstat->DIMMValidDCT[0]) { - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[0]; - Set_OtherTiming(pMCTstat, pDCTstat, 0); - } - if (pDCTstat->DIMMValidDCT[1] && !pDCTstat->GangedMode) { - pDCTstat->DIMMValid = pDCTstat->DIMMValidDCT[1]; - Set_OtherTiming(pMCTstat, pDCTstat, 1); - } - } /* Node is present*/ - } /* while Node */ -} - -static void Set_OtherTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 reg; - u32 val; - u32 dword; - u32 dev = pDCTstat->dev_dct; - - Get_DqsRcvEnGross_Diff(pDCTstat, dev, dct, 0x98); - Get_WrDatGross_Diff(pDCTstat, dct, dev, 0x98); - Get_Trdrd(pMCTstat, pDCTstat, dct); - Get_Twrwr(pMCTstat, pDCTstat, dct); - Get_Twrrd(pMCTstat, pDCTstat, dct); - Get_TrwtTO(pMCTstat, pDCTstat, dct); - Get_TrwtWB(pMCTstat, pDCTstat); - - if (!is_fam15h()) { - reg = 0x8c; /* Dram Timing Hi */ - val = Get_NB32_DCT(dev, dct, reg); - val &= 0xffff0300; - dword = pDCTstat->TrwtTO; - val |= dword << 4; - dword = pDCTstat->Twrrd & 3; - val |= dword << 10; - dword = pDCTstat->Twrwr & 3; - val |= dword << 12; - dword = (pDCTstat->Trdrd - 0x3) & 3; - val |= dword << 14; - dword = pDCTstat->TrwtWB; - val |= dword; - Set_NB32_DCT(dev, dct, reg, val); - - reg = 0x78; - val = Get_NB32_DCT(dev, dct, reg); - val &= 0xffffc0ff; - dword = pDCTstat->Twrrd >> 2; - val |= dword << 8; - dword = pDCTstat->Twrwr >> 2; - val |= dword << 10; - dword = (pDCTstat->Trdrd - 0x3) >> 2; - val |= dword << 12; - Set_NB32_DCT(dev, dct, reg, val); - } -} - -static void Get_Trdrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - int8_t Trdrd; - - Trdrd = ((int8_t)(pDCTstat->DqsRcvEnGrossMax - pDCTstat->DqsRcvEnGrossMin) >> 1) + 1; - if (Trdrd > 8) - Trdrd = 8; - if (Trdrd < 3) - Trdrd = 3; - pDCTstat->Trdrd = Trdrd; -} - -static void Get_Twrwr(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - int8_t Twrwr = 0; - - Twrwr = ((int8_t)(pDCTstat->WrDatGrossMax - pDCTstat->WrDatGrossMin) >> 1) + 2; - - if (Twrwr < 2) - Twrwr = 2; - else if (Twrwr > 9) - Twrwr = 9; - - pDCTstat->Twrwr = Twrwr; -} - -static void Get_Twrrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 LDplus1; - int8_t Twrrd; - - LDplus1 = Get_Latency_Diff(pMCTstat, pDCTstat, dct); - - Twrrd = ((int8_t)(pDCTstat->WrDatGrossMax - pDCTstat->DqsRcvEnGrossMin) >> 1) + 4 - LDplus1; - - if (Twrrd < 2) - Twrrd = 2; - else if (Twrrd > 10) - Twrrd = 10; - pDCTstat->Twrrd = Twrrd; -} - -static void Get_TrwtTO(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 LDplus1; - int8_t TrwtTO; - - LDplus1 = Get_Latency_Diff(pMCTstat, pDCTstat, dct); - - TrwtTO = ((int8_t)(pDCTstat->DqsRcvEnGrossMax - pDCTstat->WrDatGrossMin) >> 1) + LDplus1; - - pDCTstat->TrwtTO = TrwtTO; -} - -static void Get_TrwtWB(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* TrwtWB ensures read-to-write data-bus turnaround. - This value should be one more than the programmed TrwtTO.*/ - pDCTstat->TrwtWB = pDCTstat->TrwtTO; -} - -static u8 Get_Latency_Diff(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 dev = pDCTstat->dev_dct; - u32 val1, val2; - - val1 = Get_NB32_DCT(dev, dct, 0x88) & 0xF; - val2 = (Get_NB32_DCT(dev, dct, 0x84) >> 20) & 7; - - return val1 - val2; -} - -static void Get_DqsRcvEnGross_Diff(struct DCTStatStruc *pDCTstat, - u32 dev, uint8_t dct, u32 index_reg) -{ - u8 Smallest, Largest; - u32 val; - u8 byte, bytex; - - /* The largest DqsRcvEnGrossDelay of any DIMM minus the - DqsRcvEnGrossDelay of any other DIMM is equal to the Critical - Gross Delay Difference (CGDD) */ - /* DqsRcvEn byte 1,0 */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, dct, index_reg, 0x10); - Largest = val & 0xFF; - Smallest = (val >> 8) & 0xFF; - - /* DqsRcvEn byte 3,2 */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, dct, index_reg, 0x11); - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - - /* DqsRcvEn byte 5,4 */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, dct, index_reg, 0x20); - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - - /* DqsRcvEn byte 7,6 */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, dct, index_reg, 0x21); - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - - if (pDCTstat->DimmECCPresent> 0) { - /*DqsRcvEn Ecc */ - val = Get_DqsRcvEnGross_MaxMin(pDCTstat, dev, dct, index_reg, 0x12); - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - } - - pDCTstat->DqsRcvEnGrossMax = Largest; - pDCTstat->DqsRcvEnGrossMin = Smallest; -} - -static void Get_WrDatGross_Diff(struct DCTStatStruc *pDCTstat, - u8 dct, u32 dev, u32 index_reg) -{ - u8 Smallest = 0, Largest = 0; - u32 val; - u8 byte, bytex; - - /* The largest WrDatGrossDlyByte of any DIMM minus the - WrDatGrossDlyByte of any other DIMM is equal to CGDD */ - if (pDCTstat->DIMMValid & (1 << 0)) { - val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x01); /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM0 */ - Largest = val & 0xFF; - Smallest = (val >> 8) & 0xFF; - } - if (pDCTstat->DIMMValid & (1 << 2)) { - val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x101); /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM1 */ - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - } - - /* If Cx, 2 more dimm need to be checked to find out the largest and smallest */ - if (pDCTstat->LogicalCPUID & AMD_DR_Cx) { - if (pDCTstat->DIMMValid & (1 << 4)) { - val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x201); /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM2 */ - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - } - if (pDCTstat->DIMMValid & (1 << 6)) { - val = Get_WrDatGross_MaxMin(pDCTstat, dct, dev, index_reg, 0x301); /* WrDatGrossDlyByte byte 0,1,2,3 for DIMM2 */ - byte = val & 0xFF; - bytex = (val >> 8) & 0xFF; - if (bytex < Smallest) - Smallest = bytex; - if (byte > Largest) - Largest = byte; - } - } - - pDCTstat->WrDatGrossMax = Largest; - pDCTstat->WrDatGrossMin = Smallest; -} - -static u16 Get_DqsRcvEnGross_MaxMin(struct DCTStatStruc *pDCTstat, - u32 dev, uint8_t dct, u32 index_reg, - u32 index) -{ - u8 Smallest, Largest; - u8 i; - u8 byte; - u32 val; - u16 word; - u8 ecc_reg = 0; - - Smallest = 7; - Largest = 0; - - if (index == 0x12) - ecc_reg = 1; - - for (i = 0; i < 8; i+=2) { - if (pDCTstat->DIMMValid & (1 << i)) { - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index); - val &= 0x00E000E0; - byte = (val >> 5) & 0xFF; - if (byte < Smallest) - Smallest = byte; - if (byte > Largest) - Largest = byte; - if (!(ecc_reg)) { - byte = (val >> (16 + 5)) & 0xFF; - if (byte < Smallest) - Smallest = byte; - if (byte > Largest) - Largest = byte; - } - } - index += 3; - } /* while ++i */ - - word = Smallest; - word <<= 8; - word |= Largest; - - return word; -} - -static u16 Get_WrDatGross_MaxMin(struct DCTStatStruc *pDCTstat, - u8 dct, u32 dev, u32 index_reg, - u32 index) -{ - u8 Smallest, Largest; - u8 i, j; - u32 val; - u8 byte; - u16 word; - - Smallest = 3; - Largest = 0; - for (i = 0; i < 2; i++) { - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index); - val &= 0x60606060; - val >>= 5; - for (j = 0; j < 4; j++) { - byte = val & 0xFF; - if (byte < Smallest) - Smallest = byte; - if (byte > Largest) - Largest = byte; - val >>= 8; - } /* while ++j */ - index++; - } /*while ++i*/ - - if (pDCTstat->DimmECCPresent > 0) { - index++; - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index); - val &= 0x00000060; - val >>= 5; - byte = val & 0xFF; - if (byte < Smallest) - Smallest = byte; - if (byte > Largest) - Largest = byte; - } - - word = Smallest; - word <<= 8; - word |= Largest; - - return word; -} - -static void mct_PhyController_Config(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - uint8_t index; - uint32_t dword; - u32 index_reg = 0x98; - u32 dev = pDCTstat->dev_dct; - - if (pDCTstat->LogicalCPUID & (AMD_DR_DAC2_OR_C3 | AMD_RB_C3 | AMD_FAM15_ALL)) { - if (is_fam15h()) { - /* Set F2x[1, 0]98_x0D0F0F13 DllDisEarlyU and DllDisEarlyL to save power */ - for (index = 0; index < 0x9; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0013 | (index << 8)); - dword |= (0x1 << 1); /* DllDisEarlyU = 1 */ - dword |= 0x1; /* DllDisEarlyL = 1 */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0013 | (index << 8), dword); - } - } - - if (pDCTstat->Dimmx4Present == 0) { - /* Set bit7 RxDqsUDllPowerDown to register F2x[1, 0]98_x0D0F0F13 for - * additional power saving when x4 DIMMs are not present. - */ - for (index = 0; index < 0x9; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0013 | (index << 8)); - dword |= (0x1 << 7); /* RxDqsUDllPowerDown = 1 */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0013 | (index << 8), dword); - } - } - } - - if (pDCTstat->LogicalCPUID & (AMD_DR_DAC2_OR_C3 | AMD_FAM15_ALL)) { - if (pDCTstat->DimmECCPresent == 0) { - /* Set bit4 PwrDn to register F2x[1, 0]98_x0D0F0830 for power saving */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0830); - dword |= 1 << 4; /* BIOS should set this bit if ECC DIMMs are not present */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0830, dword); - } - } - -} - -static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - struct DCTStatStruc *pDCTstat; - u32 val; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - mct_PhyController_Config(pMCTstat, pDCTstat, 0); - mct_PhyController_Config(pMCTstat, pDCTstat, 1); - - if (!is_fam15h()) { - /* Family 10h CPUs */ - mct_ExtMCTConfig_Cx(pDCTstat); - mct_ExtMCTConfig_Bx(pDCTstat); - mct_ExtMCTConfig_Dx(pDCTstat); - } else { - /* Family 15h CPUs */ - uint8_t nvram; - uint8_t enable_experimental_memory_speed_boost; - - /* Check to see if cache partitioning is allowed */ - enable_experimental_memory_speed_boost = 0; - if (get_option(&nvram, "experimental_memory_speed_boost") == CB_SUCCESS) - enable_experimental_memory_speed_boost = !!nvram; - - val = 0x0ce00f00; /* FlushWrOnStpGnt = 0x0 */ - val |= 0x10 << 2; /* MctWrLimit = 0x10 */ - val |= 0x1; /* DctWrLimit = 0x1 */ - Set_NB32(pDCTstat->dev_dct, 0x11c, val); - - val = Get_NB32(pDCTstat->dev_dct, 0x1b0); - val &= ~0x3; /* AdapPrefMissRatio = 0x1 */ - val |= 0x1; - val &= ~(0x3 << 2); /* AdapPrefPositiveStep = 0x0 */ - val &= ~(0x3 << 4); /* AdapPrefNegativeStep = 0x0 */ - val &= ~(0x7 << 8); /* CohPrefPrbLmt = 0x1 */ - val |= (0x1 << 8); - val |= (0x1 << 12); /* EnSplitDctLimits = 0x1 */ - if (enable_experimental_memory_speed_boost) - val |= (0x1 << 20); /* DblPrefEn = 0x1 */ - val |= (0x7 << 22); /* PrefFourConf = 0x7 */ - val |= (0x7 << 25); /* PrefFiveConf = 0x7 */ - val &= ~(0xf << 28); /* DcqBwThrotWm = 0x0 */ - Set_NB32(pDCTstat->dev_dct, 0x1b0, val); - - uint8_t wm1; - uint8_t wm2; - - switch (pDCTstat->Speed) { - case 0x4: - wm1 = 0x3; - wm2 = 0x4; - break; - case 0x6: - wm1 = 0x3; - wm2 = 0x5; - break; - case 0xa: - wm1 = 0x4; - wm2 = 0x6; - break; - case 0xe: - wm1 = 0x5; - wm2 = 0x8; - break; - case 0x12: - wm1 = 0x6; - wm2 = 0x9; - break; - default: - wm1 = 0x7; - wm2 = 0xa; - break; - } - - val = Get_NB32(pDCTstat->dev_dct, 0x1b4); - val &= ~(0x3ff); - val |= ((wm2 & 0x1f) << 5); - val |= (wm1 & 0x1f); - Set_NB32(pDCTstat->dev_dct, 0x1b4, val); - } - } - } - - /* ClrClToNB_D postponed until we're done executing from ROM */ - mct_ClrWbEnhWsbDis_D(pMCTstat, pDCTstat); - - /* set F3x8C[DisFastTprWr] on all DR, if L3Size = 0 */ - if (pDCTstat->LogicalCPUID & AMD_DR_ALL) { - if (!(cpuid_edx(0x80000006) & 0xFFFC0000)) { - val = Get_NB32(pDCTstat->dev_nbmisc, 0x8C); - val |= 1 << 24; - Set_NB32(pDCTstat->dev_nbmisc, 0x8C, val); - } - } -} - -void mct_ForceNBPState0_En_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Force the NB P-state to P0 */ - uint32_t dword; - uint32_t dword2; - - dword = Get_NB32(pDCTstat->dev_nbctl, 0x174); - if (!(dword & 0x1)) { - dword = Get_NB32(pDCTstat->dev_nbctl, 0x170); - pDCTstat->SwNbPstateLoDis = (dword >> 14) & 0x1; - pDCTstat->NbPstateDisOnP0 = (dword >> 13) & 0x1; - pDCTstat->NbPstateThreshold = (dword >> 9) & 0x7; - pDCTstat->NbPstateHi = (dword >> 6) & 0x3; - dword &= ~(0x1 << 14); /* SwNbPstateLoDis = 0 */ - dword &= ~(0x1 << 13); /* NbPstateDisOnP0 = 0 */ - dword &= ~(0x7 << 9); /* NbPstateThreshold = 0 */ - dword &= ~(0x3 << 3); /* NbPstateLo = NbPstateMaxVal */ - dword |= ((dword & 0x3) << 3); - Set_NB32(pDCTstat->dev_nbctl, 0x170, dword); - - if (!is_model10_1f()) { - /* Wait until CurNbPState == NbPstateLo */ - do { - dword2 = Get_NB32(pDCTstat->dev_nbctl, 0x174); - } while (((dword2 >> 19) & 0x7) != (dword & 0x3)); - } - dword = Get_NB32(pDCTstat->dev_nbctl, 0x170); - dword &= ~(0x3 << 6); /* NbPstateHi = 0 */ - dword |= (0x3 << 14); /* SwNbPstateLoDis = 1 */ - Set_NB32(pDCTstat->dev_nbctl, 0x170, dword); - - if (!is_model10_1f()) { - /* Wait until CurNbPState == 0 */ - do { - dword2 = Get_NB32(pDCTstat->dev_nbctl, 0x174); - } while (((dword2 >> 19) & 0x7) != 0); - } - } -} - -void mct_ForceNBPState0_Dis_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Restore normal NB P-state functionailty */ - uint32_t dword; - - dword = Get_NB32(pDCTstat->dev_nbctl, 0x174); - if (!(dword & 0x1)) { - dword = Get_NB32(pDCTstat->dev_nbctl, 0x170); - dword &= ~(0x1 << 14); /* SwNbPstateLoDis*/ - dword |= ((pDCTstat->SwNbPstateLoDis & 0x1) << 14); - dword &= ~(0x1 << 13); /* NbPstateDisOnP0 */ - dword |= ((pDCTstat->NbPstateDisOnP0 & 0x1) << 13); - dword &= ~(0x7 << 9); /* NbPstateThreshold */ - dword |= ((pDCTstat->NbPstateThreshold & 0x7) << 9); - dword &= ~(0x3 << 6); /* NbPstateHi */ - dword |= ((pDCTstat->NbPstateHi & 0x3) << 3); - Set_NB32(pDCTstat->dev_nbctl, 0x170, dword); - } -} - -static void mct_InitialMCT_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) -{ - if (is_fam15h()) { - msr_t p0_state_msr; - uint8_t cpu_fid; - uint8_t cpu_did; - uint32_t cpu_divisor; - uint8_t boost_states; - - /* Retrieve the number of boost states */ - boost_states = (Get_NB32(pDCTstat->dev_link, 0x15c) >> 2) & 0x7; - - /* Retrieve and store the TSC frequency (P0 COF) */ - p0_state_msr = rdmsr(PSTATE_0_MSR + boost_states); - cpu_fid = p0_state_msr.lo & 0x3f; - cpu_did = (p0_state_msr.lo >> 6) & 0x7; - cpu_divisor = (0x1 << cpu_did); - pMCTstat->TSCFreq = (100 * (cpu_fid + 0x10)) / cpu_divisor; - - printk(BIOS_DEBUG, "mct_InitialMCT_D: mct_ForceNBPState0_En_Fam15\n"); - mct_ForceNBPState0_En_Fam15(pMCTstat, pDCTstat); - } else { - /* K10 BKDG v3.62 section 2.8.9.2 */ - printk(BIOS_DEBUG, "mct_InitialMCT_D: clear_legacy_Mode\n"); - clear_legacy_Mode(pMCTstat, pDCTstat); - - /* Northbridge configuration */ - mct_SetClToNB_D(pMCTstat, pDCTstat); - mct_SetWbEnhWsbDis_D(pMCTstat, pDCTstat); - } -} - -static u32 mct_NodePresent_D(void) -{ - u32 val; - if (is_fam15h()) { - if (is_model10_1f()) { - val = 0x14001022; - } else { - val = 0x16001022; - } - } else { - val = 0x12001022; - } - return val; -} - -static void mct_init(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 lo, hi; - u32 addr; - - pDCTstat->GangedMode = 0; - pDCTstat->DRPresent = 1; - - /* enable extend PCI configuration access */ - addr = NB_CFG_MSR; - _RDMSR(addr, &lo, &hi); - if (hi & (1 << (46-32))) { - pDCTstat->Status |= 1 << SB_ExtConfig; - } else { - hi |= 1 << (46-32); - _WRMSR(addr, lo, hi); - } -} - -static void clear_legacy_Mode(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 reg; - u32 val; - u32 dev = pDCTstat->dev_dct; - - /* Clear Legacy BIOS Mode bit */ - reg = 0x94; - val = Get_NB32_DCT(dev, 0, reg); - val &= ~(1<<LegacyBiosMode); - Set_NB32_DCT(dev, 0, reg, val); - - val = Get_NB32_DCT(dev, 1, reg); - val &= ~(1<<LegacyBiosMode); - Set_NB32_DCT(dev, 1, reg, val); -} - -static void mct_HTMemMapExt(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - u32 Drambase, Dramlimit; - u32 val; - u32 reg; - u32 dev; - u32 devx; - u32 dword; - struct DCTStatStruc *pDCTstat; - - pDCTstat = pDCTstatA + 0; - dev = pDCTstat->dev_map; - - /* Copy dram map from F1x40/44,F1x48/4c, - to F1x120/124(Node0),F1x120/124(Node1),...*/ - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - devx = pDCTstat->dev_map; - - /* get base/limit from Node0 */ - reg = 0x40 + (Node << 3); /* Node0/Dram Base 0 */ - val = Get_NB32(dev, reg); - Drambase = val >> (16 + 3); - - reg = 0x44 + (Node << 3); /* Node0/Dram Base 0 */ - val = Get_NB32(dev, reg); - Dramlimit = val >> (16 + 3); - - /* set base/limit to F1x120/124 per Node */ - if (pDCTstat->NodePresent) { - reg = 0x120; /* F1x120,DramBase[47:27] */ - val = Get_NB32(devx, reg); - val &= 0xFFE00000; - val |= Drambase; - Set_NB32(devx, reg, val); - - reg = 0x124; - val = Get_NB32(devx, reg); - val &= 0xFFE00000; - val |= Dramlimit; - Set_NB32(devx, reg, val); - - if (pMCTstat->GStatus & (1 << GSB_HWHole)) { - reg = 0xF0; - val = Get_NB32(devx, reg); - val |= (1 << DramMemHoistValid); - val &= ~(0xFF << 24); - dword = (pMCTstat->HoleBase >> (24 - 8)) & 0xFF; - dword <<= 24; - val |= dword; - Set_NB32(devx, reg, val); - } - - } - } -} - -static void SetCSTriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dev = pDCTstat->dev_dct; - u32 index_reg = 0x98; - u16 word; - - if (is_fam15h()) { - word = fam15h_cs_tristate_enable_code(pDCTstat, dct); - } else { - /* Tri-state unused chipselects when motherboard - termination is available */ - - /* FIXME: skip for Ax */ - - word = pDCTstat->CSPresent; - if (pDCTstat->Status & (1 << SB_Registered)) { - word |= (word & 0x55) << 1; - } - word = (~word) & 0xff; - } - - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c); - val &= ~0xff; - val |= word; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, val); -} - -static void SetCKETriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dev; - u32 index_reg = 0x98; - u16 word; - - /* Tri-state unused CKEs when motherboard termination is available */ - - /* FIXME: skip for Ax */ - - dev = pDCTstat->dev_dct; - word = pDCTstat->CSPresent; - - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c); - val &= ~(0x3 << 12); - if ((word & 0x55) == 0) - val |= 1 << 12; - if ((word & 0xaa) == 0) - val |= 1 << 13; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, val); -} - -static void SetODTTriState(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 val; - u32 dev; - u32 index_reg = 0x98; - u8 cs; - u8 odt; - - dev = pDCTstat->dev_dct; - - if (is_fam15h()) { - odt = fam15h_odt_tristate_enable_code(pDCTstat, dct); - } else { - /* FIXME: skip for Ax */ - - /* Tri-state unused ODTs when motherboard termination is available */ - odt = 0x0f; /* ODT tri-state setting */ - - if (pDCTstat->Status & (1 <<SB_Registered)) { - for (cs = 0; cs < 8; cs += 2) { - if (pDCTstat->CSPresent & (1 << cs)) { - odt &= ~(1 << (cs / 2)); - if (mctGet_NVbits(NV_4RANKType) != 0) { /* quad-rank capable platform */ - if (pDCTstat->CSPresent & (1 << (cs + 1))) - odt &= ~(4 << (cs / 2)); - } - } - } - } else { /* AM3 package */ - val = ~(pDCTstat->CSPresent); - odt = val & 9; /* swap bits 1 and 2 */ - if (val & (1 << 1)) - odt |= 1 << 2; - if (val & (1 << 2)) - odt |= 1 << 1; - } - } - - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c); - val &= ~(0xf << 8); /* ODTTri = odt */ - val |= (odt & 0xf) << 8; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, val); -} - -/* Family 15h */ -static void InitDDRPhy(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - uint8_t index; - uint32_t dword; - uint8_t ddr_voltage_index; - uint8_t amd_voltage_level_index = 0; - uint32_t index_reg = 0x98; - uint32_t dev = pDCTstat->dev_dct; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - /* Find current DDR supply voltage for this DCT */ - ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct); - - /* Fam15h BKDG v3.14 section 2.10.5.3 - * The remainder of the Phy Initialization algorithm picks up in phyAssistedMemFnceTraining - */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000b, 0x80000000); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe013, 0x00000118); - - /* Program desired VDDIO level */ - if (ddr_voltage_index & 0x4) { - /* 1.25V */ - amd_voltage_level_index = 0x2; - } else if (ddr_voltage_index & 0x2) { - /* 1.35V */ - amd_voltage_level_index = 0x1; - } else if (ddr_voltage_index & 0x1) { - /* 1.50V */ - amd_voltage_level_index = 0x0; - } - - /* D18F2x9C_x0D0F_0[F,8:0]1F_dct[1:0][RxVioLvl] */ - for (index = 0; index < 0x9; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f001f | (index << 8)); - dword &= ~(0x3 << 3); - dword |= (amd_voltage_level_index << 3); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f001f | (index << 8), dword); - } - - /* D18F2x9C_x0D0F_[C,8,2][2:0]1F_dct[1:0][RxVioLvl] */ - for (index = 0; index < 0x3; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f201f | (index << 8)); - dword &= ~(0x3 << 3); - dword |= (amd_voltage_level_index << 3); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f201f | (index << 8), dword); - } - for (index = 0; index < 0x2; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f801f | (index << 8)); - dword &= ~(0x3 << 3); - dword |= (amd_voltage_level_index << 3); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f801f | (index << 8), dword); - } - for (index = 0; index < 0x1; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc01f | (index << 8)); - dword &= ~(0x3 << 3); - dword |= (amd_voltage_level_index << 3); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc01f | (index << 8), dword); - } - - /* D18F2x9C_x0D0F_4009_dct[1:0][CmpVioLvl, ComparatorAdjust] */ - /* NOTE: CmpVioLvl and ComparatorAdjust only take effect when set on DCT 0 */ - dword = Get_NB32_index_wait_DCT(dev, 0, index_reg, 0x0d0f4009); - dword &= ~(0x0000c00c); - dword |= (amd_voltage_level_index << 14); - dword |= (amd_voltage_level_index << 2); - Set_NB32_index_wait_DCT(dev, 0, index_reg, 0x0d0f4009, dword); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -void InitPhyCompensation(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 i; - u32 index_reg = 0x98; - u32 dev = pDCTstat->dev_dct; - u32 valx = 0; - uint8_t index; - uint32_t dword; - const u8 *p; - - printk(BIOS_DEBUG, "%s: DCT %d: Start\n", __func__, dct); - - if (is_fam15h()) { - /* Algorithm detailed in the Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 */ - uint32_t tx_pre; - uint32_t drive_strength; - - /* Program D18F2x9C_x0D0F_E003_dct[1:0][DisAutoComp] */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe003); - dword |= (0x1 << 14); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe003, dword); - - /* Program D18F2x9C_x0D0F_E003_dct[1:0][DisablePredriverCal] */ - /* NOTE: DisablePredriverCal only takes effect when set on DCT 0 */ - dword = Get_NB32_index_wait_DCT(dev, 0, index_reg, 0x0d0fe003); - dword |= (0x1 << 13); - Set_NB32_index_wait_DCT(dev, 0, index_reg, 0x0d0fe003, dword); - - /* Determine TxPreP/TxPreN for data lanes (Stage 1) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000000); - drive_strength = (dword >> 20) & 0x7; /* DqsDrvStren */ - tx_pre = fam15h_phy_predriver_calibration_code(pDCTstat, dct, drive_strength); - - /* Program TxPreP/TxPreN for data lanes (Stage 1) */ - for (index = 0; index < 0x9; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0006 | (index << 8)); - dword &= ~(0xffff); - dword |= tx_pre; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0006 | (index << 8), dword); - } - - /* Determine TxPreP/TxPreN for data lanes (Stage 2) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000000); - drive_strength = (dword >> 16) & 0x7; /* DataDrvStren */ - tx_pre = fam15h_phy_predriver_calibration_code(pDCTstat, dct, drive_strength); - - /* Program TxPreP/TxPreN for data lanes (Stage 2) */ - for (index = 0; index < 0x9; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f000a | (index << 8)); - dword &= ~(0xffff); - dword |= tx_pre; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f000a | (index << 8), dword); - } - for (index = 0; index < 0x9; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0002 | (index << 8)); - dword &= ~(0xffff); - dword |= (0x8000 | tx_pre); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0002 | (index << 8), dword); - } - - /* Determine TxPreP/TxPreN for command/address lines (Stage 1) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000000); - drive_strength = (dword >> 4) & 0x7; /* CsOdtDrvStren */ - tx_pre = fam15h_phy_predriver_cmd_addr_calibration_code(pDCTstat, dct, drive_strength); - - /* Program TxPreP/TxPreN for command/address lines (Stage 1) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8006); - dword &= ~(0xffff); - dword |= tx_pre; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8006, dword); - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f800a); - dword &= ~(0xffff); - dword |= tx_pre; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f800a, dword); - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8002); - dword &= ~(0xffff); - dword |= (0x8000 | tx_pre); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8002, dword); - - /* Determine TxPreP/TxPreN for command/address lines (Stage 2) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000000); - drive_strength = (dword >> 8) & 0x7; /* AddrCmdDrvStren */ - tx_pre = fam15h_phy_predriver_cmd_addr_calibration_code(pDCTstat, dct, drive_strength); - - /* Program TxPreP/TxPreN for command/address lines (Stage 2) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8106); - dword &= ~(0xffff); - dword |= tx_pre; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8106, dword); - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f810a); - dword &= ~(0xffff); - dword |= tx_pre; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f810a, dword); - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc006); - dword &= ~(0xffff); - dword |= tx_pre; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc006, dword); - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc00a); - dword &= ~(0xffff); - dword |= tx_pre; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc00a, dword); - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc00e); - dword &= ~(0xffff); - dword |= tx_pre; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc00e, dword); - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc012); - dword &= ~(0xffff); - dword |= tx_pre; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc012, dword); - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8102); - dword &= ~(0xffff); - dword |= (0x8000 | tx_pre); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8102, dword); - - /* Determine TxPreP/TxPreN for command/address lines (Stage 3) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000000); - drive_strength = (dword >> 0) & 0x7; /* CkeDrvStren */ - tx_pre = fam15h_phy_predriver_cmd_addr_calibration_code(pDCTstat, dct, drive_strength); - - /* Program TxPreP/TxPreN for command/address lines (Stage 3) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc002); - dword &= ~(0xffff); - dword |= (0x8000 | tx_pre); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc002, dword); - - /* Determine TxPreP/TxPreN for clock lines */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000000); - drive_strength = (dword >> 12) & 0x7; /* ClkDrvStren */ - tx_pre = fam15h_phy_predriver_clk_calibration_code(pDCTstat, dct, drive_strength); - - /* Program TxPreP/TxPreN for clock lines */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2002); - dword &= ~(0xffff); - dword |= (0x8000 | tx_pre); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2002, dword); - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2102); - dword &= ~(0xffff); - dword |= (0x8000 | tx_pre); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2102, dword); - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2202); - dword &= ~(0xffff); - dword |= (0x8000 | tx_pre); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2202, dword); - - if (!is_model10_1f()) { - /* Be extra safe and wait for the predriver calibration - * to be applied to the hardware. The BKDG does not - * require this, but it does take some time for the - * data to propagate, so it's probably a good idea. - */ - uint8_t predriver_cal_pending = 1; - printk(BIOS_DEBUG, "Waiting for predriver calibration to be applied..."); - while (predriver_cal_pending) { - predriver_cal_pending = 0; - for (index = 0; index < 0x9; index++) { - if (Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0002 | (index << 8)) & 0x8000) - predriver_cal_pending = 1; - } - } - printk(BIOS_DEBUG, "done!\n"); - } - } else { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00); - dword = 0; - for (i = 0; i < 6; i++) { - switch (i) { - case 0: - case 4: - p = Table_Comp_Rise_Slew_15x; - valx = p[(dword >> 16) & 3]; - break; - case 1: - case 5: - p = Table_Comp_Fall_Slew_15x; - valx = p[(dword >> 16) & 3]; - break; - case 2: - p = Table_Comp_Rise_Slew_20x; - valx = p[(dword >> 8) & 3]; - break; - case 3: - p = Table_Comp_Fall_Slew_20x; - valx = p[(dword >> 8) & 3]; - break; - } - dword |= valx << (5 * i); - } - - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0a, dword); - } - - printk(BIOS_DEBUG, "%s: DCT %d: Done\n", __func__, dct); -} - -static void mct_EarlyArbEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - if (!is_fam15h()) { - u32 reg; - u32 val; - u32 dev = pDCTstat->dev_dct; - - /* GhEnhancement #18429 modified by askar: For low NB CLK : - * Memclk ratio, the DCT may need to arbitrate early to avoid - * unnecessary bubbles. - * bit 19 of F2x[1,0]78 Dram Control Register, set this bit only when - * NB CLK : Memclk ratio is between 3:1 (inclusive) to 4:5 (inclusive) - */ - reg = 0x78; - val = Get_NB32_DCT(dev, dct, reg); - - if (pDCTstat->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx)) - val |= (1 << EarlyArbEn); - else if (CheckNBCOFEarlyArbEn(pMCTstat, pDCTstat)) - val |= (1 << EarlyArbEn); - - Set_NB32_DCT(dev, dct, reg, val); - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static u8 CheckNBCOFEarlyArbEn(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 reg; - u32 val; - u32 tmp; - u32 rem; - u32 dev = pDCTstat->dev_dct; - u32 hi, lo; - u8 NbDid = 0; - - /* Check if NB COF >= 4*Memclk, if it is not, return a fatal error - */ - - /* 3*(Fn2xD4[NBFid]+4)/(2^NbDid)/(3+Fn2x94[MemClkFreq]) */ - _RDMSR(MSR_COFVID_STS, &lo, &hi); - if (lo & (1 << 22)) - NbDid |= 1; - - reg = 0x94; - val = Get_NB32_DCT(dev, 0, reg); - if (!(val & (1 << MemClkFreqVal))) - val = Get_NB32_DCT(dev, 1, reg); /* get the DCT1 value */ - - val &= 0x07; - val += 3; - if (NbDid) - val <<= 1; - tmp = val; - - dev = pDCTstat->dev_nbmisc; - reg = 0xD4; - val = Get_NB32(dev, reg); - val &= 0x1F; - val += 3; - val *= 3; - val = val / tmp; - rem = val % tmp; - tmp >>= 1; - - /* Yes this could be nicer but this was how the asm was.... */ - if (val < 3) { /* NClk:MemClk < 3:1 */ - return 0; - } else if (val > 4) { /* NClk:MemClk >= 5:1 */ - return 0; - } else if ((val == 4) && (rem > tmp)) { /* NClk:MemClk > 4.5:1 */ - return 0; - } else { - return 1; /* 3:1 <= NClk:MemClk <= 4.5:1*/ - } -} - -static void mct_ResetDataStruct_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - uint8_t Node; - struct DCTStatStruc *pDCTstat; - - /* Initialize Data structures by clearing all entries to 0 */ - memset(pMCTstat, 0, sizeof(*pMCTstat)); - - for (Node = 0; Node < 8; Node++) { - pDCTstat = pDCTstatA + Node; - memset(pDCTstat, 0, sizeof(*pDCTstat) - sizeof(pDCTstat->persistentData)); - } -} - -static void mct_BeforeDramInit_Prod_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - mct_ProgramODT_D(pMCTstat, pDCTstat, dct); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static void mct_ProgramODT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 i; - u32 dword; - u32 dev = pDCTstat->dev_dct; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - if (is_fam15h()) { - /* Obtain number of DIMMs on channel */ - uint8_t dimm_count = pDCTstat->MAdimms[dct]; - uint8_t rank_count_dimm0; - uint8_t rank_count_dimm1; - uint32_t odt_pattern_0; - uint32_t odt_pattern_1; - uint32_t odt_pattern_2; - uint32_t odt_pattern_3; - uint8_t write_odt_duration; - uint8_t read_odt_duration; - uint8_t write_odt_delay; - uint8_t read_odt_delay; - - /* NOTE - * Rank count per DIMM and DCT is encoded by pDCTstat->DimmRanks[(<dimm number> * 2) + dct] - */ - - /* Select appropriate ODT pattern for installed DIMMs - * Refer to the Fam15h BKDG Rev. 3.14, page 149 onwards - */ - if (pDCTstat->Status & (1 << SB_Registered)) { - if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - if (rank_count_dimm1 == 1) { - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00020000; - } else if (rank_count_dimm1 == 2) { - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x08020000; - } else if (rank_count_dimm1 == 4) { - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x020a0000; - odt_pattern_3 = 0x080a0000; - } else { - /* Fallback */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x08020000; - } - } else { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) { - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x01010202; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x09030603; - } else if ((rank_count_dimm0 < 4) && (rank_count_dimm1 == 4)) { - odt_pattern_0 = 0x01010000; - odt_pattern_1 = 0x01010a0a; - odt_pattern_2 = 0x01090000; - odt_pattern_3 = 0x01030e0b; - } else if ((rank_count_dimm0 == 4) && (rank_count_dimm1 < 4)) { - odt_pattern_0 = 0x00000202; - odt_pattern_1 = 0x05050202; - odt_pattern_2 = 0x00000206; - odt_pattern_3 = 0x0d070203; - } else if ((rank_count_dimm0 == 4) && (rank_count_dimm1 == 4)) { - odt_pattern_0 = 0x05050a0a; - odt_pattern_1 = 0x05050a0a; - odt_pattern_2 = 0x050d0a0e; - odt_pattern_3 = 0x05070a0b; - } else { - /* Fallback */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00000000; - } - } - } else { - /* FIXME - * 3 DIMMs per channel UNIMPLEMENTED - */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00000000; - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* TODO - * Load reduced dimms UNIMPLEMENTED - */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00000000; - } else { - if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - if (rank_count_dimm1 == 1) { - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00020000; - } else if (rank_count_dimm1 == 2) { - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x08020000; - } else { - /* Fallback */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x08020000; - } - } else { - /* 2 DIMMs detected */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x01010202; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x09030603; - } - } else { - /* FIXME - * 3 DIMMs per channel UNIMPLEMENTED - */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00000000; - } - } - - if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* TODO - * Load reduced dimms UNIMPLEMENTED - */ - write_odt_duration = 0x0; - read_odt_duration = 0x0; - write_odt_delay = 0x0; - read_odt_delay = 0x0; - } else { - uint8_t tcl; - uint8_t tcwl; - tcl = Get_NB32_DCT(dev, dct, 0x200) & 0x1f; - tcwl = Get_NB32_DCT(dev, dct, 0x20c) & 0x1f; - - write_odt_duration = 0x6; - read_odt_duration = 0x6; - write_odt_delay = 0x0; - if (tcl > tcwl) - read_odt_delay = tcl - tcwl; - else - read_odt_delay = 0x0; - } - - /* Program ODT pattern */ - Set_NB32_DCT(dev, dct, 0x230, odt_pattern_1); - Set_NB32_DCT(dev, dct, 0x234, odt_pattern_0); - Set_NB32_DCT(dev, dct, 0x238, odt_pattern_3); - Set_NB32_DCT(dev, dct, 0x23c, odt_pattern_2); - dword = Get_NB32_DCT(dev, dct, 0x240); - dword &= ~(0x7 << 12); /* WrOdtOnDuration = write_odt_duration */ - dword |= (write_odt_duration & 0x7) << 12; - dword &= ~(0x7 << 8); /* WrOdtTrnOnDly = write_odt_delay */ - dword |= (write_odt_delay & 0x7) << 8; - dword &= ~(0xf << 4); /* RdOdtOnDuration = read_odt_duration */ - dword |= (read_odt_duration & 0xf) << 4; - dword &= ~(0xf); /* RdOdtTrnOnDly = read_odt_delay */ - dword |= (read_odt_delay & 0xf); - Set_NB32_DCT(dev, dct, 0x240, dword); - - printk(BIOS_SPEW, "Programmed DCT %d ODT pattern %08x %08x %08x %08x\n", dct, odt_pattern_0, odt_pattern_1, odt_pattern_2, odt_pattern_3); - } else if (pDCTstat->LogicalCPUID & AMD_DR_Dx) { - if (pDCTstat->Speed == 3) - dword = 0x00000800; - else - dword = 0x00000000; - for (i = 0; i < 2; i++) { - Set_NB32_DCT(dev, i, 0x98, 0x0D000030); - Set_NB32_DCT(dev, i, 0x9C, dword); - Set_NB32_DCT(dev, i, 0x98, 0x4D040F30); - - /* Obtain number of DIMMs on channel */ - uint8_t dimm_count = pDCTstat->MAdimms[i]; - uint8_t rank_count_dimm0; - uint8_t rank_count_dimm1; - uint32_t odt_pattern_0; - uint32_t odt_pattern_1; - uint32_t odt_pattern_2; - uint32_t odt_pattern_3; - - /* Select appropriate ODT pattern for installed DIMMs - * Refer to the Fam10h BKDG Rev. 3.62, page 120 onwards - */ - if (pDCTstat->Status & (1 << SB_Registered)) { - if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + i]; - if (rank_count_dimm1 == 1) { - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00020000; - } else if (rank_count_dimm1 == 2) { - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x02080000; - } else if (rank_count_dimm1 == 4) { - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x020a0000; - odt_pattern_3 = 0x080a0000; - } else { - /* Fallback */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00000000; - } - } else { - /* 2 DIMMs detected */ - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + i]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + i]; - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) { - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x01010202; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x09030603; - } else if ((rank_count_dimm0 < 4) && (rank_count_dimm1 == 4)) { - odt_pattern_0 = 0x01010000; - odt_pattern_1 = 0x01010a0a; - odt_pattern_2 = 0x01090000; - odt_pattern_3 = 0x01030e0b; - } else if ((rank_count_dimm0 == 4) && (rank_count_dimm1 < 4)) { - odt_pattern_0 = 0x00000202; - odt_pattern_1 = 0x05050202; - odt_pattern_2 = 0x00000206; - odt_pattern_3 = 0x0d070203; - } else if ((rank_count_dimm0 == 4) && (rank_count_dimm1 == 4)) { - odt_pattern_0 = 0x05050a0a; - odt_pattern_1 = 0x05050a0a; - odt_pattern_2 = 0x050d0a0e; - odt_pattern_3 = 0x05070a0b; - } else { - /* Fallback */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00000000; - } - } - } else { - /* FIXME - * 3 DIMMs per channel UNIMPLEMENTED - */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00000000; - } - } else { - if (MaxDimmsInstallable == 2) { - if (dimm_count == 1) { - /* 1 DIMM detected */ - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + i]; - if (rank_count_dimm1 == 1) { - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00020000; - } else if (rank_count_dimm1 == 2) { - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x02080000; - } else { - /* Fallback */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00000000; - } - } else { - /* 2 DIMMs detected */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x01010202; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x09030603; - } - } else { - /* FIXME - * 3 DIMMs per channel UNIMPLEMENTED - */ - odt_pattern_0 = 0x00000000; - odt_pattern_1 = 0x00000000; - odt_pattern_2 = 0x00000000; - odt_pattern_3 = 0x00000000; - } - } - - /* Program ODT pattern */ - Set_NB32_index_wait_DCT(dev, i, 0xf0, 0x180, odt_pattern_1); - Set_NB32_index_wait_DCT(dev, i, 0xf0, 0x181, odt_pattern_0); - Set_NB32_index_wait_DCT(dev, i, 0xf0, 0x182, odt_pattern_3); - Set_NB32_index_wait_DCT(dev, i, 0xf0, 0x183, odt_pattern_2); - - printk(BIOS_SPEW, "Programmed ODT pattern %08x %08x %08x %08x\n", odt_pattern_0, odt_pattern_1, odt_pattern_2, odt_pattern_3); - } - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static void mct_EnDllShutdownSR(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 dev = pDCTstat->dev_dct, val; - - /* Write 0000_07D0h to register F2x[1, 0]98_x4D0FE006 */ - if (pDCTstat->LogicalCPUID & (AMD_DR_DAC2_OR_C3)) { - Set_NB32_DCT(dev, dct, 0x9C, 0x1C); - Set_NB32_DCT(dev, dct, 0x98, 0x4D0FE006); - Set_NB32_DCT(dev, dct, 0x9C, 0x13D); - Set_NB32_DCT(dev, dct, 0x98, 0x4D0FE007); - - val = Get_NB32_DCT(dev, dct, 0x90); - val &= ~(1 << 27/* DisDllShutdownSR */); - Set_NB32_DCT(dev, dct, 0x90, val); - } -} - -static u32 mct_DisDllShutdownSR(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 DramConfigLo, u8 dct) -{ - u32 dev = pDCTstat->dev_dct; - - /* Write 0000_07D0h to register F2x[1, 0]98_x4D0FE006 */ - if (pDCTstat->LogicalCPUID & (AMD_DR_DAC2_OR_C3)) { - Set_NB32_DCT(dev, dct, 0x9C, 0x7D0); - Set_NB32_DCT(dev, dct, 0x98, 0x4D0FE006); - Set_NB32_DCT(dev, dct, 0x9C, 0x190); - Set_NB32_DCT(dev, dct, 0x98, 0x4D0FE007); - - DramConfigLo |= /* DisDllShutdownSR */ 1 << 27; - } - - return DramConfigLo; -} - -void mct_SetClToNB_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 lo, hi; - u32 msr; - - /* FIXME: Maybe check the CPUID? - not for now. */ - /* pDCTstat->LogicalCPUID; */ - - msr = BU_CFG2_MSR; - _RDMSR(msr, &lo, &hi); - lo |= 1 << ClLinesToNbDis; - _WRMSR(msr, lo, hi); -} - -void mct_ClrClToNB_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - - u32 lo, hi; - u32 msr; - - /* FIXME: Maybe check the CPUID? - not for now. */ - /* pDCTstat->LogicalCPUID; */ - - msr = BU_CFG2_MSR; - _RDMSR(msr, &lo, &hi); - if (!pDCTstat->ClToNB_flag) - lo &= ~(1<<ClLinesToNbDis); - _WRMSR(msr, lo, hi); - -} - -void mct_SetWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 lo, hi; - u32 msr; - - /* FIXME: Maybe check the CPUID? - not for now. */ - /* pDCTstat->LogicalCPUID; */ - - msr = BU_CFG_MSR; - _RDMSR(msr, &lo, &hi); - hi |= (1 << WbEnhWsbDis_D); - _WRMSR(msr, lo, hi); -} - -void mct_ClrWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 lo, hi; - u32 msr; - - /* FIXME: Maybe check the CPUID? - not for now. */ - /* pDCTstat->LogicalCPUID; */ - - msr = BU_CFG_MSR; - _RDMSR(msr, &lo, &hi); - hi &= ~(1 << WbEnhWsbDis_D); - _WRMSR(msr, lo, hi); -} - -void ProgDramMRSReg_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 DramMRS, dword; - u8 byte; - - DramMRS = 0; - - /* Set chip select CKE control mode */ - if (mctGet_NVbits(NV_CKE_CTL)) { - if (pDCTstat->CSPresent == 3) { - u16 word; - word = pDCTstat->DIMMSPDCSE; - if (dct == 0) - word &= 0b01010100; - else - word &= 0b10101000; - if (word == 0) - DramMRS |= 1 << 23; - } - } - - if (is_fam15h()) { - DramMRS |= (0x1 << 23); /* PchgPDModeSel = 1 */ - } else { - /* - DRAM MRS Register - DrvImpCtrl: drive impedance control.01b(34 ohm driver; Ron34 = Rzq/7) - */ - DramMRS |= 1 << 2; - /* Dram nominal termination: */ - byte = pDCTstat->MAdimms[dct]; - if (!(pDCTstat->Status & (1 << SB_Registered))) { - DramMRS |= 1 << 7; /* 60 ohms */ - if (byte & 2) { - if (pDCTstat->Speed < 6) - DramMRS |= 1 << 8; /* 40 ohms */ - else - DramMRS |= 1 << 9; /* 30 ohms */ - } - } - /* Dram dynamic termination: Disable(1DIMM), 120ohm(>=2DIMM) */ - if (!(pDCTstat->Status & (1 << SB_Registered))) { - if (byte >= 2) { - if (pDCTstat->Speed == 7) - DramMRS |= 1 << 10; - else - DramMRS |= 1 << 11; - } - } else { - DramMRS |= mct_DramTermDyn_RDimm(pMCTstat, pDCTstat, byte); - } - - /* Qoff = 0, output buffers enabled */ - /* Tcwl */ - DramMRS |= (pDCTstat->Speed - 4) << 20; - /* ASR = 1, auto self refresh */ - /* SRT = 0 */ - DramMRS |= 1 << 18; - } - - /* burst length control */ - if (pDCTstat->Status & (1 << SB_128bitmode)) - DramMRS |= 1 << 1; - - dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x84); - if (is_fam15h()) { - dword &= ~0x00800003; - dword |= DramMRS; - } else { - dword &= ~0x00fc2f8f; - dword |= DramMRS; - } - Set_NB32_DCT(pDCTstat->dev_dct, dct, 0x84, dword); -} - -void mct_SetDramConfigHi_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 dct, u32 DramConfigHi) -{ - /* Bug#15114: Comp. update interrupted by Freq. change can cause - * subsequent update to be invalid during any MemClk frequency change: - * Solution: From the bug report: - * 1. A software-initiated frequency change should be wrapped into the - * following sequence : - * a) Disable Compensation (F2[1, 0]9C_x08[30]) - * b) Reset the Begin Compensation bit (D3CMP->COMP_CONFIG[0]) in - * all the compensation engines - * c) Do frequency change - * d) Enable Compensation (F2[1, 0]9C_x08[30]) - * 2. A software-initiated Disable Compensation should always be - * followed by step b) of the above steps. - * Silicon Status: Fixed In Rev B0 - * - * Errata#177: DRAM Phy Automatic Compensation Updates May Be Invalid - * Solution: BIOS should disable the phy automatic compensation prior - * to initiating a memory clock frequency change as follows: - * 1. Disable PhyAutoComp by writing 1'b1 to F2x[1, 0]9C_x08[30] - * 2. Reset the Begin Compensation bits by writing 32'h0 to - * F2x[1, 0]9C_x4D004F00 - * 3. Perform frequency change - * 4. Enable PhyAutoComp by writing 1'b0 to F2x[1, 0]9C_08[30] - * In addition, any time software disables the automatic phy - * compensation it should reset the begin compensation bit per step 2. - * Silicon Status: Fixed in DR-B0 - */ - - u32 dev = pDCTstat->dev_dct; - u32 index_reg = 0x98; - u32 index; - - uint32_t dword; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - if (is_fam15h()) { - /* Initial setup for frequency change - * 9C_x0000_0004 must be configured before MemClkFreqVal is set - */ - - /* Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 0x190 */ - dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, index_reg, 0x0d0fe006); - dword &= ~(0x0000ffff); - dword |= 0x00000190; - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, index_reg, 0x0d0fe006, dword); - - dword = Get_NB32_DCT(dev, dct, 0x94); - dword &= ~(1 << MemClkFreqVal); - Set_NB32_DCT(dev, dct, 0x94, dword); - - dword = DramConfigHi; - dword &= ~(1 << MemClkFreqVal); - Set_NB32_DCT(dev, dct, 0x94, dword); - - mctGet_PS_Cfg_D(pMCTstat, pDCTstat, dct); - set_2t_configuration(pMCTstat, pDCTstat, dct); - mct_BeforePlatformSpec(pMCTstat, pDCTstat, dct); - mct_PlatformSpec(pMCTstat, pDCTstat, dct); - } else { - index = 0x08; - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, index); - if (!(dword & (1 << DisAutoComp))) - Set_NB32_index_wait_DCT(dev, dct, index_reg, index, dword | (1 << DisAutoComp)); - - mct_Wait(100); - } - - printk(BIOS_DEBUG, "mct_SetDramConfigHi_D: DramConfigHi: %08x\n", DramConfigHi); - - /* Program the DRAM Configuration High register */ - Set_NB32_DCT(dev, dct, 0x94, DramConfigHi); - - if (is_fam15h()) { - /* Wait until F2x[1, 0]94[FreqChgInProg]=0. */ - do { - printk(BIOS_DEBUG, "*"); - dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94); - } while (dword & (1 << FreqChgInProg)); - printk(BIOS_DEBUG, "\n"); - - /* Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 0xf */ - dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, index_reg, 0x0d0fe006); - dword &= ~(0x0000ffff); - dword |= 0x0000000f; - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, dct, index_reg, 0x0d0fe006, dword); - } - - /* Clear MC4 error status */ - pci_write_config32(pDCTstat->dev_nbmisc, 0x48, 0x0); - pci_write_config32(pDCTstat->dev_nbmisc, 0x4c, 0x0); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static void mct_BeforeDQSTrain_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - if (!is_fam15h()) { - u8 Node; - struct DCTStatStruc *pDCTstat; - - /* Errata 178 - * - * 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. - * Solution: At least, set WrDqs fine delay to be 0 for DDR3 training. - */ - for (Node = 0; Node < 8; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->NodePresent) { - mct_BeforeDQSTrainSamp(pDCTstat); /* only Bx */ - mct_ResetDLL_D(pMCTstat, pDCTstat, 0); - mct_ResetDLL_D(pMCTstat, pDCTstat, 1); - } - } - } -} - -/* Erratum 350 */ -static void mct_ResetDLL_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 Receiver; - u32 dev = pDCTstat->dev_dct; - u32 addr; - u32 lo, hi; - u8 wrap32dis = 0; - u8 valid = 0; - - /* Skip reset DLL for B3 */ - if (pDCTstat->LogicalCPUID & AMD_DR_B3) { - return; - } - - /* Skip reset DLL for Family 15h */ - if (is_fam15h()) { - return; - } - - addr = HWCR_MSR; - _RDMSR(addr, &lo, &hi); - if (lo & (1<<17)) { /* save the old value */ - wrap32dis = 1; - } - lo |= (1<<17); /* HWCR.wrap32dis */ - /* Setting wrap32dis allows 64-bit memory references in 32bit mode */ - _WRMSR(addr, lo, hi); - - pDCTstat->Channel = dct; - Receiver = mct_InitReceiver_D(pDCTstat, dct); - /* there are four receiver pairs, loosely associated with chipselects.*/ - for (; Receiver < 8; Receiver += 2) { - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, Receiver)) { - addr = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, dct, Receiver, &valid); - if (valid) { - mct_Read1LTestPattern_D(pMCTstat, pDCTstat, addr); /* cache fills */ - - /* Write 0000_8000h to register F2x[1,0]9C_xD080F0C */ - Set_NB32_index_wait_DCT(dev, dct, 0x98, 0xD080F0C, 0x00008000); - mct_Wait(80); /* wait >= 300ns */ - - /* Write 0000_0000h to register F2x[1,0]9C_xD080F0C */ - Set_NB32_index_wait_DCT(dev, dct, 0x98, 0xD080F0C, 0x00000000); - mct_Wait(800); /* wait >= 2us */ - break; - } - } - } - - if (!wrap32dis) { - addr = HWCR_MSR; - _RDMSR(addr, &lo, &hi); - lo &= ~(1<<17); /* restore HWCR.wrap32dis */ - _WRMSR(addr, lo, hi); - } -} - -void mct_EnableDatIntlv_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 dev = pDCTstat->dev_dct; - u32 val; - - /* Enable F2x110[DctDatIntlv] */ - /* Call back not required mctHookBeforeDatIntlv_D() */ - /* FIXME Skip for Ax */ - if (!pDCTstat->GangedMode) { - val = Get_NB32(dev, 0x110); - val |= 1 << 5; /* DctDatIntlv */ - Set_NB32(dev, 0x110, val); - - /* FIXME Skip for Cx */ - dev = pDCTstat->dev_nbmisc; - val = Get_NB32(dev, 0x8C); /* NB Configuration Hi */ - val |= 1 << (36-32); /* DisDatMask */ - Set_NB32(dev, 0x8C, val); - } -} - -void SetDllSpeedUp_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - if (!is_fam15h()) { - u32 val; - u32 dev = pDCTstat->dev_dct; - - if (pDCTstat->Speed >= mhz_to_memclk_config(800)) { /* DDR1600 and above */ - /* Set bit13 PowerDown to register F2x[1, 0]98_x0D080F10 */ - Set_NB32_DCT(dev, dct, 0x98, 0x0D080F10); - val = Get_NB32_DCT(dev, dct, 0x9C); - val |= 1 < 13; - Set_NB32_DCT(dev, dct, 0x9C, val); - Set_NB32_DCT(dev, dct, 0x98, 0x4D080F10); - - /* Set bit13 PowerDown to register F2x[1, 0]98_x0D080F11 */ - Set_NB32_DCT(dev, dct, 0x98, 0x0D080F11); - val = Get_NB32_DCT(dev, dct, 0x9C); - val |= 1 < 13; - Set_NB32_DCT(dev, dct, 0x9C, val); - Set_NB32_DCT(dev, dct, 0x98, 0x4D080F11); - - /* Set bit13 PowerDown to register F2x[1, 0]98_x0D088F30 */ - Set_NB32_DCT(dev, dct, 0x98, 0x0D088F30); - val = Get_NB32_DCT(dev, dct, 0x9C); - val |= 1 < 13; - Set_NB32_DCT(dev, dct, 0x9C, val); - Set_NB32_DCT(dev, dct, 0x98, 0x4D088F30); - - /* Set bit13 PowerDown to register F2x[1, 0]98_x0D08CF30 */ - Set_NB32_DCT(dev, dct, 0x98, 0x0D08CF30); - val = Get_NB32_DCT(dev, dct, 0x9C); - val |= 1 < 13; - Set_NB32_DCT(dev, dct, 0x9C, val); - Set_NB32_DCT(dev, dct, 0x98, 0x4D08CF30); - } - } -} - -static void SyncSetting(struct DCTStatStruc *pDCTstat) -{ - /* set F2x78[ChSetupSync] when F2x[1, 0]9C_x04[AddrCmdSetup, CsOdtSetup, - * CkeSetup] setups for one DCT are all 0s and at least one of the setups, - * F2x[1, 0]9C_x04[AddrCmdSetup, CsOdtSetup, CkeSetup], of the other - * controller is 1 - */ - u32 cha, chb; - u32 dev = pDCTstat->dev_dct; - u32 val; - - cha = pDCTstat->CH_ADDR_TMG[0] & 0x0202020; - chb = pDCTstat->CH_ADDR_TMG[1] & 0x0202020; - - if ((cha != chb) && ((cha == 0) || (chb == 0))) { - val = Get_NB32(dev, 0x78); - val |= 1 << ChSetupSync; - Set_NB32(dev, 0x78, val); - } -} - -static void AfterDramInit_D(struct DCTStatStruc *pDCTstat, u8 dct) { - - u32 val; - u32 dev = pDCTstat->dev_dct; - - if (pDCTstat->LogicalCPUID & (AMD_DR_B2 | AMD_DR_B3)) { - mct_Wait(10000); /* Wait 50 us*/ - val = Get_NB32(dev, 0x110); - if (!(val & (1 << DramEnabled))) { - /* If 50 us expires while DramEnable =0 then do the following */ - val = Get_NB32_DCT(dev, dct, 0x90); - val &= ~(1 << Width128); /* Program Width128 = 0 */ - Set_NB32_DCT(dev, dct, 0x90, val); - - val = Get_NB32_index_wait_DCT(dev, dct, 0x98, 0x05); /* Perform dummy CSR read to F2x09C_x05 */ - - if (pDCTstat->GangedMode) { - val = Get_NB32_DCT(dev, dct, 0x90); - val |= 1 << Width128; /* Program Width128 = 0 */ - Set_NB32_DCT(dev, dct, 0x90, val); - } - } - } -} - -/* ========================================================== - * 6-bit Bank Addressing Table - * RR = rows-13 binary - * B = Banks-2 binary - * CCC = Columns-9 binary - * ========================================================== - * DCT CCCBRR Rows Banks Columns 64-bit CS Size - * Encoding - * 0000 000000 13 2 9 128MB - * 0001 001000 13 2 10 256MB - * 0010 001001 14 2 10 512MB - * 0011 010000 13 2 11 512MB - * 0100 001100 13 3 10 512MB - * 0101 001101 14 3 10 1GB - * 0110 010001 14 2 11 1GB - * 0111 001110 15 3 10 2GB - * 1000 010101 14 3 11 2GB - * 1001 010110 15 3 11 4GB - * 1010 001111 16 3 10 4GB - * 1011 010111 16 3 11 8GB - */ -uint8_t crcCheck(struct DCTStatStruc *pDCTstat, uint8_t dimm) -{ - u16 crc_calc = spd_ddr3_calc_crc(pDCTstat->spd_data.spd_bytes[dimm], - sizeof(pDCTstat->spd_data.spd_bytes[dimm])); - u16 checksum_spd = pDCTstat->spd_data.spd_bytes[dimm][SPD_byte_127] << 8 - | pDCTstat->spd_data.spd_bytes[dimm][SPD_byte_126]; - - return crc_calc == checksum_spd; -} - -int32_t abs(int32_t val) -{ - if (val < 0) - return -val; - return val; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h deleted file mode 100644 index 952a66f71a..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h +++ /dev/null @@ -1,1165 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2015-2017 Raptor Engineering, LLC - * 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. - */ - -/* - * Description: Include file for all generic DDR 3 MCT files. - */ -#ifndef MCT_D_H -#define MCT_D_H - -#define DQS_TRAIN_DEBUG 0 - -#include <stdint.h> -#include <northbridge/amd/amdfam10/raminit.h> - -/*=========================================================================== - CPU - K8/FAM10 -===========================================================================*/ -#define PT_L1 0 /* CPU Package Type */ -#define PT_M2 1 -#define PT_S1 2 -#define PT_GR 3 -#define PT_AS 4 -#define PT_C3 5 -#define PT_FM2 6 - -#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_LINK(Node) ((((0x18+Node) << 3)+4) << 12) /*Node 0 Link Control bits [15:0]*/ -#define PA_NBCTL(Node) ((((0x18+Node) << 3)+5) << 12) /*Node 0 NB Control 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 5 /* bias to convert bus clocks to bit field value*/ -#define Bias_TrrdT 4 -#define Bias_TrcdT 5 -#define Bias_TrasT 15 -#define Bias_TrcT 11 -#define Bias_TrtpT 4 -#define Bias_TwrT 4 -#define Bias_TwtrT 4 -#define Bias_TfawT 14 - -#define Min_TrpT 5 /* min programmable value in busclocks */ -#define Max_TrpT 12 /* max programmable value in busclocks */ -#define Min_TrrdT 4 -#define Max_TrrdT 7 -#define Min_TrcdT 5 -#define Max_TrcdT 12 -#define Min_TrasT 15 -#define Max_TrasT 30 -#define Min_TrcT 11 -#define Max_TrcT 42 -#define Min_TrtpT 4 -#define Max_TrtpT 7 -#define Min_TwrT 5 -#define Max_TwrT 12 -#define Min_TwtrT 4 -#define Max_TwtrT 7 -#define Min_TfawT 16 -#define Max_TfawT 32 - -/*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 PchgPDModeSel 23 /* func 2, offset 84h, bit 23 */ -#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 ((is_fam15h())?7:3) /* func 2, offset 94h, bit 3 or 7*/ -#define RDqsEn 12 /* func 2, offset 94h, bit 12*/ -#define DisDramInterface 14 /* func 2, offset 94h, bit 14*/ -#define PowerDownEn 15 /* func 2, offset 94h, bit 15*/ -#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 SendZQCmd 29 /* func 2, offset 7Ch, bit 29 */ -#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 */ - -#define Ddr3Mode 8 /* func 2, offset 94h, bit 8 */ -#define EnterSelfRef 17 /* func 2, offset 90h, bit 17 */ -#define onDimmMirror 3 /* func 2, offset 5C:40h, bit 3 */ -#define OdtSwizzle 6 /* func 2, offset A8h, bit 6 */ -#define FreqChgInProg 21 /* func 2, offset 94h, bit 21 */ -#define ExitSelfRef 1 /* func 2, offset 90h, bit 1 */ - -#define SubMemclkRegDly 5 /* func 2, offset A8h, bit 5 */ -#define Ddr3FourSocketCh 2 /* func 2, offset A8h, bit 2 */ -#define SendControlWord 30 /* func 2, offset 7Ch, bit 30 */ - -#define NB_GfxNbPstateDis 62 /* MSRC001_001F Northbridge Configuration Register (NB_CFG) bit 62 GfxNbPstateDis disable northbridge p-state transitions */ -/*============================================================================= - SW Initialization -============================================================================*/ -#define DLL_Enable 1 -#define OCD_Default 2 -#define OCD_Exit 3 - -/*============================================================================= - Jedec DDR II -=============================================================================*/ -#define SPD_ByteUse 0 -#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 JED_DDR3SDRAM 0x0B /* Jedec defined bit field*/ - -#define SPD_DIMMTYPE 3 -#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 JED_RDIMM 0x1 /* RDIMM */ - #define JED_MiniRDIMM 0x5 /* Mini-RDIMM */ - #define JED_LRDIMM 0xb /* Load-reduced DIMM */ -#define SPD_Density 4 /* Bank address bits,SDRAM capacity */ -#define SPD_Addressing 5 /* Row/Column address bits */ -#define SPD_Voltage 6 /* Supported voltage bitfield */ -#define SPD_Organization 7 /* rank#,Device width */ -#define SPD_BusWidth 8 /* ECC, Bus width */ - #define JED_ECC 8 /* ECC capability */ - -#define SPD_MTBDividend 10 -#define SPD_MTBDivisor 11 -#define SPD_tCKmin 12 -#define SPD_CASLow 14 -#define SPD_CASHigh 15 -#define SPD_tAAmin 16 - -#define SPD_DEVATTRIB 22 -#define SPD_EDCTYPE 11 - #define JED_ADRCPAR 0x04 - -#define SPD_tWRmin 17 -#define SPD_tRCDmin 18 -#define SPD_tRRDmin 19 -#define SPD_tRPmin 20 -#define SPD_Upper_tRAS_tRC 21 -#define SPD_tRASmin 22 -#define SPD_tRCmin 23 -#define SPD_tWTRmin 26 -#define SPD_tRTPmin 27 -#define SPD_Upper_tFAW 28 -#define SPD_tFAWmin 29 -#define SPD_Thermal 31 - -#define SPD_RefRawCard 62 -#define SPD_AddressMirror 63 -#define SPD_RegManufactureID_L 65 /* not used */ -#define SPD_RegManufactureID_H 66 /* not used */ -#define SPD_RegManRevID 67 /* not used */ - -#define SPD_byte_126 126 -#define SPD_byte_127 127 - -#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)*/ - -#define SPD_MANID_START 117 -#define SPD_SERIAL_START 122 -#define SPD_PARTN_START 128 -#define SPD_PARTN_LENGTH 18 -#define SPD_REVNO_START 146 - -/*----------------------------- - 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)*/ - uint32_t TSCFreq; - uint16_t nvram_checksum; - uint8_t try_ecc; -} __attribute__((packed, aligned(4))); - -/*============================================================================= - 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 */ -#define GSB_ConfigRestored 18 /* Training configuration was restored from NVRAM */ - -/*=============================================================================== - Local DCT Status structure (a structure for each DCT) -===============================================================================*/ -#include "mwlc_d.h" /* I have to */ - -struct amd_spd_node_data { - uint8_t spd_bytes[MAX_DIMMS_SUPPORTED][256]; /* [DIMM][byte] */ - uint8_t spd_address[MAX_DIMMS_SUPPORTED]; /* [DIMM] */ - uint64_t spd_hash[MAX_DIMMS_SUPPORTED]; /* [DIMM] */ - uint64_t nvram_spd_hash[MAX_DIMMS_SUPPORTED]; /* [DIMM] */ - uint8_t nvram_spd_match; - uint8_t nvram_memclk[2]; /* [channel] */ -} __attribute__((packed, aligned(4))); - -struct DCTPersistentStatStruc { - u8 CH_D_B_TxDqs[2][4][9]; /* [A/B] [DIMM1-4] [DQS] */ - /* CHA DIMM0 Byte 0 - 7 TxDqs */ - /* CHA DIMM0 Byte 0 - 7 TxDqs */ - /* CHA DIMM1 Byte 0 - 7 TxDqs */ - /* CHA DIMM1 Byte 0 - 7 TxDqs */ - /* CHB DIMM0 Byte 0 - 7 TxDqs */ - /* CHB DIMM0 Byte 0 - 7 TxDqs */ - /* CHB DIMM1 Byte 0 - 7 TxDqs */ - /* CHB DIMM1 Byte 0 - 7 TxDqs */ - 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.*/ -} __attribute__((packed, aligned(4))); - -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[2]; /* 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][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 DIMMTfaw; /* Minimax Tfaw*16 (ns) of DIMMs */ - u8 Tfaw; /* DCT Tfaw (busclocks) */ - u16 CSUsrTestFail; /* Chip selects excluded by user */ -/* DCTStatStruct_F - end */ - - u16 CH_MaxRdLat[2][2]; /* Max Read Latency (nclks) [dct][pstate] */ - /* Max Read Latency (ns) for DCT 1*/ - 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*/ - u16 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*/ - u16 CH_D_BC_RCVRDLY[2][4]; - /* CHA DIMM 0 - 4 Check Byte Receiver Enable Delay*/ - /* CHB DIMM 0 - 4 Check Byte Receiver Enable Delay*/ - u8 DIMMValidDCT[2]; /* DIMM# in DCT0*/ - /* DIMM# in DCT1*/ - u16 CSPresent_DCT[2]; /* DCT# CS mapping */ - u16 MirrPresU_NumRegR; /* Address mapping from edge connect to DIMM present for unbuffered dimm - Number of registers on the dimm for registered dimm */ - 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 */ - - /* Fam15h specific backup variables */ - uint8_t SwNbPstateLoDis; - uint8_t NbPstateDisOnP0; - uint8_t NbPstateThreshold; - uint8_t NbPstateHi; - - /* New for LB Support */ - u8 NodePresent; - u32 dev_host; - u32 dev_map; - u32 dev_dct; - u32 dev_nbmisc; - u32 dev_link; - u32 dev_nbctl; - u8 TargetFreq; - u8 TargetCASL; - uint32_t CtrlWrd3; - uint32_t CtrlWrd4; - uint32_t CtrlWrd5; - u8 DqsRdWrPos_Saved; - u8 DqsRcvEnGrossMax; - u8 DqsRcvEnGrossMin; - u8 WrDatGrossMax; - u8 WrDatGrossMin; - uint8_t tcwl_delay[2]; - - u16 RegMan1Present; /* DIMM present bitmap of Register manufacture 1 */ - u16 RegMan2Present; /* DIMM present bitmap of Register manufacture 2 */ - - struct _sMCTStruct *C_MCTPtr; - struct _sDCTStruct *C_DCTPtr[2]; - /* struct _sDCTStruct *C_DCT1Ptr; */ - - struct _sMCTStruct s_C_MCTPtr; - struct _sDCTStruct s_C_DCTPtr[2]; - /* struct _sDCTStruct s_C_DCT1Ptr[8]; */ - - /* DIMM supported voltage bitmap ([2:0]: 1.25V, 1.35V, 1.5V) */ - uint8_t DimmSupportedVoltages[MAX_DIMMS_SUPPORTED]; - uint32_t DimmConfiguredVoltage[MAX_DIMMS_SUPPORTED]; /* mV */ - - 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]; - uint64_t DimmChipSize[MAX_DIMMS_SUPPORTED]; - uint32_t DimmChipWidth[MAX_DIMMS_SUPPORTED]; - uint8_t DimmRegistered[MAX_DIMMS_SUPPORTED]; - uint8_t DimmLoadReduced[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]; - - struct amd_spd_node_data spd_data; - - /* NOTE: This must remain the last entry in this structure */ - struct DCTPersistentStatStruc persistentData; -} __attribute__((packed, aligned(4))); - -struct amd_s3_persistent_mct_channel_data { - /* Stage 1 (1 dword) */ - uint32_t f2x110; - - /* Stage 2 (88 dwords) */ - uint32_t f1x40; - uint32_t f1x44; - uint32_t f1x48; - uint32_t f1x4c; - uint32_t f1x50; - uint32_t f1x54; - uint32_t f1x58; - uint32_t f1x5c; - uint32_t f1x60; - uint32_t f1x64; - uint32_t f1x68; - uint32_t f1x6c; - uint32_t f1x70; - uint32_t f1x74; - uint32_t f1x78; - uint32_t f1x7c; - uint32_t f1xf0; - uint32_t f1x120; - uint32_t f1x124; - uint32_t f2x10c; - uint32_t f2x114; - uint32_t f2x118; - uint32_t f2x11c; - uint32_t f2x1b0; - uint32_t f3x44; - uint64_t msr0000020[16]; - uint64_t msr00000250; - uint64_t msr00000258; - uint64_t msr0000026[8]; - uint64_t msr000002ff; - uint64_t msrc0010010; - uint64_t msrc001001a; - uint64_t msrc001001d; - uint64_t msrc001001f; - - /* Stage 3 (21 dwords) */ - uint32_t f2x40; - uint32_t f2x44; - uint32_t f2x48; - uint32_t f2x4c; - uint32_t f2x50; - uint32_t f2x54; - uint32_t f2x58; - uint32_t f2x5c; - uint32_t f2x60; - uint32_t f2x64; - uint32_t f2x68; - uint32_t f2x6c; - uint32_t f2x78; - uint32_t f2x7c; - uint32_t f2x80; - uint32_t f2x84; - uint32_t f2x88; - uint32_t f2x8c; - uint32_t f2x90; - uint32_t f2xa4; - uint32_t f2xa8; - - /* Stage 4 (1 dword) */ - uint32_t f2x94; - - /* Stage 6 (33 dwords) */ - uint32_t f2x9cx0d0f0_f_8_0_0_8_4_0[9][3]; /* [lane][setting] */ - uint32_t f2x9cx00; - uint32_t f2x9cx0a; - uint32_t f2x9cx0c; - - /* Stage 7 (1 dword) */ - uint32_t f2x9cx04; - - /* Stage 9 (2 dwords) */ - uint32_t f2x9cx0d0fe006; - uint32_t f2x9cx0d0fe007; - - /* Stage 10 (78 dwords) */ - uint32_t f2x9cx10[12]; - uint32_t f2x9cx20[12]; - uint32_t f2x9cx3_0_0_3_1[4][3]; /* [dimm][setting] */ - uint32_t f2x9cx3_0_0_7_5[4][3]; /* [dimm][setting] */ - uint32_t f2x9cx0d; - uint32_t f2x9cx0d0f0_f_0_13[9]; /* [lane] */ - uint32_t f2x9cx0d0f0_f_0_30[9]; /* [lane] */ - uint32_t f2x9cx0d0f2_f_0_30[4]; /* [pad select] */ - uint32_t f2x9cx0d0f8_8_4_0[2][3]; /* [offset][pad select] */ - uint32_t f2x9cx0d0f812f; - - /* Stage 11 (24 dwords) */ - uint32_t f2x9cx30[12]; - uint32_t f2x9cx40[12]; - - /* Other (3 dwords) */ - uint32_t f3x58; - uint32_t f3x5c; - uint32_t f3x60; - - /* Family 15h-specific registers (91 dwords) */ - uint32_t f2x200; - uint32_t f2x204; - uint32_t f2x208; - uint32_t f2x20c; - uint32_t f2x210[4]; /* [nb pstate] */ - uint32_t f2x214; - uint32_t f2x218; - uint32_t f2x21c; - uint32_t f2x22c; - uint32_t f2x230; - uint32_t f2x234; - uint32_t f2x238; - uint32_t f2x23c; - uint32_t f2x240; - uint32_t f2x9cx0d0fe003; - uint32_t f2x9cx0d0fe013; - uint32_t f2x9cx0d0f0_8_0_1f[9]; /* [lane]*/ - uint32_t f2x9cx0d0f201f; - uint32_t f2x9cx0d0f211f; - uint32_t f2x9cx0d0f221f; - uint32_t f2x9cx0d0f801f; - uint32_t f2x9cx0d0f811f; - uint32_t f2x9cx0d0f821f; - uint32_t f2x9cx0d0fc01f; - uint32_t f2x9cx0d0fc11f; - uint32_t f2x9cx0d0fc21f; - uint32_t f2x9cx0d0f4009; - uint32_t f2x9cx0d0f0_8_0_02[9]; /* [lane]*/ - uint32_t f2x9cx0d0f0_8_0_06[9]; /* [lane]*/ - uint32_t f2x9cx0d0f0_8_0_0a[9]; /* [lane]*/ - uint32_t f2x9cx0d0f2002; - uint32_t f2x9cx0d0f2102; - uint32_t f2x9cx0d0f2202; - uint32_t f2x9cx0d0f8002; - uint32_t f2x9cx0d0f8006; - uint32_t f2x9cx0d0f800a; - uint32_t f2x9cx0d0f8102; - uint32_t f2x9cx0d0f8106; - uint32_t f2x9cx0d0f810a; - uint32_t f2x9cx0d0fc002; - uint32_t f2x9cx0d0fc006; - uint32_t f2x9cx0d0fc00a; - uint32_t f2x9cx0d0fc00e; - uint32_t f2x9cx0d0fc012; - uint32_t f2x9cx0d0f2031; - uint32_t f2x9cx0d0f2131; - uint32_t f2x9cx0d0f2231; - uint32_t f2x9cx0d0f8031; - uint32_t f2x9cx0d0f8131; - uint32_t f2x9cx0d0f8231; - uint32_t f2x9cx0d0fc031; - uint32_t f2x9cx0d0fc131; - uint32_t f2x9cx0d0fc231; - uint32_t f2x9cx0d0f0_0_f_31[9]; /* [lane] */ - uint32_t f2x9cx0d0f8021; - uint32_t f2x9cx0d0fe00a; - - /* TOTAL: 343 dwords */ -} __attribute__((packed, aligned(4))); - -struct amd_s3_persistent_node_data { - uint32_t node_present; - uint64_t spd_hash[MAX_DIMMS_SUPPORTED]; - uint8_t memclk[2]; - struct amd_s3_persistent_mct_channel_data channel[2]; -} __attribute__((packed, aligned(4))); - -struct amd_s3_persistent_data { - struct amd_s3_persistent_node_data node[MAX_NODES_SUPPORTED]; - uint16_t nvram_checksum; -} __attribute__((packed, aligned(4))); - -/*=============================================================================== - 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 */ -#define SB_RetryConfigTrain 17 /* Retry configuration and training */ -#define SB_FatalError 18 /* Fatal training error detected */ - -/*=============================================================================== - Local Configuration Status (DCTStatStruc.Status[31:0]) -===============================================================================*/ -#define SB_Registered 0 /* All DIMMs are Registered*/ -#define SB_LoadReduced 1 /* All DIMMs are Load-Reduced*/ -#define SB_ECCDIMMs 2 /* All banks ECC capable*/ -#define SB_PARDIMMs 3 /* All banks Addr/CMD Parity capable*/ -#define SB_DiagClks 4 /* Jedec ALL slots clock enable diag mode*/ -#define SB_128bitmode 5 /* DCT in 128-bit mode operation*/ -#define SB_64MuxedMode 6 /* DCT in 64-bit mux'ed mode.*/ -#define SB_2TMode 7 /* 2T CMD timing mode is enabled.*/ -#define SB_SWNodeHole 8 /* Remapping of Node Base on this Node to create a gap.*/ -#define SB_HWHole 9 /* Memory Hole created on this Node using HW remapping.*/ -#define SB_Over400MHz 10 /* DCT freq >= 400MHz flag*/ -#define SB_DQSPos_Pass2 11 /* Using for TrainDQSPos DIMM0/1, when freq >= 400MHz*/ -#define SB_DQSRcvLimit 12 /* Using for DQSRcvEnTrain to know we have reached to upper bound.*/ -#define SB_ExtConfig 13 /* 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 */ - -/*=============================================================================== - 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; -} __attribute__((packed, aligned(4))); - -extern const u8 Table_DQSRcvEn_Offset[]; -extern const u32 TestPattern0_D[]; -extern const u32 TestPattern1_D[]; -extern const u32 TestPattern2_D[]; - -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); -u16 mct_Average_RcvrEnDly_Pass(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly, u16 RcvrEnDlyLimit, u8 Channel, u8 Receiver, u8 Pass); -void initialize_mca(uint8_t bsp, uint8_t suppress_errors); -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 TrainMaxRdLatency_En_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -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, u16 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 MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u32 dct, u32 DramConfigHi); -void mct_DramInit_Hw_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct); -void mct_SetClToNB_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void mct_SetWbEnhWsbDis_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void mct_ForceNBPState0_En_Fam15(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void mct_ForceNBPState0_Dis_Fam15(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 DIMMSetVoltages(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -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 phyAssistedMemFnceTraining(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA, int16_t Node); -u8 mct_SaveRcvEnDly_D_1Pass(struct DCTStatStruc *pDCTstat, u8 pass); -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 mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -void calculate_spd_hash(uint8_t *spd_data, uint64_t *spd_hash); -int8_t load_spd_hashes_from_nvram(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -int8_t restore_mct_information_from_nvram(uint8_t training_only); -uint16_t calculate_nvram_mct_hash(void); - -uint32_t fam10h_address_timing_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct); -uint32_t fam15h_output_driver_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct); -uint32_t fam15h_address_timing_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct); -uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dct); -void precise_memclk_delay_fam15(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, uint32_t clocks); -void mct_EnableDatIntlv_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -void SetDllSpeedUp_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -uint8_t get_available_lane_count(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void read_dqs_receiver_enable_control_registers(uint16_t *current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg); -void read_dqs_write_timing_control_registers(uint16_t *current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg); -void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t enable); -void read_dqs_read_data_timing_registers(uint16_t *delay, uint32_t dev, - uint8_t dct, uint8_t dimm, uint32_t index_reg); -void write_dqs_read_data_timing_registers(uint16_t *delay, uint32_t dev, - uint8_t dct, uint8_t dimm, uint32_t index_reg); -void dqsTrainMaxRdLatency_SW_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -void proc_IOCLFLUSH_D(u32 addr_hi); -u8 ChipSelPresent_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 ChipSel); -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 DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -void SPD2ndTiming(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -void ProgDramMRSReg_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -u8 PlatformSpec_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -void StartupDCT_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -uint16_t mhz_to_memclk_config(uint16_t freq); -void SetTargetFreq(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, uint8_t Node); -void mct_WriteLevelization_HW(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, uint8_t Pass); -uint8_t AgesaHwWlPhase1(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u8 dimm, u8 pass); -uint8_t AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t pass); -uint8_t AgesaHwWlPhase3(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u8 dimm, u8 pass); -void EnableZQcalibration(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void DisableZQcalibration(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void PrepareC_MCT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void PrepareC_DCT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct); -void Restore_OnDimmMirror(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void Clear_OnDimmMirror(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat); -void MCTMemClr_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -void mct_BeforeDQSTrainSamp(struct DCTStatStruc *pDCTstat); -void mct_ExtMCTConfig_Bx(struct DCTStatStruc *pDCTstat); -void mct_ExtMCTConfig_Cx(struct DCTStatStruc *pDCTstat); -void mct_ExtMCTConfig_Dx(struct DCTStatStruc *pDCTstat); -u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, - uint8_t dct, uint32_t misc2, uint32_t DramControl); - -uint8_t dct_ddr_voltage_index(struct DCTStatStruc *pDCTstat, uint8_t dct); -void mct_DramControlReg_Init_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct); -void precise_ndelay_fam15(struct MCTStatStruc *pMCTstat, uint32_t nanoseconds); -void FreqChgCtrlWrd(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct); -u32 mct_MR1Odt_RDimm(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel); -void mct_DramInit_Sw_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -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, uint8_t dct, u32 index_reg, u32 index); -void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t calc_min); -void write_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, - uint8_t Receiver, uint8_t lane, uint8_t stop_on_error); -void read_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, - uint8_t Receiver, uint8_t lane, uint8_t stop_on_error); -void write_dqs_receiver_enable_control_registers(uint16_t *current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg); - -uint32_t fenceDynTraining_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct); -int32_t abs(int32_t val); -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); -void set_2t_configuration(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -u8 mct_BeforePlatformSpec(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -u8 mct_PlatformSpec(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -void InitPhyCompensation(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct); -u32 mct_MR1(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel); -u32 mct_MR2(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel); -uint8_t fam15_rttwr(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type); -uint8_t fam15_rttnom(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type); -uint8_t fam15_dimm_dic(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type); -u32 mct_DramTermDyn_RDimm(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dimm); - -void restore_mct_data_from_save_variable(struct amd_s3_persistent_data* persistent_data, uint8_t training_only); -#endif diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.c deleted file mode 100644 index ccea732709..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h deleted file mode 100644 index 629e6e639b..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d_gcc.h +++ /dev/null @@ -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 diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctardk5.c b/src/northbridge/amd/amdmct/mct_ddr3/mctardk5.c deleted file mode 100644 index e8116340c4..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctardk5.c +++ /dev/null @@ -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; - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c b/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c deleted file mode 100644 index d6480ab91a..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctardk6.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctchi_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctchi_d.c deleted file mode 100644 index d458f3a48e..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctchi_d.c +++ /dev/null @@ -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"); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c deleted file mode 100644 index 85e7930b24..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c +++ /dev/null @@ -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"); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c deleted file mode 100644 index d34b2dc2ba..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c +++ /dev/null @@ -1,2493 +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 <stdint.h> -#include <console/console.h> -#include <cpu/x86/cr.h> -#include <string.h> -#include <arch/cpu.h> -#include <cpu/amd/msr.h> -#include <cpu/amd/mtrr.h> -#include "mct_d.h" -#include "mct_d_gcc.h" - -static void CalcEccDQSPos_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u16 like, - u8 scale, u8 ChipSel); -static void GetDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel); -static void WriteDQSTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo); -static void WriteL18TestPattern_D(struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo); -static void WriteL9TestPattern_D(struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo); -static u16 CompareDQSTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 addr_lo); -static void FlushDQSTestPattern_D(struct DCTStatStruc *pDCTstat, - u32 addr_lo); -static void mct_SetDQSDelayCSR_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 ChipSel); -static void SetupDqsPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 *buffer); - -static void StoreDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 ChipSel); - -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; -} - -#define DQS_TRAIN_DEBUG 0 -// #define PRINT_PASS_FAIL_BITMAPS 1 - -void print_debug_dqs(const char *str, u32 val, u8 level) -{ -#if DQS_TRAIN_DEBUG > 0 - if (DQS_TRAIN_DEBUG >= level) { - printk(BIOS_DEBUG, "%s%x\n", str, val); - } -#endif -} - -void print_debug_dqs_pair(const char *str, u32 val, const char *str2, u32 val2, u8 level) -{ -#if DQS_TRAIN_DEBUG > 0 - if (DQS_TRAIN_DEBUG >= level) { - printk(BIOS_DEBUG, "%s%08x%s%08x\n", str, val, str2, val2); - } -#endif -} - -/*Warning: These must be located so they do not cross a logical 16-bit segment boundary!*/ -static const u32 TestPatternJD1a_D[] = { - 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF, /* QW0-1, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW2-3, ALL-EVEN */ - 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF, /* QW4-5, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW6-7, ALL-EVEN */ - 0xFeFeFeFe,0xFeFeFeFe,0x01010101,0x01010101, /* QW0-1, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0x01010101,0x01010101, /* QW2-3, DQ0-ODD */ - 0x01010101,0x01010101,0xFeFeFeFe,0xFeFeFeFe, /* QW4-5, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0x01010101,0x01010101, /* QW6-7, DQ0-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW0-1, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, /* QW2-3, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0x02020202,0x02020202, /* QW4-5, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW6-7, DQ1-ODD */ - 0x04040404,0x04040404,0xfBfBfBfB,0xfBfBfBfB, /* QW0-1, DQ2-ODD */ - 0x04040404,0x04040404,0x04040404,0x04040404, /* QW2-3, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW4-5, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW6-7, DQ2-ODD */ - 0x08080808,0x08080808,0xF7F7F7F7,0xF7F7F7F7, /* QW0-1, DQ3-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW2-3, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0x08080808,0x08080808, /* QW4-5, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW6-7, DQ3-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW0-1, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0x10101010,0x10101010, /* QW2-3, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW4-5, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0x10101010,0x10101010, /* QW6-7, DQ4-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW0-1, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0x20202020,0x20202020, /* QW2-3, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW4-5, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW6-7, DQ5-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW0-1, DQ6-ODD */ - 0x40404040,0x40404040,0xBfBfBfBf,0xBfBfBfBf, /* QW2-3, DQ6-ODD */ - 0x40404040,0x40404040,0xBfBfBfBf,0xBfBfBfBf, /* QW4-5, DQ6-ODD */ - 0x40404040,0x40404040,0xBfBfBfBf,0xBfBfBfBf, /* QW6-7, DQ6-ODD */ - 0x80808080,0x80808080,0x7F7F7F7F,0x7F7F7F7F, /* QW0-1, DQ7-ODD */ - 0x80808080,0x80808080,0x7F7F7F7F,0x7F7F7F7F, /* QW2-3, DQ7-ODD */ - 0x80808080,0x80808080,0x7F7F7F7F,0x7F7F7F7F, /* QW4-5, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080 /* QW6-7, DQ7-ODD */ -}; -static const u32 TestPatternJD1b_D[] = { - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW0,CHA-B, ALL-EVEN */ - 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, /* QW1,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW2,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW3,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW4,CHA-B, ALL-EVEN */ - 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, /* QW5,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW6,CHA-B, ALL-EVEN */ - 0x00000000,0x00000000,0x00000000,0x00000000, /* QW7,CHA-B, ALL-EVEN */ - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, /* QW0,CHA-B, DQ0-ODD */ - 0x01010101,0x01010101,0x01010101,0x01010101, /* QW1,CHA-B, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, /* QW2,CHA-B, DQ0-ODD */ - 0x01010101,0x01010101,0x01010101,0x01010101, /* QW3,CHA-B, DQ0-ODD */ - 0x01010101,0x01010101,0x01010101,0x01010101, /* QW4,CHA-B, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, /* QW5,CHA-B, DQ0-ODD */ - 0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe,0xFeFeFeFe, /* QW6,CHA-B, DQ0-ODD */ - 0x01010101,0x01010101,0x01010101,0x01010101, /* QW7,CHA-B, DQ0-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW0,CHA-B, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW1,CHA-B, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, /* QW2,CHA-B, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, /* QW3,CHA-B, DQ1-ODD */ - 0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd,0xFdFdFdFd, /* QW4,CHA-B, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW5,CHA-B, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW6,CHA-B, DQ1-ODD */ - 0x02020202,0x02020202,0x02020202,0x02020202, /* QW7,CHA-B, DQ1-ODD */ - 0x04040404,0x04040404,0x04040404,0x04040404, /* QW0,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW1,CHA-B, DQ2-ODD */ - 0x04040404,0x04040404,0x04040404,0x04040404, /* QW2,CHA-B, DQ2-ODD */ - 0x04040404,0x04040404,0x04040404,0x04040404, /* QW3,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW4,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW5,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW6,CHA-B, DQ2-ODD */ - 0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB,0xfBfBfBfB, /* QW7,CHA-B, DQ2-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW0,CHA-B, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW1,CHA-B, DQ3-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW2,CHA-B, DQ3-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW3,CHA-B, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW4,CHA-B, DQ3-ODD */ - 0x08080808,0x08080808,0x08080808,0x08080808, /* QW5,CHA-B, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW6,CHA-B, DQ3-ODD */ - 0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7,0xF7F7F7F7, /* QW7,CHA-B, DQ3-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW0,CHA-B, DQ4-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW1,CHA-B, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW2,CHA-B, DQ4-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW3,CHA-B, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW4,CHA-B, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW5,CHA-B, DQ4-ODD */ - 0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF,0xeFeFeFeF, /* QW6,CHA-B, DQ4-ODD */ - 0x10101010,0x10101010,0x10101010,0x10101010, /* QW7,CHA-B, DQ4-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW0,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW1,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW2,CHA-B, DQ5-ODD */ - 0x20202020,0x20202020,0x20202020,0x20202020, /* QW3,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW4,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW5,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW6,CHA-B, DQ5-ODD */ - 0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF,0xdFdFdFdF, /* QW7,CHA-B, DQ5-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW0,CHA-B, DQ6-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW1,CHA-B, DQ6-ODD */ - 0x40404040,0x40404040,0x40404040,0x40404040, /* QW2,CHA-B, DQ6-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW3,CHA-B, DQ6-ODD */ - 0x40404040,0x40404040,0x40404040,0x40404040, /* QW4,CHA-B, DQ6-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW5,CHA-B, DQ6-ODD */ - 0x40404040,0x40404040,0x40404040,0x40404040, /* QW6,CHA-B, DQ6-ODD */ - 0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf,0xBfBfBfBf, /* QW7,CHA-B, DQ6-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080, /* QW0,CHA-B, DQ7-ODD */ - 0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F, /* QW1,CHA-B, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080, /* QW2,CHA-B, DQ7-ODD */ - 0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F, /* QW3,CHA-B, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080, /* QW4,CHA-B, DQ7-ODD */ - 0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F,0x7F7F7F7F, /* QW5,CHA-B, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080, /* QW6,CHA-B, DQ7-ODD */ - 0x80808080,0x80808080,0x80808080,0x80808080 /* QW7,CHA-B, DQ7-ODD */ -}; - -void TrainReceiverEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, u8 Pass) -{ - u8 Node; - struct DCTStatStruc *pDCTstat; - u32 val; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - - if (pDCTstat->DCTSysLimit) { - if (!is_fam15h()) { - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x78); - val |= 1 <<DqsRcvEnTrain; - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x78, val); - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x78); - val |= 1 <<DqsRcvEnTrain; - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x78, val); - } - mct_TrainRcvrEn_D(pMCTstat, pDCTstat, Pass); - } - } -} - -void TrainMaxRdLatency_En_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - uint8_t node; - struct DCTStatStruc *pDCTstat; - - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - pDCTstat = pDCTstatA + node; - - if (pDCTstat->DCTSysLimit) { - if (is_fam15h()) { - dqsTrainMaxRdLatency_SW_Fam15(pMCTstat, pDCTstat); - } else { - /* FIXME - * Implement Family 10h MaxRdLatency training - */ - } - } - } -} - -static void SetEccDQSRdWrPos_D_Fam10(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel) -{ - u8 channel; - u8 direction; - - for (channel = 0; channel < 2; channel++) { - for (direction = 0; direction < 2; direction++) { - pDCTstat->Channel = channel; /* Channel A or B */ - pDCTstat->Direction = direction; /* Read or write */ - CalcEccDQSPos_D(pMCTstat, pDCTstat, pDCTstat->CH_EccDQSLike[channel], pDCTstat->CH_EccDQSScale[channel], ChipSel); - print_debug_dqs_pair("\t\tSetEccDQSRdWrPos: channel ", channel, direction == DQS_READDIR? " R dqs_delay":" W dqs_delay", pDCTstat->DQSDelay, 2); - pDCTstat->ByteLane = 8; - StoreDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel); - mct_SetDQSDelayCSR_D(pMCTstat, pDCTstat, ChipSel); - } - } -} - -static void CalcEccDQSPos_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u16 like, u8 scale, u8 ChipSel) -{ - uint8_t DQSDelay0, DQSDelay1; - int16_t delay_differential; - uint16_t DQSDelay; - - if (pDCTstat->Status & (1 << SB_Registered)) { - pDCTstat->ByteLane = 0x2; - GetDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel); - DQSDelay0 = pDCTstat->DQSDelay; - - pDCTstat->ByteLane = 0x3; - GetDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel); - DQSDelay1 = pDCTstat->DQSDelay; - - if (pDCTstat->Direction == DQS_READDIR) { - DQSDelay = DQSDelay1; - } else { - delay_differential = (int16_t)DQSDelay1 - (int16_t)DQSDelay0; - delay_differential += (int16_t)DQSDelay1; - - DQSDelay = delay_differential; - } - } else { - pDCTstat->ByteLane = like & 0xff; - GetDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel); - DQSDelay0 = pDCTstat->DQSDelay; - - pDCTstat->ByteLane = (like >> 8) & 0xff; - GetDQSDatStrucVal_D(pMCTstat, pDCTstat, ChipSel); - DQSDelay1 = pDCTstat->DQSDelay; - - if (DQSDelay0 > DQSDelay1) { - DQSDelay = DQSDelay0 - DQSDelay1; - } else { - DQSDelay = DQSDelay1 - DQSDelay0; - } - - DQSDelay = DQSDelay * (~scale); - - DQSDelay += 0x80; /* round it */ - - DQSDelay >>= 8; /* 256 */ - - if (DQSDelay0 > DQSDelay1) { - DQSDelay = DQSDelay1 - DQSDelay; - } else { - DQSDelay += DQSDelay1; - } - } - - pDCTstat->DQSDelay = (u8)DQSDelay; -} - -static void read_dqs_write_data_timing_registers(uint16_t *delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg) -{ - uint32_t dword; - uint32_t mask; - - if (is_fam15h()) - mask = 0xff; - else - mask = 0x7f; - - /* Lanes 0 - 3 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x1 | (dimm << 8)); - delay[3] = (dword >> 24) & mask; - delay[2] = (dword >> 16) & mask; - delay[1] = (dword >> 8) & mask; - delay[0] = dword & mask; - - /* Lanes 4 - 7 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x2 | (dimm << 8)); - delay[7] = (dword >> 24) & mask; - delay[6] = (dword >> 16) & mask; - delay[5] = (dword >> 8) & mask; - delay[4] = dword & mask; - - /* Lane 8 (ECC) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x3 | (dimm << 8)); - delay[8] = dword & mask; -} - -static void write_dqs_write_data_timing_registers(uint16_t *delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg) -{ - uint32_t dword; - uint32_t mask; - - if (is_fam15h()) - mask = 0xff; - else - mask = 0x7f; - - /* Lanes 0 - 3 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x1 | (dimm << 8)); - dword &= ~(mask << 24); - dword &= ~(mask << 16); - dword &= ~(mask << 8); - dword &= ~mask; - dword |= (delay[3] & mask) << 24; - dword |= (delay[2] & mask) << 16; - dword |= (delay[1] & mask) << 8; - dword |= delay[0] & mask; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x1 | (dimm << 8), dword); - - /* Lanes 4 - 7 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x2 | (dimm << 8)); - dword &= ~(mask << 24); - dword &= ~(mask << 16); - dword &= ~(mask << 8); - dword &= ~mask; - dword |= (delay[7] & mask) << 24; - dword |= (delay[6] & mask) << 16; - dword |= (delay[5] & mask) << 8; - dword |= delay[4] & mask; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x2 | (dimm << 8), dword); - - /* Lane 8 (ECC) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x3 | (dimm << 8)); - dword &= ~mask; - dword |= delay[8] & mask; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x3 | (dimm << 8), dword); -} - -/* DQS Position Training - * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.3 - */ -static void TrainDQSRdWrPos_D_Fam10(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 Errors; - u8 Channel; - u8 Receiver; - u8 _DisableDramECC = 0; - u32 PatternBuffer[304]; /* 288 + 16 */ - u8 _Wrap32Dis = 0, _SSE2 = 0; - - u32 dev; - u32 addr; - u8 valid; - CRx_TYPE cr4; - u32 lo, hi; - u32 index_reg; - uint32_t TestAddr; - - uint8_t dual_rank; - uint8_t iter; - uint8_t lane; - uint16_t bytelane_test_results; - uint16_t current_write_dqs_delay[MAX_BYTE_LANES]; - uint16_t current_read_dqs_delay[MAX_BYTE_LANES]; - uint16_t write_dqs_delay_stepping_done[MAX_BYTE_LANES]; - uint8_t dqs_read_results_array[2][MAX_BYTE_LANES][64]; /* [rank][lane][step] */ - uint8_t dqs_write_results_array[2][MAX_BYTE_LANES][128]; /* [rank][lane][step] */ - - uint8_t last_pos = 0; - uint8_t cur_count = 0; - uint8_t best_pos = 0; - uint8_t best_count = 0; - - print_debug_dqs("\nTrainDQSRdWrPos: Node_ID ", pDCTstat->Node_ID, 0); - cr4 = read_cr4(); - if (cr4 & (1<<9)) { - _SSE2 = 1; - } - cr4 |= (1<<9); /* OSFXSR enable SSE2 */ - write_cr4(cr4); - - addr = HWCR_MSR; - _RDMSR(addr, &lo, &hi); - if (lo & (1<<17)) { - _Wrap32Dis = 1; - } - lo |= (1<<17); /* HWCR.wrap32dis */ - _WRMSR(addr, lo, hi); /* allow 64-bit memory references in real mode */ - - /* Disable ECC correction of reads on the dram bus. */ - _DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat); - - SetupDqsPattern_D(pMCTstat, pDCTstat, PatternBuffer); - - /* mct_BeforeTrainDQSRdWrPos_D */ - - dev = pDCTstat->dev_dct; - pDCTstat->Direction = DQS_READDIR; - - /* 2.8.9.9.3 (2) - * Loop over each channel, lane, and rank - */ - - /* NOTE - * The BKDG originally stated to iterate over lane, then rank, however this process is quite slow - * compared to an equivalent loop over rank, then lane as the latter allows multiple lanes to be - * tested simultaneously, thus improving performance by around 8x. - */ - - Errors = 0; - for (Channel = 0; Channel < 2; Channel++) { - print_debug_dqs("\tTrainDQSRdWrPos: 1 Channel ", Channel, 1); - pDCTstat->Channel = Channel; - - if (pDCTstat->DIMMValidDCT[Channel] == 0) /* mct_BeforeTrainDQSRdWrPos_D */ - continue; - - index_reg = 0x98; - - dual_rank = 0; - Receiver = mct_InitReceiver_D(pDCTstat, Channel); - /* There are four receiver pairs, loosely associated with chipselects. - * This is essentially looping over each rank of each DIMM. - */ - for (; Receiver < 8; Receiver++) { - if ((Receiver & 0x1) == 0) { - /* Even rank of DIMM */ - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver+1)) - dual_rank = 1; - else - dual_rank = 0; - } - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver)) { - continue; - } - - /* Select the base test address for the current rank */ - TestAddr = mct_GetMCTSysAddr_D(pMCTstat, pDCTstat, Channel, Receiver, &valid); - if (!valid) { /* Address not supported on current CS */ - continue; - } - - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 14 TestAddr ", TestAddr, 4); - SetUpperFSbase(TestAddr); /* fs:eax = far ptr to target */ - - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 12 Receiver ", Receiver, 2); - - /* 2.8.9.9.3 (DRAM Write Data Timing Loop) - * Iterate over all possible DQS delay values (0x0 - 0x7f) - */ - uint8_t test_write_dqs_delay = 0; - uint8_t test_read_dqs_delay = 0; - uint8_t passing_dqs_delay_found[MAX_BYTE_LANES]; - - /* Initialize variables */ - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - current_write_dqs_delay[lane] = 0; - passing_dqs_delay_found[lane] = 0; - write_dqs_delay_stepping_done[lane] = 0; - } - - for (test_write_dqs_delay = 0; test_write_dqs_delay < 128; test_write_dqs_delay++) { - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 16 test_write_dqs_delay ", test_write_dqs_delay, 6); - - /* Break out of loop if passing window already found, */ - if (write_dqs_delay_stepping_done[0] && write_dqs_delay_stepping_done[1] - && write_dqs_delay_stepping_done[2] && write_dqs_delay_stepping_done[3] - && write_dqs_delay_stepping_done[4] && write_dqs_delay_stepping_done[5] - && write_dqs_delay_stepping_done[6] && write_dqs_delay_stepping_done[7]) - break; - - /* Commit the current Write Data Timing settings to the hardware registers */ - write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, Channel, (Receiver >> 1), index_reg); - - /* Write the DRAM training pattern to the base test address */ - WriteDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8); - - /* 2.8.9.9.3 (DRAM Read DQS Timing Control Loop) - * Iterate over all possible DQS delay values (0x0 - 0x3f) - */ - for (test_read_dqs_delay = 0; test_read_dqs_delay < 64; test_read_dqs_delay++) { - print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 161 test_read_dqs_delay ", test_read_dqs_delay, 6); - - /* Initialize Read DQS Timing Control settings for this iteration */ - for (lane = 0; lane < MAX_BYTE_LANES; lane++) - if (!write_dqs_delay_stepping_done[lane]) - current_read_dqs_delay[lane] = test_read_dqs_delay; - - /* Commit the current Read DQS Timing Control settings to the hardware registers */ - write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, Channel, (Receiver >> 1), index_reg); - - /* Initialize test result variable */ - bytelane_test_results = 0xff; - - /* Read the DRAM training pattern from the base test address three times - * NOTE - * While the BKDG states to read three times this is probably excessive! - * Decrease training time by only reading the test pattern once per iteration - */ - for (iter = 0; iter < 1; iter++) { - /* Flush caches */ - SetTargetWTIO_D(TestAddr); - FlushDQSTestPattern_D(pDCTstat, TestAddr << 8); - ResetTargetWTIO_D(); - - /* Read and compare pattern */ - bytelane_test_results &= (CompareDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8) & 0xff); /* [Lane 7 :: Lane 0] 0 = fail, 1 = pass */ - - /* If all lanes have already failed testing bypass remaining re-read attempt(s) */ - if (bytelane_test_results == 0x0) - break; - } - - /* Store any lanes that passed testing for later use */ - for (lane = 0; lane < 8; lane++) - if (!write_dqs_delay_stepping_done[lane]) - dqs_read_results_array[Receiver & 0x1][lane][test_read_dqs_delay] = (!!(bytelane_test_results & (1 << lane))); - - print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 162 bytelane_test_results ", bytelane_test_results, 6); - } - - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - if (write_dqs_delay_stepping_done[lane]) - continue; - - /* Determine location and length of longest consecutive string of passing values - * Output is stored in best_pos and best_count - */ - last_pos = 0; - cur_count = 0; - best_pos = 0; - best_count = 0; - for (iter = 0; iter < 64; iter++) { - if ((dqs_read_results_array[Receiver & 0x1][lane][iter]) && (iter < 63)) { - /* Pass */ - cur_count++; - } else { - /* Failure or end of loop */ - if (cur_count > best_count) { - best_count = cur_count; - best_pos = last_pos; - } - cur_count = 0; - last_pos = iter; - } - } - - if (best_count > 2) { - /* Exit the DRAM Write Data Timing Loop after programming the Read DQS Timing Control - * register with the center of the passing window - */ - current_read_dqs_delay[lane] = (best_pos + (best_count / 2)); - passing_dqs_delay_found[lane] = 1; - - /* Commit the current Read DQS Timing Control settings to the hardware registers */ - write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, Channel, (Receiver >> 1), index_reg); - - /* Exit the DRAM Write Data Timing Loop */ - write_dqs_delay_stepping_done[lane] = 1; - - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 142 largest passing region ", best_count, 4); - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 143 largest passing region start ", best_pos, 4); - } - - /* Increment the DQS Write Delay value if needed for the next DRAM Write Data Timing Loop iteration */ - if (!write_dqs_delay_stepping_done[lane]) - current_write_dqs_delay[lane]++; - } - } - - /* Flag failure(s) if present */ - for (lane = 0; lane < 8; lane++) { - if (!passing_dqs_delay_found[lane]) { - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 121 Unable to find passing region for lane ", lane, 2); - - /* Flag absence of passing window */ - Errors |= 1 << SB_NODQSPOS; - } - } - - /* Iterate over all possible Write Data Timing values (0x0 - 0x7f) - * Note that the Read DQS Timing Control was calibrated / centered in the prior nested loop - */ - for (test_write_dqs_delay = 0; test_write_dqs_delay < 128; test_write_dqs_delay++) { - /* Initialize Write Data Timing settings for this iteration */ - for (lane = 0; lane < MAX_BYTE_LANES; lane++) - current_write_dqs_delay[lane] = test_write_dqs_delay; - - /* Commit the current Write Data Timing settings to the hardware registers */ - write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, Channel, (Receiver >> 1), index_reg); - - /* Write the DRAM training pattern to the base test address */ - WriteDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8); - - /* Flush caches */ - SetTargetWTIO_D(TestAddr); - FlushDQSTestPattern_D(pDCTstat, TestAddr << 8); - ResetTargetWTIO_D(); - - /* Read and compare pattern from the base test address */ - bytelane_test_results = (CompareDQSTestPattern_D(pMCTstat, pDCTstat, TestAddr << 8) & 0xff); /* [Lane 7 :: Lane 0] 0 = fail, 1 = pass */ - - /* Store any lanes that passed testing for later use */ - for (lane = 0; lane < 8; lane++) - dqs_write_results_array[Receiver & 0x1][lane][test_write_dqs_delay] = (!!(bytelane_test_results & (1 << lane))); - } - - for (lane = 0; lane < 8; lane++) { - if ((!dual_rank) || (dual_rank && (Receiver & 0x1))) { - -#ifdef PRINT_PASS_FAIL_BITMAPS - for (iter = 0; iter < 64; iter++) { - if (dqs_read_results_array[0][lane][iter]) - printk(BIOS_DEBUG, "+"); - else - printk(BIOS_DEBUG, "."); - } - printk(BIOS_DEBUG, "\n"); - for (iter = 0; iter < 64; iter++) { - if (dqs_read_results_array[1][lane][iter]) - printk(BIOS_DEBUG, "+"); - else - printk(BIOS_DEBUG, "."); - } - printk(BIOS_DEBUG, "\n\n"); - for (iter = 0; iter < 128; iter++) { - if (dqs_write_results_array[0][lane][iter]) - printk(BIOS_DEBUG, "+"); - else - printk(BIOS_DEBUG, "."); - } - printk(BIOS_DEBUG, "\n"); - for (iter = 0; iter < 128; iter++) { - if (dqs_write_results_array[1][lane][iter]) - printk(BIOS_DEBUG, "+"); - else - printk(BIOS_DEBUG, "."); - } - printk(BIOS_DEBUG, "\n\n"); -#endif - - /* Base rank of single-rank DIMM, or odd rank of dual-rank DIMM */ - if (dual_rank) { - /* Intersect the passing windows of both ranks */ - for (iter = 0; iter < 64; iter++) - if (!dqs_read_results_array[1][lane][iter]) - dqs_read_results_array[0][lane][iter] = 0; - for (iter = 0; iter < 128; iter++) - if (!dqs_write_results_array[1][lane][iter]) - dqs_write_results_array[0][lane][iter] = 0; - } - - /* Determine location and length of longest consecutive string of passing values for read DQS timing - * Output is stored in best_pos and best_count - */ - last_pos = 0; - cur_count = 0; - best_pos = 0; - best_count = 0; - for (iter = 0; iter < 64; iter++) { - if ((dqs_read_results_array[0][lane][iter]) && (iter < 63)) { - /* Pass */ - cur_count++; - } else { - /* Failure or end of loop */ - if (cur_count > best_count) { - best_count = cur_count; - best_pos = last_pos; - } - cur_count = 0; - last_pos = iter; - } - } - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 144 largest read passing region ", best_count, 4); - if (best_count > 0) { - if (best_count < MIN_DQS_WNDW) { - /* Flag excessively small passing window */ - Errors |= 1 << SB_SMALLDQS; - } - - /* Find the center of the passing window */ - current_read_dqs_delay[lane] = (best_pos + (best_count / 2)); - - /* Commit the current Read DQS Timing Control settings to the hardware registers */ - write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, Channel, (Receiver >> 1), index_reg); - - /* Save the final Read DQS Timing Control settings for later use */ - pDCTstat->CH_D_DIR_B_DQS[Channel][Receiver >> 1][DQS_READDIR][lane] = current_read_dqs_delay[lane]; - } else { - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 122 Unable to find read passing region for lane ", lane, 2); - - /* Flag absence of passing window */ - Errors |= 1 << SB_NODQSPOS; - } - - /* Determine location and length of longest consecutive string of passing values for write DQS timing - * Output is stored in best_pos and best_count - */ - last_pos = 0; - cur_count = 0; - best_pos = 0; - best_count = 0; - for (iter = 0; iter < 128; iter++) { - if ((dqs_write_results_array[0][lane][iter]) && (iter < 127)) { - /* Pass */ - cur_count++; - } else { - /* Failure or end of loop */ - if (cur_count > best_count) { - best_count = cur_count; - best_pos = last_pos; - } - cur_count = 0; - last_pos = iter; - } - } - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 145 largest write passing region ", best_count, 4); - if (best_count > 0) { - if (best_count < MIN_DQS_WNDW) { - /* Flag excessively small passing window */ - Errors |= 1 << SB_SMALLDQS; - } - - /* Find the center of the passing window */ - current_write_dqs_delay[lane] = (best_pos + (best_count / 2)); - - /* Commit the current Write Data Timing settings to the hardware registers */ - write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, Channel, (Receiver >> 1), index_reg); - - /* Save the final Write Data Timing settings for later use */ - pDCTstat->CH_D_DIR_B_DQS[Channel][Receiver >> 1][DQS_WRITEDIR][lane] = current_write_dqs_delay[lane]; - } else { - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 123 Unable to find write passing region for lane ", lane, 2); - - /* Flag absence of passing window */ - Errors |= 1 << SB_NODQSPOS; - } - } - } - - } - } - - pDCTstat->TrainErrors |= Errors; - pDCTstat->ErrStatus |= Errors; - -#if DQS_TRAIN_DEBUG > 0 - { - u8 val; - u8 i; - u8 ChannelDTD, ReceiverDTD, Dir; - u8 *p; - - for (Dir = 0; Dir < 2; Dir++) { - if (Dir == 1) { - printk(BIOS_DEBUG, "TrainDQSRdWrPos: CH_D_DIR_B_DQS WR:\n"); - } else { - printk(BIOS_DEBUG, "TrainDQSRdWrPos: CH_D_DIR_B_DQS RD:\n"); - } - for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) { - printk(BIOS_DEBUG, "Channel: %02x\n", ChannelDTD); - for (ReceiverDTD = 0; ReceiverDTD < MAX_CS_SUPPORTED; ReceiverDTD += 2) { - printk(BIOS_DEBUG, "\t\tReceiver: %02x:", ReceiverDTD); - p = pDCTstat->CH_D_DIR_B_DQS[ChannelDTD][ReceiverDTD >> 1][Dir]; - for (i = 0; i < 8; i++) { - val = p[i]; - printk(BIOS_DEBUG, " %02x", val); - } - printk(BIOS_DEBUG, "\n"); - } - } - } - - } -#endif - 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); - } - - printk(BIOS_DEBUG, "TrainDQSRdWrPos: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "TrainDQSRdWrPos: TrainErrors %x\n", pDCTstat->TrainErrors); - printk(BIOS_DEBUG, "TrainDQSRdWrPos: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "TrainDQSRdWrPos: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "TrainDQSRdWrPos: Done\n\n"); -} - -/* Calcuate and set MaxRdLatency - * Algorithm detailed in the Fam15h BKDG Rev. 3.14 section 2.10.5.8.5 - */ -void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t calc_min) -{ - uint8_t dimm; - uint8_t lane; - uint32_t dword; - uint32_t dword2; - uint32_t max_delay; - uint8_t mem_clk = 0; - uint8_t nb_pstate; - uint32_t nb_clk; - uint32_t p = 0; - uint32_t n = 0; - uint32_t t = 0; - uint16_t current_phy_phase_delay[MAX_BYTE_LANES]; - uint16_t current_read_dqs_delay[MAX_BYTE_LANES]; - - uint32_t index_reg = 0x98; - uint32_t dev = pDCTstat->dev_dct; - 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}; - -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "%s: Start\n", __func__); -#endif - - uint8_t lane_count; - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - mem_clk = Get_NB32_DCT(dev, dct, 0x94) & 0x1f; - if (fam15h_freq_tab[mem_clk] == 0) { - pDCTstat->CH_MaxRdLat[dct][0] = 0x55; - pDCTstat->CH_MaxRdLat[dct][1] = 0x55; - return; - } - - /* P is specified in PhyCLKs (1/2 MEMCLKs) */ - for (nb_pstate = 0; nb_pstate < 2; nb_pstate++) { - /* 2.10.5.8.5 (2) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000004); - if ((!(dword & (0x1 << 21))) && (!(dword & (0x1 << 13))) && (!(dword & (0x1 << 5)))) - p += 1; - else - p += 2; - - /* 2.10.5.8.5 (3) */ - dword = Get_NB32_DCT_NBPstate(dev, dct, nb_pstate, 0x210) & 0xf; /* Retrieve RdPtrInit */ - p += (9 - dword); - - /* 2.10.5.8.5 (4) */ - if (!calc_min) - p += 5; - - /* 2.10.5.8.5 (5) */ - dword = Get_NB32_DCT(dev, dct, 0xa8); - dword2 = Get_NB32_DCT(dev, dct, 0x90); - if ((!(dword & (0x1 << 5))) && (!(dword2 & (0x1 << 16)))) - p += 2; - - /* 2.10.5.8.5 (6) */ - dword = Get_NB32_DCT(dev, dct, 0x200) & 0x1f; /* Retrieve Tcl */ - p += (2 * (dword - 1)); - - /* 2.10.5.8.5 (7) */ - max_delay = 0; - for (dimm = 0; dimm < 4; dimm++) { - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, dimm * 2)) - continue; - - read_dqs_receiver_enable_control_registers(current_phy_phase_delay, dev, dct, dimm, index_reg); - read_dqs_read_data_timing_registers(current_read_dqs_delay, dev, dct, dimm, index_reg); - for (lane = 0; lane < lane_count; lane++) - if ((current_phy_phase_delay[lane] + current_read_dqs_delay[lane]) > max_delay) - max_delay = (current_phy_phase_delay[lane] + current_read_dqs_delay[lane]); - } - p += (max_delay >> 5); - - /* 2.10.5.8.5 (8) */ - if (!calc_min) - p += 5; - - /* 2.10.5.8.5 (9) */ - t += 800; - - /* 2.10.5.8.5 (10) */ - dword = Get_NB32(pDCTstat->dev_nbctl, (0x160 + (nb_pstate * 4))); /* Retrieve NbDid, NbFid */ - nb_clk = (200 * (((dword >> 1) & 0x1f) + 0x4)) / (((dword >> 7) & 0x1)?2:1); - n = (((((uint64_t)p * 1000000000000ULL)/(((uint64_t)fam15h_freq_tab[mem_clk] * 1000000ULL) * 2)) + ((uint64_t)t)) * ((uint64_t)nb_clk * 1000)) / 1000000000ULL; - - /* 2.10.5.8.5 (11) */ - if (!calc_min) - n -= 1; - - /* 2.10.5.8.5 (12) */ - if (!calc_min) { - dword = Get_NB32_DCT_NBPstate(dev, dct, nb_pstate, 0x210); - dword &= ~(0x3ff << 22); - dword |= (((n - 1) & 0x3ff) << 22); - Set_NB32_DCT_NBPstate(dev, dct, nb_pstate, 0x210, dword); - } - - /* Save result for later use */ - pDCTstat->CH_MaxRdLat[dct][nb_pstate] = n - 1; - -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "%s: CH_MaxRdLat[%d][%d]: %03x\n", __func__, dct, nb_pstate, pDCTstat->CH_MaxRdLat[dct][nb_pstate]); -#endif - } - -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "%s: Done\n", __func__); -#endif -} - -static void start_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t Receiver) -{ - uint32_t dword; - uint32_t dev = pDCTstat->dev_dct; - - /* 2.10.5.7.1.1 - * It appears that the DCT only supports 8-beat burst length mode, - * so do nothing here... - */ - - /* Wait for CmdSendInProg == 0 */ - do { - dword = Get_NB32_DCT(dev, dct, 0x250); - } while (dword & (0x1 << 12)); - - /* Set CmdTestEnable = 1 */ - dword = Get_NB32_DCT(dev, dct, 0x250); - dword |= (0x1 << 2); - Set_NB32_DCT(dev, dct, 0x250, dword); - - /* 2.10.5.8.6.1.1 Send Activate Command (Target A) */ - dword = Get_NB32_DCT(dev, dct, 0x28c); - dword &= ~(0xff << 22); /* CmdChipSelect = Receiver */ - dword |= ((0x1 << Receiver) << 22); - dword &= ~(0x7 << 19); /* CmdBank = 0 */ - dword &= ~(0x3ffff); /* CmdAddress = 0 */ - dword |= (0x1 << 31); /* SendActCmd = 1 */ - Set_NB32_DCT(dev, dct, 0x28c, dword); - - /* Wait for SendActCmd == 0 */ - do { - dword = Get_NB32_DCT(dev, dct, 0x28c); - } while (dword & (0x1 << 31)); - - /* Wait 75 MEMCLKs. */ - precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 75); - - /* 2.10.5.8.6.1.1 Send Activate Command (Target B) */ - dword = Get_NB32_DCT(dev, dct, 0x28c); - dword &= ~(0xff << 22); /* CmdChipSelect = Receiver */ - dword |= ((0x1 << Receiver) << 22); - dword &= ~(0x7 << 19); /* CmdBank = 1 */ - dword |= (0x1 << 19); - dword &= ~(0x3ffff); /* CmdAddress = 0 */ - dword |= (0x1 << 31); /* SendActCmd = 1 */ - Set_NB32_DCT(dev, dct, 0x28c, dword); - - /* Wait for SendActCmd == 0 */ - do { - dword = Get_NB32_DCT(dev, dct, 0x28c); - } while (dword & (0x1 << 31)); - - /* Wait 75 MEMCLKs. */ - precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 75); -} - -static void stop_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t Receiver) -{ - uint32_t dword; - uint32_t dev = pDCTstat->dev_dct; - - /* 2.10.5.8.6.1.1 Send Precharge Command */ - /* Wait 25 MEMCLKs. */ - precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 25); - - dword = Get_NB32_DCT(dev, dct, 0x28c); - dword &= ~(0xff << 22); /* CmdChipSelect = Receiver */ - dword |= ((0x1 << Receiver) << 22); - dword &= ~(0x7 << 19); /* CmdBank = 0 */ - dword &= ~(0x3ffff); /* CmdAddress = 0x400 */ - dword |= 0x400; - dword |= (0x1 << 30); /* SendPchgCmd = 1 */ - Set_NB32_DCT(dev, dct, 0x28c, dword); - - /* Wait for SendPchgCmd == 0 */ - do { - dword = Get_NB32_DCT(dev, dct, 0x28c); - } while (dword & (0x1 << 30)); - - /* Wait 25 MEMCLKs. */ - precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 25); - - /* Set CmdTestEnable = 0 */ - dword = Get_NB32_DCT(dev, dct, 0x250); - dword &= ~(0x1 << 2); - Set_NB32_DCT(dev, dct, 0x250, dword); -} - -void read_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, - uint8_t Receiver, uint8_t lane, uint8_t stop_on_error) -{ - uint32_t dword; - uint32_t dev = pDCTstat->dev_dct; - - start_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, dct, Receiver); - - /* 2.10.5.8.6.1.2 */ - /* Configure DQMask */ - if (lane < 4) { - Set_NB32_DCT(dev, dct, 0x274, ~(0xff << (lane * 8))); - Set_NB32_DCT(dev, dct, 0x278, ~0x0); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword |= 0xff; /* EccMask = 0xff */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else if (lane < 8) { - Set_NB32_DCT(dev, dct, 0x274, ~0x0); - Set_NB32_DCT(dev, dct, 0x278, ~(0xff << ((lane - 4) * 8))); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword |= 0xff; /* EccMask = 0xff */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else if (lane == 8) { - Set_NB32_DCT(dev, dct, 0x274, ~0x0); - Set_NB32_DCT(dev, dct, 0x278, ~0x0); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword &= ~(0xff); /* EccMask = 0x0 */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else if (lane == 0xff) { - Set_NB32_DCT(dev, dct, 0x274, ~0xffffffff); - Set_NB32_DCT(dev, dct, 0x278, ~0xffffffff); - dword = Get_NB32_DCT(dev, dct, 0x27c); - if (get_available_lane_count(pMCTstat, pDCTstat) < 9) - dword |= 0xff; /* EccMask = 0xff */ - else - dword &= ~(0xff); /* EccMask = 0x0 */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else { - Set_NB32_DCT(dev, dct, 0x274, ~0x0); - Set_NB32_DCT(dev, dct, 0x278, ~0x0); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword |= 0xff; /* EccMask = 0xff */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } - - dword = Get_NB32_DCT(dev, dct, 0x270); - dword &= ~(0x7ffff); /* DataPrbsSeed = 55555 */ -// dword |= (0x55555); - dword |= (0x44443); /* Use AGESA seed */ - Set_NB32_DCT(dev, dct, 0x270, dword); - - /* 2.10.5.8.4 */ - dword = Get_NB32_DCT(dev, dct, 0x260); - dword &= ~(0x1fffff); /* CmdCount = 256 */ - dword |= 256; - Set_NB32_DCT(dev, dct, 0x260, dword); - - /* Configure Target A */ - dword = Get_NB32_DCT(dev, dct, 0x254); - dword &= ~(0x7 << 24); /* TgtChipSelect = Receiver */ - dword |= (Receiver & 0x7) << 24; - dword &= ~(0x7 << 21); /* TgtBank = 0 */ - dword &= ~(0x3ff); /* TgtAddress = 0 */ - Set_NB32_DCT(dev, dct, 0x254, dword); - - /* Configure Target B */ - dword = Get_NB32_DCT(dev, dct, 0x258); - dword &= ~(0x7 << 24); /* TgtChipSelect = Receiver */ - dword |= (Receiver & 0x7) << 24; - dword &= ~(0x7 << 21); /* TgtBank = 1 */ - dword |= (0x1 << 21); - dword &= ~(0x3ff); /* TgtAddress = 0 */ - Set_NB32_DCT(dev, dct, 0x258, dword); - - dword = Get_NB32_DCT(dev, dct, 0x250); - dword |= (0x1 << 3); /* ResetAllErr = 1 */ - dword &= ~(0x1 << 4); /* StopOnErr = stop_on_error */ - dword |= (stop_on_error & 0x1) << 4; - dword &= ~(0x3 << 8); /* CmdTgt = 1 (Alternate between Target A and Target B) */ - dword |= (0x1 << 8); - dword &= ~(0x7 << 5); /* CmdType = 0 (Read) */ - dword |= (0x1 << 11); /* SendCmd = 1 */ - Set_NB32_DCT(dev, dct, 0x250, dword); - - /* 2.10.5.8.6.1.2 Wait for TestStatus == 1 and CmdSendInProg == 0 */ - do { - dword = Get_NB32_DCT(dev, dct, 0x250); - } while ((dword & (0x1 << 12)) || (!(dword & (0x1 << 10)))); - - dword = Get_NB32_DCT(dev, dct, 0x250); - dword &= ~(0x1 << 11); /* SendCmd = 0 */ - Set_NB32_DCT(dev, dct, 0x250, dword); - - stop_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, dct, Receiver); -} - -void write_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, - uint8_t Receiver, uint8_t lane, uint8_t stop_on_error) -{ - uint32_t dword; - uint32_t dev = pDCTstat->dev_dct; - - start_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, dct, Receiver); - - /* 2.10.5.8.6.1.2 */ - /* Configure DQMask */ - if (lane < 4) { - Set_NB32_DCT(dev, dct, 0x274, ~(0xff << (lane * 8))); - Set_NB32_DCT(dev, dct, 0x278, ~0x0); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword |= 0xff; /* EccMask = 0xff */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else if (lane < 8) { - Set_NB32_DCT(dev, dct, 0x274, ~0x0); - Set_NB32_DCT(dev, dct, 0x278, ~(0xff << ((lane - 4) * 8))); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword |= 0xff; /* EccMask = 0xff */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else if (lane == 8) { - Set_NB32_DCT(dev, dct, 0x274, ~0x0); - Set_NB32_DCT(dev, dct, 0x278, ~0x0); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword &= ~(0xff); /* EccMask = 0x0 */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else if (lane == 0xff) { - Set_NB32_DCT(dev, dct, 0x274, ~0xffffffff); - Set_NB32_DCT(dev, dct, 0x278, ~0xffffffff); - dword = Get_NB32_DCT(dev, dct, 0x27c); - if (get_available_lane_count(pMCTstat, pDCTstat) < 9) - dword |= 0xff; /* EccMask = 0xff */ - else - dword &= ~(0xff); /* EccMask = 0x0 */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } else { - Set_NB32_DCT(dev, dct, 0x274, ~0x0); - Set_NB32_DCT(dev, dct, 0x278, ~0x0); - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword |= 0xff; /* EccMask = 0xff */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - } - - dword = Get_NB32_DCT(dev, dct, 0x270); - dword &= ~(0x7ffff); /* DataPrbsSeed = 55555 */ -// dword |= (0x55555); - dword |= (0x44443); /* Use AGESA seed */ - Set_NB32_DCT(dev, dct, 0x270, dword); - - /* 2.10.5.8.4 */ - dword = Get_NB32_DCT(dev, dct, 0x260); - dword &= ~(0x1fffff); /* CmdCount = 256 */ - dword |= 256; - Set_NB32_DCT(dev, dct, 0x260, dword); - - /* Configure Target A */ - dword = Get_NB32_DCT(dev, dct, 0x254); - dword &= ~(0x7 << 24); /* TgtChipSelect = Receiver */ - dword |= (Receiver & 0x7) << 24; - dword &= ~(0x7 << 21); /* TgtBank = 0 */ - dword &= ~(0x3ff); /* TgtAddress = 0 */ - Set_NB32_DCT(dev, dct, 0x254, dword); - - /* Configure Target B */ - dword = Get_NB32_DCT(dev, dct, 0x258); - dword &= ~(0x7 << 24); /* TgtChipSelect = Receiver */ - dword |= (Receiver & 0x7) << 24; - dword &= ~(0x7 << 21); /* TgtBank = 1 */ - dword |= (0x1 << 21); - dword &= ~(0x3ff); /* TgtAddress = 0 */ - Set_NB32_DCT(dev, dct, 0x258, dword); - - dword = Get_NB32_DCT(dev, dct, 0x250); - dword |= (0x1 << 3); /* ResetAllErr = 1 */ - dword &= ~(0x1 << 4); /* StopOnErr = stop_on_error */ - dword |= (stop_on_error & 0x1) << 4; - dword &= ~(0x3 << 8); /* CmdTgt = 1 (Alternate between Target A and Target B) */ - dword |= (0x1 << 8); - dword &= ~(0x7 << 5); /* CmdType = 1 (Write) */ - dword |= (0x1 << 5); - dword |= (0x1 << 11); /* SendCmd = 1 */ - Set_NB32_DCT(dev, dct, 0x250, dword); - - /* 2.10.5.8.6.1.2 Wait for TestStatus == 1 and CmdSendInProg == 0 */ - do { - dword = Get_NB32_DCT(dev, dct, 0x250); - } while ((dword & (0x1 << 12)) || (!(dword & (0x1 << 10)))); - - dword = Get_NB32_DCT(dev, dct, 0x250); - dword &= ~(0x1 << 11); /* SendCmd = 0 */ - Set_NB32_DCT(dev, dct, 0x250, dword); - - stop_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, dct, Receiver); -} - -#define LANE_DIFF 1 - -/* DQS Position Training - * Algorithm detailed in the Fam15h BKDG Rev. 3.14 section 2.10.5.8.4 - */ -static uint8_t TrainDQSRdWrPos_D_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - uint8_t dct, uint8_t receiver_start, - uint8_t receiver_end, uint8_t lane_start) -{ - uint8_t dimm; - uint8_t lane; - uint32_t dword; - uint32_t Errors; - uint8_t Receiver; - uint8_t dual_rank; - uint8_t write_iter; - uint8_t read_iter; - uint8_t check_antiphase; - uint8_t passing_read_dqs_delay_found; - uint8_t passing_write_dqs_delay_found; - uint16_t initial_write_dqs_delay[MAX_BYTE_LANES]; - uint16_t initial_read_dqs_delay[MAX_BYTE_LANES]; - uint16_t initial_write_data_timing[MAX_BYTE_LANES]; - uint16_t current_write_data_delay[MAX_BYTE_LANES]; - uint16_t current_read_dqs_delay[MAX_BYTE_LANES]; - uint16_t current_write_dqs_delay[MAX_BYTE_LANES]; - uint8_t passing_dqs_delay_found[MAX_BYTE_LANES]; - /* [rank][lane][write step][read step + 16] */ - uint8_t dqs_results_array[2][LANE_DIFF][32][48]; - - uint8_t last_pos = 0; - uint8_t cur_count = 0; - uint8_t best_pos = 0; - uint8_t best_count = 0; - - uint32_t index_reg = 0x98; - uint32_t dev = pDCTstat->dev_dct; - - uint8_t lane_end = lane_start + LANE_DIFF; - - uint8_t lane_count; - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - /* Calculate and program MaxRdLatency */ - Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, dct, 0); - - Errors = 0; - dual_rank = 0; - - /* There are four receiver pairs, loosely associated with chipselects. - * This is essentially looping over each rank within each DIMM. - */ - for (Receiver = receiver_start; Receiver < receiver_end; Receiver++) { - dimm = (Receiver >> 1); - if ((Receiver & 0x1) == 0) { - /* Even rank of DIMM */ - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, Receiver+1)) - dual_rank = 1; - else - dual_rank = 0; - } - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, Receiver)) { - continue; - } - -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "TrainDQSRdWrPos: Training DQS read/write position for receiver %d (DIMM %d)\n", Receiver, dimm); -#endif - - /* Initialize variables */ - for (lane = lane_start; lane < lane_end; lane++) { - passing_dqs_delay_found[lane] = 0; - } - if ((Receiver & 0x1) == 0) { - /* Even rank of DIMM */ - memset(dqs_results_array, 0, sizeof(dqs_results_array)); - - /* Read initial read / write DQS delays */ - read_dqs_write_timing_control_registers(initial_write_dqs_delay, dev, dct, dimm, index_reg); - read_dqs_read_data_timing_registers(initial_read_dqs_delay, dev, dct, dimm, index_reg); - - /* Read current settings of other (previously trained) lanes */ - read_dqs_write_data_timing_registers(initial_write_data_timing, dev, dct, dimm, index_reg); - } - - /* Initialize iterators */ - memcpy(current_write_data_delay, initial_write_data_timing, sizeof(current_write_data_delay)); - - for (lane = lane_start; lane < lane_end; lane++) { - passing_read_dqs_delay_found = 0; - passing_write_dqs_delay_found = 0; - - /* 2.10.5.8.4 (2) - * For each Write Data Delay value from Write DQS Delay to Write DQS Delay + 1 UI - */ - for (current_write_data_delay[lane] = initial_write_dqs_delay[lane]; current_write_data_delay[lane] < (initial_write_dqs_delay[lane] + 0x20); current_write_data_delay[lane]++) { - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 16 current_write_data_delay[lane] ", current_write_data_delay[lane], 6); - - /* 2.10.5.8.4 (2 A) - * Commit the current Write Data Timing settings to the hardware registers - */ - write_dqs_write_data_timing_registers(current_write_data_delay, dev, dct, dimm, index_reg); - - /* 2.10.5.8.4 (2 B) - * Write the DRAM training pattern to the test address - */ - write_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, dct, Receiver, lane, 0); - - /* Read current settings of other (previously trained) lanes */ - read_dqs_read_data_timing_registers(current_read_dqs_delay, dev, dct, dimm, index_reg); - - /* 2.10.5.8.4 (2 C) - * For each Read DQS Delay value from 0 to 1 UI - */ - for (current_read_dqs_delay[lane] = 0; current_read_dqs_delay[lane] < 0x20; current_read_dqs_delay[lane]++) { - print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 161 current_read_dqs_delay[lane] ", current_read_dqs_delay[lane], 6); - - if (current_read_dqs_delay[lane] >= (32 - 16)) { - check_antiphase = 1; - } else { - check_antiphase = 0; - } - - /* 2.10.5.8.4 (2 A i) - * Commit the current Read DQS Timing Control settings to the hardware registers - */ - write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, dct, dimm, index_reg); - - /* 2.10.5.8.4 (2 A ii) - * Read the DRAM training pattern from the test address - */ - read_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, dct, Receiver, lane, ((check_antiphase == 0)?1:0)); - - if (check_antiphase == 0) { - /* Check for early abort before analyzing per-nibble status */ - dword = Get_NB32_DCT(dev, dct, 0x264); - if ((dword & 0x1ffffff) != 0) { - print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 162 early abort: F2x264 ", dword, 6); - dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][current_read_dqs_delay[lane] + 16] = 0; /* Fail */ - continue; - } - } - - /* 2.10.5.8.4 (2 A iii) - * Record pass / fail status - */ - dword = Get_NB32_DCT(dev, dct, 0x268) & 0x3ffff; - print_debug_dqs("\t\t\t\t\tTrainDQSRdWrPos: 163 read results: F2x268 ", dword, 6); - if (dword & (0x3 << (lane * 2))) - dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][current_read_dqs_delay[lane] + 16] = 0; /* Fail */ - else - dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][current_read_dqs_delay[lane] + 16] = 1; /* Pass */ - if (check_antiphase == 1) { - /* Check antiphase results */ - dword = Get_NB32_DCT(dev, dct, 0x26c) & 0x3ffff; - if (dword & (0x3 << (lane * 2))) - dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][16 - (32 - current_read_dqs_delay[lane])] = 0; /* Fail */ - else - dqs_results_array[Receiver & 0x1][lane - lane_start][current_write_data_delay[lane] - initial_write_dqs_delay[lane]][16 - (32 - current_read_dqs_delay[lane])] = 1; /* Pass */ - } - } - } - - if (dual_rank && (Receiver & 0x1)) { - /* Overlay the previous rank test results with the current rank */ - for (write_iter = 0; write_iter < 32; write_iter++) { - for (read_iter = 0; read_iter < 48; read_iter++) { - if ((dqs_results_array[0][lane - lane_start][write_iter][read_iter]) - && (dqs_results_array[1][lane - lane_start][write_iter][read_iter])) - dqs_results_array[1][lane - lane_start][write_iter][read_iter] = 1; - else - dqs_results_array[1][lane - lane_start][write_iter][read_iter] = 0; - } - } - } - - /* Determine location and length of longest consecutive string of read passing values - * Output is stored in best_pos and best_count - */ - last_pos = 0; - cur_count = 0; - best_pos = 0; - best_count = 0; - for (write_iter = 0; write_iter < 32; write_iter++) { - for (read_iter = 0; read_iter < 48; read_iter++) { - if ((dqs_results_array[Receiver & 0x1][lane - lane_start][write_iter][read_iter]) && (read_iter < 47)) { - /* Pass */ - cur_count++; - } else { - /* Failure or end of loop */ - if (cur_count > best_count) { - best_count = cur_count; - best_pos = last_pos; - } - cur_count = 0; - last_pos = read_iter + 1; - } - } - last_pos = 0; - } - - if (best_count > 2) { - uint16_t region_center = (best_pos + (best_count / 2)); - - if (region_center < 16) { - printk(BIOS_WARNING, "TrainDQSRdWrPos: negative DQS recovery delay detected!" - " Attempting to continue but your system may be unstable...\n"); - region_center = 0; - } else { - region_center -= 16; - } - - /* Restore current settings of other (previously trained) lanes to the active array */ - memcpy(current_read_dqs_delay, initial_read_dqs_delay, sizeof(current_read_dqs_delay)); - - /* Program the Read DQS Timing Control register with the center of the passing window */ - current_read_dqs_delay[lane] = region_center; - passing_dqs_delay_found[lane] = 1; - - /* Commit the current Read DQS Timing Control settings to the hardware registers */ - write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, dct, dimm, index_reg); - - /* Save the final Read DQS Timing Control settings for later use */ - pDCTstat->CH_D_DIR_B_DQS[dct][Receiver >> 1][DQS_READDIR][lane] = current_read_dqs_delay[lane]; - - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 142 largest read passing region ", best_count, 4); - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 143 largest read passing region start ", best_pos, 4); - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 144 largest read passing region center (raw hardware value) ", region_center, 4); - } else { - /* Restore current settings of other (previously trained) lanes to the active array */ - memcpy(current_read_dqs_delay, initial_read_dqs_delay, sizeof(current_read_dqs_delay)); - - /* Reprogram the Read DQS Timing Control register with the original settings */ - write_dqs_read_data_timing_registers(initial_read_dqs_delay, dev, dct, dimm, index_reg); - } - - /* Determine location and length of longest consecutive string of write passing values - * Output is stored in best_pos and best_count - */ - last_pos = 0; - cur_count = 0; - best_pos = 0; - best_count = 0; - for (read_iter = 0; read_iter < 48; read_iter++) { - for (write_iter = 0; write_iter < 32; write_iter++) { - if ((dqs_results_array[Receiver & 0x1][lane - lane_start][write_iter][read_iter]) && (write_iter < 31)) { - /* Pass */ - cur_count++; - } else { - /* Failure or end of loop */ - if (cur_count > best_count) { - best_count = cur_count; - best_pos = last_pos; - } - cur_count = 0; - last_pos = write_iter + 1; - } - } - last_pos = 0; - } - - if (best_count > 2) { - /* Restore current settings of other (previously trained) lanes to the active array */ - memcpy(current_write_dqs_delay, initial_write_data_timing, sizeof(current_write_data_delay)); - - /* Program the Write DQS Timing Control register with the optimal region within the passing window */ - if (pDCTstat->Status & (1 << SB_LoadReduced)) - current_write_dqs_delay[lane] = ((best_pos + initial_write_dqs_delay[lane]) + (best_count / 3)); - else - current_write_dqs_delay[lane] = ((best_pos + initial_write_dqs_delay[lane]) + (best_count / 2)); - passing_write_dqs_delay_found = 1; - - /* Commit the current Write DQS Timing Control settings to the hardware registers */ - write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, dct, dimm, index_reg); - - /* Save the final Write Data Timing settings for later use */ - pDCTstat->CH_D_DIR_B_DQS[dct][Receiver >> 1][DQS_WRITEDIR][lane] = current_write_dqs_delay[lane]; - - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 145 largest write passing region ", best_count, 4); - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 146 largest write passing region start ", best_pos, 4); - } else { - /* Restore current settings of other (previously trained) lanes to the active array */ - memcpy(current_write_dqs_delay, initial_write_data_timing, sizeof(current_write_data_delay)); - - /* Reprogram the Write DQS Timing Control register with the original settings */ - write_dqs_write_data_timing_registers(current_write_dqs_delay, dev, dct, dimm, index_reg); - } - - if (passing_read_dqs_delay_found && passing_write_dqs_delay_found) - passing_dqs_delay_found[lane] = 1; - } - -#ifdef PRINT_PASS_FAIL_BITMAPS - for (lane = lane_start; lane < lane_end; lane++) { - for (write_iter = 0; write_iter < 32; write_iter++) { - for (read_iter = 0; read_iter < 48; read_iter++) { - if (dqs_results_array[Receiver & 0x1][lane - lane_start][write_iter][read_iter]) { - printk(BIOS_DEBUG, "+"); - } else { - if (read_iter < 16) - printk(BIOS_DEBUG, ":"); - else - printk(BIOS_DEBUG, "."); - } - } - printk(BIOS_DEBUG, "\n"); - } - printk(BIOS_DEBUG, "\n\n"); - } -#endif - - /* Flag failure(s) if present */ - for (lane = lane_start; lane < lane_end; lane++) { - if (!passing_dqs_delay_found[lane]) { - print_debug_dqs("\t\t\t\tTrainDQSRdWrPos: 121 Unable to find passing region for lane ", lane, 2); - - /* Flag absence of passing window */ - Errors |= 1 << SB_NODQSPOS; - } - } - - pDCTstat->TrainErrors |= Errors; - pDCTstat->ErrStatus |= Errors; - -#if DQS_TRAIN_DEBUG > 0 - { - u8 val; - u8 i; - u8 ChannelDTD, ReceiverDTD, Dir; - u8 *p; - - for (Dir = 0; Dir < 2; Dir++) { - if (Dir == 1) { - printk(BIOS_DEBUG, "TrainDQSRdWrPos: CH_D_DIR_B_DQS WR:\n"); - } else { - printk(BIOS_DEBUG, "TrainDQSRdWrPos: CH_D_DIR_B_DQS RD:\n"); - } - for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) { - printk(BIOS_DEBUG, "Channel: %02x\n", ChannelDTD); - for (ReceiverDTD = 0; ReceiverDTD < MAX_CS_SUPPORTED; ReceiverDTD += 2) { - printk(BIOS_DEBUG, "\t\tReceiver: %02x:", ReceiverDTD); - p = pDCTstat->CH_D_DIR_B_DQS[ChannelDTD][ReceiverDTD >> 1][Dir]; - for (i = 0; i < 8; i++) { - val = p[i]; - printk(BIOS_DEBUG, " %02x", val); - } - printk(BIOS_DEBUG, "\n"); - } - } - } - - } -#endif - } - - /* Return 1 on success, 0 on failure */ - return !Errors; -} - -/* DQS Receiver Enable Cycle Training - * Algorithm detailed in the Fam15h BKDG Rev. 3.14 section 2.10.5.8.3 - */ -static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 Errors; - u8 Receiver; - u8 _DisableDramECC = 0; - u8 _Wrap32Dis = 0, _SSE2 = 0; - - u32 addr; - CRx_TYPE cr4; - u32 lo, hi; - - uint8_t dct; - uint8_t prev; - uint8_t dimm; - uint8_t lane; - uint32_t dword; - uint32_t rx_en_offset; - uint8_t internal_lane; - uint8_t dct_training_success; - uint8_t lane_success_count; - uint16_t initial_phy_phase_delay[MAX_BYTE_LANES]; - uint16_t current_phy_phase_delay[MAX_BYTE_LANES]; - uint16_t current_read_dqs_delay[MAX_BYTE_LANES]; - uint8_t lane_training_success[MAX_BYTE_LANES]; - uint8_t dqs_results_array[1024]; - - uint16_t ren_step = 0x40; - uint32_t index_reg = 0x98; - uint32_t dev = pDCTstat->dev_dct; - - uint8_t lane_count; - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - print_debug_dqs("\nTrainDQSReceiverEnCyc: Node_ID ", pDCTstat->Node_ID, 0); - cr4 = read_cr4(); - if (cr4 & (1<<9)) { - _SSE2 = 1; - } - cr4 |= (1<<9); /* OSFXSR enable SSE2 */ - write_cr4(cr4); - - addr = HWCR_MSR; - _RDMSR(addr, &lo, &hi); - if (lo & (1<<17)) { - _Wrap32Dis = 1; - } - lo |= (1<<17); /* HWCR.wrap32dis */ - _WRMSR(addr, lo, hi); /* allow 64-bit memory references in real mode */ - - /* Disable ECC correction of reads on the dram bus. */ - _DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat); - - Errors = 0; - - for (dct = 0; dct < 2; dct++) { - /* Program D18F2x9C_x0D0F_E003_dct[1:0][DisAutoComp, DisablePredriverCal] */ - /* NOTE: DisablePredriverCal only takes effect when set on DCT 0 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe003); - dword &= ~(0x3 << 13); - dword |= (0x1 << 13); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fe003, dword); - } - - for (dct = 0; dct < 2; dct++) { - /* 2.10.5.6 */ - fam15EnableTrainingMode(pMCTstat, pDCTstat, dct, 1); - - /* 2.10.5.8.3 */ - Receiver = mct_InitReceiver_D(pDCTstat, dct); - - /* Indicate success unless training the DCT explicitly fails */ - dct_training_success = 1; - - /* There are four receiver pairs, loosely associated with chipselects. - * This is essentially looping over each DIMM. - */ - for (; Receiver < 8; Receiver += 2) { - dimm = (Receiver >> 1); - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, dct, Receiver)) { - continue; - } - - /* Initialize variables */ - memset(lane_training_success, 0, sizeof(lane_training_success)); - memset(current_phy_phase_delay, 0, sizeof(current_phy_phase_delay)); - - /* 2.10.5.8.3 (2) */ - read_dqs_receiver_enable_control_registers(initial_phy_phase_delay, dev, dct, dimm, index_reg); - - /* Reset the read data timing registers to 1UI before calculating MaxRdLatency */ - for (internal_lane = 0; internal_lane < MAX_BYTE_LANES; internal_lane++) - current_read_dqs_delay[internal_lane] = 0x20; - write_dqs_read_data_timing_registers(current_read_dqs_delay, dev, dct, dimm, index_reg); - - for (lane = 0; lane < lane_count; lane++) { - /* Initialize variables */ - memset(dqs_results_array, 0, sizeof(dqs_results_array)); - lane_success_count = 0; - - /* 2.10.5.8.3 (1) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0030 | (lane << 8)); - dword |= (0x1 << 8); /* BlockRxDqsLock = 1 */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0030 | (lane << 8), dword); - - /* 2.10.5.8.3 (3) */ - rx_en_offset = (initial_phy_phase_delay[lane] + 0x10) % 0x40; - - /* 2.10.5.8.3 (4) */ -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc_D_Fam15 Receiver %d lane %d initial phy delay %04x: iterating from %04x to %04x\n", Receiver, lane, initial_phy_phase_delay[lane], rx_en_offset, 0x3ff); -#endif - for (current_phy_phase_delay[lane] = rx_en_offset; current_phy_phase_delay[lane] < 0x3ff; current_phy_phase_delay[lane] += ren_step) { -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "%s: Receiver %d lane %d current phy delay: %04x\n", __func__, Receiver, lane, current_phy_phase_delay[lane]); -#endif - - /* 2.10.5.8.3 (4 A) */ - write_dqs_receiver_enable_control_registers(current_phy_phase_delay, dev, dct, dimm, index_reg); - - /* Calculate and program MaxRdLatency */ - Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, dct, 0); - - /* 2.10.5.8.3 (4 B) */ - dqs_results_array[current_phy_phase_delay[lane]] = - TrainDQSRdWrPos_D_Fam15(pMCTstat, pDCTstat, dct, - Receiver, Receiver + 2, - lane); - - if (dqs_results_array[current_phy_phase_delay[lane]]) - lane_success_count++; - - /* Don't bother testing larger values if the end of the passing window was already found */ - if (!dqs_results_array[current_phy_phase_delay[lane]] && (lane_success_count > 1)) - break; - } - - uint16_t phase_delay; - for (phase_delay = 0; phase_delay < 0x3ff; phase_delay++) - if (dqs_results_array[phase_delay]) - lane_training_success[lane] = 1; - - if (!lane_training_success[lane]) { - if (pDCTstat->tcwl_delay[dct] >= 1) { - Errors |= 1 << SB_FatalError; - printk(BIOS_ERR, "%s: lane %d failed to train! " - "Training for receiver %d on DCT %d aborted\n", - __func__, lane, Receiver, dct); - } - - /* Restore BlockRxDqsLock setting to normal operation in preparation for retraining */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0030 | (lane << 8)); - dword &= ~(0x1 << 8); /* BlockRxDqsLock = 0 */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0030 | (lane << 8), dword); - - break; - } - -#ifdef PRINT_PASS_FAIL_BITMAPS - for (phase_delay = 0; phase_delay < 0x3ff; phase_delay++) { - if (dqs_results_array[phase_delay]) - printk(BIOS_DEBUG, "+"); - else - printk(BIOS_DEBUG, "."); - } - printk(BIOS_DEBUG, "\n"); -#endif - - /* 2.10.5.8.3 (5) */ - prev = dqs_results_array[rx_en_offset]; - for (current_phy_phase_delay[lane] = rx_en_offset + ren_step; current_phy_phase_delay[lane] < 0x3ff; current_phy_phase_delay[lane] += ren_step) { - if ((dqs_results_array[current_phy_phase_delay[lane]] == 0) && (prev == 1)) { - /* Restore last known good delay */ - current_phy_phase_delay[lane] -= ren_step; - - /* 2.10.5.8.3 (5 A B) */ - if (current_phy_phase_delay[lane] < 0x10) - current_phy_phase_delay[lane] = 0x0; - else - current_phy_phase_delay[lane] -= 0x10; - - /* Update hardware registers with final values */ - write_dqs_receiver_enable_control_registers(current_phy_phase_delay, dev, dct, dimm, index_reg); - TrainDQSRdWrPos_D_Fam15(pMCTstat, pDCTstat, dct, - Receiver, Receiver + 2, - lane); - break; - } - prev = dqs_results_array[current_phy_phase_delay[lane]]; - } - - /* 2.10.5.8.3 (6) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0030 | (lane << 8)); - dword &= ~(0x1 << 8); /* BlockRxDqsLock = 0 */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0030 | (lane << 8), dword); - } - - for (lane = 0; lane < lane_count; lane++) { - if (!lane_training_success[lane]) { - dct_training_success = 0; - Errors |= 1 << SB_NODQSPOS; - } - } - -#if DQS_TRAIN_DEBUG > 0 - printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc_D_Fam15 DQS receiver enable timing: "); - for (lane = 0; lane < lane_count; lane++) { - printk(BIOS_DEBUG, " %03x", current_phy_phase_delay[lane]); - } - printk(BIOS_DEBUG, "\n"); -#endif - } - - if (!dct_training_success) { - if (pDCTstat->tcwl_delay[dct] < 1) { - /* Increase TCWL */ - pDCTstat->tcwl_delay[dct]++; - /* Request retraining */ - Errors |= 1 << SB_RetryConfigTrain; - } - } - } - - pDCTstat->TrainErrors |= Errors; - pDCTstat->ErrStatus |= Errors; - -#if DQS_TRAIN_DEBUG > 0 - { - u8 val; - u8 i; - u8 ChannelDTD, ReceiverDTD, Dir; - u8 *p; - - for (Dir = 0; Dir < 2; Dir++) { - if (Dir == 1) { - printk(BIOS_DEBUG, "TrainDQSRdWrPos: CH_D_DIR_B_DQS WR:\n"); - } else { - printk(BIOS_DEBUG, "TrainDQSRdWrPos: CH_D_DIR_B_DQS RD:\n"); - } - for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) { - printk(BIOS_DEBUG, "Channel: %02x\n", ChannelDTD); - for (ReceiverDTD = 0; ReceiverDTD < MAX_CS_SUPPORTED; ReceiverDTD += 2) { - printk(BIOS_DEBUG, "\t\tReceiver: %02x:", ReceiverDTD); - p = pDCTstat->CH_D_DIR_B_DQS[ChannelDTD][ReceiverDTD >> 1][Dir]; - for (i = 0; i < 8; i++) { - val = p[i]; - printk(BIOS_DEBUG, " %02x", val); - } - printk(BIOS_DEBUG, "\n"); - } - } - } - - } -#endif - 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); - } - - printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc: TrainErrors %x\n", pDCTstat->TrainErrors); - printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "TrainDQSReceiverEnCyc: Done\n\n"); -} - -static void SetupDqsPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 *buffer) -{ - /* 1. Set the Pattern type (0 or 1) in DCTStatstruc.Pattern - * 2. Copy the pattern from ROM to Cache, aligning on 16 byte boundary - * 3. Set the ptr to Cacheable copy in DCTStatstruc.PtrPatternBufA - */ - - u32 *buf; - u16 i; - - buf = (u32 *)(((u32)buffer + 0x10) & (0xfffffff0)); - if (pDCTstat->Status & (1<<SB_128bitmode)) { - pDCTstat->Pattern = 1; /* 18 cache lines, alternating qwords */ - for (i = 0; i < 16*18; i++) - buf[i] = TestPatternJD1b_D[i]; - } else { - pDCTstat->Pattern = 0; /* 9 cache lines, sequential qwords */ - for (i = 0; i < 16*9; i++) - buf[i] = TestPatternJD1a_D[i]; - } - pDCTstat->PtrPatternBufA = (u32)buf; -} - -static void StoreDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel) -{ - /* Store the DQSDelay value, found during a training sweep, into the DCT - * status structure for this node - */ - - /* When 400, 533, 667, it will support dimm0/1/2/3, - * and set conf for dimm0, hw will copy to dimm1/2/3 - * set for dimm1, hw will copy to dimm3 - * Rev A/B only support DIMM0/1 when 800MHz and above + 0x100 to next dimm - * Rev C support DIMM0/1/2/3 when 800MHz and above + 0x100 to next dimm - */ - - /* FindDQSDatDimmVal_D is not required since we use an array */ - u8 dn = 0; - - dn = ChipSel>>1; /* if odd or even logical DIMM */ - - pDCTstat->CH_D_DIR_B_DQS[pDCTstat->Channel][dn][pDCTstat->Direction][pDCTstat->ByteLane] = - pDCTstat->DQSDelay; -} - -static void GetDQSDatStrucVal_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel) -{ - u8 dn = 0; - - /* When 400, 533, 667, it will support dimm0/1/2/3, - * and set conf for dimm0, hw will copy to dimm1/2/3 - * set for dimm1, hw will copy to dimm3 - * Rev A/B only support DIMM0/1 when 800MHz and above + 0x100 to next dimm - * Rev C support DIMM0/1/2/3 when 800MHz and above + 0x100 to next dimm - */ - - /* FindDQSDatDimmVal_D is not required since we use an array */ - dn = ChipSel >> 1; /*if odd or even logical DIMM */ - - pDCTstat->DQSDelay = - pDCTstat->CH_D_DIR_B_DQS[pDCTstat->Channel][dn][pDCTstat->Direction][pDCTstat->ByteLane]; -} - -/* FindDQSDatDimmVal_D is not required since we use an array */ - -void proc_IOCLFLUSH_D(u32 addr_hi) -{ - SetTargetWTIO_D(addr_hi); - proc_CLFLUSH(addr_hi); - ResetTargetWTIO_D(); -} - -u8 ChipSelPresent_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 ChipSel) -{ - u32 val; - u32 reg; - u32 dev = pDCTstat->dev_dct; - uint8_t dct = 0; - u8 ret = 0; - - if (!pDCTstat->GangedMode) - dct = Channel; - else - dct = 0; - - if (ChipSel < MAX_CS_SUPPORTED) { - reg = 0x40 + (ChipSel << 2); - val = Get_NB32_DCT(dev, dct, reg); - if (val & (1 << 0)) - ret = 1; - } - - return ret; -} - -/* proc_CLFLUSH_D located in mct_gcc.h */ - -static void WriteDQSTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo) -{ - /* Write a pattern of 72 bit times (per DQ), to test dram functionality. - * The pattern is a stress pattern which exercises both ISI and - * crosstalk. The number of cache lines to fill is dependent on DCT - * width mode and burstlength. - * Mode BL Lines Pattern no. - * ----+---+------------------- - * 64 4 9 0 - * 64 8 9 0 - * 64M 4 9 0 - * 64M 8 9 0 - * 128 4 18 1 - * 128 8 N/A - - */ - if (pDCTstat->Pattern == 0) - WriteL9TestPattern_D(pDCTstat, TestAddr_lo); - else - WriteL18TestPattern_D(pDCTstat, TestAddr_lo); -} - -static void WriteL18TestPattern_D(struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo) -{ - u8 *buf; - - buf = (u8 *)pDCTstat->PtrPatternBufA; - WriteLNTestPattern(TestAddr_lo, buf, 18); - -} - -static void WriteL9TestPattern_D(struct DCTStatStruc *pDCTstat, - u32 TestAddr_lo) -{ - u8 *buf; - - buf = (u8 *)pDCTstat->PtrPatternBufA; - WriteLNTestPattern(TestAddr_lo, buf, 9); -} - -static u16 CompareDQSTestPattern_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u32 addr_lo) -{ - /* Compare a pattern of 72 bit times (per DQ), to test dram functionality. - * The pattern is a stress pattern which exercises both ISI and - * crosstalk. The number of cache lines to fill is dependent on DCT - * width mode and burstlength. - * Mode BL Lines Pattern no. - * ----+---+------------------- - * 64 4 9 0 - * 64 8 9 0 - * 64M 4 9 0 - * 64M 8 9 0 - * 128 4 18 1 - * 128 8 N/A - - */ - - u32 *test_buf; - u16 MEn1Results, bitmap; - u8 bytelane; - u8 i; - u32 value; - u8 j; - u32 value_test; - u32 value_r = 0, value_r_test = 0; - u8 pattern, channel, BeatCnt; - struct DCTStatStruc *ptrAddr; - - ptrAddr = pDCTstat; - pattern = pDCTstat->Pattern; - channel = pDCTstat->Channel; - test_buf = (u32 *)pDCTstat->PtrPatternBufA; - - if (pattern && channel) { - addr_lo += 8; /* second channel */ - test_buf += 2; - } - - bytelane = 0; /* bytelane counter */ - bitmap = 0xFFFF; /* bytelane test bitmap, 1 = pass */ - MEn1Results = 0xFFFF; - BeatCnt = 0; - for (i = 0; i < (9 * 64 / 4); i++) { /* sizeof testpattern. /4 due to next loop */ - value = read32_fs(addr_lo); - value_test = *test_buf; - - print_debug_dqs_pair("\t\t\t\t\t\ttest_buf = ", (u32)test_buf, " value = ", value_test, 7); - print_debug_dqs_pair("\t\t\t\t\t\ttaddr_lo = ", addr_lo, " value = ", value, 7); - - if (pDCTstat->Direction == DQS_READDIR) { - if (BeatCnt != 0) { - value_r = *test_buf; - if (pattern) /* if multi-channel */ - value_r_test = read32_fs(addr_lo - 16); - else - value_r_test = read32_fs(addr_lo - 8); - } - print_debug_dqs_pair("\t\t\t\t\t\t\ttest_buf = ", (u32)test_buf, " value_r_test = ", value_r, 7); - print_debug_dqs_pair("\t\t\t\t\t\t\ttaddr_lo = ", addr_lo, " value_r = ", value_r_test, 7); - } - - for (j = 0; j < (4 * 8); j += 8) { /* go through a 32bit data, on 1 byte step. */ - if (((value >> j) & 0xff) != ((value_test >> j) & 0xff)) { - bitmap &= ~(1 << bytelane); - } - - if (pDCTstat->Direction == DQS_READDIR) { - if (BeatCnt != 0) { - if (((value_r >> j) & 0xff) != ((value_r_test >> j) & 0xff)) { - MEn1Results &= ~(1 << bytelane); - } - } - } - bytelane++; - bytelane &= 0x7; - } - - print_debug_dqs("\t\t\t\t\t\tbitmap = ", bitmap, 7); - print_debug_dqs("\t\t\t\t\t\tMEn1Results = ", MEn1Results, 7); - - if (!bitmap) - break; - - if (bytelane == 0) { - BeatCnt += 4; - if (!(pDCTstat->Status & (1 << SB_128bitmode))) { - if (BeatCnt == 8) BeatCnt = 0; /* 8 beat burst */ - } else { - if (BeatCnt == 4) BeatCnt = 0; /* 4 beat burst */ - } - if (pattern == 1) { /* dual channel */ - addr_lo += 8; /* skip over other channel's data */ - test_buf += 2; - } - } - addr_lo += 4; - test_buf += 1; - } - - if (pDCTstat->Direction == DQS_READDIR) { - bitmap &= 0xFF; - bitmap |= MEn1Results << 8; - } - - print_debug_dqs("\t\t\t\t\t\tbitmap = ", bitmap, 6); - - return bitmap; -} - -static void FlushDQSTestPattern_D(struct DCTStatStruc *pDCTstat, - u32 addr_lo) -{ - /* Flush functions in mct_gcc.h */ - if (pDCTstat->Pattern == 0) { - FlushDQSTestPattern_L9(addr_lo); - } else { - FlushDQSTestPattern_L18(addr_lo); - } -} - -void SetTargetWTIO_D(u32 TestAddr) -{ - u32 lo, hi; - hi = TestAddr >> 24; - lo = TestAddr << 8; - _WRMSR(MTRR_IORR0_BASE, lo, hi); /* IORR0 Base */ - hi = 0xFF; - lo = 0xFC000800; /* 64MB Mask */ - _WRMSR(MTRR_IORR0_MASK, lo, hi); /* IORR0 Mask */ -} - -void ResetTargetWTIO_D(void) -{ - u32 lo, hi; - - hi = 0; - lo = 0; - _WRMSR(MTRR_IORR0_MASK, lo, hi); /* IORR0 Mask */ -} - -u32 SetUpperFSbase(u32 addr_hi) -{ - /* Set the upper 32-bits of the Base address, 4GB aligned) for the - * FS selector. - */ - u32 lo, hi; - u32 addr; - lo = 0; - hi = addr_hi>>24; - addr = FS_Base; - _WRMSR(addr, lo, hi); - return addr_hi << 8; -} - -void ResetDCTWrPtr_D(u32 dev, uint8_t dct, u32 index_reg, u32 index) -{ - u32 val; - - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index); - Set_NB32_index_wait_DCT(dev, dct, index_reg, index, val); -} - -void mct_TrainDQSPos_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - u8 ChipSel; - struct DCTStatStruc *pDCTstat; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - pDCTstat = pDCTstatA + Node; - if (pDCTstat->DCTSysLimit) { - if (is_fam15h()) { - TrainDQSReceiverEnCyc_D_Fam15(pMCTstat, pDCTstat); - } else { - TrainDQSRdWrPos_D_Fam10(pMCTstat, pDCTstat); - for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel += 2) { - SetEccDQSRdWrPos_D_Fam10(pMCTstat, pDCTstat, ChipSel); - } - } - } - } -} - -/* mct_BeforeTrainDQSRdWrPos_D - * Function is inline. - */ -u8 mct_DisableDimmEccEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 _DisableDramECC = 0; - u32 val; - u32 reg; - u32 dev; - - /*Disable ECC correction of reads on the dram bus. */ - - dev = pDCTstat->dev_dct; - reg = 0x90; - val = Get_NB32_DCT(dev, 0, reg); - if (val & (1<<DimmEcEn)) { - _DisableDramECC |= 0x01; - val &= ~(1<<DimmEcEn); - Set_NB32_DCT(dev, 0, reg, val); - } - if (!pDCTstat->GangedMode) { - val = Get_NB32_DCT(dev, 1, reg); - if (val & (1<<DimmEcEn)) { - _DisableDramECC |= 0x02; - val &= ~(1<<DimmEcEn); - Set_NB32_DCT(dev, 1, reg, val); - } - } - return _DisableDramECC; -} - -void mct_EnableDimmEccEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 _DisableDramECC) -{ - u32 val; - u32 dev; - - /* Enable ECC correction if it was previously disabled */ - dev = pDCTstat->dev_dct; - - if ((_DisableDramECC & 0x01) == 0x01) { - val = Get_NB32_DCT(dev, 0, 0x90); - val |= (1<<DimmEcEn); - Set_NB32_DCT(dev, 0, 0x90, val); - } - if ((_DisableDramECC & 0x02) == 0x02) { - val = Get_NB32_DCT(dev, 1, 0x90); - val |= (1<<DimmEcEn); - Set_NB32_DCT(dev, 1, 0x90, val); - } -} - -/* - * Set DQS delay value to related register - */ -static void mct_SetDQSDelayCSR_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 ChipSel) -{ - u8 ByteLane; - u32 val; - u32 index_reg = 0x98; - u8 shift; - u32 dqs_delay = (u32)pDCTstat->DQSDelay; - u32 dev = pDCTstat->dev_dct; - u32 index; - - ByteLane = pDCTstat->ByteLane; - - if (!(pDCTstat->DqsRdWrPos_Saved & (1 << ByteLane))) { - /* Channel is offset */ - if (ByteLane < 4) { - index = 1; - } else if (ByteLane <8) { - index = 2; - } else { - index = 3; - } - - if (pDCTstat->Direction == DQS_READDIR) { - index += 4; - } - - /* get the proper register index */ - shift = ByteLane % 4; - shift <<= 3; /* get bit position of bytelane, 8 bit */ - - index += (ChipSel>>1) << 8; - - val = Get_NB32_index_wait_DCT(dev, pDCTstat->Channel, index_reg, index); - if (ByteLane < 8) { - if (pDCTstat->Direction == DQS_WRITEDIR) { - dqs_delay += pDCTstat->persistentData.CH_D_B_TxDqs[pDCTstat->Channel][ChipSel>>1][ByteLane]; - } else { - dqs_delay <<= 1; - } - } - val &= ~(0x7f << shift); - val |= (dqs_delay << shift); - Set_NB32_index_wait_DCT(dev, pDCTstat->Channel, index_reg, index, val); - } -} - -u8 mct_RcvrRankEnabled_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 ChipSel) -{ - u8 ret; - - ret = ChipSelPresent_D(pMCTstat, pDCTstat, Channel, ChipSel); - return ret; -} - -u32 mct_GetRcvrSysAddr_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 channel, u8 receiver, u8 *valid) -{ - return mct_GetMCTSysAddr_D(pMCTstat, pDCTstat, channel, receiver, valid); -} - -u32 mct_GetMCTSysAddr_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u8 Channel, u8 receiver, u8 *valid) -{ - u32 val; - uint8_t dct = 0; - u32 reg; - u32 dword; - u32 dev = pDCTstat->dev_dct; - - *valid = 0; - - - if (!pDCTstat->GangedMode) { - dct = Channel; - } - - /* get the local base addr of the chipselect */ - reg = 0x40 + (receiver << 2); - val = Get_NB32_DCT(dev, dct, reg); - - val &= ~0xe007c01f; - - /* unganged mode DCT0+DCT1, sys addr of DCT1 = node - * base+DctSelBaseAddr+local ca base*/ - if ((Channel) && (pDCTstat->GangedMode == 0) && (pDCTstat->DIMMValidDCT[0] > 0)) { - reg = 0x110; - dword = Get_NB32(dev, reg); - dword &= 0xfffff800; - dword <<= 8; /* scale [47:27] of F2x110[31:11] to [39:8]*/ - val += dword; - - /* if DCTSelBaseAddr < Hole, and eax > HoleBase, then add Hole size to test address */ - if ((val >= pDCTstat->DCTHoleBase) && (pDCTstat->DCTHoleBase > dword)) { - dword = (~(pDCTstat->DCTHoleBase >> (24 - 8)) + 1) & 0xFF; - dword <<= (24 - 8); - val += dword; - } - } else { - /* sys addr = node base+local cs base */ - val += pDCTstat->DCTSysBase; - - /* New stuff */ - if (pDCTstat->DCTHoleBase && (val >= pDCTstat->DCTHoleBase)) { - val -= pDCTstat->DCTSysBase; - dword = Get_NB32(pDCTstat->dev_map, 0xF0); /* get Hole Offset */ - val += (dword & 0x0000ff00) << (24-8-8); - } - } - - /* New stuff */ - val += ((1 << 21) >> 8); /* Add 2MB offset to avoid compat area */ - if (val >= MCT_TRNG_KEEPOUT_START) { - while (val < MCT_TRNG_KEEPOUT_END) - val += (1 << (15-8)); /* add 32K */ - } - - /* Add a node seed */ - val += (((1 * pDCTstat->Node_ID) << 20) >> 8); /* Add 1MB per node to avoid aliases */ - - /* HW remap disabled? */ - if (!(pDCTstat->Status & (1 << SB_HWHole))) { - if (!(pDCTstat->Status & (1 << SB_SWNodeHole))) { - /* SW memhole disabled */ - u32 lo, hi; - _RDMSR(TOP_MEM, &lo, &hi); - lo >>= 8; - if ((val >= lo) && (val < _4GB_RJ8)) { - val = 0; - *valid = 0; - goto exitGetAddr; - } else { - *valid = 1; - goto exitGetAddrWNoError; - } - } else { - *valid = 1; - goto exitGetAddrWNoError; - } - } else { - *valid = 1; - goto exitGetAddrWNoError; - } - -exitGetAddrWNoError: - - /* Skip if Address is in UMA region */ - dword = pMCTstat->Sub4GCacheTop; - dword >>= 8; - if (dword != 0) { - if ((val >= dword) && (val < _4GB_RJ8)) { - val = 0; - *valid = 0; - } else { - *valid = 1; - } - } - print_debug_dqs("mct_GetMCTSysAddr_D: receiver ", receiver, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: Channel ", Channel, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: base_addr ", val, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: valid ", *valid, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: status ", pDCTstat->Status, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: SysBase ", pDCTstat->DCTSysBase, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: HoleBase ", pDCTstat->DCTHoleBase, 2); - print_debug_dqs("mct_GetMCTSysAddr_D: Cachetop ", pMCTstat->Sub4GCacheTop, 2); - -exitGetAddr: - return val; -} - -void mct_Write1LTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, - u32 TestAddr, u8 pattern) -{ - - u8 *buf; - - /* Issue the stream of writes. When F2x11C[MctWrLimit] is reached - * (or when F2x11C[FlushWr] is set again), all the writes are written - * to DRAM. - */ - - SetUpperFSbase(TestAddr); - - if (pattern) - buf = (u8 *)pDCTstat->PtrPatternBufB; - else - buf = (u8 *)pDCTstat->PtrPatternBufA; - - WriteLNTestPattern(TestAddr << 8, buf, 1); -} - -void mct_Read1LTestPattern_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 addr) -{ - u32 value; - - /* BIOS issues the remaining (Ntrain - 2) reads after checking that - * F2x11C[PrefDramTrainMode] is cleared. These reads must be to - * consecutive cache lines (i.e., 64 bytes apart) and must not cross - * a naturally aligned 4KB boundary. These reads hit the prefetches and - * read the data from the prefetch buffer. - */ - - /* get data from DIMM */ - SetUpperFSbase(addr); - - /* 1st move causes read fill (to exclusive or shared)*/ - value = read32_fs(addr << 8); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c deleted file mode 100644 index 4c33b9e4b6..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mcthdi.c b/src/northbridge/amd/amdmct/mct_ddr3/mcthdi.c deleted file mode 100644 index c821ec0628..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mcthdi.c +++ /dev/null @@ -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); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c b/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c deleted file mode 100644 index 1ee10608b9..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mcthwl.c +++ /dev/null @@ -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); - } - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c deleted file mode 100644 index 73370e715b..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctmtr_d.c +++ /dev/null @@ -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; - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c deleted file mode 100644 index 29949e02d4..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctndi_d.c +++ /dev/null @@ -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"); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctprob.c b/src/northbridge/amd/amdmct/mct_ddr3/mctprob.c deleted file mode 100644 index 3cb75675df..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctprob.c +++ /dev/null @@ -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 */); - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c b/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c deleted file mode 100644 index ddaaaab8d5..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c +++ /dev/null @@ -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); - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctprod.c b/src/northbridge/amd/amdmct/mct_ddr3/mctprod.c deleted file mode 100644 index b203942058..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctprod.c +++ /dev/null @@ -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); - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c b/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c deleted file mode 100644 index 93cfb4bf1b..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c deleted file mode 100644 index f215695580..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c +++ /dev/null @@ -1,1210 +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 "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; -} - -uint8_t fam15_dimm_dic(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type) -{ - uint8_t dic; - - /* Calculate DIC based on recommendations in MR1_dct[1:0] */ - if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* TODO - * LRDIMM unimplemented - */ - dic = 0x0; - } else { - dic = 0x1; - } - - return dic; -} - -uint8_t fam15_rttwr(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type) -{ - uint8_t term = 0; - uint8_t number_of_dimms = pDCTstat->MAdimms[dct]; - uint8_t frequency_index; - uint8_t rank_count = pDCTstat->DimmRanks[(dimm * 2) + dct]; - - uint8_t rank_count_dimm0; - uint8_t rank_count_dimm1; - uint8_t rank_count_dimm2; - - if (is_fam15h()) - frequency_index = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f; - else - frequency_index = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x7; - - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - if (is_fam15h()) { - if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* TODO - * LRDIMM unimplemented - */ - } else if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - if (package_type == PT_GR) { - /* Socket G34: Fam15h BKDG v3.14 Table 57 */ - if (MaxDimmsInstallable == 1) { - if ((frequency_index == 0x4) || (frequency_index == 0x6) - || (frequency_index == 0xa) || (frequency_index == 0xe)) { - /* DDR3-667 - DDR3-1333 */ - if (rank_count < 3) - term = 0x0; - else - term = 0x2; - } else { - /* DDR3-1600 */ - term = 0x0; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((frequency_index == 0x4) || (frequency_index == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if ((number_of_dimms == 1) && ((rank_count_dimm0 < 4) - && (rank_count_dimm1 < 4))) - term = 0x0; - else - term = 0x2; - } else if (frequency_index == 0xa) { - /* DDR3-1066 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x0; - else - term = 0x2; - } else { - term = 0x1; - } - } else if (frequency_index == 0xe) { - /* DDR3-1333 */ - term = 0x2; - } else { - /* DDR3-1600 */ - if (number_of_dimms == 1) - term = 0x0; - else - term = 0x1; - } - } else if (MaxDimmsInstallable == 3) { - rank_count_dimm2 = pDCTstat->DimmRanks[(2 * 2) + dct]; - - if ((frequency_index == 0xa) || (frequency_index == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (rank_count_dimm2 < 4) - term = 0x1; - else - term = 0x2; - } else if (frequency_index == 0x12) { - /* DDR3-1600 */ - term = 0x1; - } else { - term = 0x2; - } - } - } else if (package_type == PT_C3) { - /* Socket C32: Fam15h BKDG v3.14 Table 60 */ - if (MaxDimmsInstallable == 1) { - if ((frequency_index == 0x4) || (frequency_index == 0x6) - || (frequency_index == 0xa) || (frequency_index == 0xe)) { - /* DDR3-667 - DDR3-1333 */ - if (rank_count < 3) - term = 0x0; - else - term = 0x2; - } else { - /* DDR3-1600 */ - term = 0x0; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((frequency_index == 0x4) || (frequency_index == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if ((number_of_dimms == 1) && ((rank_count_dimm0 < 4) - && (rank_count_dimm1 < 4))) - term = 0x0; - else - term = 0x2; - } else if (frequency_index == 0xa) { - /* DDR3-1066 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x0; - else - term = 0x2; - } else { - term = 0x1; - } - } else if (frequency_index == 0xe) { - /* DDR3-1333 */ - term = 0x2; - } else { - /* DDR3-1600 */ - if (number_of_dimms == 1) - term = 0x0; - else - term = 0x1; - } - } else if (MaxDimmsInstallable == 3) { - rank_count_dimm2 = pDCTstat->DimmRanks[(2 * 2) + dct]; - - if ((frequency_index == 0xa) || (frequency_index == 0xe)) { - /* DDR3-1066 - DDR3-1333 */ - if (rank_count_dimm2 < 4) - term = 0x1; - else - term = 0x2; - } else if (frequency_index == 0x12) { - /* DDR3-1600 */ - term = 0x1; - } else { - term = 0x2; - } - } - } else { - /* TODO - * Other sockets unimplemented - */ - } - } else { - /* UDIMM */ - if (package_type == PT_GR) { - /* Socket G34: Fam15h BKDG v3.14 Table 56 */ - if (MaxDimmsInstallable == 1) { - term = 0x0; - } else if (MaxDimmsInstallable == 2) { - if ((number_of_dimms == 2) && (frequency_index == 0x12)) { - term = 0x1; - } else if (number_of_dimms == 1) { - term = 0x0; - } else { - term = 0x2; - } - } else if (MaxDimmsInstallable == 3) { - if (number_of_dimms == 1) { - if (frequency_index <= 0xa) { - term = 0x2; - } else { - if (rank_count < 3) { - term = 0x1; - } else { - term = 0x2; - } - } - } else if (number_of_dimms == 2) { - term = 0x2; - } - } - } else if (package_type == PT_C3) { - /* Socket C32: Fam15h BKDG v3.14 Table 59 */ - if (MaxDimmsInstallable == 1) { - term = 0x0; - } else if (MaxDimmsInstallable == 2) { - if ((number_of_dimms == 2) && (frequency_index == 0x12)) { - term = 0x1; - } else if (number_of_dimms == 1) { - term = 0x0; - } else { - term = 0x2; - } - } else if (MaxDimmsInstallable == 3) { - if (number_of_dimms == 1) { - if (frequency_index <= 0xa) { - term = 0x2; - } else { - if (rank_count < 3) { - term = 0x1; - } else { - term = 0x2; - } - } - } else if (number_of_dimms == 2) { - term = 0x2; - } - } - } else if (package_type == PT_FM2) { - /* Socket FM2: Fam15h Model10 BKDG 3.12 Table 32 */ - if (MaxDimmsInstallable == 1) { - term = 0x0; - } else if (MaxDimmsInstallable == 2) { - if ((number_of_dimms == 2) && (frequency_index >= 0x12)) { - term = 0x1; - } else if (number_of_dimms == 1) { - term = 0x0; - } else { - term = 0x2; - } - } - } else { - /* TODO - * Other sockets unimplemented - */ - } - } - } - - printk(BIOS_INFO, "DIMM %d RttWr: %01x\n", dimm, term); - - return term; -} - -uint8_t fam15_rttnom(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type) -{ - uint8_t term = 0; - uint8_t number_of_dimms = pDCTstat->MAdimms[dct]; - uint8_t frequency_index; - - uint8_t rank_count_dimm0; - uint8_t rank_count_dimm1; - - if (is_fam15h()) - frequency_index = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x1f; - else - frequency_index = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x7; - - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - if (is_fam15h()) { - if (pDCTstat->Status & (1 << SB_LoadReduced)) { - /* TODO - * LRDIMM unimplemented - */ - } else if (pDCTstat->Status & (1 << SB_Registered)) { - /* RDIMM */ - if (package_type == PT_GR) { - /* Socket G34: Fam15h BKDG v3.14 Table 57 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - - if ((frequency_index == 0x4) || (frequency_index == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (rank_count_dimm0 < 4) { - term = 0x2; - } else { - if (!rank) - term = 0x2; - else - term = 0x0; - } - } else if (frequency_index == 0xa) { - /* DDR3-1066 */ - term = 0x1; - } else if (frequency_index == 0xe) { - /* DDR3-1333 */ - if (rank_count_dimm0 < 4) { - term = 0x1; - } else { - if (!rank) - term = 0x3; - else - term = 0x0; - } - } else { - term = 0x3; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((frequency_index == 0x4) || (frequency_index == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x2; - else if (rank) - term = 0x0; - else - term = 0x2; - } else { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) { - term = 0x3; - } else { - if (rank_count_dimm0 == 4) { - if (rank_count_dimm1 == 1) - term = 0x5; - else - term = 0x1; - } else if (rank_count_dimm1 == 4) { - if (rank_count_dimm0 == 1) - term = 0x5; - else - term = 0x1; - } - if (rank) - term = 0x0; - } - } - } else if (frequency_index == 0xa) { - /* DDR3-1066 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x1; - else if (rank) - term = 0x0; - else - term = 0x1; - } else { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) { - term = 0x3; - } else { - if (rank_count_dimm0 == 4) { - if (rank_count_dimm1 == 1) - term = 0x5; - else - term = 0x1; - } else if (rank_count_dimm1 == 4) { - if (rank_count_dimm0 == 1) - term = 0x5; - else - term = 0x1; - } - if (rank) - term = 0x0; - } - } - } else if (frequency_index == 0xe) { - /* DDR3-1333 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x1; - else if (rank) - term = 0x0; - else - term = 0x3; - } else { - term = 0x5; - } - } else { - /* DDR3-1600 */ - if (number_of_dimms == 1) - term = 0x3; - else - term = 0x4; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else if (package_type == PT_C3) { - /* Socket C32: Fam15h BKDG v3.14 Table 60 */ - if (MaxDimmsInstallable == 1) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - - if ((frequency_index == 0x4) || (frequency_index == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (rank_count_dimm0 < 4) { - term = 0x2; - } else { - if (!rank) - term = 0x2; - else - term = 0x0; - } - } else if (frequency_index == 0xa) { - /* DDR3-1066 */ - term = 0x1; - } else if (frequency_index == 0xe) { - /* DDR3-1333 */ - if (rank_count_dimm0 < 4) { - term = 0x1; - } else { - if (!rank) - term = 0x3; - else - term = 0x0; - } - } else { - term = 0x3; - } - } else if (MaxDimmsInstallable == 2) { - rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct]; - rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct]; - - if ((frequency_index == 0x4) || (frequency_index == 0x6)) { - /* DDR3-667 - DDR3-800 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x2; - else if (rank) - term = 0x0; - else - term = 0x2; - } else { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) { - term = 0x3; - } else { - if (rank_count_dimm0 == 4) { - if (rank_count_dimm1 == 1) - term = 0x5; - else - term = 0x1; - } else if (rank_count_dimm1 == 4) { - if (rank_count_dimm0 == 1) - term = 0x5; - else - term = 0x1; - } - if (rank) - term = 0x0; - } - } - } else if (frequency_index == 0xa) { - /* DDR3-1066 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x1; - else if (rank) - term = 0x0; - else - term = 0x1; - } else { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) { - term = 0x3; - } else { - if (rank_count_dimm0 == 4) { - if (rank_count_dimm1 == 1) - term = 0x5; - else - term = 0x1; - } else if (rank_count_dimm1 == 4) { - if (rank_count_dimm0 == 1) - term = 0x5; - else - term = 0x1; - } - if (rank) - term = 0x0; - } - } - } else if (frequency_index == 0xe) { - /* DDR3-1333 */ - if (number_of_dimms == 1) { - if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4)) - term = 0x1; - else if (rank) - term = 0x0; - else - term = 0x3; - } else { - term = 0x5; - } - } else { - /* DDR3-1600 */ - if (number_of_dimms == 1) - term = 0x3; - else - term = 0x4; - } - } else if (MaxDimmsInstallable == 3) { - /* TODO - * 3 DIMM/channel support unimplemented - */ - } - } else { - /* TODO - * Other sockets unimplemented - */ - } - } else { - /* UDIMM */ - if (package_type == PT_GR) { - /* Socket G34: Fam15h BKDG v3.14 Table 56 */ - if (MaxDimmsInstallable == 1) { - if ((frequency_index == 0x4) || (frequency_index == 0x6)) - term = 0x2; - else if ((frequency_index == 0xa) || (frequency_index == 0xe)) - term = 0x1; - else - term = 0x3; - } - if (MaxDimmsInstallable == 2) { - if (number_of_dimms == 1) { - if (frequency_index <= 0x6) { - term = 0x2; - } else if (frequency_index <= 0xe) { - term = 0x1; - } else { - term = 0x3; - } - } else { - if (frequency_index <= 0xa) { - term = 0x3; - } else if (frequency_index <= 0xe) { - term = 0x5; - } else { - term = 0x4; - } - } - } else if (MaxDimmsInstallable == 3) { - if (number_of_dimms == 1) { - term = 0x0; - } else if (number_of_dimms == 2) { - if (frequency_index <= 0xa) { - if (rank == 1) { - term = 0x0; - } else { - term = 0x3; - } - } else if (frequency_index <= 0xe) { - if (rank == 1) { - term = 0x0; - } else { - term = 0x5; - } - } - } - } - } else if (package_type == PT_C3) { - /* Socket C32: Fam15h BKDG v3.14 Table 62 */ - if (MaxDimmsInstallable == 1) { - if ((frequency_index == 0x4) || (frequency_index == 0x6)) - term = 0x2; - else if ((frequency_index == 0xa) || (frequency_index == 0xe)) - term = 0x1; - else - term = 0x3; - } - if (MaxDimmsInstallable == 2) { - if (number_of_dimms == 1) { - if (frequency_index <= 0x6) { - term = 0x2; - } else if (frequency_index <= 0xe) { - term = 0x1; - } else { - term = 0x3; - } - } else { - if (frequency_index <= 0xa) { - term = 0x3; - } else if (frequency_index <= 0xe) { - term = 0x5; - } else { - term = 0x4; - } - } - } else if (MaxDimmsInstallable == 3) { - if (number_of_dimms == 1) { - term = 0x0; - } else if (number_of_dimms == 2) { - if (frequency_index <= 0xa) { - if (rank == 1) { - term = 0x0; - } else { - term = 0x3; - } - } else if (frequency_index <= 0xe) { - if (rank == 1) { - term = 0x0; - } else { - term = 0x5; - } - } - } - } - } else if (package_type == PT_FM2) { - /* Socket FM2: Fam15h Model10 BKDG 3.12 Table 32 */ - if (MaxDimmsInstallable == 1) { - if ((frequency_index == 0x4) - || (frequency_index == 0x6) - || (frequency_index == 0xa)) - term = 0x4; - else if (frequency_index == 0xe) - term = 0x3; - else if (frequency_index >= 0x12) - term = 0x2; - } - if (MaxDimmsInstallable == 2) { - if (number_of_dimms == 1) { - if (frequency_index <= 0xa) { - term = 0x4; - } else if (frequency_index <= 0xe) { - term = 0x3; - } else { - term = 0x2; - } - } else { - if (frequency_index <= 0xa) { - term = 0x2; - } else if (frequency_index <= 0xe) { - term = 0x1; - } else { - term = 0x0; - } - } - } - } else { - /* TODO - * Other sockets unimplemented - */ - } - } - } - - printk(BIOS_INFO, "DIMM %d RttNom: %01x\n", dimm, term); - return term; -} - -static void mct_DCTAccessDone(struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 dev = pDCTstat->dev_dct; - u32 val; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - do { - val = Get_NB32_DCT(dev, dct, 0x98); - } while (!(val & (1 << DctAccessDone))); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static u32 swapAddrBits(struct DCTStatStruc *pDCTstat, u32 MR_register_setting, u8 MrsChipSel, u8 dct) -{ - u16 word; - u32 ret; - - if (!(pDCTstat->Status & (1 << SB_Registered))) { - word = pDCTstat->MirrPresU_NumRegR; - if (dct == 0) { - word &= 0x55; - word <<= 1; - } else - word &= 0xAA; - - if (word & (1 << MrsChipSel)) { - /* A3<->A4,A5<->A6,A7<->A8,BA0<->BA1 */ - ret = 0; - if (MR_register_setting & (1 << 3)) ret |= 1 << 4; - if (MR_register_setting & (1 << 4)) ret |= 1 << 3; - if (MR_register_setting & (1 << 5)) ret |= 1 << 6; - if (MR_register_setting & (1 << 6)) ret |= 1 << 5; - if (MR_register_setting & (1 << 7)) ret |= 1 << 8; - if (MR_register_setting & (1 << 8)) ret |= 1 << 7; - if (is_fam15h()) { - if (MR_register_setting & (1 << 18)) ret |= 1 << 19; - if (MR_register_setting & (1 << 19)) ret |= 1 << 18; - MR_register_setting &= ~0x000c01f8; - } else { - if (MR_register_setting & (1 << 16)) ret |= 1 << 17; - if (MR_register_setting & (1 << 17)) ret |= 1 << 16; - MR_register_setting &= ~0x000301f8; - } - MR_register_setting |= ret; - } - } - return MR_register_setting; -} - -static void mct_SendMrsCmd(struct DCTStatStruc *pDCTstat, u8 dct, u32 EMRS) -{ - u32 dev = pDCTstat->dev_dct; - u32 val; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - val = Get_NB32_DCT(dev, dct, 0x7c); - val &= ~0x00ffffff; - val |= EMRS; - val |= 1 << SendMrsCmd; - Set_NB32_DCT(dev, dct, 0x7c, val); - - do { - val = Get_NB32_DCT(dev, dct, 0x7c); - } while (val & (1 << SendMrsCmd)); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -u32 mct_MR2(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel) -{ - u32 dev = pDCTstat->dev_dct; - u32 dword, ret; - - /* The formula for chip select number is: CS = dimm*2+rank */ - uint8_t dimm = MrsChipSel / 2; - uint8_t rank = MrsChipSel % 2; - - if (is_fam15h()) { - uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE); - - /* FIXME: These parameters should be configurable - * For now, err on the side of caution and enable automatic 2x refresh - * when the DDR temperature rises above the internal limits - */ - uint8_t force_2x_self_refresh = 0; /* ASR */ - uint8_t auto_2x_self_refresh = 1; /* SRT */ - - ret = 0x80000; - ret |= (MrsChipSel << 21); - - /* Set self refresh parameters */ - ret |= (force_2x_self_refresh << 6); - ret |= (auto_2x_self_refresh << 7); - - /* Obtain Tcwl, adjust, and set CWL with the adjusted value */ - dword = Get_NB32_DCT(dev, dct, 0x20c) & 0x1f; - dword -= pDCTstat->tcwl_delay[dct]; - ret |= ((dword - 5) << 3); - - /* Obtain and set RttWr */ - ret |= (fam15_rttwr(pDCTstat, dct, dimm, rank, package_type) << 9); - } else { - ret = 0x20000; - ret |= (MrsChipSel << 20); - - /* program MrsAddress[5:3]=CAS write latency (CWL): - * based on F2x[1,0]84[Tcwl] */ - dword = Get_NB32_DCT(dev, dct, 0x84); - dword = mct_AdjustSPDTimings(pMCTstat, pDCTstat, dword); - - ret |= ((dword >> 20) & 7) << 3; - - /* program MrsAddress[6]=auto self refresh method (ASR): - * based on F2x[1,0]84[ASR] - * program MrsAddress[7]=self refresh temperature range (SRT): - * based on F2x[1,0]84[ASR and SRT] - */ - ret |= ((dword >> 18) & 3) << 6; - - /* program MrsAddress[10:9]=dynamic termination during writes (RTT_WR) - * based on F2x[1,0]84[DramTermDyn] - */ - ret |= ((dword >> 10) & 3) << 9; - } - - printk(BIOS_SPEW, "Going to send DCT %d DIMM %d rank %d MR2 control word %08x\n", dct, dimm, rank, ret); - - return ret; -} - -static u32 mct_MR3(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel) -{ - u32 dev = pDCTstat->dev_dct; - u32 dword, ret; - - /* The formula for chip select number is: CS = dimm*2+rank */ - uint8_t dimm = MrsChipSel / 2; - uint8_t rank = MrsChipSel % 2; - - if (is_fam15h()) { - ret = 0xc0000; - ret |= (MrsChipSel << 21); - - /* Program MPR and MPRLoc to 0 */ - // ret |= 0x0; /* MPR */ - // ret |= (0x0 << 2); /* MPRLoc */ - } else { - ret = 0x30000; - ret |= (MrsChipSel << 20); - - /* program MrsAddress[1:0]=multi purpose register address location - * (MPR Location):based on F2x[1,0]84[MprLoc] - * program MrsAddress[2]=multi purpose register - * (MPR):based on F2x[1,0]84[MprEn] - */ - dword = Get_NB32_DCT(dev, dct, 0x84); - ret |= (dword >> 24) & 7; - } - - printk(BIOS_SPEW, "Going to send DCT %d DIMM %d rank %d MR3 control word %08x\n", dct, dimm, rank, ret); - - return ret; -} - -u32 mct_MR1(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel) -{ - u32 dev = pDCTstat->dev_dct; - u32 dword, ret; - - /* The formula for chip select number is: CS = dimm*2+rank */ - uint8_t dimm = MrsChipSel / 2; - uint8_t rank = MrsChipSel % 2; - - if (is_fam15h()) { - uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE); - - /* Set defaults */ - uint8_t qoff = 0; /* Enable output buffers */ - uint8_t wrlvl = 0; /* Disable write levelling */ - uint8_t tqds = 0; - uint8_t rttnom = 0; - uint8_t dic = 0; - uint8_t additive_latency = 0; - uint8_t dll_enable = 0; - - ret = 0x40000; - ret |= (MrsChipSel << 21); - - /* Determine if TQDS should be set */ - if ((pDCTstat->Dimmx8Present & (1 << dimm)) - && (((dimm & 0x1)?(pDCTstat->Dimmx4Present&0x55):(pDCTstat->Dimmx4Present&0xaa)) != 0x0) - && (pDCTstat->Status & (1 << SB_LoadReduced))) - tqds = 1; - - /* Obtain RttNom */ - rttnom = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type); - - /* Obtain DIC */ - dic = fam15_dimm_dic(pDCTstat, dct, dimm, rank, package_type); - - /* Load data into MRS word */ - ret |= (qoff & 0x1) << 12; - ret |= (tqds & 0x1) << 11; - ret |= ((rttnom & 0x4) >> 2) << 9; - ret |= ((rttnom & 0x2) >> 1) << 6; - ret |= ((rttnom & 0x1) >> 0) << 2; - ret |= (wrlvl & 0x1) << 7; - ret |= ((dic & 0x2) >> 1) << 5; - ret |= ((dic & 0x1) >> 0) << 1; - ret |= (additive_latency & 0x3) << 3; - ret |= (dll_enable & 0x1); - } else { - ret = 0x10000; - ret |= (MrsChipSel << 20); - - /* program MrsAddress[5,1]=output driver impedance control (DIC): - * based on F2x[1,0]84[DrvImpCtrl] - */ - dword = Get_NB32_DCT(dev, dct, 0x84); - if (dword & (1 << 3)) - ret |= 1 << 5; - if (dword & (1 << 2)) - ret |= 1 << 1; - - /* program MrsAddress[9,6,2]=nominal termination resistance of ODT (RTT): - * based on F2x[1,0]84[DramTerm] - */ - if (!(pDCTstat->Status & (1 << SB_Registered))) { - if (dword & (1 << 9)) - ret |= 1 << 9; - if (dword & (1 << 8)) - ret |= 1 << 6; - if (dword & (1 << 7)) - ret |= 1 << 2; - } else { - ret |= mct_MR1Odt_RDimm(pMCTstat, pDCTstat, dct, MrsChipSel); - } - - /* program MrsAddress[11]=TDQS: based on F2x[1,0]94[RDqsEn] */ - if (Get_NB32_DCT(dev, dct, 0x94) & (1 << RDqsEn)) { - u8 bit; - /* Set TDQS = 1b for x8 DIMM, TDQS = 0b for x4 DIMM, when mixed x8 & x4 */ - bit = (ret >> 21) << 1; - if ((dct & 1) != 0) - bit ++; - if (pDCTstat->Dimmx8Present & (1 << bit)) - ret |= 1 << 11; - } - - /* program MrsAddress[12]=QOFF: based on F2x[1,0]84[Qoff] */ - if (dword & (1 << 13)) - ret |= 1 << 12; - } - - printk(BIOS_SPEW, "Going to send DCT %d DIMM %d rank %d MR1 control word %08x\n", dct, dimm, rank, ret); - - return ret; -} - -static u32 mct_MR0(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel) -{ - u32 dev = pDCTstat->dev_dct; - u32 dword, ret, dword2; - - /* The formula for chip select number is: CS = dimm*2+rank */ - uint8_t dimm = MrsChipSel / 2; - uint8_t rank = MrsChipSel % 2; - - if (is_fam15h()) { - ret = 0x00000; - ret |= (MrsChipSel << 21); - - /* Set defaults */ - uint8_t ppd = 0; - uint8_t wr_ap = 0; - uint8_t dll_reset = 1; - uint8_t test_mode = 0; - uint8_t cas_latency = 0; - uint8_t read_burst_type = 1; - uint8_t burst_length = 0; - - /* Obtain PchgPDModeSel */ - dword = Get_NB32_DCT(dev, dct, 0x84); - ppd = (dword >> 23) & 0x1; - - /* Obtain Twr */ - dword = Get_NB32_DCT(dev, dct, 0x22c) & 0x1f; - - /* Calculate wr_ap (Fam15h BKDG v3.14 Table 82) */ - if (dword == 0x10) - wr_ap = 0x0; - else if (dword == 0x5) - wr_ap = 0x1; - else if (dword == 0x6) - wr_ap = 0x2; - else if (dword == 0x7) - wr_ap = 0x3; - else if (dword == 0x8) - wr_ap = 0x4; - else if (dword == 0xa) - wr_ap = 0x5; - else if (dword == 0xc) - wr_ap = 0x6; - else if (dword == 0xe) - wr_ap = 0x7; - - /* Obtain Tcl */ - dword = Get_NB32_DCT(dev, dct, 0x200) & 0x1f; - - /* Calculate cas_latency (Fam15h BKDG v3.14 Table 83) */ - if (dword == 0x5) - cas_latency = 0x2; - else if (dword == 0x6) - cas_latency = 0x4; - else if (dword == 0x7) - cas_latency = 0x6; - else if (dword == 0x8) - cas_latency = 0x8; - else if (dword == 0x9) - cas_latency = 0xa; - else if (dword == 0xa) - cas_latency = 0xc; - else if (dword == 0xb) - cas_latency = 0xe; - else if (dword == 0xc) - cas_latency = 0x1; - else if (dword == 0xd) - cas_latency = 0x3; - else if (dword == 0xe) - cas_latency = 0x5; - else if (dword == 0xf) - cas_latency = 0x7; - else if (dword == 0x10) - cas_latency = 0x9; - - /* Obtain BurstCtrl */ - burst_length = Get_NB32_DCT(dev, dct, 0x84) & 0x3; - - /* Load data into MRS word */ - ret |= (ppd & 0x1) << 12; - ret |= (wr_ap & 0x7) << 9; - ret |= (dll_reset & 0x1) << 8; - ret |= (test_mode & 0x1) << 7; - ret |= ((cas_latency & 0xe) >> 1) << 4; - ret |= ((cas_latency & 0x1) >> 0) << 2; - ret |= (read_burst_type & 0x1) << 3; - ret |= (burst_length & 0x3); - } else { - ret = 0x00000; - ret |= (MrsChipSel << 20); - - /* program MrsAddress[1:0]=burst length and control method - (BL):based on F2x[1,0]84[BurstCtrl] */ - dword = Get_NB32_DCT(dev, dct, 0x84); - ret |= dword & 3; - - /* program MrsAddress[3]=1 (BT):interleaved */ - ret |= 1 << 3; - - /* program MrsAddress[6:4,2]=read CAS latency - (CL):based on F2x[1,0]88[Tcl] */ - dword2 = Get_NB32_DCT(dev, dct, 0x88); - ret |= (dword2 & 0x7) << 4; /* F2x88[2:0] to MrsAddress[6:4] */ - ret |= ((dword2 & 0x8) >> 3) << 2; /* F2x88[3] to MrsAddress[2] */ - - /* program MrsAddress[12]=0 (PPD):slow exit */ - if (dword & (1 << 23)) - ret |= 1 << 12; - - /* program MrsAddress[11:9]=write recovery for auto-precharge - (WR):based on F2x[1,0]84[Twr] */ - ret |= ((dword >> 4) & 7) << 9; - - /* program MrsAddress[8]=1 (DLL):DLL reset - just issue DLL reset at first time */ - ret |= 1 << 8; - } - - printk(BIOS_SPEW, "Going to send DCT %d DIMM %d rank %d MR0 control word %08x\n", dct, dimm, rank, ret); - - return ret; -} - -static void mct_SendZQCmd(struct DCTStatStruc *pDCTstat, u8 dct) -{ - u32 dev = pDCTstat->dev_dct; - u32 dword; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - /*1.Program MrsAddress[10]=1 - 2.Set SendZQCmd = 1 - */ - dword = Get_NB32_DCT(dev, dct, 0x7C); - dword &= ~0xFFFFFF; - dword |= 1 << 10; - dword |= 1 << SendZQCmd; - Set_NB32_DCT(dev, dct, 0x7C, dword); - - /* Wait for SendZQCmd = 0 */ - do { - dword = Get_NB32_DCT(dev, dct, 0x7C); - } while (dword & (1 << SendZQCmd)); - - /* 4.Wait 512 MEMCLKs */ - mct_Wait(300); - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -void mct_DramInit_Sw_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 MrsChipSel; - u32 dword; - u32 dev = pDCTstat->dev_dct; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - if (pDCTstat->DIMMAutoSpeed == mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) { - /* 3.Program F2x[1,0]7C[EnDramInit]=1 */ - dword = Get_NB32_DCT(dev, dct, 0x7c); - dword |= 1 << EnDramInit; - Set_NB32_DCT(dev, dct, 0x7c, dword); - mct_DCTAccessDone(pDCTstat, dct); - - /* 4.wait 200us */ - mct_Wait(40000); - - /* 5.Program F2x[1, 0]7C[DeassertMemRstX] = 1. */ - dword = Get_NB32_DCT(dev, dct, 0x7c); - dword |= 1 << DeassertMemRstX; - Set_NB32_DCT(dev, dct, 0x7c, dword); - - /* 6.wait 500us */ - mct_Wait(200000); - - /* 7.Program F2x[1,0]7C[AssertCke]=1 */ - dword = Get_NB32_DCT(dev, dct, 0x7c); - dword |= 1 << AssertCke; - Set_NB32_DCT(dev, dct, 0x7c, dword); - - /* 8.wait 360ns */ - mct_Wait(80); - - /* Set up address parity */ - if ((pDCTstat->Status & (1 << SB_Registered)) - || (pDCTstat->Status & (1 << SB_LoadReduced))) { - if (is_fam15h()) { - dword = Get_NB32_DCT(dev, dct, 0x90); - dword |= 1 << ParEn; - Set_NB32_DCT(dev, dct, 0x90, dword); - } - } - - /* The following steps are performed with registered DIMMs only and - * must be done for each chip select pair */ - if (pDCTstat->Status & (1 << SB_Registered)) - mct_DramControlReg_Init_D(pMCTstat, pDCTstat, dct); - - /* The following steps are performed with load reduced DIMMs only and - * must be done for each DIMM */ - // if (pDCTstat->Status & (1 << SB_LoadReduced)) - /* TODO - * Implement LRDIMM configuration - */ - } - - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct]; - if (pDCTstat->GangedMode & 1) - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0]; - - /* The following steps are performed once for unbuffered DIMMs and once for each - * chip select on registered DIMMs: */ - for (MrsChipSel = 0; MrsChipSel < 8; MrsChipSel++) { - if (pDCTstat->CSPresent & (1 << MrsChipSel)) { - u32 EMRS; - /* 13.Send EMRS(2) */ - EMRS = mct_MR2(pMCTstat, pDCTstat, dct, MrsChipSel); - EMRS = swapAddrBits(pDCTstat, EMRS, MrsChipSel, dct); - mct_SendMrsCmd(pDCTstat, dct, EMRS); - /* 14.Send EMRS(3). Ordinarily at this time, MrsAddress[2:0]=000b */ - EMRS= mct_MR3(pMCTstat, pDCTstat, dct, MrsChipSel); - EMRS = swapAddrBits(pDCTstat, EMRS, MrsChipSel, dct); - mct_SendMrsCmd(pDCTstat, dct, EMRS); - /* 15.Send EMRS(1) */ - EMRS= mct_MR1(pMCTstat, pDCTstat, dct, MrsChipSel); - EMRS = swapAddrBits(pDCTstat, EMRS, MrsChipSel, dct); - mct_SendMrsCmd(pDCTstat, dct, EMRS); - /* 16.Send MRS with MrsAddress[8]=1(reset the DLL) */ - EMRS= mct_MR0(pMCTstat, pDCTstat, dct, MrsChipSel); - EMRS = swapAddrBits(pDCTstat, EMRS, MrsChipSel, dct); - mct_SendMrsCmd(pDCTstat, dct, EMRS); - - if (pDCTstat->DIMMAutoSpeed == mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) - if (!(pDCTstat->Status & (1 << SB_Registered))) - break; /* For UDIMM, only send MR commands once per channel */ - } - if (pDCTstat->LogicalCPUID & (AMD_DR_Bx/* | AMD_RB_C0 */)) /* TODO: We dont support RB_C0 now. need to be added and tested. */ - if (!(pDCTstat->Status & (1 << SB_Registered))) - MrsChipSel ++; - } - - if (pDCTstat->DIMMAutoSpeed == mhz_to_memclk_config(mctGet_NVbits(NV_MIN_MEMCLK))) { - /* 17.Send two ZQCL commands */ - mct_SendZQCmd(pDCTstat, dct); - mct_SendZQCmd(pDCTstat, dct); - - /* 18.Program F2x[1,0]7C[EnDramInit]=0 */ - dword = Get_NB32_DCT(dev, dct, 0x7C); - dword &= ~(1 << EnDramInit); - Set_NB32_DCT(dev, dct, 0x7C, dword); - mct_DCTAccessDone(pDCTstat, dct); - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c deleted file mode 100644 index dbb989fe3d..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c +++ /dev/null @@ -1,2438 +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; 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. - */ - -/****************************************************************************** - Description: Receiver En and DQS Timing Training feature for DDR 3 MCT -******************************************************************************/ - -#include <arch/cpu.h> -#include <stdint.h> -#include <console/console.h> -#include <cpu/x86/cr.h> -#include <string.h> -#include <cpu/x86/msr.h> -#include <cpu/amd/msr.h> -#include "mct_d.h" -#include "mct_d_gcc.h" - -static void dqsTrainRcvrEn_SW_Fam10(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Pass); -static void dqsTrainRcvrEn_SW_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Pass); -static void mct_InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -static void InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Channel); -static void CalcEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Channel); -static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u16 DQSRcvEnDly); -static void mct_DisableDQSRcvEn_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; -} - -/* Warning: These must be located so they do not cross a logical 16-bit - segment boundary! */ -const u32 TestPattern0_D[] = { - 0x55555555, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x55555555, 0x55555555, 0x55555555, -}; -const u32 TestPattern1_D[] = { - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, - 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, -}; -const u32 TestPattern2_D[] = { - 0x12345678, 0x87654321, 0x23456789, 0x98765432, - 0x59385824, 0x30496724, 0x24490795, 0x99938733, - 0x40385642, 0x38465245, 0x29432163, 0x05067894, - 0x12349045, 0x98723467, 0x12387634, 0x34587623, -}; - -static void SetupRcvrPattern(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u32 *buffer, u8 pass) -{ - /* - * 1. Copy the alpha and Beta patterns from ROM to Cache, - * aligning on 16 byte boundary - * 2. Set the ptr to DCTStatstruc.PtrPatternBufA for Alpha - * 3. Set the ptr to DCTStatstruc.PtrPatternBufB for Beta - */ - u32 *buf_a; - u32 *buf_b; - u32 *p_A; - u32 *p_B; - u8 i; - - buf_a = (u32 *)(((u32)buffer + 0x10) & (0xfffffff0)); - buf_b = buf_a + 32; /* ?? */ - p_A = (u32 *)SetupDqsPattern_1PassB(pass); - p_B = (u32 *)SetupDqsPattern_1PassA(pass); - - for (i = 0; i < 16; i++) { - buf_a[i] = p_A[i]; - buf_b[i] = p_B[i]; - } - - pDCTstat->PtrPatternBufA = (u32)buf_a; - pDCTstat->PtrPatternBufB = (u32)buf_b; -} - -void mct_TrainRcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Pass) -{ - if (mct_checkNumberOfDqsRcvEn_1Pass(Pass)) { - if (is_fam15h()) - dqsTrainRcvrEn_SW_Fam15(pMCTstat, pDCTstat, Pass); - else - dqsTrainRcvrEn_SW_Fam10(pMCTstat, pDCTstat, Pass); - } -} - -static uint16_t fam15_receiver_enable_training_seed(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t rank, uint8_t package_type) -{ - uint32_t dword; - uint16_t seed = 0; - - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - uint8_t channel = dct; - if (package_type == PT_GR) { - /* Get the internal node number */ - dword = Get_NB32(pDCTstat->dev_nbmisc, 0xe8); - dword = (dword >> 30) & 0x3; - if (dword == 1) { - channel += 2; - } - } - - if (pDCTstat->Status & (1 << SB_Registered)) { - if (package_type == PT_GR) { - /* Socket G34: Fam15h BKDG v3.14 Table 99 */ - if (MaxDimmsInstallable == 1) { - if (channel == 0) - seed = 0x43; - else if (channel == 1) - seed = 0x3f; - else if (channel == 2) - seed = 0x3a; - else if (channel == 3) - seed = 0x35; - } else if (MaxDimmsInstallable == 2) { - if (channel == 0) - seed = 0x54; - else if (channel == 1) - seed = 0x4d; - else if (channel == 2) - seed = 0x45; - else if (channel == 3) - seed = 0x40; - } else if (MaxDimmsInstallable == 3) { - if (channel == 0) - seed = 0x6b; - else if (channel == 1) - seed = 0x5e; - else if (channel == 2) - seed = 0x4b; - else if (channel == 3) - seed = 0x3d; - } - } else if (package_type == PT_C3) { - /* Socket C32: Fam15h BKDG v3.14 Table 100 */ - if ((MaxDimmsInstallable == 1) || (MaxDimmsInstallable == 2)) { - if (channel == 0) - seed = 0x3f; - else if (channel == 1) - seed = 0x3e; - } else if (MaxDimmsInstallable == 3) { - if (channel == 0) - seed = 0x47; - else if (channel == 1) - seed = 0x38; - } - } - } else if (pDCTstat->Status & (1 << SB_LoadReduced)) { - if (package_type == PT_GR) { - /* Socket G34: Fam15h BKDG v3.14 Table 99 */ - if (MaxDimmsInstallable == 1) { - if (channel == 0) - seed = 0x123; - else if (channel == 1) - seed = 0x122; - else if (channel == 2) - seed = 0x112; - else if (channel == 3) - seed = 0x102; - } - } else if (package_type == PT_C3) { - /* Socket C32: Fam15h BKDG v3.14 Table 100 */ - if (channel == 0) - seed = 0x132; - else if (channel == 1) - seed = 0x122; - } - } else { - if (package_type == PT_GR) { - /* Socket G34: Fam15h BKDG v3.14 Table 99 */ - if (MaxDimmsInstallable == 1) { - if (channel == 0) - seed = 0x3e; - else if (channel == 1) - seed = 0x38; - else if (channel == 2) - seed = 0x37; - else if (channel == 3) - seed = 0x31; - } else if (MaxDimmsInstallable == 2) { - if (channel == 0) - seed = 0x51; - else if (channel == 1) - seed = 0x4a; - else if (channel == 2) - seed = 0x46; - else if (channel == 3) - seed = 0x3f; - } else if (MaxDimmsInstallable == 3) { - if (channel == 0) - seed = 0x5e; - else if (channel == 1) - seed = 0x52; - else if (channel == 2) - seed = 0x48; - else if (channel == 3) - seed = 0x3c; - } - } else if (package_type == PT_C3) { - /* Socket C32: Fam15h BKDG v3.14 Table 100 */ - if ((MaxDimmsInstallable == 1) || (MaxDimmsInstallable == 2)) { - if (channel == 0) - seed = 0x39; - else if (channel == 1) - seed = 0x32; - } else if (MaxDimmsInstallable == 3) { - if (channel == 0) - seed = 0x45; - else if (channel == 1) - seed = 0x37; - } - } else if (package_type == PT_M2) { - /* Socket AM3: Fam15h BKDG v3.14 Table 101 */ - seed = 0x3a; - } else if (package_type == PT_FM2) { - /* Socket FM2: Fam15h Model10 BKDG 3.12 Table 43 */ - seed = 0x32; - } - } - - printk(BIOS_DEBUG, "%s: using seed: %04x\n", __func__, seed); - - return seed; -} - -void read_dqs_write_timing_control_registers(uint16_t *current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg) -{ - uint8_t lane; - uint32_t dword; - - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - uint32_t wdt_reg; - if ((lane == 0) || (lane == 1)) - wdt_reg = 0x30; - if ((lane == 2) || (lane == 3)) - wdt_reg = 0x31; - if ((lane == 4) || (lane == 5)) - wdt_reg = 0x40; - if ((lane == 6) || (lane == 7)) - wdt_reg = 0x41; - if (lane == 8) - wdt_reg = 0x32; - wdt_reg += dimm * 3; - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, wdt_reg); - if ((lane == 7) || (lane == 5) || (lane == 3) || (lane == 1)) - current_total_delay[lane] = (dword & 0x00ff0000) >> 16; - if ((lane == 8) || (lane == 6) || (lane == 4) || (lane == 2) || (lane == 0)) - current_total_delay[lane] = dword & 0x000000ff; - } -} - -#ifdef UNUSED_CODE -static void write_dqs_write_timing_control_registers(uint16_t *current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg) -{ - uint8_t lane; - uint32_t dword; - - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - uint32_t ret_reg; - if ((lane == 0) || (lane == 1)) - ret_reg = 0x30; - if ((lane == 2) || (lane == 3)) - ret_reg = 0x31; - if ((lane == 4) || (lane == 5)) - ret_reg = 0x40; - if ((lane == 6) || (lane == 7)) - ret_reg = 0x41; - if (lane == 8) - ret_reg = 0x32; - ret_reg += dimm * 3; - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, ret_reg); - if ((lane == 7) || (lane == 5) || (lane == 3) || (lane == 1)) { - dword &= ~(0xff << 16); - dword |= (current_total_delay[lane] & 0xff) << 16; - } - if ((lane == 8) || (lane == 6) || (lane == 4) || (lane == 2) || (lane == 0)) { - dword &= ~0xff; - dword |= current_total_delay[lane] & 0xff; - } - Set_NB32_index_wait_DCT(dev, dct, index_reg, ret_reg, dword); - } -} -#endif - -static void write_write_data_timing_control_registers(uint16_t *current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg) -{ - uint8_t lane; - uint32_t dword; - - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - uint32_t wdt_reg; - - /* Calculate Write Data Timing register location */ - if ((lane == 0) || (lane == 1) || (lane == 2) || (lane == 3)) - wdt_reg = 0x1; - if ((lane == 4) || (lane == 5) || (lane == 6) || (lane == 7)) - wdt_reg = 0x2; - if (lane == 8) - wdt_reg = 0x3; - wdt_reg |= (dimm << 8); - - /* Set Write Data Timing register values */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, wdt_reg); - if ((lane == 7) || (lane == 3)) { - dword &= ~(0x7f << 24); - dword |= (current_total_delay[lane] & 0x7f) << 24; - } - if ((lane == 6) || (lane == 2)) { - dword &= ~(0x7f << 16); - dword |= (current_total_delay[lane] & 0x7f) << 16; - } - if ((lane == 5) || (lane == 1)) { - dword &= ~(0x7f << 8); - dword |= (current_total_delay[lane] & 0x7f) << 8; - } - if ((lane == 8) || (lane == 4) || (lane == 0)) { - dword &= ~0x7f; - dword |= current_total_delay[lane] & 0x7f; - } - Set_NB32_index_wait_DCT(dev, dct, index_reg, wdt_reg, dword); - } -} - -void read_dqs_receiver_enable_control_registers(uint16_t *current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg) -{ - uint8_t lane; - uint32_t mask; - uint32_t dword; - - if (is_fam15h()) - mask = 0x3ff; - else - mask = 0x1ff; - - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - uint32_t ret_reg; - if ((lane == 0) || (lane == 1)) - ret_reg = 0x10; - if ((lane == 2) || (lane == 3)) - ret_reg = 0x11; - if ((lane == 4) || (lane == 5)) - ret_reg = 0x20; - if ((lane == 6) || (lane == 7)) - ret_reg = 0x21; - if (lane == 8) - ret_reg = 0x12; - ret_reg += dimm * 3; - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, ret_reg); - if ((lane == 7) || (lane == 5) || (lane == 3) || (lane == 1)) { - current_total_delay[lane] = (dword & (mask << 16)) >> 16; - } - if ((lane == 8) || (lane == 6) || (lane == 4) || (lane == 2) || (lane == 0)) { - current_total_delay[lane] = dword & mask; - } - } -} - -void write_dqs_receiver_enable_control_registers(uint16_t *current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg) -{ - uint8_t lane; - uint32_t mask; - uint32_t dword; - - if (is_fam15h()) - mask = 0x3ff; - else - mask = 0x1ff; - - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - uint32_t ret_reg; - if ((lane == 0) || (lane == 1)) - ret_reg = 0x10; - if ((lane == 2) || (lane == 3)) - ret_reg = 0x11; - if ((lane == 4) || (lane == 5)) - ret_reg = 0x20; - if ((lane == 6) || (lane == 7)) - ret_reg = 0x21; - if (lane == 8) - ret_reg = 0x12; - ret_reg += dimm * 3; - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, ret_reg); - if ((lane == 7) || (lane == 5) || (lane == 3) || (lane == 1)) { - dword &= ~(mask << 16); - dword |= (current_total_delay[lane] & mask) << 16; - } - if ((lane == 8) || (lane == 6) || (lane == 4) || (lane == 2) || (lane == 0)) { - dword &= ~mask; - dword |= current_total_delay[lane] & mask; - } - Set_NB32_index_wait_DCT(dev, dct, index_reg, ret_reg, dword); - } -} - -static void read_dram_phase_recovery_control_registers(uint16_t *current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg) -{ - uint8_t lane; - uint32_t dword; - - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - uint32_t prc_reg; - - /* Calculate DRAM Phase Recovery Control register location */ - if ((lane == 0) || (lane == 1) || (lane == 2) || (lane == 3)) - prc_reg = 0x50; - if ((lane == 4) || (lane == 5) || (lane == 6) || (lane == 7)) - prc_reg = 0x51; - if (lane == 8) - prc_reg = 0x52; - - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, prc_reg); - if ((lane == 7) || (lane == 3)) { - current_total_delay[lane] = (dword >> 24) & 0x7f; - } - if ((lane == 6) || (lane == 2)) { - current_total_delay[lane] = (dword >> 16) & 0x7f; - } - if ((lane == 5) || (lane == 1)) { - current_total_delay[lane] = (dword >> 8) & 0x7f; - } - if ((lane == 8) || (lane == 4) || (lane == 0)) { - current_total_delay[lane] = dword & 0x7f; - } - } -} - -static void write_dram_phase_recovery_control_registers(uint16_t *current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg) -{ - uint8_t lane; - uint32_t dword; - - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - uint32_t prc_reg; - - /* Calculate DRAM Phase Recovery Control register location */ - if ((lane == 0) || (lane == 1) || (lane == 2) || (lane == 3)) - prc_reg = 0x50; - if ((lane == 4) || (lane == 5) || (lane == 6) || (lane == 7)) - prc_reg = 0x51; - if (lane == 8) - prc_reg = 0x52; - - /* Set DRAM Phase Recovery Control register values */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, prc_reg); - if ((lane == 7) || (lane == 3)) { - dword &= ~(0x7f << 24); - dword |= (current_total_delay[lane] & 0x7f) << 24; - } - if ((lane == 6) || (lane == 2)) { - dword &= ~(0x7f << 16); - dword |= (current_total_delay[lane] & 0x7f) << 16; - } - if ((lane == 5) || (lane == 1)) { - dword &= ~(0x7f << 8); - dword |= (current_total_delay[lane] & 0x7f) << 8; - } - if ((lane == 8) || (lane == 4) || (lane == 0)) { - dword &= ~0x7f; - dword |= current_total_delay[lane] & 0x7f; - } - Set_NB32_index_wait_DCT(dev, dct, index_reg, prc_reg, dword); - } -} - -void read_dqs_read_data_timing_registers(uint16_t *delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg) -{ - uint8_t shift; - uint32_t dword; - uint32_t mask; - - if (is_fam15h()) { - mask = 0x3e; - shift = 1; - } - else { - mask = 0x3f; - shift = 0; - } - - /* Lanes 0 - 3 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x5 | (dimm << 8)); - delay[3] = ((dword >> 24) & mask) >> shift; - delay[2] = ((dword >> 16) & mask) >> shift; - delay[1] = ((dword >> 8) & mask) >> shift; - delay[0] = (dword & mask) >> shift; - - /* Lanes 4 - 7 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x6 | (dimm << 8)); - delay[7] = ((dword >> 24) & mask) >> shift; - delay[6] = ((dword >> 16) & mask) >> shift; - delay[5] = ((dword >> 8) & mask) >> shift; - delay[4] = (dword & mask) >> shift; - - /* Lane 8 (ECC) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x7 | (dimm << 8)); - delay[8] = (dword & mask) >> shift; -} - -void write_dqs_read_data_timing_registers(uint16_t *delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg) -{ - uint8_t shift; - uint32_t dword; - uint32_t mask; - - if (is_fam15h()) { - mask = 0x3e; - shift = 1; - } - else { - mask = 0x3f; - shift = 0; - } - - /* Lanes 0 - 3 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x5 | (dimm << 8)); - dword &= ~(mask << 24); - dword &= ~(mask << 16); - dword &= ~(mask << 8); - dword &= ~mask; - dword |= ((delay[3] << shift) & mask) << 24; - dword |= ((delay[2] << shift) & mask) << 16; - dword |= ((delay[1] << shift) & mask) << 8; - dword |= (delay[0] << shift) & mask; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x5 | (dimm << 8), dword); - - /* Lanes 4 - 7 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x6 | (dimm << 8)); - dword &= ~(mask << 24); - dword &= ~(mask << 16); - dword &= ~(mask << 8); - dword &= ~mask; - dword |= ((delay[7] << shift) & mask) << 24; - dword |= ((delay[6] << shift) & mask) << 16; - dword |= ((delay[5] << shift) & mask) << 8; - dword |= (delay[4] << shift) & mask; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x6 | (dimm << 8), dword); - - /* Lane 8 (ECC) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x7 | (dimm << 8)); - dword &= ~mask; - dword |= (delay[8] << shift) & mask; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x7 | (dimm << 8), dword); -} - -static uint32_t convert_testaddr_and_channel_to_address(struct DCTStatStruc *pDCTstat, uint32_t testaddr, uint8_t channel) -{ - SetUpperFSbase(testaddr); - testaddr <<= 8; - - if ((pDCTstat->Status & (1<<SB_128bitmode)) && channel) { - testaddr += 8; /* second channel */ - } - - return testaddr; -} - -/* DQS Receiver Enable Training (Family 10h) - * Algorithm detailed in: - * The Fam10h BKDG Rev. 3.62 section 2.8.9.9.2 - */ -static void dqsTrainRcvrEn_SW_Fam10(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Pass) -{ - u8 Channel; - u8 _2Ranks; - u8 Addl_Index = 0; - u8 Receiver; - u8 _DisableDramECC = 0, _Wrap32Dis = 0, _SSE2 = 0; - u16 CTLRMaxDelay; - u16 MaxDelay_CH[2]; - u32 TestAddr0, TestAddr1, TestAddr0B, TestAddr1B; - u32 PatternBuffer[64+4]; /* FIXME: need increase 8? */ - u32 Errors; - - u32 val; - u32 reg; - u32 dev; - u32 index_reg; - u32 ch_start, ch_end, ch; - msr_t msr; - CRx_TYPE cr4; - - uint32_t dword; - uint8_t dimm; - uint8_t rank; - uint8_t lane; - uint16_t current_total_delay[MAX_BYTE_LANES]; - uint16_t candidate_total_delay[8]; - uint8_t data_test_pass_sr[2][8]; /* [rank][lane] */ - uint8_t data_test_pass[8]; /* [lane] */ - uint8_t data_test_pass_prev[8]; /* [lane] */ - uint8_t window_det_toggle[8]; - uint8_t trained[8]; - uint64_t result_qword1; - uint64_t result_qword2; - - u8 valid; - - print_debug_dqs("\nTrainRcvEn: Node", pDCTstat->Node_ID, 0); - print_debug_dqs("TrainRcvEn: Pass", Pass, 0); - - dev = pDCTstat->dev_dct; - ch_start = 0; - if (!pDCTstat->GangedMode) { - ch_end = 2; - } else { - ch_end = 1; - } - - for (ch = ch_start; ch < ch_end; ch++) { - reg = 0x78; - val = Get_NB32_DCT(dev, ch, reg); - val &= ~(0x3ff << 22); - val |= (0x0c8 << 22); /* MaxRdLatency = 0xc8 */ - Set_NB32_DCT(dev, ch, reg, val); - } - - if (Pass == FirstPass) { - mct_InitDQSPos4RcvrEn_D(pMCTstat, pDCTstat); - } else { - pDCTstat->DimmTrainFail = 0; - pDCTstat->CSTrainFail = ~pDCTstat->CSPresent; - } - - cr4 = read_cr4(); - if (cr4 & (1 << 9)) { /* save the old value */ - _SSE2 = 1; - } - cr4 |= (1 << 9); /* OSFXSR enable SSE2 */ - write_cr4(cr4); - - msr = rdmsr(HWCR_MSR); - /* FIXME: Why use SSEDIS */ - if (msr.lo & (1 << 17)) { /* save the old value */ - _Wrap32Dis = 1; - } - msr.lo |= (1 << 17); /* HWCR.wrap32dis */ - msr.lo &= ~(1 << 15); /* SSEDIS */ - wrmsr(HWCR_MSR, msr); /* Setting wrap32dis allows 64-bit memory - references in real mode */ - - _DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat); - - SetupRcvrPattern(pMCTstat, pDCTstat, PatternBuffer, Pass); - - Errors = 0; - dev = pDCTstat->dev_dct; - - for (Channel = 0; Channel < 2; Channel++) { - print_debug_dqs("\tTrainRcvEn51: Node ", pDCTstat->Node_ID, 1); - print_debug_dqs("\tTrainRcvEn51: Channel ", Channel, 1); - pDCTstat->Channel = Channel; - - CTLRMaxDelay = 0; - MaxDelay_CH[Channel] = 0; - index_reg = 0x98; - - Receiver = mct_InitReceiver_D(pDCTstat, Channel); - /* There are four receiver pairs, loosely associated with chipselects. - * This is essentially looping over each DIMM. - */ - for (; Receiver < 8; Receiver += 2) { - Addl_Index = (Receiver >> 1) * 3 + 0x10; - dimm = (Receiver >> 1); - - print_debug_dqs("\t\tTrainRcvEnd52: index ", Addl_Index, 2); - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver)) { - continue; - } - - /* Clear data structures */ - for (lane = 0; lane < 8; lane++) { - data_test_pass_prev[lane] = 0; - trained[lane] = 0; - } - - /* 2.8.9.9.2 (1, 6) - * Retrieve gross and fine timing fields from write DQS registers - */ - read_dqs_write_timing_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - - /* 2.8.9.9.2 (1) - * Program the Write Data Timing and Write ECC Timing register to - * the values stored in the DQS Write Timing Control register - * for each lane - */ - write_write_data_timing_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - - /* 2.8.9.9.2 (2) - * Program the Read DQS Timing Control and the Read DQS ECC Timing Control registers - * to 1/2 MEMCLK for all lanes - */ - for (lane = 0; lane < MAX_BYTE_LANES; lane++) { - uint32_t rdt_reg; - if ((lane == 0) || (lane == 1) || (lane == 2) || (lane == 3)) - rdt_reg = 0x5; - if ((lane == 4) || (lane == 5) || (lane == 6) || (lane == 7)) - rdt_reg = 0x6; - if (lane == 8) - rdt_reg = 0x7; - rdt_reg |= (dimm << 8); - if (lane == 8) - dword = 0x0000003f; - else - dword = 0x3f3f3f3f; - Set_NB32_index_wait_DCT(dev, Channel, index_reg, rdt_reg, dword); - } - - /* 2.8.9.9.2 (3) - * Select two test addresses for each rank present - */ - TestAddr0 = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, Channel, Receiver, &valid); - if (!valid) { /* Address not supported on current CS */ - continue; - } - - TestAddr0B = TestAddr0 + (BigPagex8_RJ8 << 3); - - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver+1)) { - TestAddr1 = mct_GetRcvrSysAddr_D(pMCTstat, pDCTstat, Channel, Receiver+1, &valid); - if (!valid) { /* Address not supported on current CS */ - continue; - } - TestAddr1B = TestAddr1 + (BigPagex8_RJ8 << 3); - _2Ranks = 1; - } else { - _2Ranks = TestAddr1 = TestAddr1B = 0; - } - - print_debug_dqs("\t\tTrainRcvEn53: TestAddr0 ", TestAddr0, 2); - print_debug_dqs("\t\tTrainRcvEn53: TestAddr0B ", TestAddr0B, 2); - print_debug_dqs("\t\tTrainRcvEn53: TestAddr1 ", TestAddr1, 2); - print_debug_dqs("\t\tTrainRcvEn53: TestAddr1B ", TestAddr1B, 2); - - /* 2.8.9.9.2 (4, 5) - * Write 1 cache line of the appropriate test pattern to each test address - */ - mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr0, 0); /* rank 0 of DIMM, testpattern 0 */ - mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr0B, 1); /* rank 0 of DIMM, testpattern 1 */ - if (_2Ranks) { - mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr1, 0); /*rank 1 of DIMM, testpattern 0 */ - mct_Write1LTestPattern_D(pMCTstat, pDCTstat, TestAddr1B, 1); /*rank 1 of DIMM, testpattern 1 */ - } - -#if DQS_TRAIN_DEBUG > 0 - for (lane = 0; lane < 8; lane++) { - print_debug_dqs("\t\tTrainRcvEn54: lane: ", lane, 2); - print_debug_dqs("\t\tTrainRcvEn54: current_total_delay ", current_total_delay[lane], 2); - } -#endif - - /* 2.8.9.9.2 (6) - * Write gross and fine timing fields to read DQS registers - */ - write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - - /* 2.8.9.9.2 (7) - * Loop over all delay values up to 1 MEMCLK (0x40 delay steps) from the initial delay values - * - * FIXME - * It is not clear if training should be discontinued if any test failures occur in the first - * 1 MEMCLK window, or if it should be discontinued if no successes occur in the first 1 MEMCLK - * window. Therefore, loop over up to 2 MEMCLK (0x80 delay steps) to be on the safe side. - */ - uint16_t current_delay_step; - - for (current_delay_step = 0; current_delay_step < 0x80; current_delay_step++) { - print_debug_dqs("\t\t\tTrainRcvEn541: current_delay_step ", current_delay_step, 3); - - /* 2.8.9.9.2 (7 D) - * Terminate if all lanes are trained - */ - uint8_t all_lanes_trained = 1; - for (lane = 0; lane < 8; lane++) - if (!trained[lane]) - all_lanes_trained = 0; - - if (all_lanes_trained) - break; - - /* 2.8.9.9.2 (7 A) - * Loop over all ranks - */ - for (rank = 0; rank < (_2Ranks + 1); rank++) { - /* 2.8.9.9.2 (7 A a-d) - * Read the first test address of the current rank - * Store the first data beat for analysis - * Reset read pointer in the DRAM controller FIFO - * Read the second test address of the current rank - * Store the first data beat for analysis - * Reset read pointer in the DRAM controller FIFO - */ - if (rank & 1) { - /* 2.8.9.9.2 (7 D) - * Invert read instructions to alternate data read order on the bus - */ - proc_IOCLFLUSH_D((rank == 0)?TestAddr0B:TestAddr1B); - result_qword2 = read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 0)?TestAddr0B:TestAddr1B, Channel)); - write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - proc_IOCLFLUSH_D((rank == 0)?TestAddr0:TestAddr1); - result_qword1 = read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 0)?TestAddr0:TestAddr1, Channel)); - write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - } else { - proc_IOCLFLUSH_D((rank == 0)?TestAddr0:TestAddr1); - result_qword1 = read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 0)?TestAddr0:TestAddr1, Channel)); - write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - proc_IOCLFLUSH_D((rank == 0)?TestAddr0B:TestAddr1B); - result_qword2 = read64_fs(convert_testaddr_and_channel_to_address(pDCTstat, (rank == 0)?TestAddr0B:TestAddr1B, Channel)); - write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - } - /* 2.8.9.9.2 (7 A e) - * Compare both read patterns and flag passing ranks/lanes - */ - uint8_t result_lane_byte1; - uint8_t result_lane_byte2; - for (lane = 0; lane < 8; lane++) { - if (trained[lane] == 1) { -#if DQS_TRAIN_DEBUG > 0 - print_debug_dqs("\t\t\t\t\t\t\t\t lane already trained: ", lane, 4); -#endif - continue; - } - - result_lane_byte1 = (result_qword1 >> (lane * 8)) & 0xff; - result_lane_byte2 = (result_qword2 >> (lane * 8)) & 0xff; - if ((result_lane_byte1 == 0x55) && (result_lane_byte2 == 0xaa)) - data_test_pass_sr[rank][lane] = 1; - else - data_test_pass_sr[rank][lane] = 0; -#if DQS_TRAIN_DEBUG > 0 - print_debug_dqs_pair("\t\t\t\t\t\t\t\t ", 0x55, " | ", result_lane_byte1, 4); - print_debug_dqs_pair("\t\t\t\t\t\t\t\t ", 0xaa, " | ", result_lane_byte2, 4); -#endif - } - } - - /* 2.8.9.9.2 (7 B) - * If DIMM is dual rank, only use delays that pass testing for both ranks - */ - for (lane = 0; lane < 8; lane++) { - if (_2Ranks) { - if ((data_test_pass_sr[0][lane]) && (data_test_pass_sr[1][lane])) - data_test_pass[lane] = 1; - else - data_test_pass[lane] = 0; - } else { - data_test_pass[lane] = data_test_pass_sr[0][lane]; - } - } - - /* 2.8.9.9.2 (7 E) - * For each lane, update the DQS receiver delay setting in support of next iteration - */ - for (lane = 0; lane < 8; lane++) { - if (trained[lane] == 1) - continue; - - /* 2.8.9.9.2 (7 C a) - * Save the total delay of the first success after a failure for later use - */ - if ((data_test_pass[lane] == 1) && (data_test_pass_prev[lane] == 0)) { - candidate_total_delay[lane] = current_total_delay[lane]; - window_det_toggle[lane] = 0; - } - - /* 2.8.9.9.2 (7 C b) - * If the current delay failed testing add 1/8 UI to the current delay - */ - if (data_test_pass[lane] == 0) - current_total_delay[lane] += 0x4; - - /* 2.8.9.9.2 (7 C c) - * If the current delay passed testing alternately add either 1/32 UI or 1/4 UI to the current delay - * If 1.25 UI of delay have been added with no failures the lane is considered trained - */ - if (data_test_pass[lane] == 1) { - /* See if lane is trained */ - if ((current_total_delay[lane] - candidate_total_delay[lane]) >= 0x28) { - trained[lane] = 1; - - /* Calculate and set final lane delay value - * The final delay is the candidate delay + 7/8 UI - */ - current_total_delay[lane] = candidate_total_delay[lane] + 0x1c; - } else { - if (window_det_toggle[lane] == 0) { - current_total_delay[lane] += 0x1; - window_det_toggle[lane] = 1; - } else { - current_total_delay[lane] += 0x8; - window_det_toggle[lane] = 0; - } - } - } - } - - /* Update delays in hardware */ - write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - - /* Save previous results for comparison in the next iteration */ - for (lane = 0; lane < 8; lane++) - data_test_pass_prev[lane] = data_test_pass[lane]; - } - -#if DQS_TRAIN_DEBUG > 0 - for (lane = 0; lane < 8; lane++) - print_debug_dqs_pair("\t\tTrainRcvEn55: Lane ", lane, " current_total_delay ", current_total_delay[lane], 2); -#endif - - /* Find highest delay value and save for later use */ - for (lane = 0; lane < 8; lane++) - if (current_total_delay[lane] > CTLRMaxDelay) - CTLRMaxDelay = current_total_delay[lane]; - - /* See if any lanes failed training, and set error flags appropriately - * For all trained lanes, save delay values for later use - */ - for (lane = 0; lane < 8; lane++) { - if (trained[lane]) { - pDCTstat->CH_D_B_RCVRDLY[Channel][Receiver >> 1][lane] = current_total_delay[lane]; - } else { - printk(BIOS_WARNING, "TrainRcvrEn: WARNING: Lane %d of receiver %d on channel %d failed training!\n", lane, Receiver, Channel); - - /* Set error flags */ - pDCTstat->ErrStatus |= 1 << SB_NORCVREN; - Errors |= 1 << SB_NORCVREN; - pDCTstat->ErrCode = SC_FatalErr; - pDCTstat->CSTrainFail |= 1 << Receiver; - pDCTstat->DimmTrainFail |= 1 << (Receiver + Channel); - } - } - - /* 2.8.9.9.2 (8) - * Flush the receiver FIFO - * Write one full cache line of non-0x55/0xaa data to one of the test addresses, then read it back to flush the FIFO - */ - /* FIXME - * This does not seem to be needed, and has a tendency to lock up the - * boot process while attempting to write the test pattern. - */ - } - MaxDelay_CH[Channel] = CTLRMaxDelay; - } - - CTLRMaxDelay = MaxDelay_CH[0]; - if (MaxDelay_CH[1] > CTLRMaxDelay) - CTLRMaxDelay = MaxDelay_CH[1]; - - for (Channel = 0; Channel < 2; Channel++) { - mct_SetMaxLatency_D(pDCTstat, Channel, CTLRMaxDelay); /* program Ch A/B MaxAsyncLat to correspond with max delay */ - } - - for (Channel = 0; Channel < 2; Channel++) { - ResetDCTWrPtr_D(dev, Channel, index_reg, Addl_Index); - } - - if (_DisableDramECC) { - mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC); - } - - if (Pass == FirstPass) { - /*Disable DQSRcvrEn training mode */ - mct_DisableDQSRcvEn_D(pDCTstat); - } - - if (!_Wrap32Dis) { - msr = rdmsr(HWCR_MSR); - msr.lo &= ~(1<<17); /* restore HWCR.wrap32dis */ - wrmsr(HWCR_MSR, msr); - } - if (!_SSE2) { - cr4 = read_cr4(); - cr4 &= ~(1<<9); /* restore cr4.OSFXSR */ - write_cr4(cr4); - } - -#if DQS_TRAIN_DEBUG > 0 - { - u8 ChannelDTD; - printk(BIOS_DEBUG, "TrainRcvrEn: CH_MaxRdLat:\n"); - for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) { - printk(BIOS_DEBUG, "Channel:%x: %x\n", - ChannelDTD, pDCTstat->CH_MaxRdLat[ChannelDTD][0]); - } - } -#endif - -#if DQS_TRAIN_DEBUG > 0 - { - u16 valDTD; - u8 ChannelDTD, ReceiverDTD; - u8 i; - u16 *p; - - printk(BIOS_DEBUG, "TrainRcvrEn: CH_D_B_RCVRDLY:\n"); - for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) { - printk(BIOS_DEBUG, "Channel:%x\n", ChannelDTD); - for (ReceiverDTD = 0; ReceiverDTD < 8; ReceiverDTD+=2) { - printk(BIOS_DEBUG, "\t\tReceiver:%x:", ReceiverDTD); - p = pDCTstat->CH_D_B_RCVRDLY[ChannelDTD][ReceiverDTD>>1]; - for (i = 0; i < 8; i++) { - valDTD = p[i]; - printk(BIOS_DEBUG, " %03x", valDTD); - } - printk(BIOS_DEBUG, "\n"); - } - } - } -#endif - - printk(BIOS_DEBUG, "TrainRcvrEn: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "TrainRcvrEn: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "TrainRcvrEn: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "TrainRcvrEn: Done\n\n"); -} - -/* DQS Receiver Enable Training Pattern Generation (Family 15h) - * Algorithm detailed in: - * The Fam15h BKDG Rev. 3.14 section 2.10.5.8.2 (4) - */ -static void generate_dram_receiver_enable_training_pattern_fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t Receiver) -{ - uint32_t dword; - uint32_t dev = pDCTstat->dev_dct; - - /* 2.10.5.7.1.1 - * It appears that the DCT only supports 8-beat burst length mode, - * so do nothing here... - */ - - /* Wait for CmdSendInProg == 0 */ - do { - dword = Get_NB32_DCT(dev, dct, 0x250); - } while (dword & (0x1 << 12)); - - /* Set CmdTestEnable = 1 */ - dword = Get_NB32_DCT(dev, dct, 0x250); - dword |= (0x1 << 2); - Set_NB32_DCT(dev, dct, 0x250, dword); - - /* 2.10.5.8.6.1.1 Send Activate Command */ - dword = Get_NB32_DCT(dev, dct, 0x28c); - dword &= ~(0xff << 22); /* CmdChipSelect = Receiver */ - dword |= ((0x1 << Receiver) << 22); - dword &= ~(0x7 << 19); /* CmdBank = 0 */ - dword &= ~(0x3ffff); /* CmdAddress = 0 */ - dword |= (0x1 << 31); /* SendActCmd = 1 */ - Set_NB32_DCT(dev, dct, 0x28c, dword); - - /* Wait for SendActCmd == 0 */ - do { - dword = Get_NB32_DCT(dev, dct, 0x28c); - } while (dword & (0x1 << 31)); - - /* Wait 75 MEMCLKs. */ - precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 75); - - /* 2.10.5.8.6.1.2 */ - Set_NB32_DCT(dev, dct, 0x274, 0x0); /* DQMask = 0 */ - Set_NB32_DCT(dev, dct, 0x278, 0x0); - - dword = Get_NB32_DCT(dev, dct, 0x27c); - dword &= ~(0xff); /* EccMask = 0 */ - if (pDCTstat->DimmECCPresent == 0) - dword |= 0xff; /* EccMask = 0xff */ - Set_NB32_DCT(dev, dct, 0x27c, dword); - - /* 2.10.5.8.6.1.2 */ - dword = Get_NB32_DCT(dev, dct, 0x270); - dword &= ~(0x7ffff); /* DataPrbsSeed = 55555 */ - dword |= (0x44443); /* Use AGESA seed */ - Set_NB32_DCT(dev, dct, 0x270, dword); - - /* 2.10.5.8.2 (4) */ - dword = Get_NB32_DCT(dev, dct, 0x260); - dword &= ~(0x1fffff); /* CmdCount = 192 */ - dword |= 192; - Set_NB32_DCT(dev, dct, 0x260, dword); - - /* Configure Target A */ - dword = Get_NB32_DCT(dev, dct, 0x254); - dword &= ~(0x7 << 24); /* TgtChipSelect = Receiver */ - dword |= (Receiver & 0x7) << 24; - dword &= ~(0x7 << 21); /* TgtBank = 0 */ - dword &= ~(0x3ff); /* TgtAddress = 0 */ - Set_NB32_DCT(dev, dct, 0x254, dword); - - dword = Get_NB32_DCT(dev, dct, 0x250); - dword |= (0x1 << 3); /* ResetAllErr = 1 */ - dword &= ~(0x1 << 4); /* StopOnErr = 0 */ - dword &= ~(0x3 << 8); /* CmdTgt = 0 (Target A) */ - dword &= ~(0x7 << 5); /* CmdType = 0 (Read) */ - dword |= (0x1 << 11); /* SendCmd = 1 */ - Set_NB32_DCT(dev, dct, 0x250, dword); - - /* 2.10.5.8.6.1.2 Wait for TestStatus == 1 and CmdSendInProg == 0 */ - do { - dword = Get_NB32_DCT(dev, dct, 0x250); - } while ((dword & (0x1 << 12)) || (!(dword & (0x1 << 10)))); - - dword = Get_NB32_DCT(dev, dct, 0x250); - dword &= ~(0x1 << 11); /* SendCmd = 0 */ - Set_NB32_DCT(dev, dct, 0x250, dword); - - /* 2.10.5.8.6.1.1 Send Precharge Command */ - /* Wait 25 MEMCLKs. */ - precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 25); - - dword = Get_NB32_DCT(dev, dct, 0x28c); - dword &= ~(0xff << 22); /* CmdChipSelect = Receiver */ - dword |= ((0x1 << Receiver) << 22); - dword &= ~(0x7 << 19); /* CmdBank = 0 */ - dword &= ~(0x3ffff); /* CmdAddress = 0x400 */ - dword |= 0x400; - dword |= (0x1 << 30); /* SendPchgCmd = 1 */ - Set_NB32_DCT(dev, dct, 0x28c, dword); - - /* Wait for SendPchgCmd == 0 */ - do { - dword = Get_NB32_DCT(dev, dct, 0x28c); - } while (dword & (0x1 << 30)); - - /* Wait 25 MEMCLKs. */ - precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 25); - - /* Set CmdTestEnable = 0 */ - dword = Get_NB32_DCT(dev, dct, 0x250); - dword &= ~(0x1 << 2); - Set_NB32_DCT(dev, dct, 0x250, dword); -} - -/* DQS Receiver Enable Training (Family 15h) - * Algorithm detailed in: - * The Fam15h BKDG Rev. 3.14 section 2.10.5.8.2 - * This algorithm runs once at the lowest supported MEMCLK, - * then once again at the highest supported MEMCLK. - */ -static void dqsTrainRcvrEn_SW_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Pass) -{ - u8 Channel; - u8 _2Ranks; - u8 Addl_Index = 0; - u8 Receiver; - u8 _DisableDramECC = 0, _Wrap32Dis = 0, _SSE2 = 0; - u32 Errors; - - u32 val; - u32 dev; - u32 index_reg; - u32 ch_start, ch_end, ch; - u32 msr; - CRx_TYPE cr4; - u32 lo, hi; - - uint32_t dword; - uint8_t dimm; - uint8_t rank; - uint8_t lane; - uint8_t nibble; - uint8_t mem_clk; - uint16_t min_mem_clk; - uint16_t initial_seed; - uint8_t train_both_nibbles; - uint16_t current_total_delay[MAX_BYTE_LANES]; - uint16_t nibble0_current_total_delay[MAX_BYTE_LANES]; - uint16_t dqs_ret_pass1_total_delay[MAX_BYTE_LANES]; - uint16_t rank0_current_total_delay[MAX_BYTE_LANES]; - uint16_t phase_recovery_delays[MAX_BYTE_LANES]; - uint16_t seed[MAX_BYTE_LANES]; - uint16_t seed_gross[MAX_BYTE_LANES]; - uint16_t seed_fine[MAX_BYTE_LANES]; - uint16_t seed_pre_gross[MAX_BYTE_LANES]; - - uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE); - 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}; - - uint8_t lane_count; - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - print_debug_dqs("\nTrainRcvEn: Node", pDCTstat->Node_ID, 0); - print_debug_dqs("TrainRcvEn: Pass", Pass, 0); - - min_mem_clk = mctGet_NVbits(NV_MIN_MEMCLK); - - train_both_nibbles = 0; - if (pDCTstat->Dimmx4Present) - if (is_fam15h()) - train_both_nibbles = 1; - - dev = pDCTstat->dev_dct; - index_reg = 0x98; - ch_start = 0; - ch_end = 2; - - for (ch = ch_start; ch < ch_end; ch++) { - uint8_t max_rd_latency = 0x55; - uint8_t p_state; - - /* 2.10.5.6 */ - fam15EnableTrainingMode(pMCTstat, pDCTstat, ch, 1); - - /* 2.10.5.2 */ - for (p_state = 0; p_state < 3; p_state++) { - val = Get_NB32_DCT_NBPstate(dev, ch, p_state, 0x210); - val &= ~(0x3ff << 22); /* MaxRdLatency = max_rd_latency */ - val |= (max_rd_latency & 0x3ff) << 22; - Set_NB32_DCT_NBPstate(dev, ch, p_state, 0x210, val); - } - } - - if (Pass != FirstPass) { - pDCTstat->DimmTrainFail = 0; - pDCTstat->CSTrainFail = ~pDCTstat->CSPresent; - } - - cr4 = read_cr4(); - if (cr4 & (1 << 9)) { /* save the old value */ - _SSE2 = 1; - } - cr4 |= (1 << 9); /* OSFXSR enable SSE2 */ - write_cr4(cr4); - - msr = HWCR_MSR; - _RDMSR(msr, &lo, &hi); - /* FIXME: Why use SSEDIS */ - if (lo & (1 << 17)) { /* save the old value */ - _Wrap32Dis = 1; - } - lo |= (1 << 17); /* HWCR.wrap32dis */ - lo &= ~(1 << 15); /* SSEDIS */ - _WRMSR(msr, lo, hi); /* Setting wrap32dis allows 64-bit memory references in real mode */ - - _DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat); - - Errors = 0; - dev = pDCTstat->dev_dct; - - for (Channel = 0; Channel < 2; Channel++) { - print_debug_dqs("\tTrainRcvEn51: Node ", pDCTstat->Node_ID, 1); - print_debug_dqs("\tTrainRcvEn51: Channel ", Channel, 1); - pDCTstat->Channel = Channel; - - mem_clk = Get_NB32_DCT(dev, Channel, 0x94) & 0x1f; - - Receiver = mct_InitReceiver_D(pDCTstat, Channel); - /* There are four receiver pairs, loosely associated with chipselects. - * This is essentially looping over each DIMM. - */ - for (; Receiver < 8; Receiver += 2) { - Addl_Index = (Receiver >> 1) * 3 + 0x10; - dimm = (Receiver >> 1); - - print_debug_dqs("\t\tTrainRcvEnd52: index ", Addl_Index, 2); - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver)) { - continue; - } - - /* Retrieve the total delay values from pass 1 of DQS receiver enable training */ - if (Pass != FirstPass) { - read_dqs_receiver_enable_control_registers(dqs_ret_pass1_total_delay, dev, Channel, dimm, index_reg); - } - - /* 2.10.5.8.2 - * Loop over all ranks - */ - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver+1)) - _2Ranks = 1; - else - _2Ranks = 0; - for (rank = 0; rank < (_2Ranks + 1); rank++) { - for (nibble = 0; nibble < (train_both_nibbles + 1); nibble++) { - /* 2.10.5.8.2 (1) - * Specify the target DIMM and nibble to be trained - */ - dword = Get_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000008); - dword &= ~(0x3 << 4); /* TrDimmSel = dimm */ - dword |= ((dimm & 0x3) << 4); - dword &= ~(0x1 << 2); /* TrNibbleSel = nibble */ - dword |= ((nibble & 0x1) << 2); - Set_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000008, dword); - - /* 2.10.5.8.2 (2) - * Retrieve gross and fine timing fields from write DQS registers - */ - read_dqs_write_timing_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - - /* 2.10.5.8.2.1 - * Generate the DQS Receiver Enable Training Seed Values - */ - if (Pass == FirstPass) { - initial_seed = fam15_receiver_enable_training_seed(pDCTstat, Channel, dimm, rank, package_type); - - /* Adjust seed for the minimum platform supported frequency */ - initial_seed = (uint16_t) (((((uint64_t) initial_seed) * - fam15h_freq_tab[mem_clk] * 100) / (min_mem_clk * 100))); - - for (lane = 0; lane < lane_count; lane++) { - uint16_t wl_pass1_delay; - wl_pass1_delay = current_total_delay[lane]; - - seed[lane] = initial_seed + wl_pass1_delay; - } - } else { - uint8_t addr_prelaunch = 0; /* TODO: Fetch the correct value from RC2[0] */ - uint16_t register_delay; - int16_t seed_prescaling; - - memcpy(current_total_delay, dqs_ret_pass1_total_delay, sizeof(current_total_delay)); - if ((pDCTstat->Status & (1 << SB_Registered))) { - if (addr_prelaunch) - register_delay = 0x30; - else - register_delay = 0x20; - } else if ((pDCTstat->Status & (1 << SB_LoadReduced))) { - /* TODO - * Load reduced DIMM support unimplemented - */ - register_delay = 0x0; - } else { - register_delay = 0x0; - } - - for (lane = 0; lane < lane_count; lane++) { - seed_prescaling = current_total_delay[lane] - register_delay - 0x20; - seed[lane] = (uint16_t) (register_delay + ((((uint64_t) seed_prescaling) * fam15h_freq_tab[mem_clk] * 100) / (min_mem_clk * 100))); - } - } - - for (lane = 0; lane < lane_count; lane++) { - seed_gross[lane] = (seed[lane] >> 5) & 0x1f; - seed_fine[lane] = seed[lane] & 0x1f; - - /*if (seed_gross[lane] == 0) - seed_pre_gross[lane] = 0; - else */if (seed_gross[lane] & 0x1) - seed_pre_gross[lane] = 1; - else - seed_pre_gross[lane] = 2; - - /* Calculate phase recovery delays */ - phase_recovery_delays[lane] = ((seed_pre_gross[lane] & 0x1f) << 5) | (seed_fine[lane] & 0x1f); - - /* Set the gross delay. - * NOTE: While the BKDG states to only program DqsRcvEnGrossDelay, this appears - * to have been a misprint as DqsRcvEnFineDelay should be set to zero as well. - */ - current_total_delay[lane] = ((seed_gross[lane] & 0x1f) << 5); - } - - /* 2.10.5.8.2 (2) / 2.10.5.8.2.1 (5 6) - * Program PhRecFineDly and PhRecGrossDly - */ - write_dram_phase_recovery_control_registers(phase_recovery_delays, dev, Channel, dimm, index_reg); - - /* 2.10.5.8.2 (2) / 2.10.5.8.2.1 (7) - * Program the DQS Receiver Enable delay values for each lane - */ - write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - - /* 2.10.5.8.2 (3) - * Program DqsRcvTrEn = 1 - */ - dword = Get_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000008); - dword |= (0x1 << 13); - Set_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000008, dword); - - /* 2.10.5.8.2 (4) - * Issue 192 read requests to the target rank - */ - generate_dram_receiver_enable_training_pattern_fam15(pMCTstat, pDCTstat, Channel, Receiver + (rank & 0x1)); - - /* 2.10.5.8.2 (5) - * Program DqsRcvTrEn = 0 - */ - dword = Get_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000008); - dword &= ~(0x1 << 13); - Set_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000008, dword); - - /* 2.10.5.8.2 (6) - * Read PhRecGrossDly, PhRecFineDly - */ - read_dram_phase_recovery_control_registers(phase_recovery_delays, dev, Channel, dimm, index_reg); - - /* 2.10.5.8.2 (7) - * Calculate and program the DQS Receiver Enable delay values - */ - for (lane = 0; lane < lane_count; lane++) { - current_total_delay[lane] = (phase_recovery_delays[lane] & 0x1f); - current_total_delay[lane] |= ((seed_gross[lane] + ((phase_recovery_delays[lane] >> 5) & 0x1f) - seed_pre_gross[lane] + 1) << 5); - if (nibble == 1) { - /* 2.10.5.8.2 (1) - * Average the trained values of both nibbles on x4 DIMMs - */ - current_total_delay[lane] = (nibble0_current_total_delay[lane] + current_total_delay[lane]) / 2; - } - } - -#if DQS_TRAIN_DEBUG > 1 - for (lane = 0; lane < 8; lane++) - printk(BIOS_DEBUG, "\t\tTrainRcvEn55: Channel: %d dimm: %d nibble: %d lane %d current_total_delay: %04x CH_D_B_RCVRDLY: %04x\n", - Channel, dimm, nibble, lane, current_total_delay[lane], pDCTstat->CH_D_B_RCVRDLY[Channel][dimm][lane]); -#endif - write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - - if (nibble == 0) { - /* Back up the Nibble 0 delays for later use */ - memcpy(nibble0_current_total_delay, current_total_delay, sizeof(current_total_delay)); - } - - /* Exit nibble training if current DIMM is not x4 */ - if ((pDCTstat->Dimmx4Present & (1 << (dimm + Channel))) == 0) - break; - } - - if (_2Ranks) { - if (rank == 0) { - /* Back up the Rank 0 delays for later use */ - memcpy(rank0_current_total_delay, current_total_delay, sizeof(current_total_delay)); - } - if (rank == 1) { - /* 2.10.5.8.2 (8) - * Compute the average delay across both ranks and program the result into - * the DQS Receiver Enable delay registers - */ - for (lane = 0; lane < lane_count; lane++) { - current_total_delay[lane] = (rank0_current_total_delay[lane] + current_total_delay[lane]) / 2; - if (lane == 8) - pDCTstat->CH_D_BC_RCVRDLY[Channel][dimm] = current_total_delay[lane]; - else - pDCTstat->CH_D_B_RCVRDLY[Channel][dimm][lane] = current_total_delay[lane]; - } - write_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - } - } else { - /* Save the current delay for later use by other routines */ - for (lane = 0; lane < lane_count; lane++) { - if (lane == 8) - pDCTstat->CH_D_BC_RCVRDLY[Channel][dimm] = current_total_delay[lane]; - else - pDCTstat->CH_D_B_RCVRDLY[Channel][dimm][lane] = current_total_delay[lane]; - } - } - } - -#if DQS_TRAIN_DEBUG > 0 - for (lane = 0; lane < 8; lane++) - print_debug_dqs_pair("\t\tTrainRcvEn56: Lane ", lane, " current_total_delay ", current_total_delay[lane], 2); -#endif - } - } - - /* Calculate and program MaxRdLatency for both channels */ - Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, 0, 0); - Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, 1, 0); - - if (_DisableDramECC) { - mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC); - } - - if (Pass == FirstPass) { - /*Disable DQSRcvrEn training mode */ - mct_DisableDQSRcvEn_D(pDCTstat); - } - - if (!_Wrap32Dis) { - msr = HWCR_MSR; - _RDMSR(msr, &lo, &hi); - lo &= ~(1<<17); /* restore HWCR.wrap32dis */ - _WRMSR(msr, 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, "TrainRcvrEn: CH_MaxRdLat:\n"); - for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) { - printk(BIOS_DEBUG, "Channel:%x: %x\n", - ChannelDTD, pDCTstat->CH_MaxRdLat[ChannelDTD][0]); - } - } -#endif - -#if DQS_TRAIN_DEBUG > 0 - { - u16 valDTD; - u8 ChannelDTD, ReceiverDTD; - u8 i; - u16 *p; - - printk(BIOS_DEBUG, "TrainRcvrEn: CH_D_B_RCVRDLY:\n"); - for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) { - printk(BIOS_DEBUG, "Channel:%x\n", ChannelDTD); - for (ReceiverDTD = 0; ReceiverDTD < 8; ReceiverDTD+=2) { - printk(BIOS_DEBUG, "\t\tReceiver:%x:", ReceiverDTD); - p = pDCTstat->CH_D_B_RCVRDLY[ChannelDTD][ReceiverDTD>>1]; - for (i = 0; i < 8; i++) { - valDTD = p[i]; - printk(BIOS_DEBUG, " %03x", valDTD); - } - printk(BIOS_DEBUG, "\n"); - } - } - } -#endif - - printk(BIOS_DEBUG, "TrainRcvrEn: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "TrainRcvrEn: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "TrainRcvrEn: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "TrainRcvrEn: Done\n\n"); -} - -static void write_max_read_latency_to_registers(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct, uint16_t *latency) -{ - uint32_t dword; - uint8_t nb_pstate; - - for (nb_pstate = 0; nb_pstate < 2; nb_pstate++) { - dword = Get_NB32_DCT_NBPstate(pDCTstat->dev_dct, dct, nb_pstate, 0x210); - dword &= ~(0x3ff << 22); - dword |= ((latency[nb_pstate] & 0x3ff) << 22); - Set_NB32_DCT_NBPstate(pDCTstat->dev_dct, dct, nb_pstate, 0x210, dword); - } -} - -/* DQS MaxRdLatency Training (Family 15h) - * Algorithm detailed in: - * The Fam15h BKDG Rev. 3.14 section 2.10.5.8.5.1 - * This algorithm runs at the highest supported MEMCLK. - */ -void dqsTrainMaxRdLatency_SW_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 Channel; - u8 Receiver; - u8 _DisableDramECC = 0, _Wrap32Dis = 0, _SSE2 = 0; - u32 Errors; - - u32 dev; - u32 index_reg; - u32 ch_start, ch_end; - u32 msr; - CRx_TYPE cr4; - u32 lo, hi; - - uint32_t dword; - uint8_t dimm; - uint8_t lane; - uint8_t mem_clk; - uint32_t nb_clk; - uint8_t nb_pstate; - uint16_t current_total_delay[MAX_BYTE_LANES]; - uint16_t current_rdqs_total_delay[MAX_BYTE_LANES]; - uint8_t current_worst_case_total_delay_dimm; - uint16_t current_worst_case_total_delay_value; - - uint8_t lane_count; - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - 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}; - - print_debug_dqs("\nTrainMaxRdLatency: Node", pDCTstat->Node_ID, 0); - - dev = pDCTstat->dev_dct; - index_reg = 0x98; - ch_start = 0; - ch_end = 2; - - cr4 = read_cr4(); - if (cr4 & (1 << 9)) { /* save the old value */ - _SSE2 = 1; - } - cr4 |= (1 << 9); /* OSFXSR enable SSE2 */ - write_cr4(cr4); - - msr = HWCR_MSR; - _RDMSR(msr, &lo, &hi); - /* FIXME: Why use SSEDIS */ - if (lo & (1 << 17)) { /* save the old value */ - _Wrap32Dis = 1; - } - lo |= (1 << 17); /* HWCR.wrap32dis */ - lo &= ~(1 << 15); /* SSEDIS */ - _WRMSR(msr, lo, hi); /* Setting wrap32dis allows 64-bit memory references in real mode */ - - _DisableDramECC = mct_DisableDimmEccEn_D(pMCTstat, pDCTstat); - - Errors = 0; - dev = pDCTstat->dev_dct; - - for (Channel = 0; Channel < 2; Channel++) { - print_debug_dqs("\tTrainMaxRdLatency51: Node ", pDCTstat->Node_ID, 1); - print_debug_dqs("\tTrainMaxRdLatency51: Channel ", Channel, 1); - pDCTstat->Channel = Channel; - - if (pDCTstat->DIMMValidDCT[Channel] == 0) - continue; - - mem_clk = Get_NB32_DCT(dev, Channel, 0x94) & 0x1f; - - Receiver = mct_InitReceiver_D(pDCTstat, Channel); - - /* Find DIMM with worst case receiver enable delays */ - current_worst_case_total_delay_dimm = 0; - current_worst_case_total_delay_value = 0; - - /* There are four receiver pairs, loosely associated with chipselects. - * This is essentially looping over each DIMM. - */ - for (; Receiver < 8; Receiver += 2) { - dimm = (Receiver >> 1); - - print_debug_dqs("\t\tTrainMaxRdLatency52: Receiver ", Receiver, 2); - - if (!mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, Receiver)) { - continue; - } - - /* Retrieve the total delay values from pass 1 of DQS receiver enable training */ - read_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); - read_dqs_read_data_timing_registers(current_rdqs_total_delay, dev, Channel, dimm, index_reg); - - for (lane = 0; lane < lane_count; lane++) { - current_total_delay[lane] += current_rdqs_total_delay[lane]; - if (current_total_delay[lane] > current_worst_case_total_delay_value) { - current_worst_case_total_delay_dimm = dimm; - current_worst_case_total_delay_value = current_total_delay[lane]; - } - } - -#if DQS_TRAIN_DEBUG > 0 - for (lane = 0; lane < lane_count; lane++) - print_debug_dqs_pair("\t\tTrainMaxRdLatency56: Lane ", lane, " current_total_delay ", current_total_delay[lane], 2); -#endif - } - - /* 2.10.5.8.5.1.1 */ - Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, Channel, 1); - - /* 2.10.5.8.5.1.[2,3] - * Write the DRAM training pattern to the test address - */ - write_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, Channel, current_worst_case_total_delay_dimm << 1, 0xff, 0); - - /* 2.10.5.8.5.1.4 - * Incrementally test each MaxRdLatency candidate - */ - for (; pDCTstat->CH_MaxRdLat[Channel][0] < 0x3ff; pDCTstat->CH_MaxRdLat[Channel][0]++) { - write_max_read_latency_to_registers(pMCTstat, pDCTstat, Channel, pDCTstat->CH_MaxRdLat[Channel]); - read_dram_dqs_training_pattern_fam15(pMCTstat, pDCTstat, Channel, current_worst_case_total_delay_dimm << 1, 0xff, 0); - dword = Get_NB32_DCT(dev, Channel, 0x268) & 0x3ffff; - if (!dword) - break; - Set_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000050, 0x13131313); - } - dword = Get_NB32_DCT(dev, Channel, 0x268) & 0x3ffff; - if (dword) - printk(BIOS_ERR, "WARNING: MaxRdLatency training FAILED! Attempting to continue but your system may be unstable...\n"); - - /* 2.10.5.8.5.1.5 */ - nb_pstate = 0; - mem_clk = Get_NB32_DCT(dev, Channel, 0x94) & 0x1f; - if (fam15h_freq_tab[mem_clk] == 0) { - return; - } - dword = Get_NB32(pDCTstat->dev_nbctl, (0x160 + (nb_pstate * 4))); /* Retrieve NbDid, NbFid */ - nb_clk = (200 * (((dword >> 1) & 0x1f) + 0x4)) / (((dword >> 7) & 0x1)?2:1); - - pDCTstat->CH_MaxRdLat[Channel][0]++; - pDCTstat->CH_MaxRdLat[Channel][0] += ((((uint64_t)15 * 100000000000ULL) / ((uint64_t)fam15h_freq_tab[mem_clk] * 1000000ULL)) - * ((uint64_t)nb_clk * 1000)) / 1000000000ULL; - - write_max_read_latency_to_registers(pMCTstat, pDCTstat, Channel, pDCTstat->CH_MaxRdLat[Channel]); - } - - if (_DisableDramECC) { - mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC); - } - - if (!_Wrap32Dis) { - msr = HWCR_MSR; - _RDMSR(msr, &lo, &hi); - lo &= ~(1<<17); /* restore HWCR.wrap32dis */ - _WRMSR(msr, 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, "TrainMaxRdLatency: CH_MaxRdLat:\n"); - for (ChannelDTD = 0; ChannelDTD < 2; ChannelDTD++) { - printk(BIOS_DEBUG, "Channel:%x: %x\n", - ChannelDTD, pDCTstat->CH_MaxRdLat[ChannelDTD][0]); - } - } -#endif - - printk(BIOS_DEBUG, "TrainMaxRdLatency: Status %x\n", pDCTstat->Status); - printk(BIOS_DEBUG, "TrainMaxRdLatency: ErrStatus %x\n", pDCTstat->ErrStatus); - printk(BIOS_DEBUG, "TrainMaxRdLatency: ErrCode %x\n", pDCTstat->ErrCode); - printk(BIOS_DEBUG, "TrainMaxRdLatency: Done\n\n"); -} - -u8 mct_InitReceiver_D(struct DCTStatStruc *pDCTstat, u8 dct) -{ - if (pDCTstat->DIMMValidDCT[dct] == 0) { - return 8; - } else { - return 0; - } -} - -static void mct_DisableDQSRcvEn_D(struct DCTStatStruc *pDCTstat) -{ - u8 ch_end, ch; - u32 reg; - u32 dev; - u32 val; - - dev = pDCTstat->dev_dct; - if (pDCTstat->GangedMode) { - ch_end = 1; - } else { - ch_end = 2; - } - - for (ch = 0; ch < ch_end; ch++) { - reg = 0x78; - val = Get_NB32_DCT(dev, ch, reg); - val &= ~(1 << DqsRcvEnTrain); - Set_NB32_DCT(dev, ch, reg, val); - } -} - -/* mct_ModifyIndex_D - * Function only used once so it was inlined. - */ - -/* mct_GetInitFlag_D - * Function only used once so it was inlined. - */ - -/* Set F2x[1, 0]9C_x[2B:10] DRAM DQS Receiver Enable Timing Control Registers - * See BKDG Rev. 3.62 page 268 for more information - */ -void mct_SetRcvrEnDly_D(struct DCTStatStruc *pDCTstat, u16 RcvrEnDly, - u8 FinalValue, u8 Channel, u8 Receiver, u32 dev, - u32 index_reg, u8 Addl_Index, u8 Pass) -{ - u32 index; - u8 i; - u16 *p; - u32 val; - - if (RcvrEnDly == 0x1fe) { - /*set the boundary flag */ - pDCTstat->Status |= 1 << SB_DQSRcvLimit; - } - - /* DimmOffset not needed for CH_D_B_RCVRDLY array */ - for (i = 0; i < 8; i++) { - if (FinalValue) { - /*calculate dimm offset */ - p = pDCTstat->CH_D_B_RCVRDLY[Channel][Receiver >> 1]; - RcvrEnDly = p[i]; - } - - /* if flag = 0, set DqsRcvEn value to reg. */ - /* get the register index from table */ - index = Table_DQSRcvEn_Offset[i >> 1]; - index += Addl_Index; /* DIMMx DqsRcvEn byte0 */ - val = Get_NB32_index_wait_DCT(dev, Channel, index_reg, index); - if (i & 1) { - /* odd byte lane */ - val &= ~(0x1ff << 16); - val |= ((RcvrEnDly & 0x1ff) << 16); - } else { - /* even byte lane */ - val &= ~0x1ff; - val |= (RcvrEnDly & 0x1ff); - } - Set_NB32_index_wait_DCT(dev, Channel, index_reg, index, val); - } - -} - -/* Calculate MaxRdLatency - * Algorithm detailed in the Fam10h BKDG Rev. 3.62 section 2.8.9.9.5 - */ -static void mct_SetMaxLatency_D(struct DCTStatStruc *pDCTstat, u8 Channel, u16 DQSRcvEnDly) -{ - u32 dev; - u32 reg; - u32 SubTotal; - u32 index_reg; - u32 val; - - uint8_t cpu_val_n; - uint8_t cpu_val_p; - - u16 freq_tab[] = {400, 533, 667, 800}; - - /* Set up processor-dependent values */ - if (pDCTstat->LogicalCPUID & AMD_DR_Dx) { - /* Revision D and above */ - cpu_val_n = 4; - cpu_val_p = 29; - } else if (pDCTstat->LogicalCPUID & AMD_DR_Cx) { - /* Revision C */ - uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE); - if ((package_type == PT_L1) /* Socket F (1207) */ - || (package_type == PT_M2) /* Socket AM3 */ - || (package_type == PT_S1)) { /* Socket S1g <x> */ - cpu_val_n = 10; - cpu_val_p = 11; - } else { - cpu_val_n = 4; - cpu_val_p = 29; - } - } else { - /* Revision B and below */ - cpu_val_n = 10; - cpu_val_p = 11; - } - - if (pDCTstat->GangedMode) - Channel = 0; - - dev = pDCTstat->dev_dct; - index_reg = 0x98; - - /* 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) + 4) << 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 coarse 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; /* Retrieve gross delay portion of value */ - - /* Add "P" to the sub-total. "P" represents part of the - * processor specific constant delay value in the DRAM - * clock domain. - */ - SubTotal <<= 1; /*scale 1/2 MemClk to 1/4 MemClk */ - SubTotal += cpu_val_p; /*add "P" 1/2MemClk */ - SubTotal >>= 1; /*scale 1/4 MemClk back to 1/2 MemClk */ - - /* Convert the sub-total (in 1/2 MEMCLKs) to northbridge - * clocks (NCLKs) - */ - SubTotal *= 200 * ((Get_NB32(pDCTstat->dev_nbmisc, 0xd4) & 0x1f) + 4); - SubTotal /= freq_tab[((Get_NB32_DCT(pDCTstat->dev_dct, Channel, 0x94) & 0x7) - 3)]; - SubTotal = (SubTotal + (2 - 1)) / 2; /* Round up */ - - /* Add "N" NCLKs to the sub-total. "N" represents part of the - * processor specific constant value in the northbridge - * clock domain. - */ - SubTotal += (cpu_val_n) / 2; - - pDCTstat->CH_MaxRdLat[Channel][0] = SubTotal; - if (pDCTstat->GangedMode) { - pDCTstat->CH_MaxRdLat[1][0] = SubTotal; - } - - /* Program the F2x[1, 0]78[MaxRdLatency] register with - * the total delay value (in NCLKs). - */ - reg = 0x78; - val = Get_NB32_DCT(dev, Channel, reg); - val &= ~(0x3ff << 22); - val |= (SubTotal & 0x3ff) << 22; - - /* program MaxRdLatency to correspond with current delay */ - Set_NB32_DCT(dev, Channel, reg, val); -} - -static void mct_InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - /* Initialize the DQS Positions in preparation for - * Receiver Enable Training. - * Write Position is 1/2 Memclock Delay - * Read Position is 1/2 Memclock Delay - */ - u8 i; - for (i = 0; i < 2; i++) { - InitDQSPos4RcvrEn_D(pMCTstat, pDCTstat, i); - } -} - -static void InitDQSPos4RcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Channel) -{ - /* Initialize the DQS Positions in preparation for - * Receiver Enable Training. - * Write Position is no Delay - * Read Position is 1/2 Memclock Delay - */ - - u8 i, j; - u32 dword; - u8 dn = 4; /* TODO: Rev C could be 4 */ - u32 dev = pDCTstat->dev_dct; - u32 index_reg = 0x98; - - /* FIXME: add Cx support */ - dword = 0x00000000; - for (i = 1; i <= 3; i++) { - for (j = 0; j < dn; j++) - /* DIMM0 Write Data Timing Low */ - /* DIMM0 Write ECC Timing */ - Set_NB32_index_wait_DCT(dev, Channel, index_reg, i + 0x100 * j, dword); - } - - /* errata #180 */ - dword = 0x2f2f2f2f; - for (i = 5; i <= 6; i++) { - for (j = 0; j < dn; j++) - /* DIMM0 Read DQS Timing Control Low */ - Set_NB32_index_wait_DCT(dev, Channel, index_reg, i + 0x100 * j, dword); - } - - dword = 0x0000002f; - for (j = 0; j < dn; j++) - /* DIMM0 Read DQS ECC Timing Control */ - Set_NB32_index_wait_DCT(dev, Channel, index_reg, 7 + 0x100 * j, dword); -} - -void SetEccDQSRcvrEn_D(struct DCTStatStruc *pDCTstat, u8 Channel) -{ - u32 dev; - u32 index_reg; - u32 index; - u8 ChipSel; - u16 *p; - u32 val; - - dev = pDCTstat->dev_dct; - index_reg = 0x98; - index = 0x12; - p = pDCTstat->CH_D_BC_RCVRDLY[Channel]; - print_debug_dqs("\t\tSetEccDQSRcvrPos: Channel ", Channel, 2); - for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel += 2) { - val = p[ChipSel>>1]; - Set_NB32_index_wait_DCT(dev, Channel, index_reg, index, val); - print_debug_dqs_pair("\t\tSetEccDQSRcvrPos: ChipSel ", - ChipSel, " rcvr_delay ", val, 2); - index += 3; - } -} - -static void CalcEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 Channel) -{ - u8 ChipSel; - u16 EccDQSLike; - u8 EccDQSScale; - u32 val, val0, val1; - int16_t delay_differential; - - EccDQSLike = pDCTstat->CH_EccDQSLike[Channel]; - EccDQSScale = pDCTstat->CH_EccDQSScale[Channel]; - - for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel += 2) { - if (mct_RcvrRankEnabled_D(pMCTstat, pDCTstat, Channel, ChipSel)) { - u16 *p; - p = pDCTstat->CH_D_B_RCVRDLY[Channel][ChipSel>>1]; - - if (pDCTstat->Status & (1 << SB_Registered)) { - val0 = p[0x2]; - val1 = p[0x3]; - - delay_differential = (int16_t)val1 - (int16_t)val0; - delay_differential += (int16_t)val1; - - val = delay_differential; - } else { - /* DQS Delay Value of Data Bytelane - * most like ECC byte lane */ - val0 = p[EccDQSLike & 0x07]; - /* DQS Delay Value of Data Bytelane - * 2nd most like ECC byte lane */ - val1 = p[(EccDQSLike>>8) & 0x07]; - - if (val0 > val1) { - val = val0 - val1; - } else { - val = val1 - val0; - } - - val *= ~EccDQSScale; - val >>= 8; /* /256 */ - - if (val0 > val1) { - val -= val1; - } else { - val += val0; - } - } - - pDCTstat->CH_D_BC_RCVRDLY[Channel][ChipSel>>1] = val; - } - } - SetEccDQSRcvrEn_D(pDCTstat, Channel); -} - -/* 2.8.9.9.4 - * ECC Byte Lane Training - * DQS Receiver Enable Delay - */ -void mctSetEccDQSRcvrEn_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA) -{ - u8 Node; - u8 i; - - for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - if (!pDCTstat->NodePresent) - break; - if (pDCTstat->DCTSysLimit) { - for (i = 0; i < 2; i++) - CalcEccDQSRcvrEn_D(pMCTstat, pDCTstat, i); - } - } -} - -void phyAssistedMemFnceTraining(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, int16_t single_node_number) -{ - u8 Node = 0; - struct DCTStatStruc *pDCTstat; - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - uint8_t start_node = 0; - uint8_t end_node = MAX_NODES_SUPPORTED; - - if (single_node_number >= 0) { - start_node = single_node_number; - end_node = single_node_number + 1; - } - - /* FIXME: skip for Ax */ - for (Node = start_node; Node < end_node; Node++) { - pDCTstat = pDCTstatA + Node; - if (!pDCTstat->NodePresent) - continue; - - if (pDCTstat->DCTSysLimit) { - if (is_fam15h()) { - /* Fam15h BKDG v3.14 section 2.10.5.3.3 - * This picks up where InitDDRPhy left off - */ - uint8_t dct; - uint8_t index; - uint32_t dword; - uint32_t datc_backup; - uint32_t training_dword; - uint32_t fence2_config_dword; - uint32_t fence_tx_pad_config_dword; - uint32_t index_reg = 0x98; - uint32_t dev = pDCTstat->dev_dct; - - for (dct = 0; dct < 2; dct++) { - if (!pDCTstat->DIMMValidDCT[dct]) - continue; - - printk(BIOS_SPEW, "%s: training node %d DCT %d\n", __func__, Node, dct); - - /* Back up D18F2x9C_x0000_0004_dct[1:0] */ - datc_backup = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000004); - - /* FenceTrSel = 0x2 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000008); - dword &= ~(0x3 << 6); - dword |= (0x2 << 6); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000008, dword); - - /* Set phase recovery seed values */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000050, 0x13131313); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000051, 0x13131313); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000052, 0x00000013); - - training_dword = fenceDynTraining_D(pMCTstat, pDCTstat, dct); - - /* Save calculated fence value to the TX DLL */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c); - dword &= ~(0x1f << 26); - dword |= ((training_dword & 0x1f) << 26); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, dword); - - /* D18F2x9C_x0D0F_0[F,8:0]0F_dct[1:0][AlwaysEnDllClks]=0x1 */ - for (index = 0; index < 0x9; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f000f | (index << 8)); - dword &= ~(0x7 << 12); - dword |= (0x1 << 12); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f000f | (index << 8), dword); - } - - /* FenceTrSel = 0x1 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000008); - dword &= ~(0x3 << 6); - dword |= (0x1 << 6); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000008, dword); - - /* Set phase recovery seed values */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000050, 0x13131313); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000051, 0x13131313); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000052, 0x00000013); - - training_dword = fenceDynTraining_D(pMCTstat, pDCTstat, dct); - - /* Save calculated fence value to the RX DLL */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c); - dword &= ~(0x1f << 21); - dword |= ((training_dword & 0x1f) << 21); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, dword); - - /* D18F2x9C_x0D0F_0[F,8:0]0F_dct[1:0][AlwaysEnDllClks]=0x0 */ - for (index = 0; index < 0x9; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f000f | (index << 8)); - dword &= ~(0x7 << 12); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f000f | (index << 8), dword); - } - - /* FenceTrSel = 0x3 */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000008); - dword &= ~(0x3 << 6); - dword |= (0x3 << 6); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000008, dword); - - /* Set phase recovery seed values */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000050, 0x13131313); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000051, 0x13131313); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000052, 0x00000013); - - fence_tx_pad_config_dword = fenceDynTraining_D(pMCTstat, pDCTstat, dct); - - /* Save calculated fence value to the TX Pad */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c); - dword &= ~(0x1f << 16); - dword |= ((fence_tx_pad_config_dword & 0x1f) << 16); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, dword); - - /* Program D18F2x9C_x0D0F_[C,8,2][2:0]31_dct[1:0] */ - training_dword = fence_tx_pad_config_dword; - if (fence_tx_pad_config_dword < 16) - training_dword |= (0x1 << 4); - else - training_dword = 0; - for (index = 0; index < 0x3; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2031 | (index << 8)); - dword &= ~(0x1f); - dword |= (training_dword & 0x1f); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f2031 | (index << 8), dword); - } - for (index = 0; index < 0x3; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8031 | (index << 8)); - dword &= ~(0x1f); - dword |= (training_dword & 0x1f); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f8031 | (index << 8), dword); - } - for (index = 0; index < 0x3; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc031 | (index << 8)); - dword &= ~(0x1f); - dword |= (training_dword & 0x1f); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0fc031 | (index << 8), dword); - } - - /* Assemble Fence2 configuration word (Fam15h BKDG v3.14 page 331) */ - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c); - fence2_config_dword = 0; - - /* TxPad */ - training_dword = (dword >> 16) & 0x1f; - if (training_dword < 16) - training_dword |= 0x10; - else - training_dword = 0; - fence2_config_dword |= training_dword; - - /* RxDll */ - training_dword = (dword >> 21) & 0x1f; - if (training_dword < 16) - training_dword |= 0x10; - else - training_dword = 0; - fence2_config_dword |= (training_dword << 10); - - /* TxDll */ - training_dword = (dword >> 26) & 0x1f; - if (training_dword < 16) - training_dword |= 0x10; - else - training_dword = 0; - fence2_config_dword |= (training_dword << 5); - - /* Program D18F2x9C_x0D0F_0[F,8:0]31_dct[1:0] */ - for (index = 0; index < 0x9; index++) { - dword = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0031 | (index << 8)); - dword &= ~(0x7fff); - dword |= fence2_config_dword; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0031 | (index << 8), dword); - } - - /* Restore D18F2x9C_x0000_0004_dct[1:0] */ - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x00000004, datc_backup); - - printk(BIOS_SPEW, "%s: done training node %d DCT %d\n", __func__, Node, dct); - } - } else { - fenceDynTraining_D(pMCTstat, pDCTstat, 0); - fenceDynTraining_D(pMCTstat, pDCTstat, 1); - } - } - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -uint32_t fenceDynTraining_D(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct) -{ - u16 avRecValue; - u32 val; - u32 dev; - u32 index_reg = 0x98; - u32 index; - - dev = pDCTstat->dev_dct; - - if (is_fam15h()) { - /* Set F2x[1,0]9C_x08[PhyFenceTrEn] */ - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x08); - val |= 1 << PhyFenceTrEn; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x08, val); - - /* Wait 2000 MEMCLKs */ - precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 2000); - - /* Clear F2x[1,0]9C_x08[PhyFenceTrEn] */ - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x08); - val &= ~(1 << PhyFenceTrEn); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x08, val); - - /* BIOS reads the phase recovery engine registers - * F2x[1,0]9C_x[51:50] and F2x[1,0]9C_x52. - * Average the fine delay components only. - */ - avRecValue = 0; - for (index = 0x50; index <= 0x52; index++) { - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index); - avRecValue += val & 0x1f; - if (index != 0x52) { - avRecValue += (val >> 8) & 0x1f; - avRecValue += (val >> 16) & 0x1f; - avRecValue += (val >> 24) & 0x1f; - } - } - - val = avRecValue / 9; - if (avRecValue % 9) - val++; - avRecValue = val; - - if (avRecValue < 6) - avRecValue = 0; - else - avRecValue -= 6; - - return avRecValue; - } else { - /* BIOS first programs a seed value to the phase recovery engine - * (recommended 19) registers. - * Dram Phase Recovery Control Register (F2x[1,0]9C_x[51:50] and - * F2x[1,0]9C_x52.) . - */ - for (index = 0x50; index <= 0x52; index ++) { - val = (FenceTrnFinDlySeed & 0x1F); - if (index != 0x52) { - val |= val << 8 | val << 16 | val << 24; - } - Set_NB32_index_wait_DCT(dev, dct, index_reg, index, val); - } - - /* Set F2x[1,0]9C_x08[PhyFenceTrEn]=1. */ - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x08); - val |= 1 << PhyFenceTrEn; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x08, val); - - /* Wait 200 MEMCLKs. */ - mct_Wait(50000); /* wait 200us */ - - /* Clear F2x[1,0]9C_x08[PhyFenceTrEn]=0. */ - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x08); - val &= ~(1 << PhyFenceTrEn); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x08, val); - - /* BIOS reads the phase recovery engine registers - * F2x[1,0]9C_x[51:50] and F2x[1,0]9C_x52. */ - avRecValue = 0; - for (index = 0x50; index <= 0x52; index ++) { - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index); - avRecValue += val & 0x7F; - if (index != 0x52) { - avRecValue += (val >> 8) & 0x7F; - avRecValue += (val >> 16) & 0x7F; - avRecValue += (val >> 24) & 0x7F; - } - } - - val = avRecValue / 9; - if (avRecValue % 9) - val++; - avRecValue = val; - - /* Write the (averaged value -8) to F2x[1,0]9C_x0C[PhyFence]. */ - /* inlined mct_AdjustFenceValue() */ - /* TODO: The RBC0 is not supported. */ - /* if (pDCTstat->LogicalCPUID & AMD_RB_C0) - avRecValue -= 3; - else - */ - if (pDCTstat->LogicalCPUID & AMD_DR_Dx) - avRecValue -= 8; - else if (pDCTstat->LogicalCPUID & AMD_DR_Cx) - avRecValue -= 8; - else if (pDCTstat->LogicalCPUID & AMD_DR_Bx) - avRecValue -= 8; - - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0C); - val &= ~(0x1F << 16); - val |= (avRecValue & 0x1F) << 16; - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0C, val); - - /* Rewrite F2x[1,0]9C_x04-DRAM Address/Command Timing Control Register - * delays (both channels). - */ - val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x04); - Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x04, val); - - return avRecValue; - } -} - -void mct_Wait(u32 cycles) -{ - u32 saved; - u32 hi, lo, msr; - - /* Wait # of 50ns cycles - This seems like a hack to me... */ - - cycles <<= 3; /* x8 (number of 1.25ns ticks) */ - - msr = TSC_MSR; /* TSC */ - _RDMSR(msr, &lo, &hi); - saved = lo; - do { - _RDMSR(msr, &lo, &hi); - } while (lo - saved < cycles); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c deleted file mode 100644 index 98aadddc6c..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc1p.c +++ /dev/null @@ -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); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c deleted file mode 100644 index 8eeb93ff78..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc2p.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c b/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c deleted file mode 100644 index b6ab65e2f8..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mcttmrl.c +++ /dev/null @@ -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; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c b/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c deleted file mode 100644 index 82523e01b8..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c +++ /dev/null @@ -1,509 +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 void AgesaDelay(u32 msec) -{ - mct_Wait(msec*10); -} - -void PrepareC_MCT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - pDCTstat->C_MCTPtr->AgesaDelay = AgesaDelay; -} - -void PrepareC_DCT(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct) -{ - u8 dimm; - u16 DimmValid; - u16 Dimmx8Present; - - dct &= 1; - - pDCTstat->C_DCTPtr[dct]->DctTrain = dct; - - if (dct == 1) { - Dimmx8Present = pDCTstat->Dimmx8Present >> 1; - } else - Dimmx8Present = pDCTstat->Dimmx8Present; - Dimmx8Present &= 0x55; - - pDCTstat->C_DCTPtr[dct]->MaxDimmsInstalled = pDCTstat->MAdimms[dct]; - DimmValid = pDCTstat->DIMMValidDCT[dct]; - - pDCTstat->C_DCTPtr[dct]->NodeId = pDCTstat->Node_ID; - pDCTstat->C_DCTPtr[dct]->LogicalCPUID = pDCTstat->LogicalCPUID; - - for (dimm = 0; dimm < MAX_DIMMS; dimm++) { - if (DimmValid & (1 << (dimm << 1))) - pDCTstat->C_DCTPtr[dct]->DimmPresent[dimm] = 1; - if (Dimmx8Present & (1 << (dimm << 1))) - pDCTstat->C_DCTPtr[dct]->DimmX8Present[dimm] = 1; - } - - if (pDCTstat->GangedMode & (1 << 0)) - pDCTstat->C_DCTPtr[dct]->CurrDct = 0; - else - pDCTstat->C_DCTPtr[dct]->CurrDct = dct; - - pDCTstat->C_DCTPtr[dct]->DctCSPresent = pDCTstat->CSPresent_DCT[dct]; - if (!(pDCTstat->GangedMode & (1 << 0)) && (dct == 1)) - pDCTstat->C_DCTPtr[dct]->DctCSPresent = pDCTstat->CSPresent_DCT[0]; - - if (pDCTstat->Status & (1 << SB_Registered)) { - pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_REGISTERED] = 1; - pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_OnDimmMirror] = 0; - } else { - if (pDCTstat->MirrPresU_NumRegR > 0) - pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_OnDimmMirror] = 1; - pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_REGISTERED] = 0; - } - - if (pDCTstat->Status & (1 << SB_LoadReduced)) { - pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_LOAD_REDUCED] = 1; - } else { - pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_LOAD_REDUCED] = 0; - } - - pDCTstat->C_DCTPtr[dct]->RegMan1Present = pDCTstat->RegMan1Present; - - for (dimm = 0; dimm < MAX_TOTAL_DIMMS; dimm++) { - u8 DimmRanks; - if (DimmValid & (1 << (dimm << 1))) { - DimmRanks = 1; - if (pDCTstat->DimmDRPresent & (1 << ((dimm << 1) + dct))) - DimmRanks = 2; - else if (pDCTstat->DimmQRPresent & (1 << ((dimm << 1) + dct))) - DimmRanks = 4; - } else - DimmRanks = 0; - pDCTstat->C_DCTPtr[dct]->DimmRanks[dimm] = DimmRanks; - } -} - -void EnableZQcalibration(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) -{ - u32 val; - - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94); - val |= 1 << 11; - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, val); - - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94); - val |= 1 << 11; - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val); -} - -void DisableZQcalibration(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u32 val; - - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94); - val &= ~(1 << 11); - val &= ~(1 << 10); - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, val); - - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94); - val &= ~(1 << 11); - val &= ~(1 << 10); - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val); -} - -static void EnterSelfRefresh(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 DCT0Present, DCT1Present; - u32 val; - - DCT0Present = pDCTstat->DIMMValidDCT[0]; - if (pDCTstat->GangedMode) - DCT1Present = 0; - else - DCT1Present = pDCTstat->DIMMValidDCT[1]; - - /* Program F2x[1, 0]90[EnterSelfRefresh]=1. */ - if (DCT0Present) { - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90); - val |= 1 << EnterSelfRef; - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, val); - } - if (DCT1Present) { - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - val |= 1 << EnterSelfRef; - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, val); - } - /* Wait until the hardware resets F2x[1, 0]90[EnterSelfRefresh]=0. */ - if (DCT0Present) - do { - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90); - } while (val & (1 <<EnterSelfRef)); - if (DCT1Present) - do { - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - } while (val & (1 <<EnterSelfRef)); -} - -/* - * Change memclk for write levelization pass 2 - */ -static void ChangeMemClk(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - uint8_t DCT0Present; - uint8_t DCT1Present; - uint32_t dword; - uint32_t mask; - uint32_t offset; - - DCT0Present = pDCTstat->DIMMValidDCT[0]; - if (pDCTstat->GangedMode) - DCT1Present = 0; - else - DCT1Present = pDCTstat->DIMMValidDCT[1]; - - if (is_fam15h()) { - /* Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 0x190 */ - if (DCT0Present) { - dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006); - dword &= ~(0x0000ffff); - dword |= 0x00000190; - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006, dword); - } - if (DCT1Present) { - dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006); - dword &= ~(0x0000ffff); - dword |= 0x00000190; - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006, dword); - } - } else { - /* Program F2x[1, 0]9C[DisAutoComp]=1. */ - if (DCT0Present) { - dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8); - dword |= 1 << DisAutoComp; - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8, dword); - mct_Wait(100); /* Wait for 5us */ - } - if (DCT1Present) { - dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8); - dword |= 1 << DisAutoComp; - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8, dword); - mct_Wait(100); /* Wait for 5us */ - } - } - - /* Program F2x[1, 0]94[MemClkFreqVal] = 0. */ - if (DCT0Present) { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94); - dword &= ~(1 << MemClkFreqVal); - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword); - } - if (DCT1Present) { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94); - dword &= ~(1 << MemClkFreqVal); - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, dword); - } - - /* Program F2x[1, 0]94[MemClkFreq] to specify the target MEMCLK frequency. */ - if (is_fam15h()) { - offset = 0x0; - mask = 0x1f; - } else { - offset = 0x1; - mask = 0x7; - } - if (DCT0Present) { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94); - dword &= ~mask; - dword |= (pDCTstat->TargetFreq - offset) & mask; - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword); - } - if (DCT1Present) { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94); - dword &= ~mask; - dword |= (pDCTstat->TargetFreq - offset) & mask; - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, dword); - } - - if (is_fam15h()) { - if (DCT0Present) { - mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 0); - set_2t_configuration(pMCTstat, pDCTstat, 0); - mct_BeforePlatformSpec(pMCTstat, pDCTstat, 0); - mct_PlatformSpec(pMCTstat, pDCTstat, 0); - } - if (DCT1Present) { - mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 1); - set_2t_configuration(pMCTstat, pDCTstat, 1); - mct_BeforePlatformSpec(pMCTstat, pDCTstat, 1); - mct_PlatformSpec(pMCTstat, pDCTstat, 1); - } - } - - /* Program F2x[1, 0]94[MemClkFreqVal] = 1. */ - if (DCT0Present) { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94); - dword |= 1 << MemClkFreqVal; - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword); - } - if (DCT1Present) { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94); - dword |= 1 << MemClkFreqVal; - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, dword); - } - - /* Wait until F2x[1, 0]94[FreqChgInProg]=0. */ - if (DCT0Present) - do { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94); - } while (dword & (1 << FreqChgInProg)); - if (DCT1Present) - do { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94); - } while (dword & (1 << FreqChgInProg)); - - if (is_fam15h()) { - /* Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 0xf */ - if (DCT0Present) { - dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006); - dword &= ~(0x0000ffff); - dword |= 0x0000000f; - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006, dword); - } - if (DCT1Present) { - dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006); - dword &= ~(0x0000ffff); - dword |= 0x0000000f; - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006, dword); - } - } else { - /* Program F2x[1, 0]9C[DisAutoComp] = 0. */ - if (DCT0Present) { - dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8); - dword &= ~(1 << DisAutoComp); - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8, dword); - mct_Wait(15000); /* Wait for 750us */ - } - if (DCT1Present) { - dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8); - dword &= ~(1 << DisAutoComp); - Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8, dword); - mct_Wait(15000); /* Wait for 750us */ - } - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -/* - * the DRAM controller to bring the DRAMs out of self refresh mode. - */ -static void ExitSelfRefresh(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - u8 DCT0Present, DCT1Present; - u32 val; - - DCT0Present = pDCTstat->DIMMValidDCT[0]; - if (pDCTstat->GangedMode) - DCT1Present = 0; - else - DCT1Present = pDCTstat->DIMMValidDCT[1]; - - /* Program F2x[1, 0]90[ExitSelfRef]=1 for both DCTs. */ - if (DCT0Present) { - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90); - val |= 1 << ExitSelfRef; - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, val); - } - if (DCT1Present) { - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - val |= 1 << ExitSelfRef; - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, val); - } - /* Wait until the hardware resets F2x[1, 0]90[ExitSelfRef]=0. */ - if (DCT0Present) - do { - val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90); - } while (val & (1 << ExitSelfRef)); - if (DCT1Present) - do { - val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - } while (val & (1 << ExitSelfRef)); -} - -void SetTargetFreq(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstatA, uint8_t Node) -{ - uint32_t dword; - uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE); - - printk(BIOS_DEBUG, "%s: Start\n", __func__); - - struct DCTStatStruc *pDCTstat; - pDCTstat = pDCTstatA + Node; - - printk(BIOS_DEBUG, "%s: Node %d: New frequency code: %04x\n", __func__, Node, pDCTstat->TargetFreq); - - if (is_fam15h()) { - /* Program F2x[1, 0]90[DisDllShutDownSR]=1. */ - if (pDCTstat->DIMMValidDCT[0]) { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90); - dword |= (0x1 << 27); - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, dword); - } - if (pDCTstat->DIMMValidDCT[1]) { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - dword |= (0x1 << 27); - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, dword); - } - } - - /* Program F2x[1,0]90[EnterSelfRefresh]=1. - * Wait until the hardware resets F2x[1,0]90[EnterSelfRefresh]=0. - */ - EnterSelfRefresh(pMCTstat, pDCTstat); - - /* - * Program F2x[1,0]9C_x08[DisAutoComp]=1 - * Program F2x[1,0]94[MemClkFreqVal] = 0. - * Program F2x[1,0]94[MemClkFreq] to specify the target MEMCLK frequency. - * Program F2x[1,0]94[MemClkFreqVal] = 1. - * Wait until F2x[1,0]94[FreqChgInProg]=0. - * Program F2x[1,0]9C_x08[DisAutoComp]=0 - */ - ChangeMemClk(pMCTstat, pDCTstat); - - if (is_fam15h()) { - uint8_t dct; - for (dct = 0; dct < 2; dct++) { - if (pDCTstat->DIMMValidDCT[dct]) { - phyAssistedMemFnceTraining(pMCTstat, pDCTstatA, Node); - InitPhyCompensation(pMCTstat, pDCTstat, dct); - } - } - } - - /* Program F2x[1,0]90[ExitSelfRef]=1 for both DCTs. - * Wait until the hardware resets F2x[1, 0]90[ExitSelfRef]=0. - */ - ExitSelfRefresh(pMCTstat, pDCTstat); - - if (is_fam15h()) { - if ((package_type == PT_C3) || (package_type == PT_GR)) { - /* Socket C32 or G34 */ - /* Program F2x[1, 0]90[DisDllShutDownSR]=0. */ - if (pDCTstat->DIMMValidDCT[0]) { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90); - dword &= ~(0x1 << 27); - Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, dword); - } - if (pDCTstat->DIMMValidDCT[1]) { - dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90); - dword &= ~(0x1 << 27); - Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, dword); - } - } - } - - /* wait for 500 MCLKs after ExitSelfRef, 500*2.5ns = 1250ns */ - mct_Wait(250); - - if (pDCTstat->Status & (1 << SB_Registered)) { - u8 DCT0Present, DCT1Present; - - DCT0Present = pDCTstat->DIMMValidDCT[0]; - if (pDCTstat->GangedMode) - DCT1Present = 0; - else - DCT1Present = pDCTstat->DIMMValidDCT[1]; - - if (!DCT1Present) - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0]; - else if (pDCTstat->GangedMode) - pDCTstat->CSPresent = 0; - else - pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[1]; - - if (pDCTstat->DIMMValidDCT[0]) { - FreqChgCtrlWrd(pMCTstat, pDCTstat, 0); - } - if (pDCTstat->DIMMValidDCT[1]) { - FreqChgCtrlWrd(pMCTstat, pDCTstat, 1); - } - } - - printk(BIOS_DEBUG, "%s: Done\n", __func__); -} - -static void Modify_OnDimmMirror(struct DCTStatStruc *pDCTstat, u8 dct, u8 set) -{ - u32 val; - u32 reg = 0x44; - while (reg < 0x60) { - val = Get_NB32_DCT(pDCTstat->dev_dct, dct, reg); - if (val & (1 << CSEnable)) - set ? (val |= 1 << onDimmMirror) : (val &= ~(1<<onDimmMirror)); - Set_NB32_DCT(pDCTstat->dev_dct, dct, reg, val); - reg += 8; - } -} - -void Restore_OnDimmMirror(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - if (pDCTstat->LogicalCPUID & (AMD_DR_Bx /* | AMD_RB_C0 */)) { /* We dont support RB-C0 now */ - if (pDCTstat->MirrPresU_NumRegR & 0x55) - Modify_OnDimmMirror(pDCTstat, 0, 1); /* dct = 0, set */ - if (pDCTstat->MirrPresU_NumRegR & 0xAA) - Modify_OnDimmMirror(pDCTstat, 1, 1); /* dct = 1, set */ - } -} -void Clear_OnDimmMirror(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - if (pDCTstat->LogicalCPUID & (AMD_DR_Bx /* | AMD_RB_C0 */)) { /* We dont support RB-C0 now */ - if (pDCTstat->MirrPresU_NumRegR & 0x55) - Modify_OnDimmMirror(pDCTstat, 0, 0); /* dct = 0, clear */ - if (pDCTstat->MirrPresU_NumRegR & 0xAA) - Modify_OnDimmMirror(pDCTstat, 1, 0); /* dct = 1, clear */ - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c deleted file mode 100644 index 353aa7a1cf..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c +++ /dev/null @@ -1,1519 +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 <stdint.h> -#include <assert.h> -#include <console/console.h> -#include <northbridge/amd/amdfam10/amdfam10.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" -#include "mwlc_d.h" - -u32 swapAddrBits_wl(struct DCTStatStruc *pDCTstat, uint8_t dct, uint32_t MRSValue); -u32 swapBankBits(struct DCTStatStruc *pDCTstat, uint8_t dct, uint32_t MRSValue); -void prepareDimms(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, - u8 dct, u8 dimm, BOOL wl); -void programODT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, u8 dimm); -void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t pass, uint8_t nibble); -void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, u8 targetAddr, uint8_t pass, uint8_t lane_count); -void getWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, uint8_t pass, uint8_t nibble, uint8_t lane_count); - -#define MAX_LANE_COUNT 9 - -/*----------------------------------------------------------------------------- - * uint8_t AgesaHwWlPhase1(SPDStruct *SPDData,MCTStruct *MCTData, DCTStruct *DCTData, - * u8 Dimm, u8 Pass) - * - * Description: - * This function initialized Hardware based write levelization phase 1 - * - * Parameters: - * IN OUT *SPDData - Pointer to buffer with information about each DIMMs - * SPD information - * *MCTData - Pointer to buffer with runtime parameters, - * *DCTData - Pointer to buffer with information about each DCT - * - * IN DIMM - Logical DIMM number - * Pass - First or Second Pass - * OUT - *----------------------------------------------------------------------------- - */ -uint8_t AgesaHwWlPhase1(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, - u8 dct, u8 dimm, u8 pass) -{ - u8 ByteLane; - u32 Value, Addr; - uint8_t nibble = 0; - uint8_t train_both_nibbles; - u16 Addl_Data_Offset, Addl_Data_Port; - sMCTStruct *pMCTData = pDCTstat->C_MCTPtr; - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - uint8_t lane_count; - - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - pDCTData->WLPass = pass; - /* 1. Specify the target DIMM that is to be trained by programming - * F2x[1, 0]9C_x08[TrDimmSel]. - */ - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_ADD_DCT_PHY_CONTROL_REG, TrDimmSelStart, - TrDimmSelEnd, (u32)dimm); - - train_both_nibbles = 0; - if (pDCTstat->Dimmx4Present) - if (is_fam15h()) - train_both_nibbles = 1; - - for (nibble = 0; nibble < (train_both_nibbles + 1); nibble++) { - printk(BIOS_SPEW, "AgesaHwWlPhase1: training nibble %d\n", nibble); - - if (is_fam15h()) { - /* Program F2x[1, 0]9C_x08[WrtLvTrEn]=0 */ - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_ADD_DCT_PHY_CONTROL_REG, WrtLvTrEn, WrtLvTrEn, 0); - - /* Set TrNibbleSel */ - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_ADD_DCT_PHY_CONTROL_REG, 2, - 2, (uint32_t)nibble); - } - - /* 2. Prepare the DIMMs for write levelization using DDR3-defined - * MR commands. */ - prepareDimms(pMCTstat, pDCTstat, dct, dimm, TRUE); - - /* 3. After the DIMMs are configured, BIOS waits 40 MEMCLKs to - * satisfy DDR3-defined internal DRAM timing. - */ - if (is_fam15h()) - precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 40); - else - pMCTData->AgesaDelay(40); - - /* 4. Configure the processor's DDR phy for write levelization training: */ - procConfig(pMCTstat, pDCTstat, dct, dimm, pass, nibble); - - /* 5. Begin write levelization training: - * Program F2x[1, 0]9C_x08[WrtLvTrEn]=1. */ - if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx | AMD_FAM15_ALL)) - { - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_ADD_DCT_PHY_CONTROL_REG, WrtLvTrEn, WrtLvTrEn, 1); - } - else - { - /* Broadcast write to all D3Dbyte chipset register offset 0xc - * Set bit 0 (wrTrain) - * Program bit 4 to nibble being trained (only matters for x4dimms) - * retain value of 3:2 (Trdimmsel) - * reset bit 5 (FrzPR) - */ - if (dct) - { - Addl_Data_Offset = 0x198; - Addl_Data_Port = 0x19C; - } - else - { - Addl_Data_Offset = 0x98; - Addl_Data_Port = 0x9C; - } - Addr = 0x0D00000C; - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Offset), 31, 0, &Addr); - while ((get_Bits(pDCTData,FUN_DCT,pDCTData->NodeId, FUN_DCT, Addl_Data_Offset, - DctAccessDone, DctAccessDone)) == 0); - AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Port), 31, 0, &Value); - Value = bitTestSet(Value, 0); /* enable WL training */ - Value = bitTestReset(Value, 4); /* for x8 only */ - Value = bitTestReset(Value, 5); /* for hardware WL training */ - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Port), 31, 0, &Value); - Addr = 0x4D030F0C; - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Offset), 31, 0, &Addr); - while ((get_Bits(pDCTData,FUN_DCT,pDCTData->NodeId, FUN_DCT, Addl_Data_Offset, - DctAccessDone, DctAccessDone)) == 0); - } - - if (is_fam15h()) - proc_MFENCE(); - - /* Wait 200 MEMCLKs. If executing pass 2, wait 32 MEMCLKs. */ - if (is_fam15h()) - precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 200); - else - pMCTData->AgesaDelay(140); - - /* Program F2x[1, 0]9C_x08[WrtLevelTrEn]=0. */ - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_ADD_DCT_PHY_CONTROL_REG, WrtLvTrEn, WrtLvTrEn, 0); - - /* Read from registers F2x[1, 0]9C_x[51:50] and F2x[1, 0]9C_x52 - * to get the gross and fine delay settings - * for the target DIMM and save these values. */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - getWLByteDelay(pDCTstat, dct, ByteLane, dimm, pass, nibble, lane_count); - } - - pDCTData->WLCriticalGrossDelayPrevPass = 0x0; - - /* Exit nibble training if current DIMM is not x4 */ - if ((pDCTstat->Dimmx4Present & (1 << (dimm + dct))) == 0) - break; - } - - return 0; -} - -uint8_t AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, - uint8_t dct, uint8_t dimm, uint8_t pass) -{ - u8 ByteLane; - uint8_t status = 0; - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - uint8_t lane_count; - - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - assert(lane_count <= MAX_LANE_COUNT); - - if (is_fam15h()) { - int32_t gross_diff[MAX_LANE_COUNT]; - int32_t cgd = pDCTData->WLCriticalGrossDelayPrevPass; - uint8_t index = (uint8_t)(lane_count * dimm); - - printk(BIOS_SPEW, "\toriginal critical gross delay: %d\n", cgd); - - /* FIXME - * For now, disable CGD adjustment as it seems to interfere with registered DIMM training - */ - - /* Calculate the Critical Gross Delay */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - /* Calculate the gross delay differential for this lane */ - gross_diff[ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane] + pDCTData->WLGrossDelay[index+ByteLane]; - gross_diff[ByteLane] -= pDCTData->WLSeedPreGrossDelay[index+ByteLane]; - - /* WrDqDqsEarly values greater than 2 are reserved */ - if (gross_diff[ByteLane] < -2) - gross_diff[ByteLane] = -2; - - /* Update the Critical Gross Delay */ - if (gross_diff[ByteLane] < cgd) - cgd = gross_diff[ByteLane]; - } - - printk(BIOS_SPEW, "\tnew critical gross delay: %d\n", cgd); - - pDCTData->WLCriticalGrossDelayPrevPass = cgd; - - if (pDCTstat->Speed != pDCTstat->TargetFreq) { - /* FIXME - * Using the Pass 1 training values causes major phy training problems on - * all Family 15h processors I tested (Pass 1 values are randomly too high, - * and Pass 2 cannot lock). - * Figure out why this is and fix it, then remove the bypass code below... - */ - if (pass == FirstPass) { - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - pDCTData->WLGrossDelay[index+ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane]; - pDCTData->WLFineDelay[index+ByteLane] = pDCTData->WLSeedFineDelay[index+ByteLane]; - } - return 0; - } - } - - /* Compensate for occasional noise/instability causing sporadic training failure */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - uint8_t faulty_value_detected = 0; - uint16_t total_delay_seed = ((pDCTData->WLSeedGrossDelay[index+ByteLane] & 0x1f) << 5) | (pDCTData->WLSeedFineDelay[index+ByteLane] & 0x1f); - uint16_t total_delay_phy = ((pDCTData->WLGrossDelay[index+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[index+ByteLane] & 0x1f); - if (pass == FirstPass) { - /* Allow a somewhat higher step threshold on the first pass - * For the most part, as long as the phy isn't stepping - * several clocks at once the values are probably valid. - */ - if (abs(total_delay_phy - total_delay_seed) > 0x30) - faulty_value_detected = 1; - } else { - /* Stepping memory clocks between adjacent allowed frequencies - * should not yield large phy value differences... - */ - - if (abs(total_delay_phy - total_delay_seed) > 0x20) - faulty_value_detected = 1; - } - if (faulty_value_detected) { - printk(BIOS_INFO, "%s: overriding faulty phy value (seed: %04x phy: %04x step: %04x)\n", __func__, - total_delay_seed, total_delay_phy, abs(total_delay_phy - total_delay_seed)); - pDCTData->WLGrossDelay[index+ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane]; - pDCTData->WLFineDelay[index+ByteLane] = pDCTData->WLSeedFineDelay[index+ByteLane]; - status = 1; - } - } - } - - return status; -} - -uint8_t AgesaHwWlPhase3(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, - u8 dct, u8 dimm, u8 pass) -{ - u8 ByteLane; - sMCTStruct *pMCTData = pDCTstat->C_MCTPtr; - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - uint8_t lane_count; - - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - assert(lane_count <= MAX_LANE_COUNT); - - if (is_fam15h()) { - uint32_t dword; - int32_t gross_diff[MAX_LANE_COUNT]; - int32_t cgd = pDCTData->WLCriticalGrossDelayPrevPass; - uint8_t index = (uint8_t)(lane_count * dimm); - - /* Apply offset(s) if needed */ - if (cgd < 0) { - dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0xa8); - dword &= ~(0x3 << 24); /* WrDqDqsEarly = abs(cgd) */ - dword |= ((abs(cgd) & 0x3) << 24); - Set_NB32_DCT(pDCTstat->dev_dct, dct, 0xa8, dword); - - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - /* Calculate the gross delay differential for this lane */ - gross_diff[ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane] + pDCTData->WLGrossDelay[index+ByteLane]; - gross_diff[ByteLane] -= pDCTData->WLSeedPreGrossDelay[index+ByteLane]; - - /* Prevent underflow in the presence of noise / instability */ - if (gross_diff[ByteLane] < cgd) - gross_diff[ByteLane] = cgd; - - pDCTData->WLGrossDelay[index+ByteLane] = (gross_diff[ByteLane] + (abs(cgd) & 0x3)); - } - } else { - dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0xa8); - dword &= ~(0x3 << 24); /* WrDqDqsEarly = pDCTData->WrDqsGrossDlyBaseOffset */ - dword |= ((pDCTData->WrDqsGrossDlyBaseOffset & 0x3) << 24); - Set_NB32_DCT(pDCTstat->dev_dct, dct, 0xa8, dword); - } - } - - /* Write the adjusted gross and fine delay settings - * to the target DIMM. */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - setWLByteDelay(pDCTstat, dct, ByteLane, dimm, 1, pass, lane_count); - } - - /* 6. Configure DRAM Phy Control Register so that the phy stops driving - * write levelization ODT. */ - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_ADD_DCT_PHY_CONTROL_REG, WrLvOdtEn, WrLvOdtEn, 0); - - if (is_fam15h()) - proc_MFENCE(); - - /* Wait 10 MEMCLKs to allow for ODT signal settling. */ - if (is_fam15h()) - precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 10); - else - pMCTData->AgesaDelay(10); - - /* 7. Program the target DIMM back to normal operation by configuring - * the following (See section 2.8.5.4.1.1 - * [Phy Assisted Write Levelization] on page 97 pass 1, step #2): - * Configure all ranks of the target DIMM for normal operation. - * Enable the output drivers of all ranks of the target DIMM. - * For a two DIMM system, program the Rtt value for the target DIMM - * to the normal operating termination: - */ - prepareDimms(pMCTstat, pDCTstat, dct, dimm, FALSE); - - return 0; -} - -/*---------------------------------------------------------------------------- - * LOCAL FUNCTIONS - * - *---------------------------------------------------------------------------- - */ - -/*----------------------------------------------------------------------------- - * u32 swapAddrBits_wl(struct DCTStatStruc *pDCTstat, uint8_t dct, u32 MRSValue) - * - * Description: - * This function swaps the bits in MSR register value - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN u32: MRS value - * OUT u32: Swapped BANK BITS - * - * ---------------------------------------------------------------------------- - */ -u32 swapAddrBits_wl(struct DCTStatStruc *pDCTstat, uint8_t dct, uint32_t MRSValue) -{ - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - u32 tempW, tempW1; - - if (is_fam15h()) - tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, MrsChipSelStartFam15, MrsChipSelEndFam15); - else - tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, MrsChipSelStartFam10, MrsChipSelEndFam10); - if (tempW1 & 1) - { - if ((pDCTData->Status[DCT_STATUS_OnDimmMirror])) - { - /* swap A3/A4,A5/A6,A7/A8 */ - tempW = MRSValue; - tempW1 = MRSValue; - tempW &= 0x0A8; - tempW1 &= 0x0150; - MRSValue &= 0xFE07; - MRSValue |= (tempW << 1); - MRSValue |= (tempW1 >> 1); - } - } - return MRSValue; -} - -/*----------------------------------------------------------------------------- - * u32 swapBankBits(struct DCTStatStruc *pDCTstat, uint8_t dct, u32 MRSValue) - * - * Description: - * This function swaps the bits in MSR register value - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN u32: MRS value - * OUT u32: Swapped BANK BITS - * - * ---------------------------------------------------------------------------- - */ -u32 swapBankBits(struct DCTStatStruc *pDCTstat, uint8_t dct, u32 MRSValue) -{ - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - u32 tempW, tempW1; - - if (is_fam15h()) - tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, MrsChipSelStartFam15, MrsChipSelEndFam15); - else - tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, MrsChipSelStartFam10, MrsChipSelEndFam10); - if (tempW1 & 1) - { - if ((pDCTData->Status[DCT_STATUS_OnDimmMirror])) - { - /* swap BA0/BA1 */ - tempW = MRSValue; - tempW1 = MRSValue; - tempW &= 0x01; - tempW1 &= 0x02; - MRSValue = 0; - MRSValue |= (tempW << 1); - MRSValue |= (tempW1 >> 1); - } - } - return MRSValue; -} - -static uint16_t unbuffered_dimm_nominal_termination_emrs(uint8_t number_of_dimms, uint8_t frequency_index, uint8_t rank_count, uint8_t rank) -{ - uint16_t term; - - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - if (number_of_dimms == 1) { - if (MaxDimmsInstallable < 3) { - term = 0x04; /* Rtt_Nom = RZQ/4 = 60 Ohm */ - } else { - if (rank_count == 1) { - term = 0x04; /* Rtt_Nom = RZQ/4 = 60 Ohm */ - } else { - if (rank == 0) - term = 0x04; /* Rtt_Nom = RZQ/4 = 60 Ohm */ - else - term = 0x00; /* Rtt_Nom = OFF */ - } - } - } else { - if (frequency_index < 5) - term = 0x0044; /* Rtt_Nom = RZQ/6 = 40 Ohm */ - else - term = 0x0204; /* Rtt_Nom = RZQ/8 = 30 Ohm */ - } - - return term; -} - -static uint16_t unbuffered_dimm_dynamic_termination_emrs(uint8_t number_of_dimms, uint8_t frequency_index, uint8_t rank_count) -{ - uint16_t term; - - uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); - - if (number_of_dimms == 1) { - if (MaxDimmsInstallable < 3) { - term = 0x00; /* Rtt_WR = off */ - } else { - if (rank_count == 1) - term = 0x00; /* Rtt_WR = off */ - else - term = 0x200; /* Rtt_WR = RZQ/4 = 60 Ohm */ - } - } else { - term = 0x400; /* Rtt_WR = RZQ/2 = 120 Ohm */ - } - - return term; -} - -/*----------------------------------------------------------------------------- - * void prepareDimms(sMCTStruct *pMCTData, sDCTStruct *DCTData, u8 Dimm, BOOL WL) - * - * Description: - * This function prepares DIMMS for training - * Fam10h: BKDG Rev. 3.62 section 2.8.9.9.1 - * Fam15h: BKDG Rev. 3.14 section 2.10.5.8.1 - * ---------------------------------------------------------------------------- - */ -void prepareDimms(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, - u8 dct, u8 dimm, BOOL wl) -{ - u32 tempW, tempW1, tempW2, MrsBank; - u8 rank, currDimm, MemClkFreq; - sMCTStruct *pMCTData = pDCTstat->C_MCTPtr; - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE); - uint8_t number_of_dimms = pDCTData->MaxDimmsInstalled; - - if (is_fam15h()) { - MemClkFreq = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_CONFIG_HIGH, 0, 4); - } else { - MemClkFreq = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_CONFIG_HIGH, 0, 2); - } - /* Configure the DCT to send initialization MR commands to the target DIMM - * by programming the F2x[1,0]7C register using the following steps. - */ - rank = 0; - while ((rank < pDCTData->DimmRanks[dimm]) && (rank < 2)) - { - /* Program F2x[1, 0]7C[MrsChipSel[2:0]] for the current rank to be trained. */ - if (is_fam15h()) - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsChipSelStartFam15, MrsChipSelEndFam15, dimm*2+rank); - else - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsChipSelStartFam10, MrsChipSelEndFam10, dimm*2+rank); - - /* Program F2x[1, 0]7C[MrsBank[2:0]] for the appropriate internal DRAM - * register that defines the required DDR3-defined function for write - * levelization. - */ - MrsBank = swapBankBits(pDCTstat, dct, 1); - if (is_fam15h()) - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsBankStartFam15, MrsBankEndFam15, MrsBank); - else - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsBankStartFam10, MrsBankEndFam10, MrsBank); - - /* Program F2x[1, 0]7C[MrsAddress[15:0]] to the required DDR3-defined function - * for write levelization. - */ - tempW = 0;/* DLL_DIS = 0, DIC = 0, AL = 0, TDQS = 0 */ - - /* Retrieve normal settings of the MRS control word and clear Rtt_Nom */ - if (is_fam15h()) { - tempW = mct_MR1(pMCTstat, pDCTstat, dct, dimm*2+rank) & 0xffff; - tempW &= ~(0x0244); - } else { - /* Set TDQS = 1b for x8 DIMM, TDQS = 0b for x4 DIMM, when mixed x8 & x4 */ - tempW2 = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_CONFIG_HIGH, RDqsEn, RDqsEn); - if (tempW2) - { - if (pDCTData->DimmX8Present[dimm]) - tempW |= 0x800; - } - } - - /* determine Rtt_Nom for WL & Normal mode */ - if (is_fam15h()) { - if (wl) { - if (number_of_dimms > 1) { - if (rank == 0) { - /* Get Rtt_WR for the current DIMM and rank */ - tempW2 = fam15_rttwr(pDCTstat, dct, dimm, rank, package_type); - } else { - tempW2 = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type); - } - } else { - tempW2 = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type); - } - } else { - tempW2 = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type); - } - tempW1 = 0; - tempW1 |= ((tempW2 & 0x4) >> 2) << 9; - tempW1 |= ((tempW2 & 0x2) >> 1) << 6; - tempW1 |= ((tempW2 & 0x1) >> 0) << 2; - } else { - if (pDCTData->Status[DCT_STATUS_REGISTERED]) { - tempW1 = RttNomTargetRegDimm(pMCTData, pDCTData, dimm, wl, MemClkFreq, rank); - } else { - if (wl) { - if (number_of_dimms > 1) { - if (rank == 0) { - /* Get Rtt_WR for the current DIMM and rank */ - uint16_t dynamic_term = unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm]); - - /* Convert dynamic termination code to corresponding nominal termination code */ - if (dynamic_term == 0x200) - tempW1 = 0x04; - else if (dynamic_term == 0x400) - tempW1 = 0x40; - else - tempW1 = 0x0; - } else { - tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank); - } - } else { - tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank); - } - } else { - tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank); - } - } - } - - /* Apply Rtt_Nom to the MRS control word */ - tempW = tempW|tempW1; - - /* All ranks of the target DIMM are set to write levelization mode. */ - if (wl) - { - tempW1 = bitTestSet(tempW, MRS_Level); - if (rank == 0) - { - /* Enable the output driver of the first rank of the target DIMM. */ - tempW = tempW1; - } - else - { - /* Disable the output drivers of all other ranks for - * the target DIMM. - */ - tempW = bitTestSet(tempW1, Qoff); - } - } - - /* Program MrsAddress[5,1]=output driver impedance control (DIC) */ - if (is_fam15h()) { - tempW1 = fam15_dimm_dic(pDCTstat, dct, dimm, rank, package_type); - } else { - /* Read DIC from F2x[1,0]84[DrvImpCtrl] */ - tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_MRS_REGISTER, DrvImpCtrlStart, DrvImpCtrlEnd); - } - - /* Apply DIC to the MRS control word */ - if (bitTest(tempW1, 1)) - tempW = bitTestSet(tempW, 5); - if (bitTest(tempW1, 0)) - tempW = bitTestSet(tempW, 1); - - tempW = swapAddrBits_wl(pDCTstat, dct, tempW); - - if (is_fam15h()) - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsAddressStartFam15, MrsAddressEndFam15, tempW); - else - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsAddressStartFam10, MrsAddressEndFam10, tempW); - - /* Program F2x[1, 0]7C[SendMrsCmd]=1 to initiate the command to - * the specified DIMM. - */ - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, SendMrsCmd, SendMrsCmd, 1); - /* Wait for F2x[1, 0]7C[SendMrsCmd] to be cleared by hardware. */ - while ((get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, SendMrsCmd, SendMrsCmd)) == 0x1) - { - } - - /* Program F2x[1, 0]7C[MrsBank[2:0]] for the appropriate internal DRAM - * register that defines the required DDR3-defined function for Rtt_WR. - */ - MrsBank = swapBankBits(pDCTstat, dct, 2); - if (is_fam15h()) - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsBankStartFam15, MrsBankEndFam15, MrsBank); - else - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsBankStartFam10, MrsBankEndFam10, MrsBank); - - /* Program F2x[1, 0]7C[MrsAddress[15:0]] to the required DDR3-defined function - * for Rtt_WR (DRAMTermDyn). - */ - tempW = 0;/* PASR = 0,*/ - - /* Retrieve normal settings of the MRS control word and clear Rtt_WR */ - if (is_fam15h()) { - tempW = mct_MR2(pMCTstat, pDCTstat, dct, dimm*2+rank) & 0xffff; - tempW &= ~(0x0600); - } else { - /* program MrsAddress[7,6,5:3]=SRT,ASR,CWL, - * based on F2x[1,0]84[19,18,22:20]=,SRT,ASR,Tcwl */ - tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_MRS_REGISTER, PCI_MIN_LOW, PCI_MAX_HIGH); - if (bitTest(tempW1,19)) - {tempW = bitTestSet(tempW, 7);} - if (bitTest(tempW1,18)) - {tempW = bitTestSet(tempW, 6);} - /* tempW = tempW|(((tempW1 >> 20) & 0x7)<< 3); */ - tempW = tempW|((tempW1&0x00700000) >> 17); - /* workaround for DR-B0 */ - if ((pDCTData->LogicalCPUID & AMD_DR_Bx) && (pDCTData->Status[DCT_STATUS_REGISTERED])) - tempW+=0x8; - } - - /* determine Rtt_WR for WL & Normal mode */ - if (is_fam15h()) { - tempW1 = (fam15_rttwr(pDCTstat, dct, dimm, rank, package_type) << 9); - } else { - if (pDCTData->Status[DCT_STATUS_REGISTERED]) - tempW1 = RttWrRegDimm(pMCTData, pDCTData, dimm, wl, MemClkFreq, rank); - else - tempW1 = unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm]); - } - - /* Apply Rtt_WR to the MRS control word */ - tempW = tempW|tempW1; - tempW = swapAddrBits_wl(pDCTstat, dct, tempW); - if (is_fam15h()) - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsAddressStartFam15, MrsAddressEndFam15, tempW); - else - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsAddressStartFam10, MrsAddressEndFam10, tempW); - - /* Program F2x[1, 0]7C[SendMrsCmd]=1 to initiate the command to - the specified DIMM.*/ - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, SendMrsCmd, SendMrsCmd, 1); - - /* Wait for F2x[1, 0]7C[SendMrsCmd] to be cleared by hardware. */ - while ((get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, SendMrsCmd, SendMrsCmd)) == 0x1) - { - } - - rank++; - } - - /* Configure the non-target DIMM normally. */ - currDimm = 0; - while (currDimm < MAX_LDIMMS) - { - if (pDCTData->DimmPresent[currDimm]) - { - if (currDimm != dimm) - { - rank = 0; - while ((rank < pDCTData->DimmRanks[currDimm]) && (rank < 2)) - { - /* Program F2x[1, 0]7C[MrsChipSel[2:0]] for the current rank - * to be trained. - */ - if (is_fam15h()) - set_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, MrsChipSelStartFam15, MrsChipSelEndFam15, currDimm*2+rank); - else - set_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, MrsChipSelStartFam10, MrsChipSelEndFam10, currDimm*2+rank); - - /* Program F2x[1, 0]7C[MrsBank[2:0]] for the appropriate internal - * DRAM register that defines the required DDR3-defined function - * for write levelization. - */ - MrsBank = swapBankBits(pDCTstat, dct, 1); - if (is_fam15h()) - set_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, MrsBankStartFam15, MrsBankEndFam15, MrsBank); - else - set_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, MrsBankStartFam10, MrsBankEndFam10, MrsBank); - - /* Program F2x[1, 0]7C[MrsAddress[15:0]] to the required - * DDR3-defined function for write levelization. - */ - tempW = 0;/* DLL_DIS = 0, DIC = 0, AL = 0, TDQS = 0, Level = 0, Qoff = 0 */ - - /* Retrieve normal settings of the MRS control word and clear Rtt_Nom */ - if (is_fam15h()) { - tempW = mct_MR1(pMCTstat, pDCTstat, dct, currDimm*2+rank) & 0xffff; - tempW &= ~(0x0244); - } else { - /* Set TDQS = 1b for x8 DIMM, TDQS = 0b for x4 DIMM, when mixed x8 & x4 */ - tempW2 = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_CONFIG_HIGH, RDqsEn, RDqsEn); - if (tempW2) - { - if (pDCTData->DimmX8Present[currDimm]) - tempW |= 0x800; - } - } - - /* determine Rtt_Nom for WL & Normal mode */ - if (is_fam15h()) { - tempW2 = fam15_rttnom(pDCTstat, dct, dimm, rank, package_type); - tempW1 = 0; - tempW1 |= ((tempW2 & 0x4) >> 2) << 9; - tempW1 |= ((tempW2 & 0x2) >> 1) << 6; - tempW1 |= ((tempW2 & 0x1) >> 0) << 2; - } else { - if (pDCTData->Status[DCT_STATUS_REGISTERED]) - tempW1 = RttNomNonTargetRegDimm(pMCTData, pDCTData, currDimm, wl, MemClkFreq, rank); - else - tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[currDimm], rank); - } - - /* Apply Rtt_Nom to the MRS control word */ - tempW = tempW|tempW1; - - /* Program MrsAddress[5,1]=output driver impedance control (DIC) */ - if (is_fam15h()) { - tempW1 = fam15_dimm_dic(pDCTstat, dct, dimm, rank, package_type); - } else { - /* Read DIC from F2x[1,0]84[DrvImpCtrl] */ - tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_MRS_REGISTER, DrvImpCtrlStart, DrvImpCtrlEnd); - } - - /* Apply DIC to the MRS control word */ - if (bitTest(tempW1,1)) - {tempW = bitTestSet(tempW, 5);} - if (bitTest(tempW1,0)) - {tempW = bitTestSet(tempW, 1);} - - tempW = swapAddrBits_wl(pDCTstat, dct, tempW); - - if (is_fam15h()) - set_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, MrsAddressStartFam15, MrsAddressEndFam15, tempW); - else - set_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, MrsAddressStartFam10, MrsAddressEndFam10, tempW); - - /* Program F2x[1, 0]7C[SendMrsCmd]=1 to initiate the command - * to the specified DIMM. - */ - set_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, SendMrsCmd, SendMrsCmd, 1); - - /* Wait for F2x[1, 0]7C[SendMrsCmd] to be cleared by hardware. */ - while ((get_Bits(pDCTData, dct, - pDCTData->NodeId, FUN_DCT, DRAM_INIT, - SendMrsCmd, SendMrsCmd)) == 1); - - /* Program F2x[1, 0]7C[MrsBank[2:0]] for the appropriate internal DRAM - * register that defines the required DDR3-defined function for Rtt_WR. - */ - MrsBank = swapBankBits(pDCTstat, dct, 2); - if (is_fam15h()) - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsBankStartFam15, MrsBankEndFam15, MrsBank); - else - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsBankStartFam10, MrsBankEndFam10, MrsBank); - - /* Program F2x[1, 0]7C[MrsAddress[15:0]] to the required DDR3-defined function - * for Rtt_WR (DRAMTermDyn). - */ - tempW = 0;/* PASR = 0,*/ - - /* Retrieve normal settings of the MRS control word and clear Rtt_WR */ - if (is_fam15h()) { - tempW = mct_MR2(pMCTstat, pDCTstat, dct, currDimm*2+rank) & 0xffff; - tempW &= ~(0x0600); - } else { - /* program MrsAddress[7,6,5:3]=SRT,ASR,CWL, - * based on F2x[1,0]84[19,18,22:20]=,SRT,ASR,Tcwl */ - tempW1 = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_MRS_REGISTER, PCI_MIN_LOW, PCI_MAX_HIGH); - if (bitTest(tempW1,19)) - {tempW = bitTestSet(tempW, 7);} - if (bitTest(tempW1,18)) - {tempW = bitTestSet(tempW, 6);} - /* tempW = tempW|(((tempW1 >> 20) & 0x7) << 3); */ - tempW = tempW|((tempW1&0x00700000) >> 17); - /* workaround for DR-B0 */ - if ((pDCTData->LogicalCPUID & AMD_DR_Bx) && (pDCTData->Status[DCT_STATUS_REGISTERED])) - tempW+=0x8; - } - - /* determine Rtt_WR for WL & Normal mode */ - if (is_fam15h()) { - tempW1 = (fam15_rttwr(pDCTstat, dct, dimm, rank, package_type) << 9); - } else { - if (pDCTData->Status[DCT_STATUS_REGISTERED]) - tempW1 = RttWrRegDimm(pMCTData, pDCTData, currDimm, wl, MemClkFreq, rank); - else - tempW1 = unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[currDimm]); - } - - /* Apply Rtt_WR to the MRS control word */ - tempW = tempW|tempW1; - tempW = swapAddrBits_wl(pDCTstat, dct, tempW); - if (is_fam15h()) - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsAddressStartFam15, MrsAddressEndFam15, tempW); - else - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, MrsAddressStartFam10, MrsAddressEndFam10, tempW); - - /* Program F2x[1, 0]7C[SendMrsCmd]=1 to initiate the command to - the specified DIMM.*/ - set_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_INIT, SendMrsCmd, SendMrsCmd, 1); - - /* Wait for F2x[1, 0]7C[SendMrsCmd] to be cleared by hardware. */ - while ((get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_INIT, SendMrsCmd, SendMrsCmd)) == 0x1) - { - } - rank++; - } - } - } - currDimm++; - } -} - -/*----------------------------------------------------------------------------- - * void programODT(sMCTStruct *pMCTData, DCTStruct *DCTData, u8 dimm) - * - * Description: - * This function programs the ODT values for the NB - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN - * OUT - * ---------------------------------------------------------------------------- - */ -void programODT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm) -{ - sMCTStruct *pMCTData = pDCTstat->C_MCTPtr; - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - - u8 WrLvOdt1 = 0; - - if (is_fam15h()) { - /* On Family15h processors, the value for the specific CS being targeted - * is taken from F2x238 / F2x23C as appropriate, then loaded into F2x9C_x0000_0008 - */ - - /* Convert DIMM number to CS */ - uint32_t dword; - uint8_t cs; - uint8_t rank = 0; - - cs = (dimm * 2) + rank; - - /* Fetch preprogammed ODT pattern from configuration registers */ - dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, ((cs > 3)?0x23c:0x238)); - if ((cs == 7) || (cs == 3)) - WrLvOdt1 = ((dword >> 24) & 0xf); - else if ((cs == 6) || (cs == 2)) - WrLvOdt1 = ((dword >> 16) & 0xf); - else if ((cs == 5) || (cs == 1)) - WrLvOdt1 = ((dword >> 8) & 0xf); - else if ((cs == 4) || (cs == 0)) - WrLvOdt1 = (dword & 0xf); - } else { - if (pDCTData->Status[DCT_STATUS_REGISTERED]) { - WrLvOdt1 = WrLvOdtRegDimm(pMCTData, pDCTData, dimm); - } else { - if ((pDCTData->DctCSPresent & 0x05) == 0x05) { - WrLvOdt1 = 0x03; - } else if (bitTest((u32)pDCTData->DctCSPresent,(u8)(dimm*2+1))) { - WrLvOdt1 = (u8)bitTestSet(WrLvOdt1, dimm+2); - } else { - WrLvOdt1 = (u8)bitTestSet(WrLvOdt1, dimm); - } - } - } - - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_ADD_DCT_PHY_CONTROL_REG, 8, 11, (u32)WrLvOdt1); - - printk(BIOS_SPEW, "Programmed DCT %d write levelling ODT pattern %08x from DIMM %d data\n", dct, WrLvOdt1, dimm); - -} - -#ifdef UNUSED_CODE -static uint16_t fam15h_next_lowest_memclk_freq(uint16_t memclk_freq) -{ - uint16_t fam15h_next_lowest_freq_tab[] = {0, 0, 0, 0, 0x4, 0, 0x4, 0, 0, 0, 0x6, 0, 0, 0, 0xa, 0, 0, 0, 0xe, 0, 0, 0, 0x12}; - return fam15h_next_lowest_freq_tab[memclk_freq]; -} -#endif - -/*----------------------------------------------------------------------------- - * void procConfig(MCTStruct *MCTData,DCTStruct *DCTData, u8 Dimm, u8 Pass, u8 Nibble) - * - * Description: - * This function programs the ODT values for the NB - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * *MCTData - Pointer to buffer with runtime parameters, - * IN Dimm - Logical DIMM - * Pass - First of Second Pass - * OUT - * ---------------------------------------------------------------------------- - */ -void procConfig(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm, uint8_t pass, uint8_t nibble) -{ - u8 ByteLane, MemClkFreq; - int32_t Seed_Gross; - int32_t Seed_Fine; - uint8_t Seed_PreGross; - u32 Value, Addr; - uint32_t dword; - u16 Addl_Data_Offset, Addl_Data_Port; - sMCTStruct *pMCTData = pDCTstat->C_MCTPtr; - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - 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}; - uint8_t lane_count; - - lane_count = get_available_lane_count(pMCTstat, pDCTstat); - - assert(lane_count <= MAX_LANE_COUNT); - - if (is_fam15h()) { - /* MemClkFreq: 0x4: 333MHz; 0x6: 400MHz; 0xa: 533MHz; 0xe: 667MHz; 0x12: 800MHz; 0x16: 933MHz */ - MemClkFreq = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_CONFIG_HIGH, 0, 4); - } else { - /* MemClkFreq: 3: 400MHz; 4: 533MHz; 5: 667MHz; 6: 800MHz */ - MemClkFreq = get_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, DRAM_CONFIG_HIGH, 0, 2); - } - - /* Program F2x[1, 0]9C_x08[WrLvOdt[3:0]] to the proper ODT settings for the - * current memory subsystem configuration. - */ - programODT(pMCTstat, pDCTstat, dct, dimm); - - /* Program F2x[1,0]9C_x08[WrLvOdtEn]=1 */ - if (pDCTData->LogicalCPUID & (AMD_DR_Cx | AMD_DR_Dx | AMD_FAM15_ALL)) { - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_ADD_DCT_PHY_CONTROL_REG, WrLvOdtEn, WrLvOdtEn, (u32)1); - } - else - { - /* Program WrLvOdtEn = 1 through set bit 12 of D3CSODT reg offset 0 for Rev.B */ - if (dct) - { - Addl_Data_Offset = 0x198; - Addl_Data_Port = 0x19C; - } - else - { - Addl_Data_Offset = 0x98; - Addl_Data_Port = 0x9C; - } - Addr = 0x0D008000; - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Offset), 31, 0, &Addr); - while ((get_Bits(pDCTData,FUN_DCT,pDCTData->NodeId, FUN_DCT, Addl_Data_Offset, - DctAccessDone, DctAccessDone)) == 0); - AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Port), 31, 0, &Value); - Value = bitTestSet(Value, 12); - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Port), 31, 0, &Value); - Addr = 0x4D088F00; - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+(pDCTData->NodeId),FUN_DCT,Addl_Data_Offset), 31, 0, &Addr); - while ((get_Bits(pDCTData,FUN_DCT,pDCTData->NodeId, FUN_DCT, Addl_Data_Offset, - DctAccessDone, DctAccessDone)) == 0); - } - - if (is_fam15h()) - proc_MFENCE(); - - /* Wait 10 MEMCLKs to allow for ODT signal settling. */ - if (is_fam15h()) - precise_memclk_delay_fam15(pMCTstat, pDCTstat, dct, 10); - else - pMCTData->AgesaDelay(10); - - /* Program write levelling seed values */ - if (pass == 1) - { - /* Pass 1 */ - if (is_fam15h()) { - uint8_t AddrCmdPrelaunch = 0; /* TODO: Fetch the correct value from RC2[0] */ - uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE); - uint16_t Seed_Total = 0; - pDCTData->WrDqsGrossDlyBaseOffset = 0x0; - if (package_type == PT_GR) { - /* Socket G34: Fam15h BKDG v3.14 Table 96 */ - if (pDCTData->Status[DCT_STATUS_REGISTERED]) { - /* TODO - * Implement mainboard-specific seed and - * WrDqsGrossDly base overrides. - * 0x41 and 0x0 are the "stock" values - */ - Seed_Total = 0x41; - pDCTData->WrDqsGrossDlyBaseOffset = 0x2; - } else if (pDCTData->Status[DCT_STATUS_LOAD_REDUCED]) { - Seed_Total = 0x0; - } else { - Seed_Total = 0xf; - } - } else if (package_type == PT_C3) { - /* Socket C32: Fam15h BKDG v3.14 Table 97 */ - if (pDCTData->Status[DCT_STATUS_REGISTERED]) { - Seed_Total = 0x3e; - } else if (pDCTData->Status[DCT_STATUS_LOAD_REDUCED]) { - Seed_Total = 0x0; - } else { - Seed_Total = 0x12; - } - } else if (package_type == PT_M2) { - /* Socket AM3: Fam15h BKDG v3.14 Table 98 */ - Seed_Total = 0xf; - } else if (package_type == PT_FM2) { - /* Socket FM2: Fam15h M10 BKDG 3.12 Table 42 */ - Seed_Total = 0x15; - } - if (pDCTData->Status[DCT_STATUS_REGISTERED]) - Seed_Total += ((AddrCmdPrelaunch)?0x10:0x0); - - /* Adjust seed for the minimum platform supported frequency */ - Seed_Total = (int32_t) (((((int64_t) Seed_Total) * - fam15h_freq_tab[MemClkFreq] * 100) / (mctGet_NVbits(NV_MIN_MEMCLK) * 100))); - - Seed_Gross = (Seed_Total >> 5) & 0x1f; - Seed_Fine = Seed_Total & 0x1f; - - /* Save seed values for later use */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - pDCTData->WLSeedGrossDelay[lane_count*dimm+ByteLane] = Seed_Gross; - pDCTData->WLSeedFineDelay[lane_count*dimm+ByteLane] = Seed_Fine; - - if (Seed_Gross == 0) - Seed_PreGross = 0; - else if (Seed_Gross & 0x1) - Seed_PreGross = 1; - else - Seed_PreGross = 2; - - pDCTData->WLSeedPreGrossDelay[lane_count*dimm+ByteLane] = Seed_PreGross; - } - } else { - if (pDCTData->Status[DCT_STATUS_REGISTERED]) { - uint8_t AddrCmdPrelaunch = 0; /* TODO: Fetch the correct value from RC2[0] */ - - /* The seed values below assume Pass 1 utilizes a 400MHz clock frequency (DDR3-800) */ - if (AddrCmdPrelaunch == 0) { - Seed_Gross = 0x02; - Seed_Fine = 0x01; - } else { - Seed_Gross = 0x02; - Seed_Fine = 0x11; - } - } else { - if (MemClkFreq == 6) { - /* DDR-800 */ - Seed_Gross = 0x00; - Seed_Fine = 0x1a; - } else { - /* Use settings for DDR-400 (interpolated from BKDG) */ - Seed_Gross = 0x00; - Seed_Fine = 0x0d; - } - } - } - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) - { - /* Program an initialization value to registers F2x[1, 0]9C_x[51:50] and - * F2x[1, 0]9C_x52 to set the gross and fine delay for all the byte lane fields - * If the target frequency is different than 400MHz, BIOS must - * execute two training passes for each DIMM. - * For pass 1 at a 400MHz MEMCLK frequency, use an initial total delay value - * of 01Fh. This represents a 1UI (UI=.5MEMCLK) delay and is determined - * by design. - */ - pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] = Seed_Gross; - pDCTData->WLFineDelay[lane_count*dimm+ByteLane] = Seed_Fine; - printk(BIOS_SPEW, "\tLane %02x initial seed: %04x\n", ByteLane, ((Seed_Gross & 0x1f) << 5) | (Seed_Fine & 0x1f)); - } - } else { - if (nibble == 0) { - /* Pass 2 */ - /* From BKDG, Write Leveling Seed Value. */ - if (is_fam15h()) { - uint32_t RegisterDelay; - int32_t SeedTotal[MAX_LANE_COUNT]; - int32_t SeedTotalPreScaling[MAX_LANE_COUNT]; - uint32_t WrDqDqsEarly; - uint8_t AddrCmdPrelaunch = 0; /* TODO: Fetch the correct value from RC2[0] */ - - if (pDCTData->Status[DCT_STATUS_REGISTERED]) { - if (AddrCmdPrelaunch) - RegisterDelay = 0x30; - else - RegisterDelay = 0x20; - } else { - RegisterDelay = 0; - } - - /* Retrieve WrDqDqsEarly */ - dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0xa8); - WrDqDqsEarly = (dword >> 24) & 0x3; - - /* FIXME - * Ignore WrDqDqsEarly for now to work around training issues - */ - WrDqDqsEarly = 0; - - /* Generate new seed values */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - /* Calculate adjusted seed values */ - SeedTotal[ByteLane] = (pDCTData->WLFineDelayPrevPass[lane_count*dimm+ByteLane] & 0x1f) | - ((pDCTData->WLGrossDelayPrevPass[lane_count*dimm+ByteLane] & 0x1f) << 5); - SeedTotalPreScaling[ByteLane] = (SeedTotal[ByteLane] - RegisterDelay - (0x20 * WrDqDqsEarly)); - SeedTotal[ByteLane] = (int32_t) (RegisterDelay + ((((int64_t) SeedTotalPreScaling[ByteLane]) * - fam15h_freq_tab[MemClkFreq] * 100) / (fam15h_freq_tab[pDCTData->WLPrevMemclkFreq[dimm]] * 100))); - } - - /* Generate register values from seeds */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - printk(BIOS_SPEW, "\tLane %02x scaled delay: %04x\n", ByteLane, SeedTotal[ByteLane]); - - if (SeedTotal[ByteLane] >= 0) { - Seed_Gross = SeedTotal[ByteLane] / 32; - Seed_Fine = SeedTotal[ByteLane] % 32; - } else { - Seed_Gross = (SeedTotal[ByteLane] / 32) - 1; - Seed_Fine = (SeedTotal[ByteLane] % 32) + 32; - } - - /* The BKDG-recommended algorithm causes problems with registered DIMMs on some systems - * due to the long register delays causing premature total delay wrap-around. - * Attempt to work around this... - */ - Seed_PreGross = Seed_Gross; - - /* Save seed values for later use */ - pDCTData->WLSeedGrossDelay[lane_count*dimm+ByteLane] = Seed_Gross; - pDCTData->WLSeedFineDelay[lane_count*dimm+ByteLane] = Seed_Fine; - pDCTData->WLSeedPreGrossDelay[lane_count*dimm+ByteLane] = Seed_PreGross; - - pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] = Seed_PreGross; - pDCTData->WLFineDelay[lane_count*dimm+ByteLane] = Seed_Fine; - - printk(BIOS_SPEW, "\tLane %02x new seed: %04x\n", ByteLane, ((pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[lane_count*dimm+ByteLane] & 0x1f)); - } - } else { - uint32_t RegisterDelay; - uint32_t SeedTotalPreScaling; - uint32_t SeedTotal; - uint8_t AddrCmdPrelaunch = 0; /* TODO: Fetch the correct value from RC2[0] */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) - { - if (pDCTData->Status[DCT_STATUS_REGISTERED]) { - if (AddrCmdPrelaunch == 0) - RegisterDelay = 0x20; - else - RegisterDelay = 0x30; - } else { - RegisterDelay = 0; - } - SeedTotalPreScaling = ((pDCTData->WLFineDelay[lane_count*dimm+ByteLane] & 0x1f) | - (pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] << 5)) - RegisterDelay; - /* SeedTotalPreScaling = (the total delay value in F2x[1, 0]9C_x[4A:30] from pass 1 of write levelization - training) - RegisterDelay. */ - SeedTotal = (uint16_t) ((((uint64_t) SeedTotalPreScaling) * - fam10h_freq_tab[MemClkFreq] * 100) / (fam10h_freq_tab[3] * 100)); - Seed_Gross = SeedTotal / 32; - Seed_Fine = SeedTotal & 0x1f; - if (Seed_Gross == 0) - Seed_Gross = 0; - else if (Seed_Gross & 0x1) - Seed_Gross = 1; - else - Seed_Gross = 2; - - /* The BKDG-recommended algorithm causes problems with registered DIMMs on some systems - * due to the long register delays causing premature total delay wrap-around. - * Attempt to work around this... - */ - SeedTotal = ((Seed_Gross & 0x1f) << 5) | (Seed_Fine & 0x1f); - SeedTotal += RegisterDelay; - Seed_Gross = SeedTotal / 32; - Seed_Fine = SeedTotal & 0x1f; - - pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] = Seed_Gross; - pDCTData->WLFineDelay[lane_count*dimm+ByteLane] = Seed_Fine; - - printk(BIOS_SPEW, "\tLane %02x new seed: %04x\n", ByteLane, ((pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[lane_count*dimm+ByteLane] & 0x1f)); - } - } - - /* Save initial seeds for upper nibble pass */ - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - pDCTData->WLSeedPreGrossPrevNibble[lane_count*dimm+ByteLane] = pDCTData->WLSeedPreGrossDelay[lane_count*dimm+ByteLane]; - pDCTData->WLSeedGrossPrevNibble[lane_count*dimm+ByteLane] = pDCTData->WLGrossDelay[lane_count*dimm+ByteLane]; - pDCTData->WLSeedFinePrevNibble[lane_count*dimm+ByteLane] = pDCTData->WLFineDelay[lane_count*dimm+ByteLane]; - } - } else { - /* Restore seed values from lower nibble pass */ - if (is_fam15h()) { - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - pDCTData->WLSeedGrossDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedGrossPrevNibble[lane_count*dimm+ByteLane]; - pDCTData->WLSeedFineDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedFinePrevNibble[lane_count*dimm+ByteLane]; - pDCTData->WLSeedPreGrossDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedPreGrossPrevNibble[lane_count*dimm+ByteLane]; - - pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedPreGrossPrevNibble[lane_count*dimm+ByteLane]; - pDCTData->WLFineDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedFinePrevNibble[lane_count*dimm+ByteLane]; - - printk(BIOS_SPEW, "\tLane %02x new seed: %04x\n", ByteLane, ((pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[lane_count*dimm+ByteLane] & 0x1f)); - } - } else { - for (ByteLane = 0; ByteLane < lane_count; ByteLane++) { - pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedGrossPrevNibble[lane_count*dimm+ByteLane]; - pDCTData->WLFineDelay[lane_count*dimm+ByteLane] = pDCTData->WLSeedFinePrevNibble[lane_count*dimm+ByteLane]; - - printk(BIOS_SPEW, "\tLane %02x new seed: %04x\n", ByteLane, ((pDCTData->WLGrossDelay[lane_count*dimm+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[lane_count*dimm+ByteLane] & 0x1f)); - } - } - } - } - - pDCTData->WLPrevMemclkFreq[dimm] = MemClkFreq; - setWLByteDelay(pDCTstat, dct, ByteLane, dimm, 0, pass, lane_count); -} - -/*----------------------------------------------------------------------------- - * void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 Dimm, uint8_t lane_count){ - * - * Description: - * This function writes the write levelization byte delay for the Phase - * Recovery control registers - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN Dimm - Dimm Number - * DCTData->WLGrossDelay[index+ByteLane] - gross write delay for each - * logical DIMM - * DCTData->WLFineDelay[index+ByteLane] - fine write delay for each - * logical DIMM - * ByteLane - target byte lane to write - * targetAddr - 0: write to DRAM phase recovery control register - * 1: write to DQS write register - * OUT - * - *----------------------------------------------------------------------------- - */ -void setWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, u8 targetAddr, uint8_t pass, uint8_t lane_count) -{ - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - u8 fineStartLoc, fineEndLoc, grossStartLoc, grossEndLoc, tempB, index, offsetAddr; - u32 addr, fineDelayValue, grossDelayValue, ValueLow, ValueHigh, EccValue, tempW; - - if (targetAddr == 0) - { - index = (u8)(lane_count * dimm); - ValueLow = 0; - ValueHigh = 0; - ByteLane = 0; - EccValue = 0; - while (ByteLane < lane_count) - { - /* This subtract 0xC workaround might be temporary. */ - if ((pDCTData->WLPass == 2) && (pDCTData->RegMan1Present & (1 << (dimm*2+dct)))) { - tempW = (pDCTData->WLGrossDelay[index+ByteLane] << 5) | pDCTData->WLFineDelay[index+ByteLane]; - tempW -= 0xC; - pDCTData->WLGrossDelay[index+ByteLane] = (u8)(tempW >> 5); - pDCTData->WLFineDelay[index+ByteLane] = (u8)(tempW & 0x1F); - } - grossDelayValue = pDCTData->WLGrossDelay[index+ByteLane]; - /* Adjust seed gross delay overflow (greater than 3): - * - Program seed gross delay as 2 (gross is 4 or 6) or 1 (gross is 5). - * - Keep original seed gross delay for later reference. - */ - if (grossDelayValue >= 3) - grossDelayValue = (grossDelayValue&1)? 1 : 2; - fineDelayValue = pDCTData->WLFineDelay[index+ByteLane]; - if (ByteLane < 4) - ValueLow |= ((grossDelayValue << 5) | fineDelayValue) << 8*ByteLane; - else if (ByteLane < 8) - ValueHigh |= ((grossDelayValue << 5) | fineDelayValue) << 8*(ByteLane-4); - else - EccValue = ((grossDelayValue << 5) | fineDelayValue); - ByteLane++; - } - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_CONT_ADD_PHASE_REC_CTRL_LOW, 0, 31, (u32)ValueLow); - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_CONT_ADD_PHASE_REC_CTRL_HIGH, 0, 31, (u32)ValueHigh); - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - DRAM_CONT_ADD_ECC_PHASE_REC_CTRL, 0, 31, (u32)EccValue); - } - else - { - /* Fam10h BKDG: Rev. 3.62 2.8.9.9.1 (6) - * Fam15h BKDG: Rev. 3.14 2.10.5.8.1 - */ - index = (u8)(lane_count * dimm); - grossDelayValue = pDCTData->WLGrossDelay[index+ByteLane]; - fineDelayValue = pDCTData->WLFineDelay[index+ByteLane]; - - tempB = 0; - offsetAddr = (u8)(3 * dimm); - if (ByteLane < 2) { - tempB = (u8)(16 * ByteLane); - addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_01; - } else if (ByteLane <4) { - tempB = (u8)(16 * ByteLane); - addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_01 + 1; - } else if (ByteLane <6) { - tempB = (u8)(16 * ByteLane); - addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_45; - } else if (ByteLane <8) { - tempB = (u8)(16 * ByteLane); - addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_45 + 1; - } else { - tempB = 0; - addr = DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_01 + 2; - } - addr += offsetAddr; - - fineStartLoc = (u8)(tempB % 32); - fineEndLoc = (u8)(fineStartLoc + 4); - grossStartLoc = (u8)(fineEndLoc + 1); - grossEndLoc = (u8)(grossStartLoc + 2); - - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - (u16)addr, fineStartLoc, fineEndLoc,(u32)fineDelayValue); - set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT, - (u16)addr, grossStartLoc, grossEndLoc, (u32)grossDelayValue); - - pDCTData->WLFineDelayPrevPass[index+ByteLane] = fineDelayValue; - pDCTData->WLGrossDelayPrevPass[index+ByteLane] = grossDelayValue; - if (pass == FirstPass) { - pDCTData->WLFineDelayFirstPass[index+ByteLane] = fineDelayValue; - pDCTData->WLGrossDelayFirstPass[index+ByteLane] = grossDelayValue; - pDCTData->WLCriticalGrossDelayFirstPass = pDCTData->WLCriticalGrossDelayPrevPass; - } - } - -} - -/*----------------------------------------------------------------------------- - * void getWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 Dimm, u8 Nibble, uint8_t lane_count) - * - * Description: - * This function reads the write levelization byte delay from the Phase - * Recovery control registers - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN Dimm - Dimm Number - * ByteLane - target byte lane to read - * OUT - * DCTData->WLGrossDelay[index+ByteLane] - gross write delay for current - * byte for logical DIMM - * DCTData->WLFineDelay[index+ByteLane] - fine write delay for current - * byte for logical DIMM - * - *----------------------------------------------------------------------------- - */ -void getWLByteDelay(struct DCTStatStruc *pDCTstat, uint8_t dct, u8 ByteLane, u8 dimm, uint8_t pass, uint8_t nibble, uint8_t lane_count) -{ - sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct]; - u8 fineStartLoc, fineEndLoc, grossStartLoc, grossEndLoc, tempB, tempB1, index; - u32 addr, fine, gross; - tempB = 0; - index = (u8)(lane_count*dimm); - if (ByteLane < 4) { - tempB = (u8)(8 * ByteLane); - addr = DRAM_CONT_ADD_PHASE_REC_CTRL_LOW; - } else if (ByteLane < 8) { - tempB1 = (u8)(ByteLane - 4); - tempB = (u8)(8 * tempB1); - addr = DRAM_CONT_ADD_PHASE_REC_CTRL_HIGH; - } else { - tempB = 0; - addr = DRAM_CONT_ADD_ECC_PHASE_REC_CTRL; - } - fineStartLoc = tempB; - fineEndLoc = (u8)(fineStartLoc + 4); - grossStartLoc = (u8)(fineEndLoc + 1); - grossEndLoc = (u8)(grossStartLoc + 1); - - fine = get_ADD_DCT_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, (u16)addr, fineStartLoc, fineEndLoc); - gross = get_ADD_DCT_Bits(pDCTData, dct, pDCTData->NodeId, - FUN_DCT, (u16)addr, grossStartLoc, grossEndLoc); - - printk(BIOS_SPEW, "\tLane %02x nibble %01x raw readback: %04x\n", ByteLane, nibble, ((gross & 0x1f) << 5) | (fine & 0x1f)); - - /* Adjust seed gross delay overflow (greater than 3): - * - Adjust the trained gross delay to the original seed gross delay. - */ - if (pDCTData->WLGrossDelay[index+ByteLane] >= 3) - { - gross += pDCTData->WLGrossDelay[index+ByteLane]; - if (pDCTData->WLGrossDelay[index+ByteLane] & 1) - gross -= 1; - else - gross -= 2; - } - else if ((pDCTData->WLGrossDelay[index+ByteLane] == 0) && (gross == 3)) - { - /* If seed gross delay is 0 but PRE result gross delay is 3, it is negative. - * We will then round the negative number to 0. - */ - gross = 0; - fine = 0; - } - printk(BIOS_SPEW, "\tLane %02x nibble %01x adjusted value (pre nibble): %04x\n", ByteLane, nibble, ((gross & 0x1f) << 5) | (fine & 0x1f)); - - /* Nibble adjustments */ - if (nibble == 0) { - pDCTData->WLFineDelay[index+ByteLane] = (uint8_t)fine; - pDCTData->WLGrossDelay[index+ByteLane] = (uint8_t)gross; - } else { - uint32_t WLTotalDelay = ((pDCTData->WLGrossDelay[index+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[index+ByteLane] & 0x1f); - WLTotalDelay += ((gross & 0x1f) << 5) | (fine & 0x1f); - WLTotalDelay /= 2; - pDCTData->WLFineDelay[index+ByteLane] = (uint8_t)(WLTotalDelay & 0x1f); - pDCTData->WLGrossDelay[index+ByteLane] = (uint8_t)((WLTotalDelay >> 5) & 0x1f); - } - printk(BIOS_SPEW, "\tLane %02x nibble %01x adjusted value (post nibble): %04x\n", ByteLane, nibble, ((pDCTData->WLGrossDelay[index+ByteLane] & 0x1f) << 5) | (pDCTData->WLFineDelay[index+ByteLane] & 0x1f)); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/modtrd.c b/src/northbridge/amd/amdmct/mct_ddr3/modtrd.c deleted file mode 100644 index 954dd6f2ef..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/modtrd.c +++ /dev/null @@ -1,95 +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" - -u32 mct_MR1Odt_RDimm(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel) -{ - u8 Speed = pDCTstat->Speed; - u32 ret; - u8 DimmsInstalled, DimmNum, ChipSelect; - - ChipSelect = (MrsChipSel >> 20) & 0xF; - DimmNum = ChipSelect & 0xFE; - DimmsInstalled = pDCTstat->MAdimms[dct]; - if (dct == 1) - DimmNum ++; - ret = 0; - - if (mctGet_NVbits(NV_MAX_DIMMS) == 4) { - if (DimmsInstalled == 1) - ret |= 1 << 2; - else { - if (pDCTstat->CSPresent & 0xF0) { - if (pDCTstat->DimmQRPresent & (1 << DimmNum)) { - if (!(ChipSelect & 1)) - ret |= 1 << 2; - } else - ret |= 0x204; - } else { - if (Speed < 6) - ret |= 0x44; - else - ret |= 0x204; - } - } - } else if (DimmsInstalled == 1) - ret |= 1 << 2; - else if (Speed < 6) - ret |= 0x44; - else - ret |= 0x204; - - //ret = 0; - return ret; -} - -u32 mct_DramTermDyn_RDimm(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, u8 dimm) -{ - u8 DimmsInstalled = dimm; - u32 DramTermDyn = 0; - u8 Speed = pDCTstat->Speed; - - if (mctGet_NVbits(NV_MAX_DIMMS) == 4) { - if (pDCTstat->CSPresent & 0xF0) { - if (DimmsInstalled == 1) - if (Speed == 7) - DramTermDyn |= 1 << 10; - else - DramTermDyn |= 1 << 11; - else - if (Speed == 4) - DramTermDyn |= 1 << 11; - else - DramTermDyn |= 1 << 10; - } else { - if (DimmsInstalled != 1) { - if (Speed == 7) - DramTermDyn |= 1 << 10; - else - DramTermDyn |= 1 << 11; - } - } - } else { - if (DimmsInstalled != 1) - DramTermDyn |= 1 << 11; - } - return DramTermDyn; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/modtrdim.c b/src/northbridge/amd/amdmct/mct_ddr3/modtrdim.c deleted file mode 100644 index 06bfdba84f..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/modtrdim.c +++ /dev/null @@ -1,262 +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. - */ - -/* This file contains functions for odt setting on registered DDR3 dimms */ - -#include <stdint.h> -#include <console/console.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -/** - * - * - * This function set Rtt_Nom for registered DDR3 dimms on targeted dimm. - * - * @param *pMCTData - * @param[in] *pDCTData - Pointer to buffer with information about each DCT - * @param dimm - targeted dimm - * @param wl - current mode, either write levelization mode or normal mode - * @param MemClkFreq - current frequency - * @param rank - * - * @return tempW1 - Rtt_Nom - */ -u32 RttNomTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank) -{ - u32 tempW1; - tempW1 = 0; - if (wl) { - switch (mctGet_NVbits(NV_MAX_DIMMS_PER_CH)) { - case 2: - /* 2 dimms per channel */ - if (pDCTData->MaxDimmsInstalled == 1) { - if ((pDCTData->DimmRanks[dimm] == 2) && (rank == 0)) { - tempW1 = 0x00; /* Rtt_Nom = OFF */ - } else if (pDCTData->DimmRanks[dimm] == 4) { - if (rank == 1) { - tempW1 = 0x00; /* Rtt_Nom = OFF on second and forth rank of QR dimm */ - } else { - if (MemClkFreq == 6) { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } else { - tempW1 = 0x40; /* Rtt_Nom = 120 ohms */ - } - } - } else { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } - } else if (pDCTData->MaxDimmsInstalled == 2) { - if (((pDCTData->DimmRanks[dimm] == 2) || (pDCTData->DimmRanks[dimm] == 4)) && (rank == 1)) { - tempW1 = 0x00; /* Rtt_Nom = OFF */ - } else if ((pDCTData->DimmRanks[dimm] == 4) || (pDCTData->DctCSPresent & 0xF0)) { - if (MemClkFreq == 3) { - tempW1 = 0x40; /* Rtt_Nom = 120 ohms */ - } else { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } - } else { - if (MemClkFreq == 6) { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } else { - tempW1 = 0x40; /* Rtt_Nom = 120 ohms */ - } - } - } - break; - case 3: - /* 3 dimms per channel */ - /* QR not supported in this case on L1 package. */ - if (pDCTData->MaxDimmsInstalled == 1) { - if ((pDCTData->DimmRanks[dimm] == 2) && (rank == 1)) { - tempW1 = 0x00; /* Rtt_Nom = OFF */ - } else { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } - } else { - tempW1 = 0x40; /* Rtt_Nom = 120 ohms */ - } - break; - default: - die("modtrdim.c: WTF?"); - } - } else { - switch (mctGet_NVbits(NV_MAX_DIMMS_PER_CH)) { - case 2: - /* 2 dimms per channel */ - if ((pDCTData->DimmRanks[dimm] == 4) && (rank == 1)) { - tempW1 = 0x00; /* Rtt_Nom = OFF */ - } else if ((pDCTData->MaxDimmsInstalled == 1) || (pDCTData->DimmRanks[dimm] == 4)) { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } else { - if (pDCTData->DctCSPresent & 0xF0) { - tempW1 = 0x0204; /* Rtt_Nom = 30 ohms */ - } else { - if (MemClkFreq < 5) { - tempW1 = 0x44; /* Rtt_Nom = 40 ohms */ - } else { - tempW1 = 0x0204; /* Rtt_Nom = 30 ohms */ - } - } - } - break; - case 3: - /* 3 dimms per channel */ - /* L1 package does not support QR dimms this case. */ - if (rank == 1) { - tempW1 = 0x00; /* Rtt_Nom = OFF */ - } else if (pDCTData->MaxDimmsInstalled == 1) { - tempW1 = 0x04; /* Rtt_Nom = 60 ohms */ - } else if ((MemClkFreq < 5) || (pDCTData->MaxDimmsInstalled == 3)) { - tempW1 = 0x44; /* Rtt_Nom = 40 ohms */ - } else { - tempW1 = 0x0204; /* Rtt_Nom = 30 ohms */ - } - break; - default: - die("modtrdim.c: WTF?"); - } - } - return tempW1; -} - -/* -----------------------------------------------------------------------------*/ -/** - * - * - * This function set Rtt_Nom for registered DDR3 dimms on non-targeted dimm. - * - * @param *pMCTData - * @param[in] *pDCTData - Pointer to buffer with information about each DCT - * @param dimm - non-targeted dimm - * @param wl - current mode, either write levelization mode or normal mode - * @param MemClkFreq - current frequency - * @param rank - * - * @return tempW1 - Rtt_Nom - */ -u32 RttNomNonTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank) -{ - if ((wl) && (mctGet_NVbits(NV_MAX_DIMMS_PER_CH) == 2) && (pDCTData->DimmRanks[dimm] == 2) && (rank == 1)) { - return 0x00; /* for non-target dimm during WL, the second rank of a DR dimm need to have Rtt_Nom = OFF */ - } else { - return RttNomTargetRegDimm (pMCTData, pDCTData, dimm, FALSE, MemClkFreq, rank); /* otherwise, the same as target dimm in normal mode. */ - } -} - -/* -----------------------------------------------------------------------------*/ -/** - * - * - * This function set Rtt_Wr for registered DDR3 dimms. - * - * @param pMCTData - * @param[in] *pDCTData - Pointer to buffer with information about each DCT - * @param dimm - targeted dimm - * @param wl - current mode, either write levelization mode or normal mode - * @param MemClkFreq - current frequency - * @param rank - * - * @return tempW1 - Rtt_Wr - */ - -u32 RttWrRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank) -{ - u32 tempW1; - tempW1 = 0; - if (wl) { - tempW1 = 0x00; /* Rtt_WR = OFF */ - } else { - switch (mctGet_NVbits(NV_MAX_DIMMS_PER_CH)) { - case 2: - if (pDCTData->MaxDimmsInstalled == 1) { - if (pDCTData->DimmRanks[dimm] != 4) { - tempW1 = 0x00; - } else { - if (MemClkFreq == 6) { - tempW1 = 0x200; /* Rtt_WR = 60 ohms */ - } else { - tempW1 = 0x400; /* Rtt_WR = 120 ohms */ - } - } - } else { - if ((pDCTData->DimmRanks[dimm] == 4) || (pDCTData->DctCSPresent & 0xF0)) { - if (MemClkFreq == 3) { - tempW1 = 0x400; /* Rtt_WR = 120 ohms */ - } else { - tempW1 = 0x200; /* Rtt_WR = 60 ohms */ - } - } else { - if (MemClkFreq == 6) { - tempW1 = 0x200; /* Rtt_WR = 60 ohms */ - } else { - tempW1 = 0x400; /* Rtt_Nom = 120 ohms */ - } - } - } - break; - case 3: - if (pDCTData->MaxDimmsInstalled == 1) { - tempW1 = 0x00; /* Rtt_WR = OFF */ - } else { - tempW1 = 0x400; /* Rtt_Nom = 120 ohms */ - } - break; - default: - die("modtrdim.c: WTF?"); - } - } - return tempW1; -} - -/* -----------------------------------------------------------------------------*/ -/** - * - * - * This function set WrLvOdt for registered DDR3 dimms. - * - * @param *pMCTData - * @param[in] *pDCTData - Pointer to buffer with information about each DCT - * @param dimm - targeted dimm - * - * @return WrLvOdt - */ -u8 WrLvOdtRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm) -{ - u8 WrLvOdt1, i; - WrLvOdt1 = 0; - i = 0; - while (i < 8) { - if (pDCTData->DctCSPresent & (1 << i)) { - WrLvOdt1 = (u8)bitTestSet(WrLvOdt1, i/2); - } - i += 2; - } - if (mctGet_NVbits(NV_MAX_DIMMS_PER_CH) == 2) { - if ((pDCTData->DimmRanks[dimm] == 4) && (pDCTData->MaxDimmsInstalled != 1)) { - if (dimm >= 2) { - WrLvOdt1 = (u8)bitTestReset (WrLvOdt1, (dimm - 2)); - } else { - WrLvOdt1 = (u8)bitTestReset (WrLvOdt1, (dimm + 2)); - } - } else if ((pDCTData->DimmRanks[dimm] == 2) && (pDCTData->MaxDimmsInstalled == 1)) { - /* the case for one DR on a 2 dimms per channel is special */ - WrLvOdt1 = 0x8; - } - } - return WrLvOdt1; -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mport_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mport_d.c deleted file mode 100644 index 999cb94f24..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mport_d.c +++ /dev/null @@ -1,42 +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 <arch/io.h> -#include <stdint.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" -#include "mwlc_d.h" - -void AmdMemPCIRead(SBDFO loc, u32 *Value) -{ - /* Convert SBDFO into a CF8 Address */ - loc = (loc >> 4 & 0xFFFFFF00) | (loc & 0xFF) | ((loc & 0xF00) << 16); - loc |= 0x80000000; - - outl(loc, 0xCF8); - - *Value = inl(0xCFC); -} - -void AmdMemPCIWrite(SBDFO loc, u32 *Value) -{ - /* Convert SBDFO into a CF8 Address */ - loc = (loc >> 4 & 0xFFFFFF00) | (loc & 0xFF) | ((loc & 0xF00) << 16); - loc |= 0x80000000; - - outl(loc, 0xCF8); - outl(*Value, 0xCFC); -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mutilc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mutilc_d.c deleted file mode 100644 index 0420b660b9..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mutilc_d.c +++ /dev/null @@ -1,374 +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. - */ - -/* This file contains functions for common utility functions */ - -#include <arch/cpu.h> -#include <stdint.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" -#include "mwlc_d.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; -} - -void AmdMemPCIReadBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue) -{ - /* ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0); */ - - AmdMemPCIRead(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 AmdMemPCIWriteBits(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; - - AmdMemPCIRead(loc, &temp); - temp &= ~(mask << lowbit); - temp |= (*pValue & mask) << lowbit; - AmdMemPCIWrite(loc, &temp); -} - -/*----------------------------------------------------------------------------- - * u32 bitTestSet(u32 csMask,u32 tempD) - * - * Description: - * This routine sets a bit in a u32 - * - * Parameters: - * IN csMask = Target value in which the bit will be set - * IN tempD = Bit that will be set - * OUT value = Target value with the bit set - *----------------------------------------------------------------------------- - */ -u32 bitTestSet(u32 csMask,u32 tempD) -{ - u32 localTemp; - /* ASSERT(tempD < 32); */ - localTemp = 1; - csMask |= localTemp << tempD; - return csMask; -} - -/*----------------------------------------------------------------------------- - * u32 bitTestReset(u32 csMask,u32 tempD) - * - * Description: - * This routine re-sets a bit in a u32 - * - * Parameters: - * IN csMask = Target value in which the bit will be re-set - * IN tempD = Bit that will be re-set - * OUT value = Target value with the bit re-set - *----------------------------------------------------------------------------- - */ -u32 bitTestReset(u32 csMask,u32 tempD) -{ - u32 temp, localTemp; - /* ASSERT(tempD < 32); */ - localTemp = 1; - temp = localTemp << tempD; - temp = ~temp; - csMask &= temp; - return csMask; -} - -/*----------------------------------------------------------------------------- - * u32 get_Bits(DCTStruct *DCTData, u8 DCT, u8 Node, u8 func, u16 offset, - * u8 low, u8 high) - * - * Description: - * This routine Gets the PCT bits from the specified Node, DCT and PCI address - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN DCT - DCT number - * - 1 indicates DCT 1 - * - 0 indicates DCT 0 - * - 2 both DCTs - * Node - Node number - * Func - PCI Function number - * Offset - PCI register number - * Low - Low bit of the bit field - * High - High bit of the bit field - * - * OUT value = Value read from PCI space - *----------------------------------------------------------------------------- - */ -u32 get_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high) -{ - u32 temp; - uint32_t dword; - - /* ASSERT(node < MAX_NODES); */ - if (dct == BOTH_DCTS) - { - /* Registers exist on DCT0 only */ - if (is_fam15h()) - { - /* Select DCT 0 */ - AmdMemPCIRead(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword); - dword &= ~0x1; - AmdMemPCIWrite(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword); - } - - AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp); - } - else - { - if (is_fam15h()) - { - /* Select DCT */ - AmdMemPCIRead(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword); - dword &= ~0x1; - dword |= (dct & 0x1); - AmdMemPCIWrite(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword); - - /* Read from the selected DCT */ - AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp); - } - else - { - if (dct == 1) - { - /* Read from dct 1 */ - offset += 0x100; - AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp); - } - else - { - /* Read from dct 0 */ - AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp); - } - } - } - return temp; -} - -/*----------------------------------------------------------------------------- - * void set_Bits(DCTStruct *DCTData,u8 DCT,u8 Node,u8 func, u16 offset, - * u8 low, u8 high, u32 value) - * - * Description: - * This routine Sets the PCT bits from the specified Node, DCT and PCI address - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN DCT - DCT number - * - 1 indicates DCT 1 - * - 0 indicates DCT 0 - * - 2 both DCTs - * Node - Node number - * Func - PCI Function number - * Offset - PCI register number - * Low - Low bit of the bit field - * High - High bit of the bit field - * - * OUT - *----------------------------------------------------------------------------- - */ -void set_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high, u32 value) -{ - u32 temp; - uint32_t dword; - - temp = value; - - if (dct == BOTH_DCTS) - { - /* Registers exist on DCT0 only */ - if (is_fam15h()) - { - /* Select DCT 0 */ - AmdMemPCIRead(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword); - dword &= ~0x1; - AmdMemPCIWrite(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword); - } - - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp); - } - else - { - if (is_fam15h()) - { - /* Select DCT */ - AmdMemPCIRead(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword); - dword &= ~0x1; - dword |= (dct & 0x1); - AmdMemPCIWrite(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword); - - /* Write to the selected DCT */ - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp); - } - else - { - if (dct == 1) - { - /* Write to dct 1 */ - offset += 0x100; - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp); - } - else - { - /* Write to dct 0 */ - AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp); - } - } - } -} - -/*------------------------------------------------- - * u32 get_ADD_DCT_Bits(DCTStruct *DCTData,u8 DCT,u8 Node,u8 func, - * u16 offset,u8 low, u8 high) - * - * Description: - * This routine gets the Additional PCT register from Function 2 by specified - * Node, DCT and PCI address - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN DCT - DCT number - * - 1 indicates DCT 1 - * - 0 indicates DCT 0 - * - 2 both DCTs - * Node - Node number - * Func - PCI Function number - * Offset - Additional PCI register number - * Low - Low bit of the bit field - * High - High bit of the bit field - * - * OUT - *------------------------------------------------- - */ -u32 get_ADD_DCT_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high) -{ - u32 tempD; - tempD = offset; - tempD = bitTestReset(tempD,DctAccessWrite); - set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, - PCI_MIN_LOW, PCI_MAX_HIGH, offset); - while ((get_Bits(pDCTData,dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, - DctAccessDone, DctAccessDone)) == 0); - return (get_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_PORT_REG, - low, high)); -} - -/*------------------------------------------------- - * void set_DCT_ADDR_Bits(DCTStruct *DCTData, u8 DCT,u8 Node,u8 func, - * u16 offset,u8 low, u8 high, u32 value) - * - * Description: - * This routine sets the Additional PCT register from Function 2 by specified - * Node, DCT and PCI address - * - * Parameters: - * IN OUT *DCTData - Pointer to buffer with information about each DCT - * IN DCT - DCT number - * - 1 indicates DCT 1 - * - 0 indicates DCT 0 - * - 2 both DCTs - * Node - Node number - * Func - PCI Function number - * Offset - Additional PCI register number - * Low - Low bit of the bit field - * High - High bit of the bit field - * - * OUT - *------------------------------------------------- - */ -void set_DCT_ADDR_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high, u32 value) -{ - u32 tempD; - - set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, - PCI_MIN_LOW, PCI_MAX_HIGH, offset); - while ((get_Bits(pDCTData,dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, - DctAccessDone, DctAccessDone)) == 0); - - set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_PORT_REG, - low, high, value); - tempD = offset; - tempD = bitTestSet(tempD,DctAccessWrite); - set_Bits(pDCTData, dct, node, FUN_DCT,DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, - PCI_MIN_LOW, PCI_MAX_HIGH, tempD); - while ((get_Bits(pDCTData,dct, pDCTData->NodeId, FUN_DCT, - DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, DctAccessDone, - DctAccessDone)) == 0); -} - -/*------------------------------------------------- - * BOOL bitTest(u32 value, u8 bitLoc) - * - * Description: - * This routine tests the value to determine if the bitLoc is set - * - * Parameters: - * IN Value - value to be tested - * bitLoc - bit location to be tested - * OUT TRUE - bit is set - * FALSE - bit is clear - *------------------------------------------------- - */ -BOOL bitTest(u32 value, u8 bitLoc) -{ - u32 tempD, compD; - tempD = value; - compD = 0; - compD = bitTestSet(compD,bitLoc); - tempD &= compD; - if (compD == tempD) - { - return TRUE; - } - else - { - return FALSE; - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h deleted file mode 100644 index aa0446f090..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h +++ /dev/null @@ -1,192 +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. - */ -/* IBV defined Structure */ /* IBV Specific Options */ -#ifndef MWLC_D_H -#define MWLC_D_H - -#include <northbridge/amd/amdht/porting.h> - -#define MAX_TOTAL_DIMMS 8 /* Maximum Number of DIMMs in systems */ - /* (DCT0 + DCT1) */ -#define MAX_DIMMS 4 /* Maximum Number of DIMMs on each DCT */ -#define MAX_LDIMMS 4 /* Maximum number of Logical DIMMs per DCT */ - -/*MCT Max variables */ -#define MAX_ERRORS 32 /* Maximum number of Errors Reported */ -#define MAX_STATUS 32 /* Maximum number of Status variables*/ -#define MAX_BYTE_LANES (8+1) /* Maximum number of Byte Lanes - include ECC */ - -#define C_MAX_DIMMS 4 /* Maximum Number of DIMMs on each DCT */ - -/* STATUS Definition */ -#define DCT_STATUS_REGISTERED 3 /* Registered DIMMs support */ -#define DCT_STATUS_LOAD_REDUCED 4 /* Load-Reduced DIMMs support */ -#define DCT_STATUS_OnDimmMirror 24 /* OnDimmMirror support */ - -/* PCI Definitions */ -#define FUN_HT 0 /* Function 0 Access */ -#define FUN_MAP 1 /* Function 1 Access */ -#define FUN_DCT 2 /* Function 2 Access */ -#define FUN_MISC 3 /* Function 3 Access */ -#define FUN_ADD_DCT 0xF /* Function 2 Additional Register Access */ -#define BOTH_DCTS 2 /* The access is independent of DCTs */ -#define PCI_MIN_LOW 0 /* Lowest possible PCI register location */ -#define PCI_MAX_HIGH 31 /* Highest possible PCI register location */ - -/*Function 2 */ -/* #define DRAM_INIT 0x7C */ -#define DRAM_MRS_REGISTER 0x84 -#define DRAM_CONFIG_HIGH 0x94 -#define DRAM_CONTROLLER_ADD_DATA_OFFSET_REG 0x98 -#define DRAM_CONTROLLER_ADD_DATA_PORT_REG 0x9C - -/*Function 2 Additional DRAM control registers */ -#define DRAM_ADD_DCT_PHY_CONTROL_REG 0x8 -#define DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_01 0x30 -#define DRAM_CONT_ADD_DQS_TIMING_CTRL_BL_45 0x40 -#define DRAM_CONT_ADD_PHASE_REC_CTRL_LOW 0x50 -#define DRAM_CONT_ADD_PHASE_REC_CTRL_HIGH 0x51 -#define DRAM_CONT_ADD_ECC_PHASE_REC_CTRL 0x52 -#define DRAM_CONT_ADD_WRITE_LEV_ERROR_REG 0x53 - -/* CPU Register definitions */ - -/* Register Bit Location */ -#define DctAccessDone 31 -#define DctAccessWrite 30 -#define RDqsEn 12 -#define TrDimmSelStart 4 -#define TrDimmSelEnd 5 -#define WrLvTrMode 1 -#define TrNibbleSel 2 -#define WrLvOdtEn 12 -#define WrLvErrStart 0 -#define WrLvErrEnd 8 -#define SendMrsCmd 26 -#define Qoff 12 -#define MRS_Level 7 -#define MrsAddressStartFam10 0 -#define MrsAddressEndFam10 15 -#define MrsAddressStartFam15 0 -#define MrsAddressEndFam15 17 -#define MrsBankStartFam10 16 -#define MrsBankEndFam10 18 -#define MrsBankStartFam15 18 -#define MrsBankEndFam15 20 -#define MrsChipSelStartFam10 20 -#define MrsChipSelEndFam10 22 -#define MrsChipSelStartFam15 21 -#define MrsChipSelEndFam15 23 -#define ASR 18 -#define SRT 19 -#define DramTermDynStart 10 -#define DramTermDynEnd 11 -#define WrtLvTrMode 1 -#define TrNibbleSel 2 -#define TrDimmSelStart 4 -#define TrDimmSelEnd 5 -#define WrtLvTrEn 0 -#define DrvImpCtrlStart 2 -#define DrvImpCtrlEnd 3 -#define DramTermNbStart 7 -#define DramTermNbEnd 9 -#define onDimmMirror 3 - -typedef struct _sMCTStruct -{ - void (*AgesaDelay)(u32 delayval); /* IBV defined Delay Function */ -} __attribute__((packed, aligned(4))) sMCTStruct; - -/* DCT 0 and DCT 1 Data structure */ -typedef struct _sDCTStruct -{ - u8 NodeId; /* Node ID */ - u8 DctTrain; /* Current DCT being trained */ - u8 CurrDct; /* Current DCT number (0 or 1) */ - u8 DctCSPresent; /* Current DCT CS mapping */ - uint8_t WrDqsGrossDlyBaseOffset; - int32_t WLSeedGrossDelay[MAX_BYTE_LANES*MAX_LDIMMS]; /* Write Levelization Seed Gross Delay */ - /* per byte Lane Per Logical DIMM*/ - int32_t WLSeedFineDelay[MAX_BYTE_LANES*MAX_LDIMMS]; /* Write Levelization Seed Fine Delay */ - /* per byte Lane Per Logical DIMM*/ - int32_t WLSeedPreGrossDelay[MAX_BYTE_LANES*MAX_LDIMMS]; /* Write Levelization Seed Pre-Gross Delay */ - /* per byte Lane Per Logical DIMM*/ - uint8_t WLSeedPreGrossPrevNibble[MAX_BYTE_LANES*MAX_LDIMMS]; - uint8_t WLSeedGrossPrevNibble[MAX_BYTE_LANES*MAX_LDIMMS]; - uint8_t WLSeedFinePrevNibble[MAX_BYTE_LANES*MAX_LDIMMS]; - /* per byte Lane Per Logical DIMM*/ - u8 WLGrossDelay[MAX_BYTE_LANES*MAX_LDIMMS]; /* Write Levelization Gross Delay */ - /* per byte Lane Per Logical DIMM*/ - u8 WLFineDelay[MAX_BYTE_LANES*MAX_LDIMMS]; /* Write Levelization Fine Delay */ - /* per byte Lane Per Logical DIMM*/ - u8 WLGrossDelayFirstPass[MAX_BYTE_LANES*MAX_LDIMMS]; /* First-Pass Write Levelization Gross Delay */ - /* per byte Lane Per Logical DIMM*/ - u8 WLFineDelayFirstPass[MAX_BYTE_LANES*MAX_LDIMMS]; /* First-Pass Write Levelization Fine Delay */ - /* per byte Lane Per Logical DIMM*/ - u8 WLGrossDelayPrevPass[MAX_BYTE_LANES*MAX_LDIMMS]; /* Previous Pass Write Levelization Gross Delay */ - /* per byte Lane Per Logical DIMM*/ - u8 WLFineDelayPrevPass[MAX_BYTE_LANES*MAX_LDIMMS]; /* Previous Pass Write Levelization Fine Delay */ - /* per byte Lane Per Logical DIMM*/ - u8 WLGrossDelayFinalPass[MAX_BYTE_LANES*MAX_LDIMMS]; /* Final-Pass Write Levelization Gross Delay */ - /* per byte Lane Per Logical DIMM*/ - u8 WLFineDelayFinalPass[MAX_BYTE_LANES*MAX_LDIMMS]; /* Final-Pass Write Levelization Fine Delay */ - /* per byte Lane Per Logical DIMM*/ - int32_t WLCriticalGrossDelayFirstPass; - int32_t WLCriticalGrossDelayPrevPass; - int32_t WLCriticalGrossDelayFinalPass; - uint16_t WLPrevMemclkFreq[MAX_TOTAL_DIMMS]; - u16 RegMan1Present; - u8 DimmPresent[MAX_TOTAL_DIMMS];/* Indicates which DIMMs are present */ - /* from Total Number of DIMMs(per Node)*/ - u8 DimmX8Present[MAX_TOTAL_DIMMS]; /* Which DIMMs x8 devices */ - u8 Status[MAX_STATUS]; /* Status for DCT0 and 1 */ - u8 ErrCode[MAX_ERRORS]; /* Major Error codes for DCT0 and 1 */ - u8 ErrStatus[MAX_ERRORS]; /* Minor Error codes for DCT0 and 1 */ - u8 DimmValid[MAX_TOTAL_DIMMS]; /* Indicates which DIMMs are valid for */ - /* Total Number of DIMMs(per Node) */ - u8 WLTotalDelay[MAX_BYTE_LANES];/* Write Levelization Total Delay */ - /* per byte lane */ - u8 MaxDimmsInstalled; /* Max Dimms Installed for current DCT */ - u8 DimmRanks[MAX_TOTAL_DIMMS]; /* Total Number of Ranks(per Dimm) */ - uint64_t LogicalCPUID; - u8 WLPass; -} __attribute__((packed, aligned(4))) sDCTStruct; - -void set_DCT_ADDR_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high, u32 value); -void AmdMemPCIWriteBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue); -u32 get_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high); -void AmdMemPCIReadBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue); -u32 bitTestSet(u32 csMask,u32 tempD); -u32 bitTestReset(u32 csMask,u32 tempD); -void set_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high, u32 value); -BOOL bitTest(u32 value, u8 bitLoc); -u32 RttNomNonTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank); -u32 RttNomTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank); -u32 RttWrRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank); -u8 WrLvOdtRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm); -u32 get_ADD_DCT_Bits(sDCTStruct *pDCTData, - u8 dct, u8 node, u8 func, - u16 offset, u8 low, u8 high); -void AmdMemPCIRead(SBDFO loc, u32 *Value); -void AmdMemPCIWrite(SBDFO loc, u32 *Value); - -#endif diff --git a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c deleted file mode 100644 index 52032e9362..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c +++ /dev/null @@ -1,1237 +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. - */ - -#include <string.h> -#include <arch/cpu.h> -#include <arch/acpi.h> -#include <cpu/x86/msr.h> -#include <cpu/amd/msr.h> -#include <cpu/x86/mtrr.h> -#include <cpu/amd/mtrr.h> -#include <device/device.h> -#include <device/pci_def.h> -#include <device/pci_ops.h> -#include <console/console.h> -#include <cbfs.h> -#include <cbmem.h> -#include <spi-generic.h> -#include <spi_flash.h> -#include <pc80/mc146818rtc.h> -#include <stdint.h> -#include <types.h> - -#include "mct_d.h" -#include "mct_d_gcc.h" - -#include "s3utils.h" - -#define S3NV_FILE_NAME "s3nv" - -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 ssize_t get_s3nv_file_offset(void); - -ssize_t get_s3nv_file_offset(void) -{ - struct region_device s3nv_region; - struct cbfsf s3nv_cbfs_file; - if (cbfs_boot_locate(&s3nv_cbfs_file, S3NV_FILE_NAME, NULL)) { - printk(BIOS_DEBUG, "S3 state file not found in CBFS: %s\n", S3NV_FILE_NAME); - return -1; - } - cbfs_file_data(&s3nv_region, &s3nv_cbfs_file); - - return s3nv_region.region.offset; -} - -#if ENV_PCI_SIMPLE_DEVICE -static uint32_t read_config32_dct(pci_devfn_t dev, uint8_t node, uint8_t dct, - uint32_t reg) -#else -static uint32_t read_config32_dct(struct device *dev, uint8_t node, uint8_t dct, - uint32_t reg) -#endif -{ - if (is_fam15h()) { - uint32_t dword; -#if ENV_PCI_SIMPLE_DEVICE - pci_devfn_t dev_fn1 = PCI_DEV(0, 0x18 + node, 1); -#else - struct device *dev_fn1 = pcidev_on_root(0x18 + node, 1); -#endif - - /* Select DCT */ - dword = pci_read_config32(dev_fn1, 0x10c); - dword &= ~0x1; - dword |= (dct & 0x1); - pci_write_config32(dev_fn1, 0x10c, dword); - } else { - /* Apply offset */ - reg += dct * 0x100; - } - - return pci_read_config32(dev, reg); -} - -#if ENV_PCI_SIMPLE_DEVICE -static void write_config32_dct(pci_devfn_t dev, uint8_t node, uint8_t dct, - uint32_t reg, uint32_t value) -#else -static void write_config32_dct(struct device *dev, uint8_t node, uint8_t dct, - uint32_t reg, uint32_t value) -#endif -{ - if (is_fam15h()) { - uint32_t dword; -#if ENV_PCI_SIMPLE_DEVICE - pci_devfn_t dev_fn1 = PCI_DEV(0, 0x18 + node, 1); -#else - struct device *dev_fn1 = pcidev_on_root(0x18 + node, 1); -#endif - - /* Select DCT */ - dword = pci_read_config32(dev_fn1, 0x10c); - dword &= ~0x1; - dword |= (dct & 0x1); - pci_write_config32(dev_fn1, 0x10c, dword); - } else { - /* Apply offset */ - reg += dct * 0x100; - } - - pci_write_config32(dev, reg, value); -} - -#if ENV_PCI_SIMPLE_DEVICE -static uint32_t read_amd_dct_index_register(pci_devfn_t dev, - uint32_t index_ctl_reg, uint32_t index) -#else -static uint32_t read_amd_dct_index_register(struct device *dev, - uint32_t index_ctl_reg, uint32_t index) -#endif -{ - uint32_t dword; - - index &= ~(1 << 30); - pci_write_config32(dev, index_ctl_reg, index); - do { - dword = pci_read_config32(dev, index_ctl_reg); - } while (!(dword & (1 << 31))); - dword = pci_read_config32(dev, index_ctl_reg + 0x04); - - return dword; -} - -#if ENV_PCI_SIMPLE_DEVICE -static uint32_t read_amd_dct_index_register_dct(pci_devfn_t dev, uint8_t node, - uint8_t dct, uint32_t index_ctl_reg, uint32_t index) -#else -static uint32_t read_amd_dct_index_register_dct(struct device *dev, - uint8_t node, uint8_t dct, uint32_t index_ctl_reg, - uint32_t index) -#endif -{ - if (is_fam15h()) { - uint32_t dword; -#if ENV_PCI_SIMPLE_DEVICE - pci_devfn_t dev_fn1 = PCI_DEV(0, 0x18 + node, 1); -#else - struct device *dev_fn1 = pcidev_on_root(0x18 + node, 1); -#endif - - /* Select DCT */ - dword = pci_read_config32(dev_fn1, 0x10c); - dword &= ~0x1; - dword |= (dct & 0x1); - pci_write_config32(dev_fn1, 0x10c, dword); - } else { - /* Apply offset */ - index_ctl_reg += dct * 0x100; - } - - return read_amd_dct_index_register(dev, index_ctl_reg, index); -} - -/* Non-cryptographic 64-bit hash function taken from Stack Overflow: - * http://stackoverflow.com/a/13326345 - * Any 64-bit hash with sufficiently low collision potential - * could be used instead. - */ -void calculate_spd_hash(uint8_t *spd_data, uint64_t *spd_hash) -{ - const unsigned long long prime = 2654435789ULL; - uint16_t byte; - *spd_hash = 104395301; - - for (byte = 0; byte < 256; byte++) - *spd_hash += (spd_data[byte] * prime) ^ (*spd_hash >> 23); - - *spd_hash = *spd_hash ^ (*spd_hash << 37); -} - -uint16_t calculate_nvram_mct_hash(void) -{ - uint32_t nvram; - uint16_t ret; - - ret = 0; - if (get_option(&nvram, "max_mem_clock") == CB_SUCCESS) - ret |= nvram & 0xf; - if (get_option(&nvram, "minimum_memory_voltage") == CB_SUCCESS) - ret |= (nvram & 0x3) << 4; - if (get_option(&nvram, "ECC_memory") == CB_SUCCESS) - ret |= (nvram & 0x1) << 6; - if (get_option(&nvram, "ECC_redirection") == CB_SUCCESS) - ret |= (nvram & 0x1) << 7; - if (get_option(&nvram, "ecc_scrub_rate") == CB_SUCCESS) - ret |= (nvram & 0x1) << 8; - if (get_option(&nvram, "interleave_chip_selects") == CB_SUCCESS) - ret |= (nvram & 0x1) << 9; - if (get_option(&nvram, "interleave_nodes") == CB_SUCCESS) - ret |= (nvram & 0x1) << 10; - if (get_option(&nvram, "interleave_memory_channels") == CB_SUCCESS) - ret |= (nvram & 0x1) << 11; - if (get_option(&nvram, "cpu_c_states") == CB_SUCCESS) - ret |= (nvram & 0x1) << 12; - if (get_option(&nvram, "cpu_cc6_state") == CB_SUCCESS) - ret |= (nvram & 0x1) << 13; - - return ret; -} - -static struct amd_s3_persistent_data *map_s3nv_in_nvram(void) -{ - ssize_t s3nv_offset; - ssize_t s3nv_file_offset; - void *s3nv_cbfs_file_ptr; - struct amd_s3_persistent_data *persistent_data; - - /* Obtain CBFS file offset */ - s3nv_offset = get_s3nv_file_offset(); - if (s3nv_offset == -1) - return NULL; - - /* Align flash pointer to nearest boundary */ - s3nv_file_offset = s3nv_offset; - s3nv_offset &= ~(CONFIG_S3_DATA_SIZE-1); - s3nv_offset += CONFIG_S3_DATA_SIZE; - s3nv_file_offset = s3nv_offset - s3nv_file_offset; - - /* Map data structure in CBFS and restore settings */ - s3nv_cbfs_file_ptr = cbfs_boot_map_with_leak(S3NV_FILE_NAME, CBFS_TYPE_RAW, NULL); - if (!s3nv_cbfs_file_ptr) { - printk(BIOS_DEBUG, "S3 state file could not be mapped: %s\n", S3NV_FILE_NAME); - return NULL; - } - persistent_data = (s3nv_cbfs_file_ptr + s3nv_file_offset); - - return persistent_data; -} - -int8_t load_spd_hashes_from_nvram(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat) -{ - struct amd_s3_persistent_data *persistent_data; - - persistent_data = map_s3nv_in_nvram(); - if (!persistent_data) - return -1; - - memcpy(pDCTstat->spd_data.nvram_spd_hash, persistent_data->node[pDCTstat->Node_ID].spd_hash, sizeof(pDCTstat->spd_data.nvram_spd_hash)); - memcpy(pDCTstat->spd_data.nvram_memclk, persistent_data->node[pDCTstat->Node_ID].memclk, sizeof(pDCTstat->spd_data.nvram_memclk)); - - pMCTstat->nvram_checksum = persistent_data->nvram_checksum; - - return 0; -} - -static uint64_t rdmsr_uint64_t(unsigned long index) { - msr_t msr = rdmsr(index); - return (((uint64_t)msr.hi) << 32) | ((uint64_t)msr.lo); -} - -static void wrmsr_uint64_t(unsigned long index, uint64_t value) -{ - msr_t msr; - msr.hi = (value & 0xffffffff00000000ULL) >> 32; - msr.lo = (value & 0xffffffff); - wrmsr(index, msr); -} - -static uint32_t read_config32_dct_nbpstate(struct device *dev, uint8_t node, - uint8_t dct, uint8_t nb_pstate, - uint32_t reg) -{ - uint32_t dword; - struct device *dev_fn1 = pcidev_on_root(0x18 + node, 1); - - /* Select DCT */ - dword = pci_read_config32(dev_fn1, 0x10c); - dword &= ~0x1; - dword |= (dct & 0x1); - pci_write_config32(dev_fn1, 0x10c, dword); - - /* Select NB Pstate index */ - dword = pci_read_config32(dev_fn1, 0x10c); - dword &= ~(0x3 << 4); - dword |= (nb_pstate & 0x3) << 4; - pci_write_config32(dev_fn1, 0x10c, dword); - - return pci_read_config32(dev, reg); -} - -static void copy_cbmem_spd_data_to_save_variable(struct amd_s3_persistent_data *persistent_data, uint8_t *restored) -{ - uint8_t node; - uint8_t dimm; - uint8_t channel; - struct amdmct_memory_info *mem_info; - mem_info = cbmem_find(CBMEM_ID_AMDMCT_MEMINFO); - if (mem_info == NULL) { - /* can't find amdmct information in cbmem */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) - for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) - persistent_data->node[node].spd_hash[dimm] = 0xffffffffffffffffULL; - - return; - } - - for (node = 0; node < MAX_NODES_SUPPORTED; node++) - for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) - calculate_spd_hash(mem_info->dct_stat[node].spd_data.spd_bytes[dimm], &persistent_data->node[node].spd_hash[dimm]); - - for (node = 0; node < MAX_NODES_SUPPORTED; node++) - for (channel = 0; channel < 2; channel++) - persistent_data->node[node].memclk[channel] = mem_info->dct_stat[node].Speed; - - persistent_data->nvram_checksum = calculate_nvram_mct_hash(); - - if (restored) { - if (mem_info->mct_stat.GStatus & (1 << GSB_ConfigRestored)) - *restored = 1; - else - *restored = 0; - } -} - -void copy_mct_data_to_save_variable(struct amd_s3_persistent_data *persistent_data) -{ - uint8_t i; - uint8_t j; - uint8_t node; - uint8_t channel; - - /* Zero out data structure */ - memset(persistent_data, 0, sizeof(struct amd_s3_persistent_data)); - - /* Load data from DCTs into data structure */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - struct device *dev_fn1 = pcidev_on_root(0x18 + node, 1); - struct device *dev_fn2 = pcidev_on_root(0x18 + node, 2); - struct device *dev_fn3 = pcidev_on_root(0x18 + node, 3); - /* Test for node presence */ - if ((!dev_fn1) || (pci_read_config32(dev_fn1, PCI_VENDOR_ID) == 0xffffffff)) { - persistent_data->node[node].node_present = 0; - continue; - } - persistent_data->node[node].node_present = 1; - - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - - /* Stage 1 */ - data->f2x110 = pci_read_config32(dev_fn2, 0x110); - - /* Stage 2 */ - data->f1x40 = read_config32_dct(dev_fn1, node, channel, 0x40); - data->f1x44 = read_config32_dct(dev_fn1, node, channel, 0x44); - data->f1x48 = read_config32_dct(dev_fn1, node, channel, 0x48); - data->f1x4c = read_config32_dct(dev_fn1, node, channel, 0x4c); - data->f1x50 = read_config32_dct(dev_fn1, node, channel, 0x50); - data->f1x54 = read_config32_dct(dev_fn1, node, channel, 0x54); - data->f1x58 = read_config32_dct(dev_fn1, node, channel, 0x58); - data->f1x5c = read_config32_dct(dev_fn1, node, channel, 0x5c); - data->f1x60 = read_config32_dct(dev_fn1, node, channel, 0x60); - data->f1x64 = read_config32_dct(dev_fn1, node, channel, 0x64); - data->f1x68 = read_config32_dct(dev_fn1, node, channel, 0x68); - data->f1x6c = read_config32_dct(dev_fn1, node, channel, 0x6c); - data->f1x70 = read_config32_dct(dev_fn1, node, channel, 0x70); - data->f1x74 = read_config32_dct(dev_fn1, node, channel, 0x74); - data->f1x78 = read_config32_dct(dev_fn1, node, channel, 0x78); - data->f1x7c = read_config32_dct(dev_fn1, node, channel, 0x7c); - data->f1xf0 = pci_read_config32(dev_fn1, 0xf0); - data->f1x120 = pci_read_config32(dev_fn1, 0x120); - data->f1x124 = pci_read_config32(dev_fn1, 0x124); - data->f2x10c = pci_read_config32(dev_fn2, 0x10c); - data->f2x114 = pci_read_config32(dev_fn2, 0x114); - data->f2x118 = pci_read_config32(dev_fn2, 0x118); - data->f2x11c = pci_read_config32(dev_fn2, 0x11c); - data->f2x1b0 = pci_read_config32(dev_fn2, 0x1b0); - data->f3x44 = pci_read_config32(dev_fn3, 0x44); - for (i = 0; i < 16; i++) { - data->msr0000020[i] = - rdmsr_uint64_t(MTRR_PHYS_BASE(0) | i); - } - data->msr00000250 = rdmsr_uint64_t(MTRR_FIX_64K_00000); - data->msr00000258 = rdmsr_uint64_t(MTRR_FIX_16K_80000); - for (i = 0; i < 8; i++) - data->msr0000026[i] = rdmsr_uint64_t(0x00000260 | (i + 8)); - data->msr000002ff = rdmsr_uint64_t(MTRR_DEF_TYPE_MSR); - data->msrc0010010 = rdmsr_uint64_t(SYSCFG_MSR); - data->msrc001001a = rdmsr_uint64_t(TOP_MEM); - data->msrc001001d = rdmsr_uint64_t(TOP_MEM2); - data->msrc001001f = rdmsr_uint64_t(NB_CFG_MSR); - - /* Stage 3 */ - data->f2x40 = read_config32_dct(dev_fn2, node, channel, 0x40); - data->f2x44 = read_config32_dct(dev_fn2, node, channel, 0x44); - data->f2x48 = read_config32_dct(dev_fn2, node, channel, 0x48); - data->f2x4c = read_config32_dct(dev_fn2, node, channel, 0x4c); - data->f2x50 = read_config32_dct(dev_fn2, node, channel, 0x50); - data->f2x54 = read_config32_dct(dev_fn2, node, channel, 0x54); - data->f2x58 = read_config32_dct(dev_fn2, node, channel, 0x58); - data->f2x5c = read_config32_dct(dev_fn2, node, channel, 0x5c); - data->f2x60 = read_config32_dct(dev_fn2, node, channel, 0x60); - data->f2x64 = read_config32_dct(dev_fn2, node, channel, 0x64); - data->f2x68 = read_config32_dct(dev_fn2, node, channel, 0x68); - data->f2x6c = read_config32_dct(dev_fn2, node, channel, 0x6c); - data->f2x78 = read_config32_dct(dev_fn2, node, channel, 0x78); - data->f2x7c = read_config32_dct(dev_fn2, node, channel, 0x7c); - data->f2x80 = read_config32_dct(dev_fn2, node, channel, 0x80); - data->f2x84 = read_config32_dct(dev_fn2, node, channel, 0x84); - data->f2x88 = read_config32_dct(dev_fn2, node, channel, 0x88); - data->f2x8c = read_config32_dct(dev_fn2, node, channel, 0x8c); - data->f2x90 = read_config32_dct(dev_fn2, node, channel, 0x90); - data->f2xa4 = read_config32_dct(dev_fn2, node, channel, 0xa4); - data->f2xa8 = read_config32_dct(dev_fn2, node, channel, 0xa8); - - /* Family 15h-specific configuration */ - if (is_fam15h()) { - data->f2x200 = read_config32_dct(dev_fn2, node, channel, 0x200); - data->f2x204 = read_config32_dct(dev_fn2, node, channel, 0x204); - data->f2x208 = read_config32_dct(dev_fn2, node, channel, 0x208); - data->f2x20c = read_config32_dct(dev_fn2, node, channel, 0x20c); - for (i = 0; i < 4; i++) - data->f2x210[i] = read_config32_dct_nbpstate(dev_fn2, node, channel, i, 0x210); - data->f2x214 = read_config32_dct(dev_fn2, node, channel, 0x214); - data->f2x218 = read_config32_dct(dev_fn2, node, channel, 0x218); - data->f2x21c = read_config32_dct(dev_fn2, node, channel, 0x21c); - data->f2x22c = read_config32_dct(dev_fn2, node, channel, 0x22c); - data->f2x230 = read_config32_dct(dev_fn2, node, channel, 0x230); - data->f2x234 = read_config32_dct(dev_fn2, node, channel, 0x234); - data->f2x238 = read_config32_dct(dev_fn2, node, channel, 0x238); - data->f2x23c = read_config32_dct(dev_fn2, node, channel, 0x23c); - data->f2x240 = read_config32_dct(dev_fn2, node, channel, 0x240); - - data->f2x9cx0d0fe003 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fe003); - data->f2x9cx0d0fe013 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fe013); - for (i = 0; i < 9; i++) - data->f2x9cx0d0f0_8_0_1f[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f001f | (i << 8)); - data->f2x9cx0d0f201f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f201f); - data->f2x9cx0d0f211f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f211f); - data->f2x9cx0d0f221f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f221f); - data->f2x9cx0d0f801f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f801f); - data->f2x9cx0d0f811f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f811f); - data->f2x9cx0d0f821f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f821f); - data->f2x9cx0d0fc01f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc01f); - data->f2x9cx0d0fc11f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc11f); - data->f2x9cx0d0fc21f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc21f); - data->f2x9cx0d0f4009 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f4009); - for (i = 0; i < 9; i++) - data->f2x9cx0d0f0_8_0_02[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0002 | (i << 8)); - for (i = 0; i < 9; i++) - data->f2x9cx0d0f0_8_0_06[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0006 | (i << 8)); - for (i = 0; i < 9; i++) - data->f2x9cx0d0f0_8_0_0a[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f000a | (i << 8)); - - data->f2x9cx0d0f2002 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2002); - data->f2x9cx0d0f2102 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2102); - data->f2x9cx0d0f2202 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2202); - data->f2x9cx0d0f8002 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8002); - data->f2x9cx0d0f8006 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8006); - data->f2x9cx0d0f800a = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f800a); - data->f2x9cx0d0f8102 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8102); - data->f2x9cx0d0f8106 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8106); - data->f2x9cx0d0f810a = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f810a); - data->f2x9cx0d0fc002 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc002); - data->f2x9cx0d0fc006 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc006); - data->f2x9cx0d0fc00a = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc00a); - data->f2x9cx0d0fc00e = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc00e); - data->f2x9cx0d0fc012 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc012); - - data->f2x9cx0d0f2031 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2031); - data->f2x9cx0d0f2131 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2131); - data->f2x9cx0d0f2231 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2231); - data->f2x9cx0d0f8031 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8031); - data->f2x9cx0d0f8131 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8131); - data->f2x9cx0d0f8231 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8231); - data->f2x9cx0d0fc031 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc031); - data->f2x9cx0d0fc131 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc131); - data->f2x9cx0d0fc231 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fc231); - for (i = 0; i < 9; i++) - data->f2x9cx0d0f0_0_f_31[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0031 | (i << 8)); - - data->f2x9cx0d0f8021 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f8021); - - if (channel == 1) - data->f2x9cx0d0fe00a = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fe00a); - } - - /* Stage 4 */ - data->f2x94 = read_config32_dct(dev_fn2, node, channel, 0x94); - - /* Stage 6 */ - for (i = 0; i < 9; i++) - for (j = 0; j < 3; j++) - data->f2x9cx0d0f0_f_8_0_0_8_4_0[i][j] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0000 | (i << 8) | (j * 4)); - data->f2x9cx00 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x00); - data->f2x9cx0a = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0a); - data->f2x9cx0c = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0c); - - /* Stage 7 */ - data->f2x9cx04 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x04); - - /* Stage 9 */ - data->f2x9cx0d0fe006 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fe006); - data->f2x9cx0d0fe007 = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0fe007); - - /* Stage 10 */ - for (i = 0; i < 12; i++) - data->f2x9cx10[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x10 + i); - for (i = 0; i < 12; i++) - data->f2x9cx20[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x20 + i); - for (i = 0; i < 4; i++) - for (j = 0; j < 3; j++) - data->f2x9cx3_0_0_3_1[i][j] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, (0x01 + i) + (0x100 * j)); - for (i = 0; i < 4; i++) - for (j = 0; j < 3; j++) - data->f2x9cx3_0_0_7_5[i][j] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, (0x05 + i) + (0x100 * j)); - data->f2x9cx0d = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d); - for (i = 0; i < 9; i++) - data->f2x9cx0d0f0_f_0_13[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0013 | (i << 8)); - for (i = 0; i < 9; i++) - data->f2x9cx0d0f0_f_0_30[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0030 | (i << 8)); - for (i = 0; i < 4; i++) - data->f2x9cx0d0f2_f_0_30[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f2030 | (i << 8)); - for (i = 0; i < 2; i++) - for (j = 0; j < 3; j++) - data->f2x9cx0d0f8_8_4_0[i][j] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f0000 | (i << 8) | (j * 4)); - data->f2x9cx0d0f812f = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x0d0f812f); - - /* Stage 11 */ - if (CONFIG(DIMM_DDR3)) { - for (i = 0; i < 12; i++) - data->f2x9cx30[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x30 + i); - for (i = 0; i < 12; i++) - data->f2x9cx40[i] = read_amd_dct_index_register_dct(dev_fn2, node, channel, 0x98, 0x40 + i); - } - - /* Other */ - /* ECC scrub rate control */ - data->f3x58 = read_config32_dct(dev_fn3, node, 0, 0x58); - - /* ECC scrub location */ - write_config32_dct(dev_fn3, node, 0, 0x58, 0x0); /* Disable sequential scrub to work around non-atomic location read */ - data->f3x5c = read_config32_dct(dev_fn3, node, 0, 0x5c); - data->f3x60 = read_config32_dct(dev_fn3, node, 0, 0x60); - write_config32_dct(dev_fn3, node, 0, 0x58, data->f3x58); /* Re-enable sequential scrub */ - } - } -} - -static void write_config32_dct_nbpstate(pci_devfn_t dev, uint8_t node, - uint8_t dct, uint8_t nb_pstate, - uint32_t reg, uint32_t value) -{ - uint32_t dword; - pci_devfn_t dev_fn1 = PCI_DEV(0, 0x18 + node, 1); - - /* Select DCT */ - dword = pci_read_config32(dev_fn1, 0x10c); - dword &= ~0x1; - dword |= (dct & 0x1); - pci_write_config32(dev_fn1, 0x10c, dword); - - /* Select NB Pstate index */ - dword = pci_read_config32(dev_fn1, 0x10c); - dword &= ~(0x3 << 4); - dword |= (nb_pstate & 0x3) << 4; - pci_write_config32(dev_fn1, 0x10c, dword); - - pci_write_config32(dev, reg, value); -} - -static void write_amd_dct_index_register(pci_devfn_t dev, - uint32_t index_ctl_reg, uint32_t index, - uint32_t value) -{ - uint32_t dword; - - pci_write_config32(dev, index_ctl_reg + 0x04, value); - index |= (1 << 30); - pci_write_config32(dev, index_ctl_reg, index); - do { - dword = pci_read_config32(dev, index_ctl_reg); - } while (!(dword & (1 << 31))); -} - -static void write_amd_dct_index_register_dct(pci_devfn_t dev, uint8_t node, - uint8_t dct, - uint32_t index_ctl_reg, - uint32_t index, uint32_t value) -{ - if (is_fam15h()) { - uint32_t dword; - pci_devfn_t dev_fn1 = PCI_DEV(0, 0x18 + node, 1); - - /* Select DCT */ - dword = pci_read_config32(dev_fn1, 0x10c); - dword &= ~0x1; - dword |= (dct & 0x1); - pci_write_config32(dev_fn1, 0x10c, dword); - } else { - /* Apply offset */ - index_ctl_reg += dct * 0x100; - } - - return write_amd_dct_index_register(dev, index_ctl_reg, index, value); -} - -void restore_mct_data_from_save_variable(struct amd_s3_persistent_data *persistent_data, uint8_t training_only) -{ - uint8_t i; - uint8_t j; - uint8_t node; - uint8_t channel; - uint8_t ganged; - uint8_t dct_enabled; - uint32_t dword; - - if (training_only) { - /* Only restore the Receiver Enable and DQS training registers */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - /* Restore training parameters */ - for (i = 0; i < 4; i++) - for (j = 0; j < 3; j++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, (0x01 + i) + (0x100 * j), data->f2x9cx3_0_0_3_1[i][j]); - for (i = 0; i < 4; i++) - for (j = 0; j < 3; j++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, (0x05 + i) + (0x100 * j), data->f2x9cx3_0_0_7_5[i][j]); - - for (i = 0; i < 12; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x10 + i, data->f2x9cx10[i]); - for (i = 0; i < 12; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x20 + i, data->f2x9cx20[i]); - - if (CONFIG(DIMM_DDR3)) { - for (i = 0; i < 12; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x30 + i, data->f2x9cx30[i]); - for (i = 0; i < 12; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x40 + i, data->f2x9cx40[i]); - } - - /* Restore MaxRdLatency */ - if (is_fam15h()) { - for (i = 0; i < 4; i++) - write_config32_dct_nbpstate(PCI_DEV(0, 0x18 + node, 2), node, channel, i, 0x210, data->f2x210[i]); - } else { - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x78, data->f2x78); - } - - /* Other timing control registers */ - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x8c, data->f2x8c); - } - } - - return; - } - - /* Load data from data structure into DCTs */ - /* Stage 1 */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - pci_write_config32(PCI_DEV(0, 0x18 + node, 2), 0x110, data->f2x110); - } - } - - /* Stage 2 */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x40, data->f1x40); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x44, data->f1x44); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x48, data->f1x48); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x4c, data->f1x4c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x50, data->f1x50); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x54, data->f1x54); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x58, data->f1x58); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x5c, data->f1x5c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x60, data->f1x60); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x64, data->f1x64); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x68, data->f1x68); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x6c, data->f1x6c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x70, data->f1x70); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x74, data->f1x74); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x78, data->f1x78); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x7c, data->f1x7c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0xf0, data->f1xf0); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x120, data->f1x120); - write_config32_dct(PCI_DEV(0, 0x18 + node, 1), node, channel, 0x124, data->f1x124); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x10c, data->f2x10c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x114, data->f2x114); - if (is_fam15h()) - /* Do not set LockDramCfg or CC6SaveEn at this time */ - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x118, data->f2x118 & ~(0x3 << 18)); - else - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x118, data->f2x118); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x11c, data->f2x11c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x1b0, data->f2x1b0); - write_config32_dct(PCI_DEV(0, 0x18 + node, 3), node, channel, 0x44, data->f3x44); - for (i = 0; i < 16; i++) { - wrmsr_uint64_t(MTRR_PHYS_BASE(0) | i, - data->msr0000020[i]); - } - wrmsr_uint64_t(MTRR_FIX_64K_00000, data->msr00000250); - wrmsr_uint64_t(MTRR_FIX_16K_80000, data->msr00000258); - /* FIXME - * Restoring these MSRs causes a hang on resume due to - * destroying CAR while still executing from CAR! - * For now, skip restoration... - */ - // for (i = 0; i < 8; i++) - // wrmsr_uint64_t(0x00000260 | (i + 8), data->msr0000026[i]); - wrmsr_uint64_t(MTRR_DEF_TYPE_MSR, data->msr000002ff); - wrmsr_uint64_t(SYSCFG_MSR, data->msrc0010010); - wrmsr_uint64_t(TOP_MEM, data->msrc001001a); - wrmsr_uint64_t(TOP_MEM2, data->msrc001001d); - wrmsr_uint64_t(NB_CFG_MSR, data->msrc001001f); - } - } - - /* Stage 3 */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - if (is_fam15h()) - ganged = 0; - else - ganged = !!(data->f2x110 & 0x10); - if ((ganged == 1) && (channel > 0)) - continue; - - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x40, data->f2x40); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x44, data->f2x44); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x48, data->f2x48); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x4c, data->f2x4c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x50, data->f2x50); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x54, data->f2x54); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x58, data->f2x58); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x5c, data->f2x5c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x60, data->f2x60); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x64, data->f2x64); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x68, data->f2x68); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x6c, data->f2x6c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x78, data->f2x78); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x7c, data->f2x7c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x80, data->f2x80); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x84, data->f2x84); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x88, data->f2x88); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x8c, data->f2x8c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x90, data->f2x90); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0xa4, data->f2xa4); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0xa8, data->f2xa8); - } - } - - /* Family 15h-specific configuration */ - if (is_fam15h()) { - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - /* Initialize DCT */ - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0000000b, 0x80000000); - dword = read_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe013); - dword &= ~0xffff; - dword |= 0x118; - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe013, dword); - - /* Restore values */ - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x200, data->f2x200); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x204, data->f2x204); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x208, data->f2x208); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x20c, data->f2x20c); - for (i = 0; i < 4; i++) - write_config32_dct_nbpstate(PCI_DEV(0, 0x18 + node, 2), node, channel, i, 0x210, data->f2x210[i]); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x214, data->f2x214); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x218, data->f2x218); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x21c, data->f2x21c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x22c, data->f2x22c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x230, data->f2x230); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x234, data->f2x234); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x238, data->f2x238); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x23c, data->f2x23c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x240, data->f2x240); - - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe013, data->f2x9cx0d0fe013); - for (i = 0; i < 9; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f001f | (i << 8), data->f2x9cx0d0f0_8_0_1f[i]); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f201f, data->f2x9cx0d0f201f); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f211f, data->f2x9cx0d0f211f); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f221f, data->f2x9cx0d0f221f); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f801f, data->f2x9cx0d0f801f); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f811f, data->f2x9cx0d0f811f); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f821f, data->f2x9cx0d0f821f); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc01f, data->f2x9cx0d0fc01f); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc11f, data->f2x9cx0d0fc11f); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc21f, data->f2x9cx0d0fc21f); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f4009, data->f2x9cx0d0f4009); - - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2031, data->f2x9cx0d0f2031); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2131, data->f2x9cx0d0f2131); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2231, data->f2x9cx0d0f2231); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8031, data->f2x9cx0d0f8031); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8131, data->f2x9cx0d0f8131); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8231, data->f2x9cx0d0f8231); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc031, data->f2x9cx0d0fc031); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc131, data->f2x9cx0d0fc131); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc231, data->f2x9cx0d0fc231); - for (i = 0; i < 9; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0031 | (i << 8), data->f2x9cx0d0f0_0_f_31[i]); - - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8021, data->f2x9cx0d0f8021); - - if (channel == 1) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe00a, data->f2x9cx0d0fe00a); - } - } - } - - /* Stage 4 */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - if (is_fam15h()) - ganged = 0; - else - ganged = !!(data->f2x110 & 0x10); - if ((ganged == 1) && (channel > 0)) - continue; - - if (is_fam15h()) { - /* Program PllLockTime = 0x190 */ - dword = read_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe006); - dword &= ~0xffff; - dword |= 0x190; - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe006, dword); - - /* Program MemClkFreqVal = 0 */ - dword = read_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x94); - dword &= (0x1 << 7); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x94, dword); - - /* Restore DRAM Address/Timing Control Register */ - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x04, data->f2x9cx04); - } else { - /* Disable PHY auto-compensation engine */ - dword = read_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x08); - if (!(dword & (1 << 30))) { - dword |= (1 << 30); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x08, dword); - - /* Wait for 5us */ - mct_Wait(100); - } - } - - /* Restore DRAM Configuration High Register */ - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x94, data->f2x94); - } - } - - /* Stage 5 */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - if (is_fam15h()) - ganged = 0; - else - ganged = !!(data->f2x110 & 0x10); - if ((ganged == 1) && (channel > 0)) - continue; - - dct_enabled = !(data->f2x94 & (1 << 14)); - if (!dct_enabled) - continue; - - /* Wait for any pending PHY frequency changes to complete */ - do { - dword = read_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x94); - } while (dword & (1 << 21)); - - if (is_fam15h()) { - /* Program PllLockTime = 0xf */ - dword = read_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe006); - dword &= ~0xffff; - dword |= 0xf; - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe006, dword); - } else { - /* Enable PHY auto-compensation engine */ - dword = read_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x08); - dword &= ~(1 << 30); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x08, dword); - } - } - } - - /* Wait for 750us */ - mct_Wait(15000); - - /* Stage 6 */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - for (i = 0; i < 9; i++) - for (j = 0; j < 3; j++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0000 | (i << 8) | (j * 4), data->f2x9cx0d0f0_f_8_0_0_8_4_0[i][j]); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x00, data->f2x9cx00); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0a, data->f2x9cx0a); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0c, data->f2x9cx0c); - } - } - - /* Family 15h-specific configuration */ - if (is_fam15h()) { - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - dword = read_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe003); - dword |= (0x3 << 13); /* DisAutoComp, DisablePredriverCal = 1 */ - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe003, dword); - - for (i = 0; i < 9; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0006 | (i << 8), data->f2x9cx0d0f0_8_0_06[i]); - for (i = 0; i < 9; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f000a | (i << 8), data->f2x9cx0d0f0_8_0_0a[i]); - for (i = 0; i < 9; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0002 | (i << 8), (0x8000 | data->f2x9cx0d0f0_8_0_02[i])); - - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8006, data->f2x9cx0d0f8006); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f800a, data->f2x9cx0d0f800a); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8106, data->f2x9cx0d0f8106); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f810a, data->f2x9cx0d0f810a); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc006, data->f2x9cx0d0fc006); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc00a, data->f2x9cx0d0fc00a); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc00e, data->f2x9cx0d0fc00e); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc012, data->f2x9cx0d0fc012); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8002, (0x8000 | data->f2x9cx0d0f8002)); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f8102, (0x8000 | data->f2x9cx0d0f8102)); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fc002, (0x8000 | data->f2x9cx0d0fc002)); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2002, (0x8000 | data->f2x9cx0d0f2002)); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2102, (0x8000 | data->f2x9cx0d0f2102)); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2202, (0x8000 | data->f2x9cx0d0f2202)); - - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe003, data->f2x9cx0d0fe003); - } - } - } - - /* Stage 7 */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - if (is_fam15h()) - ganged = 0; - else - ganged = !!(data->f2x110 & 0x10); - if ((ganged == 1) && (channel > 0)) - continue; - - if (!is_fam15h()) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x04, data->f2x9cx04); - } - } - - /* Stage 8 */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - dct_enabled = !(data->f2x94 & (1 << 14)); - if (!dct_enabled) - continue; - - if (is_fam15h()) - ganged = 0; - else - ganged = !!(data->f2x110 & 0x10); - if ((ganged == 1) && (channel > 0)) - continue; - - printk(BIOS_SPEW, "Taking DIMMs out of self refresh node: %d channel: %d\n", node, channel); - - /* Exit self refresh mode */ - dword = read_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x90); - dword |= (1 << 1); - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x90, dword); - } - } - - /* Stage 9 */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - dct_enabled = !(data->f2x94 & (1 << 14)); - if (!dct_enabled) - continue; - - printk(BIOS_SPEW, "Waiting for DIMMs to exit self refresh node: %d channel: %d\n", node, channel); - - /* Wait for transition from self refresh mode to complete */ - do { - dword = read_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x90); - } while (dword & (1 << 1)); - - /* Restore registers */ - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe006, data->f2x9cx0d0fe006); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0fe007, data->f2x9cx0d0fe007); - } - } - - /* Stage 10 */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - for (i = 0; i < 12; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x10 + i, data->f2x9cx10[i]); - for (i = 0; i < 12; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x20 + i, data->f2x9cx20[i]); - for (i = 0; i < 4; i++) - for (j = 0; j < 3; j++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, (0x01 + i) + (0x100 * j), data->f2x9cx3_0_0_3_1[i][j]); - for (i = 0; i < 4; i++) - for (j = 0; j < 3; j++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, (0x05 + i) + (0x100 * j), data->f2x9cx3_0_0_7_5[i][j]); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d, data->f2x9cx0d); - for (i = 0; i < 9; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0013 | (i << 8), data->f2x9cx0d0f0_f_0_13[i]); - for (i = 0; i < 9; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0030 | (i << 8), data->f2x9cx0d0f0_f_0_30[i]); - for (i = 0; i < 4; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f2030 | (i << 8), data->f2x9cx0d0f2_f_0_30[i]); - for (i = 0; i < 2; i++) - for (j = 0; j < 3; j++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f0000 | (i << 8) | (j * 4), data->f2x9cx0d0f8_8_4_0[i][j]); - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x0d0f812f, data->f2x9cx0d0f812f); - } - } - - /* Stage 11 */ - if (CONFIG(DIMM_DDR3)) { - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - for (i = 0; i < 12; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x30 + i, data->f2x9cx30[i]); - for (i = 0; i < 12; i++) - write_amd_dct_index_register_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x98, 0x40 + i, data->f2x9cx40[i]); - } - } - } - - /* Other */ - for (node = 0; node < MAX_NODES_SUPPORTED; node++) { - for (channel = 0; channel < 2; channel++) { - struct amd_s3_persistent_mct_channel_data *data = &persistent_data->node[node].channel[channel]; - if (!persistent_data->node[node].node_present) - continue; - - /* ECC scrub location */ - write_config32_dct(PCI_DEV(0, 0x18 + node, 3), node, 0, 0x5c, data->f3x5c); - write_config32_dct(PCI_DEV(0, 0x18 + node, 3), node, 0, 0x60, data->f3x60); - - /* ECC scrub rate control */ - write_config32_dct(PCI_DEV(0, 0x18 + node, 3), node, 0, 0x58, data->f3x58); - - if (is_fam15h()) - /* Set LockDramCfg and CC6SaveEn */ - write_config32_dct(PCI_DEV(0, 0x18 + node, 2), node, channel, 0x118, data->f2x118); - } - } -} - -int8_t save_mct_information_to_nvram(void) -{ - uint8_t nvram; - uint8_t restored = 0; - - if (acpi_is_wakeup_s3()) - return 0; - - printk(BIOS_DEBUG, "Writing AMD DCT configuration to Flash\n"); - - struct spi_flash flash; - ssize_t s3nv_offset; - struct amd_s3_persistent_data *persistent_data; - - /* Allocate temporary data structures */ - persistent_data = malloc(sizeof(struct amd_s3_persistent_data)); - if (!persistent_data) { - printk(BIOS_DEBUG, "Could not allocate S3 data structure in RAM\n"); - return -1; - } - - /* Obtain MCT configuration data */ - copy_mct_data_to_save_variable(persistent_data); - - /* Save RAM SPD data at the same time */ - copy_cbmem_spd_data_to_save_variable(persistent_data, &restored); - - if (restored) { - /* Allow training bypass if DIMM configuration is unchanged on next boot */ - nvram = 1; - set_option("allow_spd_nvram_cache_restore", &nvram); - - printk(BIOS_DEBUG, "Hardware configuration unchanged since last boot; skipping write\n"); - free(persistent_data); - return 0; - } - - /* Obtain CBFS file offset */ - s3nv_offset = get_s3nv_file_offset(); - if (s3nv_offset == -1) { - free(persistent_data); - return -1; - } - - /* Align flash pointer to nearest boundary */ - s3nv_offset &= ~(CONFIG_S3_DATA_SIZE-1); - s3nv_offset += CONFIG_S3_DATA_SIZE; - - /* Initialize SPI and detect devices */ - spi_init(); - if (spi_flash_probe(0, 0, &flash)) { - printk(BIOS_DEBUG, "Could not find SPI device\n"); - return -1; - } - - spi_flash_volatile_group_begin(&flash); - - /* Erase and write data structure */ - spi_flash_erase(&flash, s3nv_offset, CONFIG_S3_DATA_SIZE); - spi_flash_write(&flash, s3nv_offset, - sizeof(struct amd_s3_persistent_data), persistent_data); - - /* Deallocate temporary data structures */ - free(persistent_data); - - spi_flash_volatile_group_end(&flash); - - /* Allow training bypass if DIMM configuration is unchanged on next boot */ - nvram = 1; - set_option("allow_spd_nvram_cache_restore", &nvram); - - return 0; -} - -int8_t restore_mct_information_from_nvram(uint8_t training_only) -{ - struct amd_s3_persistent_data *persistent_data; - - persistent_data = map_s3nv_in_nvram(); - if (!persistent_data) - return -1; - - restore_mct_data_from_save_variable(persistent_data, training_only); - - return 0; -} - -void calculate_and_store_spd_hashes(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - uint8_t dimm; - - for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) { - calculate_spd_hash(pDCTstat->spd_data.spd_bytes[dimm], &pDCTstat->spd_data.spd_hash[dimm]); - } -} - -void compare_nvram_spd_hashes(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat) -{ - uint8_t dimm; - - pDCTstat->spd_data.nvram_spd_match = 1; - for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) { - if (pDCTstat->spd_data.spd_hash[dimm] != pDCTstat->spd_data.nvram_spd_hash[dimm]) - pDCTstat->spd_data.nvram_spd_match = 0; - } -} diff --git a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.h b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.h deleted file mode 100644 index d13cb23c80..0000000000 --- a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.h +++ /dev/null @@ -1,31 +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 S3UTILS_H -#define S3UTILS_H - -#include "../wrappers/mcti.h" -#include "mct_d.h" - -#ifdef __RAMSTAGE__ -int8_t save_mct_information_to_nvram(void); -void copy_mct_data_to_save_variable(struct amd_s3_persistent_data* persistent_data); -#endif - -void calculate_and_store_spd_hashes(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); -void compare_nvram_spd_hashes(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat); - -#endif diff --git a/src/northbridge/amd/amdmct/wrappers/Makefile.inc b/src/northbridge/amd/amdmct/wrappers/Makefile.inc deleted file mode 100644 index 5773067138..0000000000 --- a/src/northbridge/amd/amdmct/wrappers/Makefile.inc +++ /dev/null @@ -1,5 +0,0 @@ -ifeq ($(CONFIG_NORTHBRIDGE_AMD_AMDFAM10),y) - -romstage-y += mcti_d.c - -endif diff --git a/src/northbridge/amd/amdmct/wrappers/mcti.h b/src/northbridge/amd/amdmct/wrappers/mcti.h deleted file mode 100644 index cc0e1b29b2..0000000000 --- a/src/northbridge/amd/amdmct/wrappers/mcti.h +++ /dev/null @@ -1,153 +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 - * 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 MCTI_H -#define MCTI_H - -#include <stdint.h> -#include <stdlib.h> -#include <pc80/mc146818rtc.h> - -struct DCTStatStruc; -struct MCTStatStruc; - -#define SERVER 0 -#define DESKTOP 1 -//#define MOBILE 2 -#define REV_F 0 -#define REV_DR 1 -#define REV_FDR 2 - -/*---------------------------------------------------------------------------- -COMMENT OUT ALL BUT 1 -----------------------------------------------------------------------------*/ -//#define BUILD_VERSION REV_F /*BIOS supports rev F only*/ -//#define BUILD_VERSION REV_DR /*BIOS supports rev 10 only*/ -//#define BUILD_VERSION REV_FDR /*BIOS supports both rev F and 10*/ - -/*---------------------------------------------------------------------------- -COMMENT OUT ALL BUT 1 -----------------------------------------------------------------------------*/ -#ifndef SYSTEM_TYPE -#define SYSTEM_TYPE SERVER -//#define SYSTEM_TYPE DESKTOP -//#define SYSTEM_TYPE MOBILE -#endif - -/*---------------------------------------------------------------------------- -UPDATE AS NEEDED -----------------------------------------------------------------------------*/ -#ifndef MAX_NODES_SUPPORTED -#define MAX_NODES_SUPPORTED 8 -#endif - -#ifndef MAX_DIMMS_SUPPORTED -#if CONFIG(DIMM_DDR3) - #define MAX_DIMMS_SUPPORTED 6 -#else - #define MAX_DIMMS_SUPPORTED 8 -#endif -#endif - -#ifndef MAX_CS_SUPPORTED -#define MAX_CS_SUPPORTED 8 -#endif - -#ifndef MCT_DIMM_SPARE_NO_WARM -#define MCT_DIMM_SPARE_NO_WARM 0 -#endif - -#ifndef MEM_MAX_LOAD_FREQ -#if CONFIG(DIMM_DDR3) - #define MEM_MAX_LOAD_FREQ 933 - #define MEM_MIN_PLATFORM_FREQ_FAM10 400 - #define MEM_MIN_PLATFORM_FREQ_FAM15 333 -#else /* AMD_FAM10_DDR2 */ - #define MEM_MAX_LOAD_FREQ 400 - #define MEM_MIN_PLATFORM_FREQ_FAM10 200 - /* DDR2 not available on Family 15h */ - #define MEM_MIN_PLATFORM_FREQ_FAM15 0 -#endif -#endif - -#define MCT_TRNG_KEEPOUT_START 0x00000C00 -#define MCT_TRNG_KEEPOUT_END 0x00000CFF - -#define NVRAM_DDR2_800 0 -#define NVRAM_DDR2_667 1 -#define NVRAM_DDR2_533 2 -#define NVRAM_DDR2_400 3 - -#define NVRAM_DDR3_1600 0 -#define NVRAM_DDR3_1333 1 -#define NVRAM_DDR3_1066 2 -#define NVRAM_DDR3_800 3 - -/* The recommended maximum GFX Upper Memory Area - * size is 256M, however, to be on the safe side - * move TOM down by 512M. - */ -#define MAXIMUM_GFXUMA_SIZE 0x20000000 - -/* Do not allow less than 16M of DRAM in 32-bit space. - * This number is not hardware constrained and can be - * changed as needed. - */ -#define MINIMUM_DRAM_BELOW_4G 0x1000000 - -static const uint16_t ddr2_limits[4] = {400, 333, 266, 200}; -static const uint16_t ddr3_limits[16] = {933, 800, 666, 533, 400, 333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -#if CONFIG(DIMM_DDR3) - #include <northbridge/amd/amdmct/mct_ddr3/mct_d.h> -#else - #include <northbridge/amd/amdmct/mct/mct_d.h> -#endif - -#if CONFIG(DIMM_DDR2) -void mctSaveDQSSigTmg_D(void); -void mctGetDQSSigTmg_D(void); -u8 mctSetNodeBoundary_D(void); -#endif -u16 mctGet_NVbits(u8 index); -void mctHookAfterDIMMpre(void); -void mctGet_MaxLoadFreq(struct DCTStatStruc *pDCTstat); -void mctAdjustAutoCycTmg_D(void); -void mctHookAfterAutoCycTmg(void); -void mctGetCS_ExcludeMap(void); -void mctHookBeforeECC(void); -void mctHookAfterECC(void); -void mctHookAfterAutoCfg(void); -void mctHookAfterPSCfg(void); -void mctHookAfterHTMap(void); -void mctHookAfterCPU(void); -void mctInitMemGPIOs_A_D(void); -void mctNodeIDDebugPort_D(void); -void mctWarmReset_D(void); -void mctHookBeforeDramInit(void); -void mctHookAfterDramInit(void); -void mctHookBeforeAnyTraining(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); -void mctHookAfterAnyTraining(void); -uint64_t mctGetLogicalCPUID_D(u8 node); - -#if CONFIG(DIMM_DDR3) -void vErratum372(struct DCTStatStruc *pDCTstat); -void vErratum414(struct DCTStatStruc *pDCTstat); -u32 mct_AdjustSPDTimings(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA, u32 val); -#endif - -#endif diff --git a/src/northbridge/amd/amdmct/wrappers/mcti_d.c b/src/northbridge/amd/amdmct/wrappers/mcti_d.c deleted file mode 100644 index b8042fe46d..0000000000 --- a/src/northbridge/amd/amdmct/wrappers/mcti_d.c +++ /dev/null @@ -1,543 +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. - */ - -/* Call-backs */ - -#include <arch/cpu.h> -#include <cpu/amd/msr.h> -#include <console/console.h> -#include <types.h> - -#include "mcti.h" - -#define NVRAM_DDR2_800 0 -#define NVRAM_DDR2_667 1 -#define NVRAM_DDR2_533 2 -#define NVRAM_DDR2_400 3 - -#define NVRAM_DDR3_1600 0 -#define NVRAM_DDR3_1333 1 -#define NVRAM_DDR3_1066 2 -#define NVRAM_DDR3_800 3 - -static inline uint8_t isfam15h(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; -} - -/* The recommended maximum GFX Upper Memory Area - * size is 256M, however, to be on the safe side - * move TOM down by 512M. - */ -#define MAXIMUM_GFXUMA_SIZE 0x20000000 - -/* Do not allow less than 16M of DRAM in 32-bit space. - * This number is not hardware constrained and can be - * changed as needed. - */ -#define MINIMUM_DRAM_BELOW_4G 0x1000000 - -u16 mctGet_NVbits(u8 index) -{ - u16 val = 0; - int nvram; - - switch (index) { - case NV_PACK_TYPE: -#if CONFIG_CPU_SOCKET_TYPE == 0x10 /* Socket F */ - val = 0; -#elif CONFIG_CPU_SOCKET_TYPE == 0x11 /* AM3 */ - val = 1; -#elif CONFIG_CPU_SOCKET_TYPE == 0x13 /* ASB2 */ - val = 4; -#elif CONFIG_CPU_SOCKET_TYPE == 0x14 /* C32 */ - val = 5; -#elif CONFIG_CPU_SOCKET_TYPE == 0x15 /* G34 */ - val = 3; -#elif CONFIG_CPU_SOCKET_TYPE == 0x16 /* FM2 */ - val = 6; -//#elif SYSTEM_TYPE == MOBILE -// val = 2; -#endif - break; - case NV_MAX_NODES: - val = MAX_NODES_SUPPORTED; - break; - case NV_MAX_DIMMS: - val = MAX_DIMMS_SUPPORTED; - //val = 8; - break; - case NV_MAX_DIMMS_PER_CH: - /* 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 - */ - val = 2; - break; - case NV_MAX_MEMCLK: - /* Maximum platform supported memclk */ - val = MEM_MAX_LOAD_FREQ; - - if (get_option(&nvram, "max_mem_clock") == CB_SUCCESS) { - int limit = val; - if (CONFIG(DIMM_DDR3)) - limit = ddr3_limits[nvram & 0xf]; - else if (CONFIG(DIMM_DDR2)) - limit = ddr2_limits[nvram & 0x3]; - val = min(limit, val); - } - break; - case NV_MIN_MEMCLK: - /* Minimum platform supported memclk */ - if (isfam15h()) - val = MEM_MIN_PLATFORM_FREQ_FAM15; - else - val = MEM_MIN_PLATFORM_FREQ_FAM10; - break; - case NV_ECC_CAP: -#if SYSTEM_TYPE == SERVER - val = 1; /* memory bus ECC capable */ -#else - val = 0; /* memory bus ECC not capable */ -#endif - break; - case NV_4RANKType: - /* Quad Rank DIMM slot type */ - val = 0; /* normal */ - //val = 1; /* R4 (registered DIMMs in AMD server configuration) */ - //val = 2; /* S4 (Unbuffered SO-DIMMS) */ - break; - case NV_BYPMAX: -#if !CONFIG(GFXUMA) - val = 4; -#elif CONFIG(GFXUMA) - val = 7; -#endif - break; - case NV_RDWRQBYP: -#if !CONFIG(GFXUMA) - val = 2; -#elif CONFIG(GFXUMA) - val = 3; -#endif - break; - case NV_MCTUSRTMGMODE: - val = 0; /* Automatic (recommended) */ - //val = 1; /* Limited */ - //val = 2; /* Manual */ - break; - case NV_MemCkVal: - //val = 0; /* 200MHz */ - //val = 1; /* 266MHz */ - val = 2; /* 333MHz */ - break; - case NV_BankIntlv: - /* Bank (chip select) interleaving */ - //val = 0; /* disabled */ - val = 1; /* enabled (recommended) */ - - if (get_option(&nvram, "interleave_chip_selects") == CB_SUCCESS) - val = !!nvram; - break; - case NV_MemHole: - //val = 0; /* Disabled */ - val = 1; /* Enabled (recommended) */ - break; - case NV_AllMemClks: - val = 0; /* Normal (only to slots that have enabled DIMMs) */ - //val = 1; /* Enable all memclocks */ - break; - case NV_SPDCHK_RESTRT: - val = 0; /* Exit current node initialization if any DIMM has SPD checksum error */ - //val = 1; /* Ignore faulty SPD checksum (DIMM will still be disabled), continue current node initialization */ - //val = 2; /* Override faulty SPD checksum (DIMM will be enabled), continue current node initialization */ - - if (get_option(&nvram, "dimm_spd_checksum") == CB_SUCCESS) - val = nvram & 0x3; - - if (val > 2) - val = 2; - - break; - case NV_DQSTrainCTL: - //val = 0; /*Skip dqs training */ - val = 1; /* Perform dqs training */ - break; - case NV_NodeIntlv: - val = 0; /* Disabled (recommended) */ - //val = 1; /* Enable */ - - if (get_option(&nvram, "interleave_nodes") == CB_SUCCESS) - val = !!nvram; - break; - case NV_BurstLen32: -#if !CONFIG(GFXUMA) - val = 0; /* 64 byte mode */ -#elif CONFIG(GFXUMA) - val = 1; /* 32 byte mode */ -#endif - break; - case NV_CKE_PDEN: - //val = 0; /* Disable */ - val = 1; /* Enable */ - break; - case NV_CKE_CTL: - val = 0; /* per channel control */ - //val = 1; /* per chip select control */ - break; - case NV_CLKHZAltVidC3: - val = 0; /* disable */ - //val = 1; /* enable */ - break; - case NV_BottomIO: - case NV_BottomUMA: - /* address bits [31:24] */ -#if !CONFIG(GFXUMA) - val = (CONFIG_MMCONF_BASE_ADDRESS >> 24); -#elif CONFIG(GFXUMA) - #if (CONFIG_MMCONF_BASE_ADDRESS < (MAXIMUM_GFXUMA_SIZE + MINIMUM_DRAM_BELOW_4G)) - #error "MMCONF_BASE_ADDRESS is too small" - #endif - val = ((CONFIG_MMCONF_BASE_ADDRESS - MAXIMUM_GFXUMA_SIZE) >> 24); -#endif - break; - case NV_ECC: -#if (SYSTEM_TYPE == SERVER) - val = 1; /* Enable */ -#else - val = 0; /* Disable */ -#endif - - if (get_option(&nvram, "ECC_memory") == CB_SUCCESS) - val = !!nvram; - break; - case NV_NBECC: -#if (SYSTEM_TYPE == SERVER) - val = 1; /* Enable */ -#else - val = 0; /* Disable */ -#endif - break; - case NV_ChipKill: -#if (SYSTEM_TYPE == SERVER) - val = 1; /* Enable */ -#else - val = 0; /* Disable */ -#endif - break; - case NV_ECCRedir: - /* - * 0: Disable - * 1: Enable - */ - val = 0; - - if (get_option(&nvram, "ECC_redirection") == CB_SUCCESS) - val = !!nvram; - break; - case NV_DramBKScrub: - /* - * 0x00: Disabled - * 0x01: 40ns - * 0x02: 80ns - * 0x03: 160ns - * 0x04: 320ns - * 0x05: 640ns - * 0x06: 1.28us - * 0x07: 2.56us - * 0x08: 5.12us - * 0x09: 10.2us - * 0x0a: 20.5us - * 0x0b: 41us - * 0x0c: 81.9us - * 0x0d: 163.8us - * 0x0e: 327.7us - * 0x0f: 655.4us - * 0x10: 1.31ms - * 0x11: 2.62ms - * 0x12: 5.24ms - * 0x13: 10.49ms - * 0x14: 20.97sms - * 0x15: 42ms - * 0x16: 84ms - */ - val = 0; - - if ((get_option(&nvram, "ecc_scrub_rate") == CB_SUCCESS) && (nvram <= 0x16)) - val = nvram; - break; - case NV_L2BKScrub: - val = 0; /* Disabled - See L2Scrub in BKDG */ - break; - case NV_L3BKScrub: - val = 0; /* Disabled - See L3Scrub in BKDG */ - break; - case NV_DCBKScrub: - val = 0; /* Disabled - See DcacheScrub in BKDG */ - break; - case NV_CS_SpareCTL: - val = 0; /* Disabled */ - //val = 1; /* Enabled */ - break; - case NV_SyncOnUnEccEn: - val = 0; /* Disabled */ - //val = 1; /* Enabled */ - break; - case NV_Unganged: - /* channel interleave is better performance than ganged mode at this time */ - val = 1; /* Enabled */ - //val = 0; /* Disabled */ - - if (get_option(&nvram, "interleave_memory_channels") == CB_SUCCESS) - val = !!nvram; - break; - case NV_ChannelIntlv: - val = 5; /* Not currently checked in mctchi_d.c */ - /* Bit 0 = 0 - Disable - * 1 - Enable - * Bits[2:1] = 00b - Address bits 6 - * 01b - Address bits 1 - * 10b - Hash*, XOR of address bits [20:16, 6] - * 11b - Hash*, XOR of address bits [20:16, 9] - */ - break; - } - - return val; -} - - -void mctHookAfterDIMMpre(void) -{ -} - - -void mctGet_MaxLoadFreq(struct DCTStatStruc *pDCTstat) -{ - pDCTstat->PresetmaxFreq = mctGet_NVbits(NV_MAX_MEMCLK); - - /* Determine the number of installed DIMMs */ - int ch1_count = 0; - int ch2_count = 0; - uint8_t ch1_registered = 0; - uint8_t ch2_registered = 0; - uint8_t ch1_voltage = 0; - uint8_t ch2_voltage = 0; - uint8_t highest_rank_count[2]; - uint8_t dimm; - int i; - for (i = 0; i < 15; i = i + 2) { - if (pDCTstat->DIMMValid & (1 << i)) - ch1_count++; - if (pDCTstat->DIMMValid & (1 << (i + 1))) - ch2_count++; - } - for (i = 0; i < MAX_DIMMS_SUPPORTED; i = i + 2) { - if (pDCTstat->DimmRegistered[i]) - ch1_registered = 1; - if (pDCTstat->DimmRegistered[i + 1]) - ch2_registered = 1; - } - if (CONFIG(DEBUG_RAM_SETUP)) { - printk(BIOS_DEBUG, "mctGet_MaxLoadFreq: Channel 1: %d DIMM(s) detected\n", ch1_count); - printk(BIOS_DEBUG, "mctGet_MaxLoadFreq: Channel 2: %d DIMM(s) detected\n", ch2_count); - } - -#if CONFIG(DIMM_DDR3) - for (i = 0; i < MAX_DIMMS_SUPPORTED; i = i + 2) { - if (pDCTstat->DIMMValid & (1 << i)) - ch1_voltage |= pDCTstat->DimmConfiguredVoltage[i]; - if (pDCTstat->DIMMValid & (1 << (i + 1))) - ch2_voltage |= pDCTstat->DimmConfiguredVoltage[i + 1]; - } -#endif - - for (i = 0; i < 2; i++) { - highest_rank_count[i] = 0x0; - for (dimm = 0; dimm < MAX_DIMMS_SUPPORTED; dimm++) { - if (pDCTstat->DimmRanks[dimm] > highest_rank_count[i]) - highest_rank_count[i] = pDCTstat->DimmRanks[dimm]; - } - } - - /* Set limits if needed */ - pDCTstat->PresetmaxFreq = mct_MaxLoadFreq(max(ch1_count, ch2_count), max(highest_rank_count[0], highest_rank_count[1]), (ch1_registered || ch2_registered), (ch1_voltage | ch2_voltage), pDCTstat->PresetmaxFreq); -} - -void mctAdjustAutoCycTmg_D(void) -{ -} - - -void mctHookAfterAutoCycTmg(void) -{ -} - - -void mctGetCS_ExcludeMap(void) -{ -} - - -void mctHookAfterAutoCfg(void) -{ -} - - -void mctHookAfterPSCfg(void) -{ -} - - -void mctHookAfterHTMap(void) -{ -} - - -void mctHookAfterCPU(void) -{ -} - - -#if CONFIG(DIMM_DDR2) -void mctSaveDQSSigTmg_D(void) -{ -} - -void mctGetDQSSigTmg_D(void) -{ -} -#endif - -void mctHookBeforeECC(void) -{ -} - -void mctHookAfterECC(void) -{ -} - -#ifdef UNUSED_CODE -void mctInitMemGPIOs_A(void) -{ -} -#endif - - -void mctInitMemGPIOs_A_D(void) -{ -} - - -void mctNodeIDDebugPort_D(void) -{ -} - - -void mctWarmReset_D(void) -{ -} - - -void mctHookBeforeDramInit(void) -{ -} - - -void mctHookAfterDramInit(void) -{ -} - -#if CONFIG(DIMM_DDR3) -void vErratum372(struct DCTStatStruc *pDCTstat) -{ - msr_t msr = rdmsr(NB_CFG_MSR); - - int nbPstate1supported = !(msr.hi & (1 << (NB_GfxNbPstateDis -32))); - - // is this the right way to check for NB pstate 1 or DDR3-1333 ? - if (((pDCTstat->PresetmaxFreq == 1333)||(nbPstate1supported)) - && (!pDCTstat->GangedMode)) { - /* DisableCf8ExtCfg */ - msr.hi &= ~(3 << (51 - 32)); - wrmsr(NB_CFG_MSR, msr); - } -} - -void vErratum414(struct DCTStatStruc *pDCTstat) -{ - int dct = 0; - for (; dct < 2 ; dct++) { - int dRAMConfigHi = Get_NB32(pDCTstat->dev_dct,0x94 + (0x100 * dct)); - int powerDown = dRAMConfigHi & (1 << PowerDownEn); - int ddr3 = dRAMConfigHi & (1 << Ddr3Mode); - int dRAMMRS = Get_NB32(pDCTstat->dev_dct,0x84 + (0x100 * dct)); - int pchgPDModeSel = dRAMMRS & (1 << PchgPDModeSel); - if (powerDown && ddr3 && pchgPDModeSel) - Set_NB32(pDCTstat->dev_dct,0x84 + (0x100 * dct), dRAMMRS & ~(1 << PchgPDModeSel)); - } -} -#endif - - -void mctHookBeforeAnyTraining(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA) -{ -#if CONFIG(DIMM_DDR3) - /* FIXME : as of 25.6.2010 errata 350 and 372 should apply to ((RB|BL|DA)-C[23])|(HY-D[01])|(PH-E0) but I don't find constants for all of them */ - if (pDCTstatA->LogicalCPUID & (AMD_DRBH_Cx | AMD_DR_Dx)) { - vErratum372(pDCTstatA); - vErratum414(pDCTstatA); - } -#endif -} - -#if CONFIG(DIMM_DDR3) -u32 mct_AdjustSPDTimings(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA, u32 val) -{ - if (pDCTstatA->LogicalCPUID & AMD_DR_Bx) { - if (pDCTstatA->Status & (1 << SB_Registered)) { - val ++; - } - } - return val; -} -#endif - -void mctHookAfterAnyTraining(void) -{ -} - -uint64_t mctGetLogicalCPUID_D(u8 node) -{ - return mctGetLogicalCPUID(node); -} - -#if CONFIG(DIMM_DDR2) -u8 mctSetNodeBoundary_D(void) -{ - return 0; -} -#endif |