mail.coreboot.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
List overview
Download
coreboot-gerrit
November 2015
----- 2024 -----
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
coreboot-gerrit@coreboot.org
1 participants
1544 discussions
Start a n
N
ew thread
Patch set updated for coreboot: northbridge/amd/amdht: Fix poor performance on Family 15h CPUs
by Timothy Pearson
16 Nov '15
16 Nov '15
Timothy Pearson (tpearson(a)raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/12030
-gerrit commit c6b5490741be05c366fb8a38dcd5786d2602c731 Author: Timothy Pearson <tpearson(a)raptorengineeringinc.com> Date: Fri Aug 7 19:05:45 2015 -0500 northbridge/amd/amdht: Fix poor performance on Family 15h CPUs Change-Id: I37db191c144c81aba5d4a1e6291db5669a35a31a Signed-off-by: Timothy Pearson <tpearson(a)raptorengineeringinc.com> --- src/northbridge/amd/amdht/h3ncmn.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/northbridge/amd/amdht/h3ncmn.c b/src/northbridge/amd/amdht/h3ncmn.c index 29524af..c97d592 100644 --- a/src/northbridge/amd/amdht/h3ncmn.c +++ b/src/northbridge/amd/amdht/h3ncmn.c @@ -1555,6 +1555,10 @@ static void setLinkData(sMainData *pDat, cNorthBridge *nb) } 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);
1
0
0
0
Patch set updated for coreboot: amd/amdmct/mct_ddr3: Fix poor performance on Family 15h CPUs
by Timothy Pearson
16 Nov '15
16 Nov '15
Timothy Pearson (tpearson(a)raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/12029
-gerrit commit 2c1a6b75fe41d932f5bffc7341b62ba4cb4b1e30 Author: Timothy Pearson <tpearson(a)raptorengineeringinc.com> Date: Fri Aug 7 19:05:29 2015 -0500 amd/amdmct/mct_ddr3: Fix poor performance on Family 15h CPUs Change-Id: Ib6bc197e43e40ba2b923b1eb1229bacafc8be360 Signed-off-by: Timothy Pearson <tpearson(a)raptorengineeringinc.com> --- src/northbridge/amd/amdmct/mct_ddr3/mct_d.c | 370 +++++++++++++++++++++---- src/northbridge/amd/amdmct/mct_ddr3/mct_d.h | 1 + src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c | 65 ++++- src/northbridge/amd/amdmct/mct_ddr3/mctproc.c | 49 +++- src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c | 195 ++++++++++++- src/northbridge/amd/amdmct/mct_ddr3/mctwl.c | 4 + 6 files changed, 604 insertions(+), 80 deletions(-) diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c index 283d897..b80918c 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c @@ -32,6 +32,8 @@ * supported. */ +// #define DEBUG_DIMM_SPD 1 + static u8 ReconfigureDIMMspare_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA); static void DQSTiming_D(struct MCTStatStruc *pMCTstat, @@ -168,7 +170,8 @@ static u32 mct_MR1Odt_RDimm(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dct, u32 MrsChipSel); static u32 mct_DramTermDyn_RDimm(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u8 dimm); -static u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, u8 dct, u32 misc2); +static u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, + uint8_t dct, uint32_t misc2, uint32_t DramControl); static void mct_BeforeDQSTrainSamp(struct DCTStatStruc *pDCTstat); static void mct_WriteLevelization_HW(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA, uint8_t Pass); @@ -1366,6 +1369,8 @@ static uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dc static 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; @@ -1388,6 +1393,8 @@ static void set_2t_configuration(struct MCTStatStruc *pMCTstat, else dword &= ~(0x1 << 20); /* Clear 2T CMD mode */ Set_NB32_DCT(dev, dct, reg, dword); + + printk(BIOS_DEBUG, "%s: Done\n", __func__); } static void precise_ndelay_fam15(struct MCTStatStruc *pMCTstat, uint32_t nanoseconds) { @@ -2009,6 +2016,7 @@ static void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, /* Disable training mode */ uint8_t lane; uint8_t dimm; + uint16_t sword; uint8_t receiver; uint8_t max_lane; uint8_t ecc_enabled; @@ -2023,21 +2031,37 @@ static void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, 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; + if (pDCTstat->DIMMValidDCT[dct] == 0) + ddr_voltage_index = 1; + else + ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct); + + ddr_voltage_index = dct_ddr_voltage_index(pDCTstat, dct); + max_dimms_installable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH); + ecc_enabled = !!(pMCTstat->GStatus & 1 << GSB_ECCDIMMs); if (ecc_enabled) max_lane = 9; @@ -2071,6 +2095,24 @@ static void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, 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. @@ -2106,7 +2148,7 @@ static void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, } /* Convert the difference to MEMCLKs */ - cdd_trdrddd = (((cdd_trdrddd >> 5) & 0x1f) + 1) / 2; + cdd_trdrddd = (((cdd_trdrddd + (1 << 6) - 1) >> 6) & 0xf); /* Calculate Trdrddd */ delay = (read_odt_delay + 3) * 2; @@ -2152,7 +2194,7 @@ static void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, } /* Convert the difference to MEMCLKs */ - cdd_twrwrdd = (((cdd_twrwrdd >> 5) & 0x1f) + 1) / 2; + cdd_twrwrdd = (((cdd_twrwrdd + (1 << 6) - 1) >> 6) & 0xf); /* Calculate Twrwrdd */ delay = (write_odt_delay + 3) * 2; @@ -2171,6 +2213,107 @@ static void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, 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 */ @@ -2223,15 +2366,98 @@ static void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, } } - /* TODO - * Calculate Twrrd per section 2.10.5.5.3 of the Family 15h BKDG - */ - twrrd = 0xb; + /* Calculate the Critical Delay Difference for Twrrd */ + cdd_twrrd = 0; + for (receiver = 0; receiver < 8; receiver += 2) { + dimm = (receiver >> 1); - /* TODO - * Calculate TrwtTO per section 2.10.5.5.4 of the Family 15h BKDG - */ - trwtto = 0x16; + 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 < max_lane; 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 { + sword = (((int16_t)cdd_twrrd + 1 - ((int16_t)write_early * 2)) + 1) / 2; + if (sword < 0) + sword = 0; + if (((uint16_t)sword) > write_odt_delay) + dword = sword; + 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 < max_lane; 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; + sword = (((int16_t)cdd_trwtto - 1 + ((int16_t)write_early * 2)) + 1) / 2; + sword += latency_difference + 3; + if (sword < 0) + sword = 0; + if (((uint16_t)sword) > min_value) + trwtto = (uint16_t)sword; + else + trwtto = min_value; dword = Get_NB32_DCT(dev, dct, 0xa4); /* DRAM Controller Temperature Throttle */ dword &= ~(0x1 << 11); /* BwCapEn = 0 */ @@ -2242,6 +2468,7 @@ static void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, 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 @@ -2249,22 +2476,6 @@ static void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, * otherwise semi-random lockups will occur due to misconfigured scrubbing hardware! */ - /* FIXME - * The BKDG-recommended settings cause memory corruption on the ASUS KGPE-D16. - * Investigate and fix... - */ -#if 0 - /* Fam15h BKDG section 2.10.5.5.1 */ - 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); /* TrdrdDd = trdrddd */ - dword |= (trdrddd & 0xf); - Set_NB32_DCT(dev, dct, 0x218, dword); /* DRAM Timing 5 */ -#endif - /* Fam15h BKDG section 2.10.5.5.2 */ dword = Get_NB32_DCT(dev, dct, 0x214); /* DRAM Timing 4 */ dword &= ~(0xf << 16); /* TwrwrSdSc = 0x1 */ @@ -2277,8 +2488,14 @@ static void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, /* 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 */ @@ -2289,12 +2506,6 @@ static void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat, dword |= ((((dword >> 8) & 0x1f) + 1) << 16); Set_NB32_DCT(dev, dct, 0x21c, dword); /* DRAM Timing 6 */ - /* 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 */ - /* Enable prefetchers */ dword = Get_NB32(dev, 0x11c); /* Memory Controller Configuration High */ dword &= ~(0x1 << 13); /* PrefIoDis = 0 */ @@ -2383,6 +2594,8 @@ static void DQSTiming_D(struct MCTStatStruc *pMCTstat, mct_TrainDQSPos_D(pMCTstat, pDCTstatA); + TrainMaxRdLatency_En_D(pMCTstat, pDCTstatA); + if (is_fam15h()) exit_training_mode_fam15(pMCTstat, pDCTstatA); else @@ -2961,6 +3174,13 @@ static void ClearDCT_D(struct MCTStatStruc *pMCTstat, } 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 */ @@ -3079,14 +3299,30 @@ static void SPD2ndTiming(struct MCTStatStruc *pMCTstat, /* Convert DRAM CycleTiming values and store into DCT structure */ byte = pDCTstat->DIMMAutoSpeed; - if (byte == 7) - tCK16x = 20; - else if (byte == 6) - tCK16x = 24; - else if (byte == 5) - tCK16x = 30; - else - tCK16x = 40; + 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. @@ -3119,7 +3355,7 @@ static void SPD2ndTiming(struct MCTStatStruc *pMCTstat, val = Max_TrpT; pDCTstat->Trp = val; - /*Trrd*/ + /* Trrd */ pDCTstat->DIMMTrrd = Trrd; val = Trrd / tCK16x; if (Trrd % tCK16x) { /* round up number of busclocks */ @@ -3237,21 +3473,31 @@ static void SPD2ndTiming(struct MCTStatStruc *pMCTstat, dword = Get_NB32_DCT(dev, dct, 0x200); /* DRAM Timing 0 */ dword &= ~(0x3f1f1f1f); - dword |= ((pDCTstat->Tras + 0xf) & 0x3f) << 24; /* Tras */ - dword |= ((pDCTstat->Trp + 0x5) & 0x1f) << 16; /* Trp */ - dword |= ((pDCTstat->Trcd + 0x5) & 0x1f) << 8; /* Trcd */ + 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 + 0x4) & 0xf) << 24; /* Trtp */ - if (pDCTstat->Tfaw != 0) - dword |= ((((pDCTstat->Tfaw - 0x1) * 2) + 0x10) & 0x3f) << 16; /* FourActWindow */ - dword |= ((pDCTstat->Trrd + 0x4) & 0xf) << 8; /* Trrd */ - dword |= ((pDCTstat->Trc + 0xb) & 0x3f); /* Trc */ + 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] = 0x4; dword = Get_NB32_DCT(dev, dct, 0x208); /* DRAM Timing 2 */ dword &= ~(0x07070707); dword |= (pDCTstat->Trfc[3] & 0x7) << 24; /* Trfc3 */ @@ -3262,14 +3508,14 @@ static void SPD2ndTiming(struct MCTStatStruc *pMCTstat, dword = Get_NB32_DCT(dev, dct, 0x20c); /* DRAM Timing 3 */ dword &= ~(0x00000f00); - dword |= ((pDCTstat->Twtr + 0x4) & 0xf) << 8; /* Twtr */ + 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 + 0x4) & 0x1f); /* Twr */ + 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))) { @@ -3865,6 +4111,8 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat, } } + 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); @@ -3876,7 +4124,6 @@ static u8 AutoConfig_D(struct MCTStatStruc *pMCTstat, Set_NB32_DCT(dev, dct, 0x78, DramControl); Set_NB32_DCT(dev, dct, 0x88, DramTimingLo); Set_NB32_DCT(dev, dct, 0xa0, DramConfigMisc); - DramConfigMisc2 = mct_SetDramConfigMisc2(pDCTstat, dct, DramConfigMisc2); Set_NB32_DCT(dev, dct, 0xa8, DramConfigMisc2); Set_NB32_DCT(dev, dct, 0x90, DramConfigLo); ProgDramMRSReg_D(pMCTstat, pDCTstat, dct); @@ -5247,6 +5494,16 @@ static void mct_PhyController_Config(struct MCTStatStruc *pMCTstat, 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. @@ -5291,8 +5548,9 @@ static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat, mct_ExtMCTConfig_Dx(pDCTstat); } else { /* Family 15h CPUs */ - val = 0x0ce00f00 | 0x1 << 29; /* FlushWrOnStpGnt */ - val |= 0x10 << 2; /* MctWrLimit = 16 */ + 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); @@ -6532,8 +6790,8 @@ void ProgDramMRSReg_D(struct MCTStatStruc *pMCTstat, dword = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x84); if (is_fam15h()) { - dword |= DramMRS; dword &= ~0x00800003; + dword |= DramMRS; } else { dword &= ~0x00fc2f8f; dword |= DramMRS; diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h index eb4c74e..b72b9da 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h +++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h @@ -984,6 +984,7 @@ void UMAMemTyping_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat 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); diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c index 3615616..06597e2 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c @@ -20,6 +20,9 @@ static void write_dqs_receiver_enable_control_registers(uint16_t* current_total_ static void read_read_dqs_timing_control_registers(uint16_t* current_total_delay, uint32_t dev, uint8_t dct, uint8_t dimm, uint32_t index_reg); +static void dqsTrainMaxRdLatency_SW_Fam15(struct MCTStatStruc *pMCTstat, + struct DCTStatStruc *pDCTstat); + static void CalcEccDQSPos_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, u16 like, u8 scale, u8 ChipSel); @@ -214,6 +217,27 @@ void TrainReceiverEn_D(struct MCTStatStruc *pMCTstat, } } +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) { @@ -894,7 +918,7 @@ static void TrainDQSRdWrPos_D_Fam10(struct MCTStatStruc *pMCTstat, * Algorithm detailed in the Fam15h BKDG Rev. 3.14 section 2.10.5.8.5 */ static void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat, - struct DCTStatStruc *pDCTstat, uint8_t dct) + struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t calc_min) { uint8_t dimm; uint8_t lane; @@ -938,7 +962,8 @@ static void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat, p += (9 - dword); /* 2.10.5.8.5 (4) */ - p += 5; + if (!calc_min) + p += 5; /* 2.10.5.8.5 (5) */ dword = Get_NB32_DCT(dev, dct, 0xa8); @@ -965,7 +990,8 @@ static void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat, p += (max_delay >> 5); /* 2.10.5.8.5 (8) */ - p += 5; + if (!calc_min) + p += 5; /* 2.10.5.8.5 (9) */ t += 800; @@ -976,13 +1002,16 @@ static void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat, 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) */ - n -= 1; + if (!calc_min) + n -= 1; /* 2.10.5.8.5 (12) */ - 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); + 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] = n - 1; @@ -1103,6 +1132,9 @@ static void read_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, } else if (lane < 8) { Set_NB32_DCT(dev, dct, 0x274, ~0x0); Set_NB32_DCT(dev, dct, 0x278, ~(0xff << (lane * 8))); + } else if (lane == 0xff) { + Set_NB32_DCT(dev, dct, 0x274, ~0xffffffff); + Set_NB32_DCT(dev, dct, 0x278, ~0xffffffff); } else { Set_NB32_DCT(dev, dct, 0x274, ~0x0); Set_NB32_DCT(dev, dct, 0x278, ~0x0); @@ -1110,8 +1142,9 @@ static void read_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, dword = Get_NB32_DCT(dev, dct, 0x27c); dword &= ~(0xff); /* EccMask = 0 */ - if ((lane != 8) || (pDCTstat->DimmECCPresent == 0)) - dword |= 0xff; /* EccMask = 0xff */ + if (lane != 0xff) + if ((lane != 8) || (pDCTstat->DimmECCPresent == 0)) + dword |= 0xff; /* EccMask = 0xff */ Set_NB32_DCT(dev, dct, 0x27c, dword); dword = Get_NB32_DCT(dev, dct, 0x270); @@ -1180,6 +1213,9 @@ static void write_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, } else if (lane < 8) { Set_NB32_DCT(dev, dct, 0x274, ~0x0); Set_NB32_DCT(dev, dct, 0x278, ~(0xff << (lane * 8))); + } else if (lane == 0xff) { + Set_NB32_DCT(dev, dct, 0x274, ~0xffffffff); + Set_NB32_DCT(dev, dct, 0x278, ~0xffffffff); } else { Set_NB32_DCT(dev, dct, 0x274, ~0x0); Set_NB32_DCT(dev, dct, 0x278, ~0x0); @@ -1187,8 +1223,9 @@ static void write_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat, dword = Get_NB32_DCT(dev, dct, 0x27c); dword &= ~(0xff); /* EccMask = 0 */ - if ((lane != 8) || (pDCTstat->DimmECCPresent == 0)) - dword |= 0xff; /* EccMask = 0xff */ + if (lane != 0xff) + if ((lane != 8) || (pDCTstat->DimmECCPresent == 0)) + dword |= 0xff; /* EccMask = 0xff */ Set_NB32_DCT(dev, dct, 0x27c, dword); dword = Get_NB32_DCT(dev, dct, 0x270); @@ -1274,7 +1311,7 @@ static uint8_t TrainDQSRdWrPos_D_Fam15(struct MCTStatStruc *pMCTstat, uint32_t dev = pDCTstat->dev_dct; /* Calculate and program MaxRdLatency */ - Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, dct); + Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, dct, 0); Errors = 0; dual_rank = 0; @@ -1632,7 +1669,7 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat, 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); + 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, lane + 1); diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c b/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c index 0922193..cf13b40 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c @@ -15,7 +15,8 @@ */ /* mct_SetDramConfigMisc2_Cx & mct_SetDramConfigMisc2_Dx */ -u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, u8 dct, u32 misc2) +u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, + uint8_t dct, uint32_t misc2, uint32_t DramControl) { u32 val; @@ -24,17 +25,47 @@ u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, u8 dct, u32 misc2) if (pDCTstat->LogicalCPUID & AMD_FAM15_ALL) { uint8_t cs_mux_45; uint8_t cs_mux_67; + uint32_t f2x80; - /* BKDG v3.14 Table 200 / Table 201 */ - if (MaxDimmsInstallable < 3) { - cs_mux_45 = 1; - cs_mux_67 = 1; - } else { + 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 & 0xa) == 0x7) || ((f2x80 & 0xb) == 0x9)) + && ((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) & 0xa) == 0x7) || (((f2x80 >> 4) & 0xb) == 0x9)) + && ((f2x64 & 0x3) > 0x1)) + cs_mux_67 = 1; + else + cs_mux_67 = 0; + } else { + /* FIXME 3 DIMMS per channel unimplemented */ cs_mux_67 = 0; } - misc2 |= (cs_mux_45 & 0x1) << 26; - misc2 |= (cs_mux_67 & 0x1) << 27; + + 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; @@ -46,8 +77,8 @@ u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, u8 dct, u32 misc2) if (pDCTstat->LogicalCPUID & AMD_DR_Cx) misc2 |= 1 << OdtSwizzle; - val = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x78); + val = DramControl; val &= 7; val = ((~val) & 0xff) + 1; val += 6; diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c index 19b1b8f..d69a1ee 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c @@ -1420,7 +1420,7 @@ static void dqsTrainRcvrEn_SW_Fam15(struct MCTStatStruc *pMCTstat, } /* Calculate and program MaxRdLatency */ - Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, Channel); + Calc_SetMaxRdLatency_D_Fam15(pMCTstat, pDCTstat, Channel, 0); if(_DisableDramECC) { mct_EnableDimmEccEn_D(pMCTstat, pDCTstat, _DisableDramECC); @@ -1483,6 +1483,199 @@ static void dqsTrainRcvrEn_SW_Fam15(struct MCTStatStruc *pMCTstat, 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 & 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. + */ +static void dqsTrainMaxRdLatency_SW_Fam15(struct MCTStatStruc *pMCTstat, + struct DCTStatStruc *pDCTstat) +{ + u8 Channel; + u8 Addl_Index = 0; + u8 Receiver; + u8 _DisableDramECC = 0, _Wrap32Dis = 0, _SSE2 = 0; + u32 Errors; + + u32 dev; + u32 index_reg; + u32 ch_start, ch_end; + u32 msr; + u32 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; + + 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; + _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) { + Addl_Index = (Receiver >> 1) * 3 + 0x10; + dimm = (Receiver >> 1); + + print_debug_dqs("\t\tTrainMaxRdLatency52: 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 */ + read_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); + read_read_dqs_timing_control_registers(current_rdqs_total_delay, dev, Channel, dimm, index_reg); + + for (lane = 0; lane < 8; 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 < 8; 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); + + /* 2.10.5.8.5.1.4 + * Incrementally test each MaxRdLatency candidate + */ + for (; pDCTstat->CH_MaxRdLat[Channel] < 0x3ff; pDCTstat->CH_MaxRdLat[Channel]++) { + 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); + dword = Get_NB32_DCT(dev, Channel, 0x268) & 0x3ffff; + if (!dword) + break; + Set_NB32_index_wait_DCT(dev, Channel, index_reg, 0x00000050, 0x13131313); + } + + /* 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]++; + pDCTstat->CH_MaxRdLat[Channel] += ((((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; + _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]); + } + } +#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 ) { diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c b/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c index 4bfcc40..b354d92 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c @@ -168,6 +168,8 @@ static void EnterSelfRefresh(struct MCTStatStruc *pMCTstat, 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; @@ -309,6 +311,8 @@ static void ChangeMemClk(struct MCTStatStruc *pMCTstat, mct_Wait(15000); /* Wait for 750us */ } } + + printk(BIOS_DEBUG, "%s: Done\n", __func__); } /*
1
0
0
0
Patch set updated for coreboot: amd/family_10h-family_15h: Fix poor performance on Family 15h CPUs
by Timothy Pearson
16 Nov '15
16 Nov '15
Timothy Pearson (tpearson(a)raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/12028
-gerrit commit 22f795691cdd2452881b1376d1fa3eee4341acbf Author: Timothy Pearson <tpearson(a)raptorengineeringinc.com> Date: Fri Aug 7 19:04:49 2015 -0500 amd/family_10h-family_15h: Fix poor performance on Family 15h CPUs Change-Id: Ieb1f1fb5653651c98764de79636669802578d5f9 Signed-off-by: Timothy Pearson <tpearson(a)raptorengineeringinc.com> --- src/cpu/amd/family_10h-family_15h/defaults.h | 13 ++++++-- src/cpu/amd/family_10h-family_15h/init_cpus.c | 45 +++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/cpu/amd/family_10h-family_15h/defaults.h b/src/cpu/amd/family_10h-family_15h/defaults.h index 3e9ec09..901b8ce 100644 --- a/src/cpu/amd/family_10h-family_15h/defaults.h +++ b/src/cpu/amd/family_10h-family_15h/defaults.h @@ -518,15 +518,15 @@ static const struct { { 3, 0x140, AMD_FAM10_ALL, AMD_PTYPE_ALL, 0x00800756, 0x00F3FFFF }, - { 3, 0x140, AMD_FAM15_ALL, AMD_PTYPE_ALL, - 0x00a11755, 0x00f3ffff }, - { 3, 0x140, AMD_FAM10_ALL, AMD_PTYPE_UMA, 0x00C37756, 0x00F3FFFF }, { 3, 0x144, AMD_FAM10_ALL, AMD_PTYPE_UMA, 0x00000036, 0x000000FF }, + { 3, 0x140, AMD_FAM15_ALL, AMD_PTYPE_ALL, + 0x00a11755, 0x00f3ffff }, + /* Errata 281 Workaround */ { 3, 0x144, ( AMD_DR_B0 | AMD_DR_B1), AMD_PTYPE_SVR, 0x00000001, 0x0000000F }, @@ -538,6 +538,13 @@ static const struct { { 3, 0x148, AMD_FAM10_ALL, AMD_PTYPE_UMA, 0x8000052A, 0xD5FFFFFF }, + /* Core Interface Buffer Count */ + { 3, 0x1a0, AMD_FAM15_ALL, AMD_PTYPE_ALL, + 0x00034004, 0x00037007 }, /* CpuToNbFreeBufCnt = 0x3, + L3ToSriReqCBC = 0x4, + L3FreeListCBC = default, + CpuCmdBufCnt = 0x4 */ + /* ACPI Power State Control Reg1 */ { 3, 0x80, AMD_FAM10_ALL, AMD_PTYPE_ALL, 0xE6002200, 0xFFFFFFFF }, diff --git a/src/cpu/amd/family_10h-family_15h/init_cpus.c b/src/cpu/amd/family_10h-family_15h/init_cpus.c index 8bc0b6f..0df77b0 100644 --- a/src/cpu/amd/family_10h-family_15h/init_cpus.c +++ b/src/cpu/amd/family_10h-family_15h/init_cpus.c @@ -843,8 +843,9 @@ static BOOL AMD_CpuFindCapability(u8 node, u8 cap_count, u8 * offset) */ static u32 AMD_checkLinkType(u8 node, u8 link, u8 regoff) { - u32 val; - u32 linktype = 0; + uint32_t val; + uint32_t val2; + uint32_t linktype = 0; /* Check connect, init and coherency */ val = pci_read_config32(NODE_PCI(node, 0), regoff + 0x18); @@ -859,8 +860,13 @@ static u32 AMD_checkLinkType(u8 node, u8 link, u8 regoff) if (linktype) { /* Check gen3 */ val = pci_read_config32(NODE_PCI(node, 0), regoff + 0x08); + val = (val >> 8) & 0xf; + if (is_gt_rev_d()) { + val2 = pci_read_config32(NODE_PCI(node, 0), regoff + 0x1c); + val |= (val2 & 0x1) << 4; + } - if (((val >> 8) & 0x0F) > 6) + if (val > 6) linktype |= HTPHY_LINKTYPE_HT3; else linktype |= HTPHY_LINKTYPE_HT1; @@ -1147,6 +1153,39 @@ static void cpuSetAMDPCI(u8 node) pci_write_config32(NODE_PCI(node, 3), 0xd4, dword); } + if (revision & AMD_FAM15_ALL) { + uint32_t f5x80; + uint8_t cu_enabled; + uint8_t compute_unit_count = 0; + uint8_t compute_unit_buffer_count; + + /* Determine the number of active compute units on this node */ + f5x80 = pci_read_config32(NODE_PCI(node, 5), 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; + + if (compute_unit_count == 1) + compute_unit_buffer_count = 0x1c; + else if (compute_unit_count == 2) + compute_unit_buffer_count = 0x18; + else if (compute_unit_count == 3) + compute_unit_buffer_count = 0x14; + else + compute_unit_buffer_count = 0x10; + + dword = pci_read_config32(NODE_PCI(node, 3), 0x1a0); + dword &= ~(0x1f << 4); /* L3FreeListCBC = compute_unit_buffer_count */ + dword |= (compute_unit_buffer_count << 4); + pci_write_config32(NODE_PCI(node, 3), 0x1a0, dword); + } + printk(BIOS_DEBUG, " done\n"); }
1
0
0
0
Patch set updated for coreboot: northbridge/amd/amdht: Add support for HT3 2.8GHz and up link frequencies
by Timothy Pearson
16 Nov '15
16 Nov '15
Timothy Pearson (tpearson(a)raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/12027
-gerrit commit fd4059722d42d877f7bf95cebf87a8c8b0c05e0e Author: Timothy Pearson <tpearson(a)raptorengineeringinc.com> Date: Sun Aug 2 21:36:24 2015 -0500 northbridge/amd/amdht: Add support for HT3 2.8GHz and up link frequencies Change-Id: Ifa1592d26ba7deb034046fd3f2a15149117d9a76 Signed-off-by: Timothy Pearson <tpearson(a)raptorengineeringinc.com> --- src/cpu/amd/family_10h-family_15h/defaults.h | 8 ++- src/mainboard/asus/kgpe-d16/cmos.layout | 30 ++++----- src/northbridge/amd/amdht/h3ffeat.h | 6 +- src/northbridge/amd/amdht/h3finit.c | 93 +++++++++++++++++----------- src/northbridge/amd/amdht/h3finit.h | 18 ++++-- src/northbridge/amd/amdht/h3ncmn.c | 82 +++++++++++++++++------- src/northbridge/amd/amdht/h3ncmn.h | 3 +- 7 files changed, 155 insertions(+), 85 deletions(-) diff --git a/src/cpu/amd/family_10h-family_15h/defaults.h b/src/cpu/amd/family_10h-family_15h/defaults.h index a3c7b1f..3e9ec09 100644 --- a/src/cpu/amd/family_10h-family_15h/defaults.h +++ b/src/cpu/amd/family_10h-family_15h/defaults.h @@ -273,7 +273,13 @@ static const struct { /* Link Global Retry Control Register */ { 0, 0x150, (AMD_FAM10_ALL | AMD_FAM15_ALL), AMD_PTYPE_ALL, - 0x00073900, 0x00073F00 }, + 0x00073900, 0x00073f70 }, /* TotalRetryAttempts = 0x7, + HtRetryCrcDatInsDynEn = 0x1, + HtRetryCrcCmdPackDynEn = 0x1, + HtRetryCrcDatIns = 0x4, + HtRetryCrcCmdPack = 0x1, + ForceErrType = 0x0, + MultRetryErr = 0x0 */ /* Errata 351 * System software should program the Link Extended Control Registers[LS2En] diff --git a/src/mainboard/asus/kgpe-d16/cmos.layout b/src/mainboard/asus/kgpe-d16/cmos.layout index 21765e3..e17fec6 100644 --- a/src/mainboard/asus/kgpe-d16/cmos.layout +++ b/src/mainboard/asus/kgpe-d16/cmos.layout @@ -120,21 +120,21 @@ enumerations 10 21 42ms 10 22 84ms 11 0 Auto -11 1 2.6GHz -11 2 2.4GHz -11 3 2.2GHz -11 4 2.0GHz -11 5 1.8GHz -11 6 1.6GHz -11 7 1.4GHz -11 8 1.2GHz -11 9 1.0GHz -11 10 800MHz -11 11 600MHz -11 12 500MHz -11 13 400MHz -11 14 300MHz -11 15 200MHz +11 1 3.2GHz +11 2 3.0GHz +11 3 2.8GHz +11 4 2.6GHz +11 5 2.4GHz +11 6 2.2GHz +11 7 2.0GHz +11 8 1.8GHz +11 9 1.6GHz +11 10 1.4GHz +11 11 1.2GHz +11 12 1.0GHz +11 13 800MHz +11 14 600MHz +11 15 500MHz 12 0 1.5V 12 1 1.35V 12 2 1.25V diff --git a/src/northbridge/amd/amdht/h3ffeat.h b/src/northbridge/amd/amdht/h3ffeat.h index 52c4def..628b86e 100644 --- a/src/northbridge/amd/amdht/h3ffeat.h +++ b/src/northbridge/amd/amdht/h3ffeat.h @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2007-2008 Advanced Micro Devices, Inc. + * Copyright (C) 2015 Timothy Pearson <tpearson(a)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 @@ -58,6 +59,7 @@ #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 @@ -123,10 +125,10 @@ typedef struct /* This section is for keeping track of capabilities and possible configurations */ BOOL RegangCap; - u16 PrvFrequencyCap; + uint32_t PrvFrequencyCap; u8 PrvWidthInCap; u8 PrvWidthOutCap; - u16 CompositeFrequencyCap; + uint32_t CompositeFrequencyCap; } sPortDescriptor; diff --git a/src/northbridge/amd/amdht/h3finit.c b/src/northbridge/amd/amdht/h3finit.c index bcdcfa2..e4ce768 100644 --- a/src/northbridge/amd/amdht/h3finit.c +++ b/src/northbridge/amd/amdht/h3finit.c @@ -48,28 +48,32 @@ #define APIC_Base_BSP 8 #define APIC_Base 0x1b -#define NVRAM_LIMIT_HT_SPEED_200 0xf -#define NVRAM_LIMIT_HT_SPEED_300 0xe -#define NVRAM_LIMIT_HT_SPEED_400 0xd -#define NVRAM_LIMIT_HT_SPEED_500 0xc -#define NVRAM_LIMIT_HT_SPEED_600 0xb -#define NVRAM_LIMIT_HT_SPEED_800 0xa -#define NVRAM_LIMIT_HT_SPEED_1000 0x9 -#define NVRAM_LIMIT_HT_SPEED_1200 0x8 -#define NVRAM_LIMIT_HT_SPEED_1400 0x7 -#define NVRAM_LIMIT_HT_SPEED_1600 0x6 -#define NVRAM_LIMIT_HT_SPEED_1800 0x5 -#define NVRAM_LIMIT_HT_SPEED_2000 0x4 -#define NVRAM_LIMIT_HT_SPEED_2200 0x3 -#define NVRAM_LIMIT_HT_SPEED_2400 0x2 -#define NVRAM_LIMIT_HT_SPEED_2600 0x1 +#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 uint16_t ht_speed_limit[16] = - {0xFFFF, 0x7FFF, 0x3FFF, 0x1FFF, - 0x0FFF, 0x07FF, 0x03FF, 0x01FF, - 0x00FF, 0x007F, 0x003F, 0x001F, - 0x000F, 0x0007, 0x0003, 0x0001}; +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; @@ -91,9 +95,12 @@ static const struct ht_speed_limit_map_t { {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 uint16_t ht_speed_mhz_to_hw(uint16_t mhz) +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++) @@ -452,7 +459,7 @@ static void htDiscoveryFloodFill(sMainData *pDat) /* Set currentNode's NodeID field to currentNode */ pDat->nb->writeNodeID(currentNode, currentNode, pDat->nb); - /* Enable routing tables on currentNode*/ + /* Enable routing tables on currentNode */ pDat->nb->enableRoutingTables(currentNode, pDat->nb); for (currentLinkID = 0; currentLinkID < pDat->nb->maxLinks; currentLinkID++) @@ -1427,19 +1434,30 @@ static void regangLinks(sMainData *pDat) static void selectOptimalWidthAndFrequency(sMainData *pDat) { u8 i, j; - u32 temp; - u16 cbPCBFreqLimit; - u16 cbPCBFreqLimit_NVRAM; + uint32_t temp; + uint32_t cbPCBFreqLimit; + uint32_t cbPCBFreqLimit_NVRAM; u8 cbPCBABDownstreamWidth; u8 cbPCBBAUpstreamWidth; - cbPCBFreqLimit_NVRAM = 0xFFFF; + 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 = 0xFFFF; // Maximum allowed by autoconfiguration + 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); @@ -1484,17 +1502,18 @@ static void selectOptimalWidthAndFrequency(sMainData *pDat) } } - temp = pDat->PortList[i].PrvFrequencyCap; temp &= pDat->PortList[i+1].PrvFrequencyCap; temp &= cbPCBFreqLimit; - pDat->PortList[i].CompositeFrequencyCap = (u16)temp; - pDat->PortList[i+1].CompositeFrequencyCap = (u16)temp; + pDat->PortList[i].CompositeFrequencyCap = temp; + pDat->PortList[i+1].CompositeFrequencyCap = temp; ASSERT (temp != 0); - for (j = 15; ; j--) + for (j = 19; ; j--) { - if (temp & ((u32)1 << j)) + if ((j == 16) || (j == 15)) + continue; + if (temp & ((uint32_t)1 << j)) break; } @@ -1638,12 +1657,14 @@ static void hammerSublinkFixup(sMainData *pDat) /* Remove hiFreq from the list of valid frequencies */ temp = temp & ~((uint32)1 << hiFreq); ASSERT (temp != 0); - pDat->PortList[hiIndex].CompositeFrequencyCap = (uint16)temp; - pDat->PortList[hiIndex+1].CompositeFrequencyCap = (uint16)temp; + pDat->PortList[hiIndex].CompositeFrequencyCap = temp; + pDat->PortList[hiIndex+1].CompositeFrequencyCap = temp; - for (k = 15; ; k--) + for (k = 19; ; k--) { - if (temp & ((u32)1 << k)) + if ((j == 16) || (j == 15)) + continue; + if (temp & ((uint32_t)1 << k)) break; } diff --git a/src/northbridge/amd/amdht/h3finit.h b/src/northbridge/amd/amdht/h3finit.h index f6ab010..1bd8616 100644 --- a/src/northbridge/amd/amdht/h3finit.h +++ b/src/northbridge/amd/amdht/h3finit.h @@ -49,6 +49,9 @@ #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 @@ -65,6 +68,9 @@ #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 @@ -220,7 +226,7 @@ typedef struct { * @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] u16* FreqCap = modify to change the link's frequency capability + * @param[in,out] u32* FreqCap = modify to change the link's frequency capability * * --------------------------------------------------------------------------------------- */ @@ -235,7 +241,7 @@ typedef struct { u8 Link, u8 *LinkWidthIn, u8 *LinkWidthOut, - u16 *FreqCap + u32 *FreqCap ); /**---------------------------------------------------------------------------------------- @@ -258,7 +264,7 @@ typedef struct { * @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] u16* PCBFreqCap = modify to change the link's frequency capability + * @param[in,out] u32* PCBFreqCap = modify to change the link's frequency capability * * --------------------------------------------------------------------------------------- */ @@ -269,7 +275,7 @@ typedef struct { u8 LinkB, u8 *ABLinkWidthLimit, u8 *BALinkWidthLimit, - u16 *PCBFreqCap + u32 *PCBFreqCap ); /**---------------------------------------------------------------------------------------- @@ -291,7 +297,7 @@ typedef struct { * @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] u16* PCBFreqCap = modify to change the link's frequency capability + * @param[in,out] u32* PCBFreqCap = modify to change the link's frequency capability * * --------------------------------------------------------------------------------------- */ @@ -301,7 +307,7 @@ typedef struct { u8 Depth, u8 *DownstreamLinkWidthLimit, u8 *UpstreamLinkWidthLimit, - u16 *PCBFreqCap + u32 *PCBFreqCap ); /**---------------------------------------------------------------------------------------- diff --git a/src/northbridge/amd/amdht/h3ncmn.c b/src/northbridge/amd/amdht/h3ncmn.c index 8ee929d..29524af 100644 --- a/src/northbridge/amd/amdht/h3ncmn.c +++ b/src/northbridge/amd/amdht/h3ncmn.c @@ -1310,7 +1310,7 @@ static u8 convertWidthToBits(u8 value, cNorthBridge *nb) * @return Frequency mask * ******************************************************************************/ -static u16 ht1NorthBridgeFreqMask(u8 node, cNorthBridge *nb) +static uint32_t ht1NorthBridgeFreqMask(u8 node, cNorthBridge *nb) { /* only up to HT1 speeds */ return (HT_FREQUENCY_LIMIT_HT1_ONLY); @@ -1331,26 +1331,43 @@ static u16 ht1NorthBridgeFreqMask(u8 node, cNorthBridge *nb) * @return = Frequency mask * ******************************************************************************/ -static u16 fam10NorthBridgeFreqMask(u8 node, cNorthBridge *nb) +static uint32_t fam10NorthBridgeFreqMask(u8 node, cNorthBridge *nb) { u8 nbCOF; - u16 supported; + 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 <= 26)) + 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 = ((u16)1 << ((nbCOF >> 1) + 2)) - 1; + supported = ((uint32_t)1 << ((nbCOF >> 1) + 2)) - 1; } - else if (nbCOF > 26) + else if ((nbCOF >= 10) && (nbCOF <= 32)) { - supported = HT_FREQUENCY_LIMIT_2600M; + /* 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) @@ -1405,8 +1422,13 @@ static void gatherLinkData(sMainData *pDat, cNorthBridge *nb) pDat->PortList[i].PrvWidthInCap = convertBitsToWidth((u8)temp, pDat->nb); AmdPCIReadBits(linkBase + HTHOST_FREQ_REV_REG, 31, 16, &temp); - pDat->PortList[i].PrvFrequencyCap = (u16)temp & 0x7FFF - & nb->northBridgeFreqMask(pDat->PortList[i].NodeID, pDat->nb); /* Mask off bit 15, reserved value */ + 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); + } } else { @@ -1463,7 +1485,7 @@ static void setLinkData(sMainData *pDat, cNorthBridge *nb) { u8 i; SBDFO linkBase; - u32 temp, widthin, widthout, bits; + u32 temp, temp2, frequency_index, widthin, widthout, bits; for (i = 0; i < pDat->TotalLinks*2; i++) { @@ -1524,10 +1546,19 @@ static void setLinkData(sMainData *pDat, cNorthBridge *nb) temp = pDat->PortList[i].SelFrequency; if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU) { - ASSERT((temp >= HT_FREQUENCY_600M && temp <= HT_FREQUENCY_2600M) + 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; + } + if (is_gt_rev_d()) + AmdPCIWriteBits(linkBase + HTHOST_FREQ_REV_REG_2, 0, 0, &temp2); AmdPCIWriteBits(linkBase + HTHOST_FREQ_REV_REG, 11, 8, &temp); - if (temp > HT_FREQUENCY_1000M) /* Gen1 = 200MHz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz */ + if (frequency_index > HT_FREQUENCY_1000M) /* Gen1 = 200MHz -> 1000MHz, Gen3 = 1200MHz -> 3200MHz */ { /* Enable for Gen3 frequencies */ temp = 1; @@ -1537,27 +1568,27 @@ static void setLinkData(sMainData *pDat, cNorthBridge *nb) /* 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), + /* 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_EXT_CONTROL0_0X170 + 4*pDat->PortList[i].Link), - 3, 3, &temp); + 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_2600M); + ASSERT(temp <= HT_FREQUENCY_3200M); /* Write the frequency setting */ AmdPCIWriteBits(linkBase + HTSLAVE_FREQ_REV_0_REG, 11, 8, &temp); @@ -1718,6 +1749,9 @@ static void fam0fWriteHTLinkCmdBufferAlloc(u8 node, u8 link, u8 req, u8 preq, u8 /* Probe Command Buffers */ temp = prb; AmdPCIWriteBits(currentPtr, 15, 12, &temp); + /* LockBc */ + temp = 1; + AmdPCIWriteBits(currentPtr, 31, 31, &temp); } #endif /* HT_BUILD_NC_ONLY */ diff --git a/src/northbridge/amd/amdht/h3ncmn.h b/src/northbridge/amd/amdht/h3ncmn.h index 328d909..3c8a346 100644 --- a/src/northbridge/amd/amdht/h3ncmn.h +++ b/src/northbridge/amd/amdht/h3ncmn.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 <tpearson(a)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 @@ -103,7 +104,7 @@ struct cNorthBridge /* Public Interfaces for northbridge clients, Optimization */ u8 (*convertBitsToWidth)(u8 value, cNorthBridge *nb); u8 (*convertWidthToBits)(u8 value, cNorthBridge *nb); - u16 (*northBridgeFreqMask)(u8 node, cNorthBridge *nb); + uint32_t (*northBridgeFreqMask)(u8 node, cNorthBridge *nb); void (*gatherLinkData)(sMainData *pDat, cNorthBridge *nb); void (*setLinkData)(sMainData *pDat, cNorthBridge *nb);
1
0
0
0
Patch set updated for coreboot: cpu/amd/family_10h-family_15h: Fix incorrect revision detection
by Timothy Pearson
16 Nov '15
16 Nov '15
Timothy Pearson (tpearson(a)raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/12026
-gerrit commit 8864c99e5546bfc00a4e2741efa0ef3e8213a256 Author: Timothy Pearson <tpearson(a)raptorengineeringinc.com> Date: Sun Aug 2 21:31:48 2015 -0500 cpu/amd/family_10h-family_15h: Fix incorrect revision detection Change-Id: I7a881a94d62ed455415f9dfc887fd698ac919429 Signed-off-by: Timothy Pearson <tpearson(a)raptorengineeringinc.com> --- src/cpu/amd/family_10h-family_15h/fidvid.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cpu/amd/family_10h-family_15h/fidvid.c b/src/cpu/amd/family_10h-family_15h/fidvid.c index 8a006cb..66bb3a2 100644 --- a/src/cpu/amd/family_10h-family_15h/fidvid.c +++ b/src/cpu/amd/family_10h-family_15h/fidvid.c @@ -371,7 +371,7 @@ static void recalculateVsSlamTimeSettingOnCorePre(device_t dev) pci_write_config32(dev, 0xd8, dtemp); } -static u32 nb_clk_did(int node, u32 cpuRev,u8 procPkg) { +static u32 nb_clk_did(int node, uint64_t cpuRev, uint8_t procPkg) { u8 link0isGen3 = 0; u8 offset; if (AMD_CpuFindCapability(node, 0, &offset)) { @@ -442,7 +442,7 @@ static u32 power_up_down(int node, u8 procPkg) { return dword; } -static void config_clk_power_ctrl_reg0(int node, u32 cpuRev, u8 procPkg) { +static void config_clk_power_ctrl_reg0(int node, uint64_t cpuRev, uint8_t procPkg) { device_t dev = NODE_PCI(node, 3); /* Program fields in Clock Power/Control register0 (F3xD4) */ @@ -467,7 +467,7 @@ static void config_clk_power_ctrl_reg0(int node, u32 cpuRev, u8 procPkg) { } -static void config_power_ctrl_misc_reg(device_t dev,u32 cpuRev, u8 procPkg) { +static void config_power_ctrl_misc_reg(device_t dev, uint64_t cpuRev, uint8_t procPkg) { /* check PVI/SVI */ u32 dword = pci_read_config32(dev, 0xa0); @@ -500,7 +500,7 @@ static void config_power_ctrl_misc_reg(device_t dev,u32 cpuRev, u8 procPkg) { pci_write_config32(dev, 0xa0, dword); } -static void config_nb_syn_ptr_adj(device_t dev, u32 cpuRev) { +static void config_nb_syn_ptr_adj(device_t dev, uint64_t cpuRev) { /* Note the following settings are additional from the ported * function setFidVidRegs() */ @@ -522,7 +522,7 @@ static void config_nb_syn_ptr_adj(device_t dev, u32 cpuRev) { pci_write_config32(dev, 0xdc, dword); } -static void config_acpi_pwr_state_ctrl_regs(device_t dev, u32 cpuRev, u8 procPkg) { +static void config_acpi_pwr_state_ctrl_regs(device_t dev, uint64_t cpuRev, uint8_t procPkg) { if (is_fam15h()) { /* Family 15h BKDG Rev. 3.14 D18F3x80 recommended settings */ pci_write_config32(dev, 0x80, 0xe20be281);
1
0
0
0
Patch set updated for coreboot: cpu/amd/fam10h-fam15h: Set northbridge throttle values
by Timothy Pearson
16 Nov '15
16 Nov '15
Timothy Pearson (tpearson(a)raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/12025
-gerrit commit 3f92e141395c9e8cb2e18fc2ce041de9eee11d2f Author: Timothy Pearson <tpearson(a)raptorengineeringinc.com> Date: Sun Aug 2 21:31:17 2015 -0500 cpu/amd/fam10h-fam15h: Set northbridge throttle values The existing code did not set the northbridge throttle values on Family 15h, leading to sporadic and random deadlocks in the crossbar per AMD notes. Properly set the northbridge throttle values on Family 15h. Change-Id: I6304b63708c65fedb9c2d46b8c862b7f0adf1102 Signed-off-by: Timothy Pearson <tpearson(a)raptorengineeringinc.com> --- src/cpu/amd/family_10h-family_15h/init_cpus.c | 21 +---------- .../amd/family_10h-family_15h/model_10xxx_init.c | 44 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/cpu/amd/family_10h-family_15h/init_cpus.c b/src/cpu/amd/family_10h-family_15h/init_cpus.c index a6d8dc4..8bc0b6f 100644 --- a/src/cpu/amd/family_10h-family_15h/init_cpus.c +++ b/src/cpu/amd/family_10h-family_15h/init_cpus.c @@ -873,6 +873,7 @@ static u32 AMD_checkLinkType(u8 node, u8 link, u8 regoff) else linktype |= HTPHY_LINKTYPE_UNGANGED; } + return linktype; } @@ -967,26 +968,6 @@ void cpuSetAMDMSR(uint8_t node_id) } AMD_Errata298(); - if (revision & AMD_FAM15_ALL) { - uint32_t f5x80; - uint8_t enabled; - uint8_t compute_unit_count = 0; - f5x80 = pci_read_config32(NODE_PCI(node_id, 5), 0x80); - enabled = f5x80 & 0xf; - if (enabled == 0x1) - compute_unit_count = 1; - if (enabled == 0x3) - compute_unit_count = 2; - if (enabled == 0x7) - compute_unit_count = 3; - if (enabled == 0xf) - compute_unit_count = 4; - msr = rdmsr(BU_CFG2); - msr.lo &= ~(0x3 << 6); /* ThrottleNbInterface[1:0] */ - msr.lo |= (((compute_unit_count - 1) & 0x3) << 6); - wrmsr(BU_CFG2, msr); - } - /* Revision C0 and above */ if (revision & AMD_OR_C0) { uint32_t f3x1fc = pci_read_config32(NODE_PCI(node_id, 3), 0x1fc); diff --git a/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c b/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c index 4ccf79d..fe9fb9c 100644 --- a/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c +++ b/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c @@ -154,6 +154,50 @@ static void model_10xxx_init(device_t dev) printk(BIOS_DEBUG, "siblings = %02d, ", siblings); #endif + /* Set bus unit configuration */ + if (is_fam15h()) { + uint32_t f5x80; + uint8_t enabled; + uint8_t compute_unit_count = 0; + f5x80 = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x18 + id.nodeid, 5)), 0x80); + enabled = f5x80 & 0xf; + if (enabled == 0x1) + compute_unit_count = 1; + if (enabled == 0x3) + compute_unit_count = 2; + if (enabled == 0x7) + compute_unit_count = 3; + if (enabled == 0xf) + compute_unit_count = 4; + msr = rdmsr(BU_CFG2_MSR); + msr.lo &= ~(0x3 << 6); /* ThrottleNbInterface[1:0] */ + msr.lo |= (((compute_unit_count - 1) & 0x3) << 6); + wrmsr(BU_CFG2_MSR, msr); + } else { + uint32_t f0x60; + uint32_t f0x160; + uint8_t core_count = 0; + uint8_t node_count = 0; + f0x60 = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x18 + id.nodeid, 0)), 0x60); + core_count = (f0x60 >> 16) & 0x1f; + node_count = ((f0x60 >> 4) & 0x7) + 1; + if (is_gt_rev_d()) { + f0x160 = pci_read_config32(dev_find_slot(0, PCI_DEVFN(0x18 + id.nodeid, 0)), 0x160); + core_count |= ((f0x160 >> 16) & 0x7) << 5; + } + core_count++; + core_count /= node_count; + msr = rdmsr(BU_CFG2_MSR); + if (is_gt_rev_d()) { + msr.hi &= ~(0x3 << (36 - 32)); /* ThrottleNbInterface[3:2] */ + msr.hi |= ((((core_count - 1) >> 2) & 0x3) << (36 - 32)); + } + msr.lo &= ~(0x3 << 6); /* ThrottleNbInterface[1:0] */ + msr.lo |= (((core_count - 1) & 0x3) << 6); + msr.lo &= ~(0x1 << 24); /* WcPlusDis = 0 */ + wrmsr(BU_CFG2_MSR, msr); + } + /* Disable Cf8ExtCfg */ msr = rdmsr(NB_CFG_MSR); msr.hi &= ~(1 << (46 - 32));
1
0
0
0
Patch set updated for coreboot: mainboard/asus/kgpe-d16: Fix I/O link detection
by Timothy Pearson
16 Nov '15
16 Nov '15
Timothy Pearson (tpearson(a)raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/12024
-gerrit commit 285010b9b38474c517520e1049c80daad79b40d3 Author: Timothy Pearson <tpearson(a)raptorengineeringinc.com> Date: Sun Aug 2 21:28:31 2015 -0500 mainboard/asus/kgpe-d16: Fix I/O link detection Change-Id: Ibefc9dc2e1e0267389eb8d716408bae6026ce084 Signed-off-by: Timothy Pearson <tpearson(a)raptorengineeringinc.com> --- src/mainboard/asus/kgpe-d16/romstage.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mainboard/asus/kgpe-d16/romstage.c b/src/mainboard/asus/kgpe-d16/romstage.c index be91eaa..6503b90 100644 --- a/src/mainboard/asus/kgpe-d16/romstage.c +++ b/src/mainboard/asus/kgpe-d16/romstage.c @@ -551,7 +551,8 @@ BOOL AMD_CB_ManualBUIDSwapList (u8 node, u8 link, const u8 **List) { /* Force BUID to 0 */ static const u8 swaplist[] = {0, 0, 0xFF, 0, 0xFF}; - if ((node == 0) && (link == 1)) { /* BSP SB link */ + if ((is_fam15h() && (node == 0) && (link == 1)) /* Family 15h BSP SB link */ + || (!is_fam15h() && (node == 0) && (link == 3))) { /* Family 10h BSP SB link */ *List = swaplist; return 1; }
1
0
0
0
Patch set updated for coreboot: northbridge/amd/amdmct/mct_ddr3: Move K10D configuration into separate file
by Timothy Pearson
16 Nov '15
16 Nov '15
Timothy Pearson (tpearson(a)raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/12023
-gerrit commit 8025ad8b4c0ebc2955a13c89adf48f9f43f04c72 Author: Timothy Pearson <tpearson(a)raptorengineeringinc.com> Date: Sun Aug 2 21:23:02 2015 -0500 northbridge/amd/amdmct/mct_ddr3: Move K10D configuration into separate file Change-Id: Id45888f266fac7810a63fef43b8d7a0ee40cbf70 Signed-off-by: Timothy Pearson <tpearson(a)raptorengineeringinc.com> --- src/northbridge/amd/amdfam10/raminit_amdmct.c | 1 + src/northbridge/amd/amdmct/amddefs.h | 5 +- src/northbridge/amd/amdmct/mct_ddr3/mct_d.c | 131 +++++++++++-------------- src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c | 4 +- src/northbridge/amd/amdmct/mct_ddr3/mctprod.c | 65 ++++++++++++ 5 files changed, 130 insertions(+), 76 deletions(-) diff --git a/src/northbridge/amd/amdfam10/raminit_amdmct.c b/src/northbridge/amd/amdfam10/raminit_amdmct.c index d8023f8..a40c5a1 100644 --- a/src/northbridge/amd/amdfam10/raminit_amdmct.c +++ b/src/northbridge/amd/amdfam10/raminit_amdmct.c @@ -373,6 +373,7 @@ static uint16_t mct_MaxLoadFreq(uint8_t count, uint8_t highest_rank_count, uint8 #include "../amdmct/mct_ddr3/mctdqs_d.c" #include "../amdmct/mct_ddr3/mctsrc.c" #include "../amdmct/mct_ddr3/mctsdi.c" +#include "../amdmct/mct_ddr3/mctprod.c" #include "../amdmct/mct_ddr3/mctproc.c" #include "../amdmct/mct_ddr3/mctprob.c" #include "../amdmct/mct_ddr3/mcthwl.c" diff --git a/src/northbridge/amd/amdmct/amddefs.h b/src/northbridge/amd/amdmct/amddefs.h index d2dfbcc..10a50d9 100644 --- a/src/northbridge/amd/amdmct/amddefs.h +++ b/src/northbridge/amd/amdmct/amddefs.h @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2007-2008 Advanced Micro Devices, Inc. + * Copyright (C) 2015 Timothy Pearson <tpearson(a)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 @@ -111,7 +112,7 @@ /* * CPU HT PHY REGISTERS, FIELDS, AND MASKS */ -#define HTPHY_OFFSET_MASK 0xE00001FF +#define HTPHY_OFFSET_MASK 0xE000FFFF #define HTPHY_WRITE_CMD 0x40000000 #define HTPHY_IS_COMPLETE_MASK 0x80000000 #define HTPHY_DIRECT_MAP 0x20000000 @@ -160,4 +161,4 @@ #define AMD_PKGTYPE_S1gX 2 #define AMD_PKGTYPE_G34 3 #define AMD_PKGTYPE_ASB2 4 -#define AMD_PKGTYPE_C32 5 \ No newline at end of file +#define AMD_PKGTYPE_C32 5 diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c index bfe7515..283d897 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c @@ -178,6 +178,7 @@ static void SyncSetting(struct DCTStatStruc *pDCTstat); static uint8_t crcCheck(struct DCTStatStruc *pDCTstat, uint8_t dimm); static void mct_ExtMCTConfig_Bx(struct DCTStatStruc *pDCTstat); static void mct_ExtMCTConfig_Cx(struct DCTStatStruc *pDCTstat); +static void mct_ExtMCTConfig_Dx(struct DCTStatStruc *pDCTstat); static 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); @@ -2687,13 +2688,11 @@ static void MCTMemClr_D(struct MCTStatStruc *pMCTstat, for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { pDCTstat = pDCTstatA + Node; - /* Configure and enable prefetchers */ - if (is_fam15h()) - dword = 0x0ce00f41; /* BKDG recommended */ - else - dword = 0x0fe40fc0; /* BKDG recommended */ - dword |= MCCH_FlushWrOnStpGnt; /* Set for S3 */ - Set_NB32(pDCTstat->dev_dct, 0x11c, dword); + /* 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 */ } } @@ -4935,31 +4934,33 @@ static void Set_OtherTiming(struct MCTStatStruc *pMCTstat, Get_TrwtTO(pMCTstat, pDCTstat, dct); Get_TrwtWB(pMCTstat, pDCTstat); - 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 & 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 >> 2; - val |= dword << 12; - Set_NB32_DCT(dev, dct, reg, val); + 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, @@ -4970,6 +4971,8 @@ static void Get_Trdrd(struct MCTStatStruc *pMCTstat, Trdrd = ((int8_t)(pDCTstat->DqsRcvEnGrossMax - pDCTstat->DqsRcvEnGrossMin) >> 1) + 1; if (Trdrd > 8) Trdrd = 8; + if (Trdrd < 3) + Trdrd = 3; pDCTstat->Trdrd = Trdrd; } @@ -5280,47 +5283,31 @@ static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat, if (pDCTstat->NodePresent) { mct_PhyController_Config(pMCTstat, pDCTstat, 0); mct_PhyController_Config(pMCTstat, pDCTstat, 1); - } - if (!(pDCTstat->LogicalCPUID & AMD_DR_Dx)) { /* mct_checkForDxSupport */ - mct_ExtMCTConfig_Cx(pDCTstat); - mct_ExtMCTConfig_Bx(pDCTstat); - } else { /* For Dx CPU */ - val = 0x0CE00F00 | 1 << 29/* FlushWrOnStpGnt */; - if (!(pDCTstat->GangedMode)) - val |= 0x20; /* MctWrLimit = 8 for Unganged mode */ - else - val |= 0x40; /* MctWrLimit = 16 for ganged mode */ - Set_NB32(pDCTstat->dev_dct, 0x11C, val); - - val = Get_NB32(pDCTstat->dev_dct, 0x1B0); - val &= 0xFFFFF8C0; - val |= 0x101; /* BKDG recommended settings */ - val |= 0x0FC00000; /* Agesa V5 */ - if (!(pDCTstat->GangedMode)) - val |= 1 << 12; - else - val &= ~(1 << 12); - val &= 0x0FFFFFFF; if (!is_fam15h()) { - switch (pDCTstat->Speed) { - case 4: - val |= 0x50000000; /* 5 for DDR800 */ - break; - case 5: - val |= 0x60000000; /* 6 for DDR1066 */ - break; - case 6: - val |= 0x80000000; /* 8 for DDR800 */ - break; - default: - val |= 0x90000000; /* 9 for DDR1600 */ - break; - } - } - Set_NB32(pDCTstat->dev_dct, 0x1B0, val); + /* Family 10h CPUs */ + mct_ExtMCTConfig_Cx(pDCTstat); + mct_ExtMCTConfig_Bx(pDCTstat); + mct_ExtMCTConfig_Dx(pDCTstat); + } else { + /* Family 15h CPUs */ + val = 0x0ce00f00 | 0x1 << 29; /* FlushWrOnStpGnt */ + val |= 0x10 << 2; /* MctWrLimit = 16 */ + 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 */ + val |= (0x7 << 22); /* PrefFourConf = 0x7 */ + val |= (0x7 << 25); /* PrefFiveConf = 0x7 */ + val &= ~(0xf << 28); /* DcqBwThrotWm = 0x0 */ + Set_NB32(pDCTstat->dev_dct, 0x1b0, val); - if (is_fam15h()) { uint8_t wm1; uint8_t wm2; @@ -5351,11 +5338,11 @@ static void mct_FinalMCT_D(struct MCTStatStruc *pMCTstat, break; } - val = Get_NB32(pDCTstat->dev_dct, 0x1B4); + val = Get_NB32(pDCTstat->dev_dct, 0x1b4); val &= ~(0x3ff); val |= ((wm2 & 0x1f) << 5); val |= (wm1 & 0x1f); - Set_NB32(pDCTstat->dev_dct, 0x1B4, val); + Set_NB32(pDCTstat->dev_dct, 0x1b4, val); } } } diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c index 253a89f..da7ce16 100644 --- a/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c +++ b/src/northbridge/amd/amdmct/mct_ddr3/mctcsi_d.c @@ -98,7 +98,7 @@ void InterleaveBanks_D(struct MCTStatStruc *pMCTstat, BitDelta = bsf(AddrHiMask) - bsf(AddrLoMask); for (ChipSel = 0; ChipSel < MAX_CS_SUPPORTED; ChipSel++) { - reg = 0x40+(ChipSel<<2); /*Dram CS Base 0 */ + reg = 0x40 + (ChipSel<<2); /* Dram CS Base 0 */ val = Get_NB32_DCT(dev, dct, reg); if (val & 3) { val_lo = val & AddrLoMask; @@ -114,7 +114,7 @@ void InterleaveBanks_D(struct MCTStatStruc *pMCTstat, if(ChipSel & 1) continue; - reg = 0x60 + ((ChipSel>>1)<<2); /*Dram CS Mask 0 */ + reg = 0x60 + ((ChipSel>>1)<<2); /* Dram CS Mask 0 */ val = Get_NB32_DCT(dev, dct, reg); val_lo = val & AddrLoMask; val_hi = val & AddrHiMask; diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctprod.c b/src/northbridge/amd/amdmct/mct_ddr3/mctprod.c new file mode 100644 index 0000000..2b62d4c --- /dev/null +++ b/src/northbridge/amd/amdmct/mct_ddr3/mctprod.c @@ -0,0 +1,65 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Timothy Pearson <tpearson(a)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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ + +void mct_ExtMCTConfig_Dx(struct DCTStatStruc *pDCTstat) +{ + uint32_t dword; + + if (pDCTstat->LogicalCPUID & AMD_DR_Dx) { + dword = 0x0ce00f00 | 0x1 << 29; /* FlushWrOnStpGnt */ + if (!(pDCTstat->GangedMode)) + dword |= 0x18 << 2; /* MctWrLimit = 0x18 for unganged mode */ + else + dword |= 0x10 << 2; /* MctWrLimit = 0x10 for ganged mode */ + Set_NB32(pDCTstat->dev_dct, 0x11c, dword); + + dword = Get_NB32(pDCTstat->dev_dct, 0x1b0); + dword &= ~0x3; /* AdapPrefMissRatio = 0x1 */ + dword |= 0x1; + dword &= ~(0x3 << 2); /* AdapPrefPositiveStep = 0x0 */ + dword &= ~(0x3 << 4); /* AdapPrefNegativeStep = 0x0 */ + dword &= ~(0x7 << 8); /* CohPrefPrbLmt = 0x1 */ + dword |= (0x1 << 8); + dword |= (0x7 << 22); /* PrefFourConf = 0x7 */ + dword |= (0x7 << 25); /* PrefFiveConf = 0x7 */ + + if (!(pDCTstat->GangedMode)) + dword |= (0x1 << 12); /* EnSplitDctLimits = 0x1 */ + else + dword &= ~(0x1 << 12); /* EnSplitDctLimits = 0x0 */ + + dword &= ~(0xf << 28); /* DcqBwThrotWm = ... */ + switch (pDCTstat->Speed) { + case 4: + dword |= (0x5 << 28); /* ...5 for DDR800 */ + break; + case 5: + dword |= (0x6 << 28); /* ...6 for DDR1066 */ + break; + case 6: + dword |= (0x8 << 28); /* ...8 for DDR800 */ + break; + default: + dword |= (0x9 << 28); /* ...9 for DDR1600 */ + break; + } + Set_NB32(pDCTstat->dev_dct, 0x1b0, dword); + } +}
1
0
0
0
Patch set updated for coreboot: cpu/amd/fam10h-fam15h: Bring HT register configuration in line with BKDG
by Timothy Pearson
16 Nov '15
16 Nov '15
Timothy Pearson (tpearson(a)raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/12022
-gerrit commit cbbc67bc35ee5c3336f78703204d312f078a4e97 Author: Timothy Pearson <tpearson(a)raptorengineeringinc.com> Date: Sun Aug 2 21:18:29 2015 -0500 cpu/amd/fam10h-fam15h: Bring HT register configuration in line with BKDG The existing HyperTransport register configuration values were incorrect in many spots. Apply the correct values from the BKDG on Family 10h and Family 15h processors. Change-Id: I009b6f478340e2dbfcda2b4534473d4397f9ecef Signed-off-by: Timothy Pearson <tpearson(a)raptorengineeringinc.com> --- src/cpu/amd/family_10h-family_15h/defaults.h | 168 +++++++++++++++++++++------ 1 file changed, 133 insertions(+), 35 deletions(-) diff --git a/src/cpu/amd/family_10h-family_15h/defaults.h b/src/cpu/amd/family_10h-family_15h/defaults.h index b6c9bc4..a3c7b1f 100644 --- a/src/cpu/amd/family_10h-family_15h/defaults.h +++ b/src/cpu/amd/family_10h-family_15h/defaults.h @@ -371,44 +371,140 @@ static const struct { [2] SyncOnUcEccEn = 1 */ /* XBAR buffer settings */ - { 3, 0x6c, AMD_FAM10_ALL, AMD_PTYPE_ALL, - 0x00018052, 0x700780f7 }, + { 3, 0x6c, AMD_FAM10_ALL & ~(AMD_DR_Dx), AMD_PTYPE_ALL, + 0x00018052, 0x700780f7 }, /* IsocRspDBC = 0x0, + UpRspDBC = 0x1, + DatBuf24 = 0x1, + DnRspDBC = 0x1, + DnReqDBC = 0x1, + UpReqDBC = 0x2 */ + + /* XBAR buffer settings */ + { 3, 0x6c, AMD_DR_Dx, AMD_PTYPE_ALL, + 0x00028052, 0x700780f7 }, /* IsocRspDBC = 0x0, + UpRspDBC = 0x2, + DatBuf24 = 0x1, + DnRspDBC = 0x1, + DnReqDBC = 0x1, + UpReqDBC = 0x2 */ /* XBAR buffer settings */ { 3, 0x6c, AMD_FAM15_ALL, AMD_PTYPE_ALL, - 0x10010052, 0x700700f7 }, + 0x10010052, 0x700700f7 }, /* IsocRspDBC = 0x1, + UpRspDBC = 0x1, + DnRspDBC = 0x1, + DnReqDBC = 0x1, + UpReqDBC = 0x2 */ /* Errata 281 Workaround */ - { 3, 0x6C, ( AMD_DR_B0 | AMD_DR_B1), + { 3, 0x6c, (AMD_DR_B0 | AMD_DR_B1), AMD_PTYPE_SVR, 0x00010094, 0x700780F7 }, - { 3, 0x6C, AMD_FAM10_ALL, AMD_PTYPE_UMA, + { 3, 0x6c, AMD_FAM10_ALL, AMD_PTYPE_UMA, 0x60018051, 0x700780F7 }, - { 3, 0x70, AMD_FAM10_ALL, AMD_PTYPE_ALL, - 0x00041153, 0x777777F7 }, + { 3, 0x70, AMD_FAM10_ALL & ~(AMD_DR_Dx), AMD_PTYPE_ALL, + 0x00041153, 0x777777f7 }, /* IsocRspCBC = 0x0, + IsocPreqCBC = 0x0, + IsocReqCBC = 0x0, + UpRspCBC = 0x4, + DnPreqCBC = 0x1, + UpPreqCBC = 0x1, + DnRspCBC = 0x1, + DnReqCBC = 0x1, + UpReqCBC = 0x3 */ + + { 3, 0x70, AMD_DR_Dx, AMD_PTYPE_ALL, + 0x00051153, 0x777777f7 }, /* IsocRspCBC = 0x0, + IsocPreqCBC = 0x0, + IsocReqCBC = 0x0, + UpRspCBC = 0x5, + DnPreqCBC = 0x1, + UpPreqCBC = 0x1, + DnRspCBC = 0x1, + DnReqCBC = 0x1, + UpReqCBC = 0x3 */ { 3, 0x70, AMD_FAM15_ALL, AMD_PTYPE_ALL, - 0x10171155, 0x777777f7 }, + 0x10171155, 0x777777f7 }, /* IsocRspCBC = 0x1, + IsocPreqCBC = 0x0, + IsocReqCBC = 0x1, + UpRspCBC = 0x7, + DnPreqCBC = 0x1, + UpPreqCBC = 0x1, + DnRspCBC = 0x1, + DnReqCBC = 0x1, + UpReqCBC = 0x5 */ { 3, 0x70, AMD_FAM10_ALL, AMD_PTYPE_UMA, - 0x61221151, 0x777777F7 }, + 0x61221151, 0x777777f7 }, /* IsocRspCBC = 0x6, + IsocPreqCBC = 0x1, + IsocReqCBC = 0x2, + UpRspCBC = 0x2, + DnPreqCBC = 0x1, + UpPreqCBC = 0x1, + DnRspCBC = 0x1, + DnReqCBC = 0x1, + UpReqCBC = 0x1 */ + + { 3, 0x74, AMD_FAM10_ALL, ~AMD_PTYPE_UMA, + 0x00081111, 0xf7ff7777 }, /* DRReqCBC = 0x0, + IsocPreqCBC = 0x0, + IsocReqCBC = 0x0, + ProbeCBC = 0x8, + DnPreqCBC = 0x1, + UpPreqCBC = 0x1, + DnReqCBC = 0x1, + UpReqCBC = 0x1 */ { 3, 0x74, AMD_FAM10_ALL, AMD_PTYPE_UMA, - 0x00080101, 0x000F7777 }, + 0x00480101, 0xf7ff7777 }, /* DRReqCBC = 0x0, + IsocPreqCBC = 0x0, + IsocReqCBC = 0x4, + ProbeCBC = 0x8, + DnPreqCBC = 0x0, + UpPreqCBC = 0x1, + DnReqCBC = 0x0, + UpReqCBC = 0x1 */ { 3, 0x74, AMD_FAM15_ALL, AMD_PTYPE_ALL, - 0x00172111, 0x77ff7777 }, - - { 3, 0x7C, AMD_FAM10_ALL, AMD_PTYPE_ALL, - 0x00090914, 0x707FFF1F }, + 0x00172111, 0xf7ff7777 }, /* DRReqCBC = 0x0, + IsocPreqCBC = 0x0, + IsocReqCBC = 0x1, + ProbeCBC = 0x7, + DnPreqCBC = 0x2, + UpPreqCBC = 0x1, + DnReqCBC = 0x1, + UpReqCBC = 0x1 */ + + { 3, 0x7c, AMD_FAM10_ALL & ~(AMD_DR_Dx), AMD_PTYPE_ALL, + 0x00090914, 0x707fff1f }, /* XBar2SriFreeListCBInc = 0x0, + Sri2XbarFreeRspDBC = 0x0, + Sri2XbarFreeXreqDBC = 0x9, + Sri2XbarFreeRspCBC = 0x0, + Sri2XbarFreeXreqCBC = 0x9, + Xbar2SriFreeListCBC = 0x14 */ + + { 3, 0x7c, AMD_DR_Dx, AMD_PTYPE_ALL, + 0x00090a18, 0x707fff1f }, /* XBar2SriFreeListCBInc = 0x0, + Sri2XbarFreeRspDBC = 0x0, + Sri2XbarFreeXreqDBC = 0x9, + Sri2XbarFreeRspCBC = 0x0, + Sri2XbarFreeXreqCBC = 0x9, + Xbar2SriFreeListCBC = 0x14 */ /* Errata 281 Workaround */ { 3, 0x7C, ( AMD_DR_B0 | AMD_DR_B1), AMD_PTYPE_SVR, 0x00144514, 0x707FFF1F }, - { 3, 0x7C, AMD_FAM15_ALL, AMD_PTYPE_ALL, - 0x040d0f16, 0x07ffff1f }, + { 3, 0x7c, AMD_FAM15_ALL, AMD_PTYPE_ALL, + 0x040d0f16, 0x77ffff1f }, /* XBar2SriFreeListCBInc = 0x0, + SrqExtFreeListBC = 0x8, + Sri2XbarFreeRspDBC = 0x0, + Sri2XbarFreeXreqDBC = 0xd, + Sri2XbarFreeRspCBC = 0x0, + Sri2XbarFreeXreqCBC = 0xf, + Xbar2SriFreeListCBC = 0x16 */ { 3, 0x7C, AMD_FAM10_ALL, AMD_PTYPE_UMA, 0x00070814, 0x007FFF1F }, @@ -630,18 +726,16 @@ static const struct { 0x00004400, 0x00006400 }, /* HT_PHY_DLL_REG */ { 0xCF, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3, - 0x00000000, 0x000000FF }, /* Provide clear setting for logical - completeness */ + 0x0000005a, 0x000000ff }, /* Use common "safe" setting for K10 */ { 0xDF, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3, - 0x00000000, 0x000000FF }, /* Provide clear setting for logical - completeness */ + 0x0000005a, 0x000000ff }, /* Use common "safe" setting for K10 */ { 0xCF, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT1, - 0x0000006D, 0x000000FF }, /* HT_PHY_HT1_FIFO_PTR_OPT_VALUE */ + 0x0000006d, 0x000000ff }, /* HT_PHY_HT1_FIFO_PTR_OPT_VALUE */ { 0xDF, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT1, - 0x0000006D, 0x000000FF }, /* HT_PHY_HT1_FIFO_PTR_OPT_VALUE */ + 0x0000006d, 0x000000ff }, /* HT_PHY_HT1_FIFO_PTR_OPT_VALUE */ /* Link Phy Receiver Loop Filter Registers */ { 0xD1, AMD_FAM10_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3, @@ -664,24 +758,29 @@ static const struct { 0x40040000, 0xe01F0000 }, /* [31:29] RttCtl = 02h, [20:16] RttIndex = 04h */ -/* FIXME - * Causes lockups for some reason when more than one package is installed - * Debug and reactivate! - */ -// #if 0 { 0xCF, AMD_FAM15_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3, - 0x00000000, 0x000000FF }, /* Provide clear setting for logical - completeness */ + 0x00000a2a, 0x000000ff }, /* P0RcvRdPtr = 0xa, + P0XmtRdPtr = 0x2 + P1RcvRdPtr = 0xa + P1XmtRdPtr = 0x0 */ { 0xDF, AMD_FAM15_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3, - 0x00000000, 0x000000FF }, /* Provide clear setting for logical - completeness */ + 0x00000a2a, 0x000000ff }, /* P0RcvRdPtr = 0xa, + P0XmtRdPtr = 0x2 + P1RcvRdPtr = 0xa + P1XmtRdPtr = 0x0 */ { 0xCF, AMD_FAM15_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT1, - 0x0000006D, 0x000000FF }, /* HT_PHY_HT1_FIFO_PTR_OPT_VALUE */ + 0x00000d4d, 0x000000ff }, /* P0RcvRdPtr = 0xd, + P0XmtRdPtr = 0x4 + P1RcvRdPtr = 0xd + P1XmtRdPtr = 0x0 */ { 0xDF, AMD_FAM15_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT1, - 0x0000006D, 0x000000FF }, /* HT_PHY_HT1_FIFO_PTR_OPT_VALUE */ + 0x00000d4d, 0x000000ff }, /* P0RcvRdPtr = 0xd, + P0XmtRdPtr = 0x4 + P1RcvRdPtr = 0xd + P1XmtRdPtr = 0x0 */ /* Link Phy Receiver Loop Filter Registers */ { 0xD1, AMD_FAM15_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_HT3, @@ -702,6 +801,5 @@ static const struct { { 0xC0, AMD_FAM15_ALL, AMD_PTYPE_ALL, HTPHY_LINKTYPE_ALL, 0x40040000, 0xe01F0000 }, /* [31:29] RttCtl = 02h, - [20:16] RttIndex = 04h */ -// #endif + [20:16] RttIndex = 04h */ };
1
0
0
0
Patch set updated for coreboot: northbridge/amd/amdfam10: Add probe filter support
by Timothy Pearson
16 Nov '15
16 Nov '15
Timothy Pearson (tpearson(a)raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at
http://review.coreboot.org/12021
-gerrit commit dce6291aaf5afebf4cd6cfb113dde28b0ed0ba4d Author: Timothy Pearson <tpearson(a)raptorengineeringinc.com> Date: Sun Aug 2 21:06:39 2015 -0500 northbridge/amd/amdfam10: Add probe filter support All modern Opteron processors support the HT probe filter, which helps to increase coherent fabric performance by reducing the number of HT transactions per cache probe. AMD recommends that the probe filter be enabled on all systems with more than two nodes, and it does not hurt to enable it on systems with 2 nodes. Change-Id: I00a27a828260be8685ae622cfa5a4995add95a8e Signed-off-by: Timothy Pearson <tpearson(a)raptorengineeringinc.com> --- src/cpu/amd/family_10h-family_15h/init_cpus.c | 13 ++ .../amd/family_10h-family_15h/model_10xxx_init.c | 22 ++++ src/northbridge/amd/amdfam10/northbridge.c | 144 ++++++++++++++++++++- src/northbridge/amd/amdht/h3ncmn.c | 22 ++++ 4 files changed, 200 insertions(+), 1 deletion(-) diff --git a/src/cpu/amd/family_10h-family_15h/init_cpus.c b/src/cpu/amd/family_10h-family_15h/init_cpus.c index a421bfcc..a6d8dc4 100644 --- a/src/cpu/amd/family_10h-family_15h/init_cpus.c +++ b/src/cpu/amd/family_10h-family_15h/init_cpus.c @@ -441,6 +441,19 @@ static u32 init_cpus(u32 cpu_init_detectedx, struct sys_info *sysinfo) cpuSetAMDMSR(id.nodeid); + /* Set up probe filter support */ + if (is_gt_rev_d()) { + uint8_t node_count; + node_count = (pci_read_config32(NODE_PCI(id.nodeid, 0), 0x60) >> 4) & 0x7; + node_count++; + + if (node_count > 1) { + msr_t msr = rdmsr(BU_CFG2_MSR); + msr.hi |= 1 << (42 - 32); + wrmsr(BU_CFG2_MSR, msr); + } + } + #if CONFIG_SET_FIDVID #if CONFIG_LOGICAL_CPUS && CONFIG_SET_FIDVID_CORE0_ONLY // Run on all AP for proper FID/VID setup. diff --git a/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c b/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c index 0a86966..4ccf79d 100644 --- a/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c +++ b/src/cpu/amd/family_10h-family_15h/model_10xxx_init.c @@ -50,6 +50,28 @@ static inline uint8_t is_fam15h(void) return fam15h; } +static inline uint8_t is_gt_rev_d(void) +{ + uint8_t fam15h = 0; + uint8_t rev_gte_d = 0; + uint32_t family; + uint32_t model; + + family = model = cpuid_eax(0x80000001); + model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4); + family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8); + + if (family >= 0x6f) + /* Family 15h or later */ + fam15h = 1; + + if ((model >= 0x8) || fam15h) + /* Revision D or later */ + rev_gte_d = 1; + + return rev_gte_d; +} + static volatile uint8_t fam15h_startup_flags[MAX_NODES_SUPPORTED][MAX_CORES_SUPPORTED] = {{ 0 }}; static void model_10xxx_init(device_t dev) diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c index a922496..8651ad0 100644 --- a/src/northbridge/amd/amdfam10/northbridge.c +++ b/src/northbridge/amd/amdfam10/northbridge.c @@ -26,10 +26,13 @@ #include <lib.h> #include <smbios.h> #include <cpu/cpu.h> +#include <delay.h> #include <cpu/x86/lapic.h> +#include <cpu/x86/cache.h> #include <cpu/amd/mtrr.h> #include <cpu/amd/amdfam10_sysconf.h> +#include <cpu/amd/model_10xxx_msr.h> #include <cpu/amd/family_10h-family_15h/ram_calc.h> #if CONFIG_LOGICAL_CPUS @@ -1523,7 +1526,7 @@ static void cpu_bus_scan(device_t dev) if(i>=32) { busn--; devn-=32; - pbus = pci_domain->link_list->next); + pbus = pci_domain->link_list->next; } #endif @@ -1643,8 +1646,147 @@ static void cpu_bus_scan(device_t dev) } } +static void detect_and_enable_probe_filter(device_t dev) +{ + uint32_t dword; + + uint8_t fam15h = 0; + uint8_t rev_gte_d = 0; + uint8_t dual_node = 0; + unsigned nb_cfg_54; + uint32_t f3xe8; + uint32_t family; + uint32_t model; + + family = model = cpuid_eax(0x80000001); + model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4); + + if (is_fam15h()) { + /* Family 15h or later */ + fam15h = 1; + nb_cfg_54 = 1; + } + + if ((model >= 0x8) || fam15h) + /* Revision D or later */ + rev_gte_d = 1; + + if (rev_gte_d) + /* Check for dual node capability */ + if (f3xe8 & 0x20000000) + dual_node = 1; + + if (rev_gte_d && (sysconf.nodes > 1)) { + /* Enable the probe filter */ + uint8_t i; + uint8_t pfmode = 0x0; + + uint32_t f3x58[MAX_NODES_SUPPORTED]; + uint32_t f3x5c[MAX_NODES_SUPPORTED]; + + printk(BIOS_DEBUG, "Enabling probe filter\n"); + + /* Disable L3 and DRAM scrubbers and configure system for probe filter support */ + for (i = 0; i < sysconf.nodes; i++) { + device_t f2x_dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 2)); + device_t f3x_dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 3)); + + f3x58[i] = pci_read_config32(f3x_dev, 0x58); + f3x5c[i] = pci_read_config32(f3x_dev, 0x5c); + pci_write_config32(f3x_dev, 0x58, f3x58[i] & ~((0x1f << 24) | 0x1f)); + pci_write_config32(f3x_dev, 0x5c, f3x5c[i] & ~0x1); + + dword = pci_read_config32(f2x_dev, 0x1b0); + dword &= ~(0x7 << 8); /* CohPrefPrbLmt = 0x0 */ + pci_write_config32(f2x_dev, 0x1b0, dword); + + msr_t msr = rdmsr_amd(BU_CFG2_MSR); + msr.hi |= 1 << (42 - 32); + wrmsr_amd(BU_CFG2_MSR, msr); + + if (is_fam15h()) { + uint8_t subcache_size = 0x0; + uint8_t pref_so_repl = 0x0; + uint32_t f3x1c4 = pci_read_config32(f3x_dev, 0x1c4); + if ((f3x1c4 & 0xffff) == 0xcccc) { + subcache_size = 0x1; + pref_so_repl = 0x2; + pfmode = 0x3; + } else { + pfmode = 0x2; + } + + dword = pci_read_config32(f3x_dev, 0x1d4); + dword |= 0x1 << 29; /* PFLoIndexHashEn = 0x1 */ + dword &= ~(0x3 << 20); /* PFPreferredSORepl = pref_so_repl */ + dword |= (pref_so_repl & 0x3) << 20; + dword |= 0x1 << 17; /* PFWayHashEn = 0x1 */ + dword |= 0xf << 12; /* PFSubCacheEn = 0xf */ + dword &= ~(0x3 << 10); /* PFSubCacheSize3 = subcache_size */ + dword |= (subcache_size & 0x3) << 10; + dword &= ~(0x3 << 8); /* PFSubCacheSize2 = subcache_size */ + dword |= (subcache_size & 0x3) << 8; + dword &= ~(0x3 << 6); /* PFSubCacheSize1 = subcache_size */ + dword |= (subcache_size & 0x3) << 6; + dword &= ~(0x3 << 4); /* PFSubCacheSize0 = subcache_size */ + dword |= (subcache_size & 0x3) << 4; + dword &= ~(0x3 << 2); /* PFWayNum = 0x2 */ + dword |= 0x2 << 2; + pci_write_config32(f3x_dev, 0x1d4, dword); + } else { + pfmode = 0x2; + + dword = pci_read_config32(f3x_dev, 0x1d4); + dword |= 0x1 << 29; /* PFLoIndexHashEn = 0x1 */ + dword &= ~(0x3 << 20); /* PFPreferredSORepl = 0x2 */ + dword |= 0x2 << 20; + dword |= 0xf << 12; /* PFSubCacheEn = 0xf */ + dword &= ~(0x3 << 10); /* PFSubCacheSize3 = 0x0 */ + dword &= ~(0x3 << 8); /* PFSubCacheSize2 = 0x0 */ + dword &= ~(0x3 << 6); /* PFSubCacheSize1 = 0x0 */ + dword &= ~(0x3 << 4); /* PFSubCacheSize0 = 0x0 */ + dword &= ~(0x3 << 2); /* PFWayNum = 0x2 */ + dword |= 0x2 << 2; + pci_write_config32(f3x_dev, 0x1d4, dword); + } + } + + udelay(40); + + disable_cache(); + asm("wbinvd"); + for (i = 0; i < sysconf.nodes; i++) { + device_t f3x_dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 3)); + + dword = pci_read_config32(f3x_dev, 0x1c4); + dword |= (0x1 << 31); /* L3TagInit = 1 */ + pci_write_config32(f3x_dev, 0x1c4, dword); + do { + } while (pci_read_config32(f3x_dev, 0x1c4) & (0x1 << 31)); + + dword = pci_read_config32(f3x_dev, 0x1d4); + dword &= ~0x3; /* PFMode = pfmode */ + dword |= pfmode & 0x3; + pci_write_config32(f3x_dev, 0x1d4, dword); + do { + } while (!(pci_read_config32(f3x_dev, 0x1d4) & (0x1 << 19))); + } + enable_cache(); + + /* Reenable L3 and DRAM scrubbers */ + for (i = 0; i < sysconf.nodes; i++) { + device_t f3x_dev = dev_find_slot(0, PCI_DEVFN(0x18 + i, 3)); + + pci_write_config32(f3x_dev, 0x58, f3x58[i]); + pci_write_config32(f3x_dev, 0x5c, f3x5c[i]); + } + + } +} + static void cpu_bus_init(device_t dev) { + detect_and_enable_probe_filter(dev); initialize_cpus(dev->link_list); #if CONFIG_AMD_SB_CIMX sb_After_Pci_Init(); diff --git a/src/northbridge/amd/amdht/h3ncmn.c b/src/northbridge/amd/amdht/h3ncmn.c index 01c0e48..8ee929d 100644 --- a/src/northbridge/amd/amdht/h3ncmn.c +++ b/src/northbridge/amd/amdht/h3ncmn.c @@ -103,6 +103,28 @@ static inline uint8_t is_fam15h(void) return fam15h; } +static inline uint8_t is_gt_rev_d(void) +{ + uint8_t fam15h = 0; + uint8_t rev_gte_d = 0; + uint32_t family; + uint32_t model; + + family = model = cpuid_eax(0x80000001); + model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4); + family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8); + + if (family >= 0x6f) + /* Family 15h or later */ + fam15h = 1; + + if ((model >= 0x8) || fam15h) + /* Revision D or later */ + rev_gte_d = 1; + + return rev_gte_d; +} + /***************************************************************************//** * * SBDFO
1
0
0
0
← Newer
1
...
60
61
62
63
64
65
66
...
155
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
Results per page:
10
25
50
100
200