summaryrefslogtreecommitdiff
path: root/src/northbridge/amd/amdfam10
diff options
context:
space:
mode:
Diffstat (limited to 'src/northbridge/amd/amdfam10')
-rw-r--r--src/northbridge/amd/amdfam10/northbridge.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/northbridge/amd/amdfam10/northbridge.c b/src/northbridge/amd/amdfam10/northbridge.c
index d1803ae667..116789ce11 100644
--- a/src/northbridge/amd/amdfam10/northbridge.c
+++ b/src/northbridge/amd/amdfam10/northbridge.c
@@ -702,6 +702,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();
@@ -745,6 +747,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)