Skip to content

Commit

Permalink
northbridge/amd/amdmct/mct_ddr3: Add initial Suspend to RAM (S3) support
Browse files Browse the repository at this point in the history
Change-Id: Ic97567851fa40295bc21cefd7537407b99d71709
Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
Reviewed-on: http://review.coreboot.org/11952
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
  • Loading branch information
madscientist159 authored and Martin Roth committed Oct 30, 2015
1 parent 4ea0cc0 commit 59d0e04
Show file tree
Hide file tree
Showing 6 changed files with 852 additions and 72 deletions.
2 changes: 2 additions & 0 deletions src/northbridge/amd/amdfam10/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ s3nv-file := $(obj)/coreboot_s3nv.rom
s3nv-align := $(CONFIG_S3_DATA_SIZE)
s3nv-type := raw

ramstage-$(CONFIG_DIMM_DDR3) += ../amdmct/mct_ddr3/s3utils.c

endif
8 changes: 8 additions & 0 deletions src/northbridge/amd/amdfam10/northbridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@
#include <sb_cimx.h>
#endif

#if IS_ENABLED(CONFIG_DIMM_DDR3)
#include "../amdmct/mct_ddr3/s3utils.h"
#endif

struct amdfam10_sysconf_t sysconf;

#define FX_DEVS NODE_NUMS
Expand Down Expand Up @@ -1413,6 +1417,10 @@ static void root_complex_enable_dev(struct device *dev)
/* Do not delay UMA setup, as a device on the PCI bus may evaluate
the global uma_memory variables already in its enable function. */
if (!done) {
#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME) && IS_ENABLED(CONFIG_DIMM_DDR3)
save_mct_information_to_nvram();
#endif

setup_bsp_ramtop();
setup_uma_memory();
done = 1;
Expand Down
154 changes: 82 additions & 72 deletions src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
Original file line number Diff line number Diff line change
Expand Up @@ -282,91 +282,101 @@ static void mctAutoInitMCT_D(struct MCTStatStruc *pMCTstat,
u8 Node, NodesWmem;
u32 node_sys_base;

uint8_t s3resume = acpi_is_wakeup_s3();

restartinit:
mctInitMemGPIOs_A_D(); /* Set any required GPIOs*/
NodesWmem = 0;
node_sys_base = 0;
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
struct DCTStatStruc *pDCTstat;
pDCTstat = pDCTstatA + Node;
if (s3resume) {
#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
printk(BIOS_DEBUG, "mctAutoInitMCT_D: Restoring DCT configuration from NVRAM\n");
restore_mct_information_from_nvram();
#endif
} else {
NodesWmem = 0;
node_sys_base = 0;
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
struct DCTStatStruc *pDCTstat;
pDCTstat = pDCTstatA + Node;

/* Zero out data structures to avoid false detection of DIMMs */
memset(pDCTstat, 0, sizeof(struct DCTStatStruc));

/* Initialize data structures */
pDCTstat->Node_ID = Node;
pDCTstat->dev_host = PA_HOST(Node);
pDCTstat->dev_map = PA_MAP(Node);
pDCTstat->dev_dct = PA_DCT(Node);
pDCTstat->dev_nbmisc = PA_NBMISC(Node);
pDCTstat->NodeSysBase = node_sys_base;

printk(BIOS_DEBUG, "%s: mct_init Node %d\n", __func__, Node);
mct_init(pMCTstat, pDCTstat);
mctNodeIDDebugPort_D();
pDCTstat->NodePresent = NodePresent_D(Node);
if (pDCTstat->NodePresent) { /* See if Node is there*/
printk(BIOS_DEBUG, "%s: clear_legacy_Mode\n", __func__);
clear_legacy_Mode(pMCTstat, pDCTstat);
pDCTstat->LogicalCPUID = mctGetLogicalCPUID_D(Node);

printk(BIOS_DEBUG, "%s: mct_InitialMCT_D\n", __func__);
mct_InitialMCT_D(pMCTstat, pDCTstat);

printk(BIOS_DEBUG, "%s: mctSMBhub_Init\n", __func__);
mctSMBhub_Init(Node); /* Switch SMBUS crossbar to proper node*/

printk(BIOS_DEBUG, "%s: mct_initDCT\n", __func__);
mct_initDCT(pMCTstat, pDCTstat);
if (pDCTstat->ErrCode == SC_FatalErr) {
goto fatalexit; /* any fatal errors?*/
} else if (pDCTstat->ErrCode < SC_StopError) {
NodesWmem++;
}
} /* if Node present */
node_sys_base = pDCTstat->NodeSysBase;
node_sys_base += (pDCTstat->NodeSysLimit + 2) & ~0x0F;
}
if (NodesWmem == 0) {
printk(BIOS_DEBUG, "No Nodes?!\n");
goto fatalexit;
}
/* Zero out data structures to avoid false detection of DIMMs */
memset(pDCTstat, 0, sizeof(struct DCTStatStruc));

/* Initialize data structures */
pDCTstat->Node_ID = Node;
pDCTstat->dev_host = PA_HOST(Node);
pDCTstat->dev_map = PA_MAP(Node);
pDCTstat->dev_dct = PA_DCT(Node);
pDCTstat->dev_nbmisc = PA_NBMISC(Node);
pDCTstat->NodeSysBase = node_sys_base;

printk(BIOS_DEBUG, "%s: mct_init Node %d\n", __func__, Node);
mct_init(pMCTstat, pDCTstat);
mctNodeIDDebugPort_D();
pDCTstat->NodePresent = NodePresent_D(Node);
if (pDCTstat->NodePresent) { /* See if Node is there*/
printk(BIOS_DEBUG, "%s: clear_legacy_Mode\n", __func__);
clear_legacy_Mode(pMCTstat, pDCTstat);
pDCTstat->LogicalCPUID = mctGetLogicalCPUID_D(Node);

printk(BIOS_DEBUG, "%s: mct_InitialMCT_D\n", __func__);
mct_InitialMCT_D(pMCTstat, pDCTstat);

printk(BIOS_DEBUG, "%s: mctSMBhub_Init\n", __func__);
mctSMBhub_Init(Node); /* Switch SMBUS crossbar to proper node*/

printk(BIOS_DEBUG, "%s: mct_initDCT\n", __func__);
mct_initDCT(pMCTstat, pDCTstat);
if (pDCTstat->ErrCode == SC_FatalErr) {
goto fatalexit; /* any fatal errors?*/
} else if (pDCTstat->ErrCode < SC_StopError) {
NodesWmem++;
}
} /* if Node present */
node_sys_base = pDCTstat->NodeSysBase;
node_sys_base += (pDCTstat->NodeSysLimit + 2) & ~0x0F;
}
if (NodesWmem == 0) {
printk(BIOS_DEBUG, "No Nodes?!\n");
goto fatalexit;
}

printk(BIOS_DEBUG, "mctAutoInitMCT_D: SyncDCTsReady_D\n");
SyncDCTsReady_D(pMCTstat, pDCTstatA); /* Make sure DCTs are ready for accesses.*/
printk(BIOS_DEBUG, "mctAutoInitMCT_D: SyncDCTsReady_D\n");
SyncDCTsReady_D(pMCTstat, pDCTstatA); /* Make sure DCTs are ready for accesses.*/

printk(BIOS_DEBUG, "mctAutoInitMCT_D: HTMemMapInit_D\n");
HTMemMapInit_D(pMCTstat, pDCTstatA); /* Map local memory into system address space.*/
mctHookAfterHTMap();
printk(BIOS_DEBUG, "mctAutoInitMCT_D: HTMemMapInit_D\n");
HTMemMapInit_D(pMCTstat, pDCTstatA); /* Map local memory into system address space.*/
mctHookAfterHTMap();

printk(BIOS_DEBUG, "mctAutoInitMCT_D: CPUMemTyping_D\n");
CPUMemTyping_D(pMCTstat, pDCTstatA); /* Map dram into WB/UC CPU cacheability */
mctHookAfterCPU(); /* Setup external northbridge(s) */
printk(BIOS_DEBUG, "mctAutoInitMCT_D: CPUMemTyping_D\n");
CPUMemTyping_D(pMCTstat, pDCTstatA); /* Map dram into WB/UC CPU cacheability */
mctHookAfterCPU(); /* Setup external northbridge(s) */

printk(BIOS_DEBUG, "mctAutoInitMCT_D: DQSTiming_D\n");
DQSTiming_D(pMCTstat, pDCTstatA); /* Get Receiver Enable and DQS signal timing*/
printk(BIOS_DEBUG, "mctAutoInitMCT_D: DQSTiming_D\n");
DQSTiming_D(pMCTstat, pDCTstatA); /* Get Receiver Enable and DQS signal timing*/

printk(BIOS_DEBUG, "mctAutoInitMCT_D: UMAMemTyping_D\n");
UMAMemTyping_D(pMCTstat, pDCTstatA); /* Fix up for UMA sizing */
printk(BIOS_DEBUG, "mctAutoInitMCT_D: UMAMemTyping_D\n");
UMAMemTyping_D(pMCTstat, pDCTstatA); /* Fix up for UMA sizing */

printk(BIOS_DEBUG, "mctAutoInitMCT_D: :OtherTiming\n");
mct_OtherTiming(pMCTstat, pDCTstatA);
printk(BIOS_DEBUG, "mctAutoInitMCT_D: :OtherTiming\n");
mct_OtherTiming(pMCTstat, pDCTstatA);

if (ReconfigureDIMMspare_D(pMCTstat, pDCTstatA)) { /* RESET# if 1st pass of DIMM spare enabled*/
goto restartinit;
}

InterleaveNodes_D(pMCTstat, pDCTstatA);
InterleaveChannels_D(pMCTstat, pDCTstatA);
if (ReconfigureDIMMspare_D(pMCTstat, pDCTstatA)) { /* RESET# if 1st pass of DIMM spare enabled*/
goto restartinit;
}

printk(BIOS_DEBUG, "mctAutoInitMCT_D: ECCInit_D\n");
if (ECCInit_D(pMCTstat, pDCTstatA)) { /* Setup ECC control and ECC check-bits*/
printk(BIOS_DEBUG, "mctAutoInitMCT_D: MCTMemClr_D\n");
MCTMemClr_D(pMCTstat,pDCTstatA);
}
InterleaveNodes_D(pMCTstat, pDCTstatA);
InterleaveChannels_D(pMCTstat, pDCTstatA);

printk(BIOS_DEBUG, "mctAutoInitMCT_D: ECCInit_D\n");
if (ECCInit_D(pMCTstat, pDCTstatA)) { /* Setup ECC control and ECC check-bits*/
printk(BIOS_DEBUG, "mctAutoInitMCT_D: MCTMemClr_D\n");
MCTMemClr_D(pMCTstat,pDCTstatA);
}

mct_FinalMCT_D(pMCTstat, pDCTstatA);
printk(BIOS_DEBUG, "mctAutoInitMCT_D Done: Global Status: %x\n", pMCTstat->GStatus);
mct_FinalMCT_D(pMCTstat, pDCTstatA);
printk(BIOS_DEBUG, "mctAutoInitMCT_D Done: Global Status: %x\n", pMCTstat->GStatus);
}

