summaryrefslogtreecommitdiffstats
path: root/resources/libreboot/patch/kgpe-d16/0046-northbridge-amd-amdfam10-Enable-CC6-DRAM-save-area-s.patch
diff options
context:
space:
mode:
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.patch259
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
+