diff options
Diffstat (limited to 'resources/libreboot/patch/kgpe-d16/0044-northbridge-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch')
-rw-r--r-- | resources/libreboot/patch/kgpe-d16/0044-northbridge-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/resources/libreboot/patch/kgpe-d16/0044-northbridge-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch b/resources/libreboot/patch/kgpe-d16/0044-northbridge-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch new file mode 100644 index 00000000..9ed1c3d4 --- /dev/null +++ b/resources/libreboot/patch/kgpe-d16/0044-northbridge-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch @@ -0,0 +1,261 @@ +From a8478c829628eb43b1222ad981600ff742d271e8 Mon Sep 17 00:00:00 2001 +From: Timothy Pearson <tpearson@raptorengineeringinc.com> +Date: Fri, 5 Jun 2015 21:13:30 -0500 +Subject: [PATCH 044/139] northbridge/amd/amdfam10: Enable CC6 DRAM save area + setup + +Change-Id: Ibeb35da3395dc77a21a2f92f0e1d0845be53d175 +Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com> +--- + src/northbridge/amd/amdfam10/northbridge.c | 70 +++++++++++++++ + src/northbridge/amd/amdmct/mct_ddr3/mct_d.c | 132 ++++++++++++++++++++++++++++ + 2 files changed, 202 insertions(+) + +diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c +index baf77d6..51eac77 100644 +--- a/src/northbridge/amd/amdfam10/northbridge.c ++++ b/src/northbridge/amd/amdfam10/northbridge.c +@@ -706,6 +706,8 @@ struct chip_operations northbridge_amd_amdfam10_ops = { + static void amdfam10_domain_read_resources(device_t dev) + { + unsigned reg; ++ uint8_t nvram; ++ uint8_t enable_cc6; + + /* Find the already assigned resource pairs */ + get_fx_devs(); +@@ -749,6 +751,74 @@ static void amdfam10_domain_read_resources(device_t dev) + /* Reserve lower DRAM region to force PCI MMIO region to correct location above 0xefffffff */ + ram_resource(dev, 7, 0, rdmsr(TOP_MEM).lo >> 10); + #endif ++ ++ if (is_fam15h()) { ++ enable_cc6 = 0; ++ if (get_option(&nvram, "cpu_cc6_state") == CB_SUCCESS) ++ enable_cc6 = !!nvram; ++ ++ if (enable_cc6) { ++ uint8_t node; ++ uint8_t interleaved; ++ int8_t range; ++ int8_t max_range; ++ uint8_t max_node; ++ uint64_t max_range_limit; ++ uint32_t dword; ++ uint32_t dword2; ++ uint64_t qword; ++ uint8_t num_nodes; ++ ++ /* Find highest DRAM range (DramLimitAddr) */ ++ max_node = 0; ++ max_range = -1; ++ interleaved = 0; ++ max_range_limit = 0; ++ for (range = 0; range < 8; range++) { ++ dword = f1_read_config32(0x40 + (range * 0x8)); ++ if (!(dword & 0x3)) ++ continue; ++ ++ if ((dword >> 8) & 0x7) ++ interleaved = 1; ++ ++ dword = f1_read_config32(0x44 + (range * 0x8)); ++ dword2 = f1_read_config32(0x144 + (range * 0x8)); ++ qword = ((((uint64_t)dword) >> 16) & 0xffff) << 24; ++ qword |= (((uint64_t)dword2) & 0xff) << 40; ++ ++ if (qword > max_range_limit) { ++ max_range = range; ++ max_range_limit = qword; ++ max_node = dword & 0x7; ++ } ++ } ++ ++ num_nodes = 0; ++ device_t node_dev; ++ for (node = 0; node < FX_DEVS; node++) { ++ node_dev = get_node_pci(node, 0); ++ /* Test for node presence */ ++ if ((node_dev) && (pci_read_config32(node_dev, PCI_VENDOR_ID) != 0xffffffff)) ++ num_nodes++; ++ } ++ ++ /* Calculate CC6 sotrage area size */ ++ if (interleaved) ++ qword = (0x1000000 * num_nodes); ++ else ++ qword = 0x1000000; ++ ++ /* Reserve the CC6 save segment */ ++ reserved_ram_resource(dev, 8, max_range_limit >> 10, qword >> 10); ++ ++ /* Set up the C-state base address */ ++ msr_t c_state_addr_msr; ++ c_state_addr_msr = rdmsr(0xc0010073); ++ c_state_addr_msr.lo = 0xe0e0; /* CstateAddr = 0xe0e0 */ ++ wrmsr(0xc0010073, c_state_addr_msr); ++ } ++ } + } + + static u32 my_find_pci_tolm(struct bus *bus, u32 tolm) +diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +index 20e66f2..2798506 100644 +--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c ++++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +@@ -1188,6 +1188,100 @@ static void compare_nvram_spd_hashes(struct MCTStatStruc *pMCTstat, + } + #endif + ++static void set_up_cc6_storage_fam15(struct MCTStatStruc *pMCTstat, ++ struct DCTStatStruc *pDCTstat, uint8_t num_nodes) ++{ ++ uint8_t interleaved; ++ uint8_t destination_node; ++ int8_t range; ++ int8_t max_range; ++ uint8_t max_node; ++ uint64_t max_range_limit; ++ uint32_t dword; ++ uint32_t dword2; ++ uint64_t qword; ++ ++ interleaved = 0; ++ if (pMCTstat->GStatus & (1 << GSB_NodeIntlv)) ++ interleaved = 1; ++ ++ /* Find highest DRAM range (DramLimitAddr) */ ++ max_node = 0; ++ max_range = -1; ++ max_range_limit = 0; ++ for (range = 0; range < 8; range++) { ++ dword = Get_NB32(pDCTstat->dev_map, 0x40 + (range * 0x8)); ++ if (!(dword & 0x3)) ++ continue; ++ ++ dword = Get_NB32(pDCTstat->dev_map, 0x44 + (range * 0x8)); ++ dword2 = Get_NB32(pDCTstat->dev_map, 0x144 + (range * 0x8)); ++ qword = ((((uint64_t)dword) >> 16) & 0xffff) << 24; ++ qword |= (((uint64_t)dword2) & 0xff) << 40; ++ ++ if (qword > max_range_limit) { ++ max_range = range; ++ max_range_limit = qword; ++ max_node = dword & 0x7; ++ } ++ } ++ ++ if (pDCTstat->Node_ID == max_node) { ++ if (max_range >= 0) { ++ if (interleaved) ++ /* Move upper limit down by 16M * the number of nodes */ ++ max_range_limit -= (0x1000000 * num_nodes); ++ else ++ /* Move upper limit down by 16M */ ++ max_range_limit -= 0x1000000; ++ ++ /* Store modified range */ ++ dword = Get_NB32(pDCTstat->dev_map, 0x44 + (range * 0x8)); ++ dword &= ~(0xffff << 16); /* DramLimit[39:24] = max_range_limit[39:24] */ ++ dword |= (max_range_limit >> 24) & 0xffff; ++ Set_NB32(pDCTstat->dev_map, 0x44 + (range * 0x8), dword); ++ ++ dword = Get_NB32(pDCTstat->dev_map, 0x144 + (range * 0x8)); ++ dword &= ~(0xffff << 16); /* DramLimit[47:40] = max_range_limit[47:40] */ ++ dword |= (max_range_limit >> 40) & 0xff; ++ Set_NB32(pDCTstat->dev_map, 0x144 + (range * 0x8), dword); ++ } ++ } ++ ++ /* Determine save state destination node */ ++ if (interleaved) ++ destination_node = Get_NB32(pDCTstat->dev_host, 0x60) & 0x7; ++ else ++ destination_node = max_node; ++ ++ /* Set save state destination node */ ++ dword = Get_NB32(pDCTstat->dev_link, 0x128); ++ dword &= ~(0x3f << 12); /* CoreSaveStateDestNode = destination_node */ ++ dword |= (destination_node & 0x3f) << 12; ++ Set_NB32(pDCTstat->dev_link, 0x128, dword); ++} ++ ++static void lock_dram_config(struct MCTStatStruc *pMCTstat, ++ struct DCTStatStruc *pDCTstat) ++{ ++ uint32_t dword; ++ ++ dword = Get_NB32(pDCTstat->dev_dct, 0x118); ++ dword |= 0x1 << 19; /* LockDramCfg = 1 */ ++ Set_NB32(pDCTstat->dev_dct, 0x118, dword); ++} ++ ++static void set_cc6_save_enable(struct MCTStatStruc *pMCTstat, ++ struct DCTStatStruc *pDCTstat, uint8_t enable) ++{ ++ uint32_t dword; ++ ++ dword = Get_NB32(pDCTstat->dev_dct, 0x118); ++ dword &= ~(0x1 << 18); /* CC6SaveEn = enable */ ++ dword |= (enable & 0x1) << 18; ++ Set_NB32(pDCTstat->dev_dct, 0x118, dword); ++} ++ + static void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat, + struct DCTStatStruc *pDCTstatA) + { +@@ -1237,6 +1331,7 @@ static void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat, + u8 Node, NodesWmem; + u32 node_sys_base; + uint8_t nvram; ++ uint8_t enable_cc6; + uint8_t allow_config_restore; + + uint8_t s3resume = acpi_is_wakeup_s3(); +@@ -1406,6 +1501,43 @@ restartinit: + mct_ForceNBPState0_Dis_Fam15(pMCTstat, pDCTstat); + } + ++ if (is_fam15h()) { ++ enable_cc6 = 0; ++ if (get_option(&nvram, "cpu_cc6_state") == CB_SUCCESS) ++ enable_cc6 = !!nvram; ++ ++ if (enable_cc6) { ++ uint8_t num_nodes; ++ ++ num_nodes = 0; ++ for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { ++ struct DCTStatStruc *pDCTstat; ++ pDCTstat = pDCTstatA + Node; ++ ++ if (pDCTstat->NodePresent) ++ num_nodes++; ++ } ++ ++ for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { ++ struct DCTStatStruc *pDCTstat; ++ pDCTstat = pDCTstatA + Node; ++ ++ if (pDCTstat->NodePresent) ++ set_up_cc6_storage_fam15(pMCTstat, pDCTstat, num_nodes); ++ } ++ ++ for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) { ++ struct DCTStatStruc *pDCTstat; ++ pDCTstat = pDCTstatA + Node; ++ ++ if (pDCTstat->NodePresent) { ++ lock_dram_config(pMCTstat, pDCTstat); ++ set_cc6_save_enable(pMCTstat, pDCTstat, 1); ++ } ++ } ++ } ++ } ++ + mct_FinalMCT_D(pMCTstat, pDCTstatA); + printk(BIOS_DEBUG, "mctAutoInitMCT_D Done: Global Status: %x\n", pMCTstat->GStatus); + } +-- +1.9.1 + |