return;

Expand Down
112 changes: 112 additions & 0 deletions src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#ifndef MCT_D_H
#define MCT_D_H

#include <cpu/x86/msr.h>

/*===========================================================================
CPU - K8/FAM10
===========================================================================*/
Expand Down Expand Up @@ -596,6 +598,116 @@ struct DCTStatStruc { /* A per Node structure*/
uint32_t DimmSerialNumber[MAX_DIMMS_SUPPORTED];
} __attribute__((packed));

struct amd_s3_persistent_mct_channel_data {
/* Stage 1 (1 dword) */
uint32_t f2x110;

/* Stage 2 (88 dwords) */
uint32_t f1x40;
uint32_t f1x44;
uint32_t f1x48;
uint32_t f1x4c;
uint32_t f1x50;
uint32_t f1x54;
uint32_t f1x58;
uint32_t f1x5c;
uint32_t f1x60;
uint32_t f1x64;
uint32_t f1x68;
uint32_t f1x6c;
uint32_t f1x70;
uint32_t f1x74;
uint32_t f1x78;
uint32_t f1x7c;
uint32_t f1xf0;
uint32_t f1x120;
uint32_t f1x124;
uint32_t f2x10c;
uint32_t f2x114;
uint32_t f2x118;
uint32_t f2x11c;
uint32_t f2x1b0;
uint32_t f3x44;
uint64_t msr0000020[16];
uint64_t msr00000250;
uint64_t msr00000258;
uint64_t msr0000026[8];
uint64_t msr000002ff;
uint64_t msrc0010010;
uint64_t msrc001001a;
uint64_t msrc001001d;
uint64_t msrc001001f;

/* Stage 3 (21 dwords) */
uint32_t f2x40;
uint32_t f2x44;
uint32_t f2x48;
uint32_t f2x4c;
uint32_t f2x50;
uint32_t f2x54;
uint32_t f2x58;
uint32_t f2x5c;
uint32_t f2x60;
uint32_t f2x64;
uint32_t f2x68;
uint32_t f2x6c;
uint32_t f2x78;
uint32_t f2x7c;
uint32_t f2x80;
uint32_t f2x84;
uint32_t f2x88;
uint32_t f2x8c;
uint32_t f2x90;
uint32_t f2xa4;
uint32_t f2xa8;

/* Stage 4 (1 dword) */
uint32_t f2x94;

/* Stage 6 (33 dwords) */
uint32_t f2x9cx0d0f0_f_8_0_0_8_4_0[9][3]; /* [lane][setting] */
uint32_t f2x9cx00;
uint32_t f2x9cx0a;
uint32_t f2x9cx0c;

/* Stage 7 (1 dword) */
uint32_t f2x9cx04;

/* Stage 9 (2 dwords) */
uint32_t f2x9cx0d0fe006;
uint32_t f2x9cx0d0fe007;

/* Stage 10 (78 dwords) */
uint32_t f2x9cx10[12];
uint32_t f2x9cx20[12];
uint32_t f2x9cx3_0_0_3_1[4][3]; /* [dimm][setting] */
uint32_t f2x9cx3_0_0_7_5[4][3]; /* [dimm][setting] */
uint32_t f2x9cx0d;
uint32_t f2x9cx0d0f0_f_0_13[9]; /* [lane] */
uint32_t f2x9cx0d0f0_f_0_30[9]; /* [lane] */
uint32_t f2x9cx0d0f2_f_0_30[4]; /* [pad select] */
uint32_t f2x9cx0d0f8_8_4_0[2][3]; /* [offset][pad select] */
uint32_t f2x9cx0d0f812f;

/* Stage 11 (24 dwords) */
uint32_t f2x9cx30[12];
uint32_t f2x9cx40[12];

/* Other (1 dword) */
uint32_t f3x58;

/* TOTAL: 250 dwords */
} __attribute__((packed));

struct amd_s3_persistent_node_data {
uint32_t node_present;
struct amd_s3_persistent_mct_channel_data channel[2];
} __attribute__((packed));

struct amd_s3_persistent_data {
struct amd_s3_persistent_node_data node[MAX_NODES_SUPPORTED];
} __attribute__((packed));

/*===============================================================================
Local Error Status Codes (DCTStatStruc.ErrCode)
===============================================================================*/
Expand Down
Loading

0 comments on commit 59d0e04

Please sign in to comment.