diff options
Diffstat (limited to 'resources/libreboot/patch/kgpe-d16/0046-northbridge-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch')
-rw-r--r-- | resources/libreboot/patch/kgpe-d16/0046-northbridge-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/resources/libreboot/patch/kgpe-d16/0046-northbridge-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch b/resources/libreboot/patch/kgpe-d16/0046-northbridge-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch new file mode 100644 index 0000000..7b5b1f8 --- /dev/null +++ b/resources/libreboot/patch/kgpe-d16/0046-northbridge-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch @@ -0,0 +1,259 @@ +From a56e3642d8003813e19d6685c7f8680e1b645b22 Mon Sep 17 00:00:00 2001 +From: Timothy Pearson <kb9vqf@pearsoncomputing.net> +Date: Fri, 5 Jun 2015 21:13:30 -0500 +Subject: [PATCH 046/146] northbridge/amd/amdfam10: Enable CC6 DRAM save area + setup + +--- + 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 a29dad9..d13932c 100644 +--- a/src/northbridge/amd/amdfam10/northbridge.c ++++ b/src/northbridge/amd/amdfam10/northbridge.c +@@ -704,6 +704,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(); +@@ -747,6 +749,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 779d9ad..0e97715 100644 +--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c ++++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +@@ -1186,6 +1186,100 @@ static void compare_nvram_spd_hashes(struct MCTStatStruc *pMCTstat, + } + } + ++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) + { +@@ -1235,6 +1329,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(); +@@ -1400,6 +1495,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.7.9.5 + |