From 730a043fb6cb4dd3cb5af8f8640365727b598648 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Fri, 16 Oct 2015 13:51:51 -0500 Subject: cpu/amd: Add initial AMD Family 15h support TEST: Booted ASUS KGPE-D16 with single Opteron 6380 * Unbuffered DDR3 DIMMs tested and working * Suspend to RAM (S3) tested and working Change-Id: Idffd2ce36ce183fbfa087e5ba69a9148f084b45e Signed-off-by: Timothy Pearson Reviewed-on: http://review.coreboot.org/11966 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/northbridge/amd/amdmct/wrappers/mcti.h | 14 ++++++--- src/northbridge/amd/amdmct/wrappers/mcti_d.c | 43 ++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 9 deletions(-) (limited to 'src/northbridge/amd/amdmct/wrappers') diff --git a/src/northbridge/amd/amdmct/wrappers/mcti.h b/src/northbridge/amd/amdmct/wrappers/mcti.h index 7bfc25dc89..762ef11f44 100644 --- a/src/northbridge/amd/amdmct/wrappers/mcti.h +++ b/src/northbridge/amd/amdmct/wrappers/mcti.h @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2007 Advanced Micro Devices, Inc. + * Copyright (C) 2015 Timothy Pearson , 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 @@ -58,10 +59,15 @@ UPDATE AS NEEDED #endif #ifndef MEM_MAX_LOAD_FREQ -#if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */ - #define MEM_MAX_LOAD_FREQ 800 -#else - #define MEM_MAX_LOAD_FREQ 400 +#if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_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 diff --git a/src/northbridge/amd/amdmct/wrappers/mcti_d.c b/src/northbridge/amd/amdmct/wrappers/mcti_d.c index fbcfd871a2..48ab8007ab 100644 --- a/src/northbridge/amd/amdmct/wrappers/mcti_d.c +++ b/src/northbridge/amd/amdmct/wrappers/mcti_d.c @@ -40,7 +40,7 @@ #define MINIMUM_DRAM_BELOW_4G 0x1000000 static const uint16_t ddr2_limits[4] = {400, 333, 266, 200}; -static const uint16_t ddr3_limits[4] = {800, 666, 533, 400}; +static const uint16_t ddr3_limits[16] = {933, 800, 666, 533, 400, 333, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static u16 mctGet_NVbits(u8 index) { @@ -77,12 +77,19 @@ static u16 mctGet_NVbits(u8 index) if (get_option(&nvram, "max_mem_clock") == CB_SUCCESS) { int limit = val; if (IS_ENABLED(CONFIG_DIMM_DDR3)) - limit = ddr3_limits[nvram & 3]; + limit = ddr3_limits[nvram & 0xf]; else if (IS_ENABLED(CONFIG_DIMM_DDR2)) - limit = ddr2_limits[nvram & 3]; + limit = ddr2_limits[nvram & 0x3]; val = min(limit, val); } break; + case NV_MIN_MEMCLK: + /* Minimum platform supported memclk */ + if (is_fam15h()) + 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 */ @@ -250,6 +257,9 @@ static u16 mctGet_NVbits(u8 index) 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; @@ -299,6 +309,9 @@ static void mctGet_MaxLoadFreq(struct DCTStatStruc *pDCTstat) 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]; int i; for (i = 0; i < 15; i = i + 2) { if (pDCTstat->DIMMValid & (1 << i)) @@ -317,8 +330,28 @@ static void mctGet_MaxLoadFreq(struct DCTStatStruc *pDCTstat) printk(BIOS_DEBUG, "mctGet_MaxLoadFreq: Channel 2: %d DIMM(s) detected\n", ch2_count); } +#if (CONFIG_DIMM_SUPPORT & 0x000F)==0x0005 /* AMD_FAM10_DDR3 */ + uint8_t dimm; + + for (i = 0; i < 15; 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]; + } + + for (i = 0; i < 2; i++) { + sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[i]; + highest_rank_count[i] = 0x0; + for (dimm = 0; dimm < 8; dimm++) { + if (pDCTData->DimmRanks[dimm] > highest_rank_count[i]) + highest_rank_count[i] = pDCTData->DimmRanks[dimm]; + } + } +#endif + /* Set limits if needed */ - pDCTstat->PresetmaxFreq = mct_MaxLoadFreq(max(ch1_count, ch2_count), (ch1_registered || ch2_registered), pDCTstat->PresetmaxFreq); + 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); } #ifdef UNUSED_CODE @@ -482,7 +515,7 @@ static void mctHookAfterAnyTraining(void) { } -static u32 mctGetLogicalCPUID_D(u8 node) +static uint64_t mctGetLogicalCPUID_D(u8 node) { return mctGetLogicalCPUID(node); } -- cgit v1.2.3