aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/amd/amdht
diff options
context:
space:
mode:
authorTimothy Pearson <tpearson@raptorengineeringinc.com>2015-10-16 13:51:51 -0500
committerMartin Roth <martinroth@google.com>2015-11-02 23:45:19 +0100
commit730a043fb6cb4dd3cb5af8f8640365727b598648 (patch)
tree59afe45caca1a8e1682939c7e44e95344104533e /src/northbridge/amd/amdht
parentd150006c4a4584bc9933c2d8ff580a54c4f0cc2a (diff)
cpu/amd: Add initial AMD Family 15h support
TEST: Booted ASUS KGPE-D16 with single Opteron 6380 * Unbuffered DDR3 DIMMs tested and working * Suspend to RAM (S3) tested and working Change-Id: Idffd2ce36ce183fbfa087e5ba69a9148f084b45e Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com> Reviewed-on: http://review.coreboot.org/11966 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth <martinroth@google.com>
Diffstat (limited to 'src/northbridge/amd/amdht')
-rw-r--r--src/northbridge/amd/amdht/h3ncmn.c171
-rw-r--r--src/northbridge/amd/amdht/ht_wrapper.c43
2 files changed, 193 insertions, 21 deletions
diff --git a/src/northbridge/amd/amdht/h3ncmn.c b/src/northbridge/amd/amdht/h3ncmn.c
index 95246e857e..ac7d393b24 100644
--- a/src/northbridge/amd/amdht/h3ncmn.c
+++ b/src/northbridge/amd/amdht/h3ncmn.c
@@ -39,6 +39,7 @@
#define CPU_HTNB_FUNC_04 4
#define CPU_ADDR_FUNC_01 1
#define CPU_NB_FUNC_03 3
+#define CPU_NB_FUNC_05 5
/* Function 0 registers */
#define REG_ROUTE0_0X40 0x40
@@ -66,6 +67,7 @@
#define REG_NB_CPUID_3XFC 0xFC
#define REG_NB_LINK_XCS_TOKEN0_3X148 0x148
#define REG_NB_DOWNCORE_3X190 0x190
+#define REG_NB_CAPABILITY_5X84 0x84
/* Function 4 registers */
@@ -551,9 +553,10 @@ static u8 fam10GetNumCoresOnNode(u8 node, cNorthBridge *nb)
15, 12, &temp);
/* bits[15,13,12] specify the cores */
- /* Support Downcoring */
temp = ((temp & 8) >> 1) + (temp & 3);
cores = temp + 1;
+
+ /* Support Downcoring */
AmdPCIReadBits (MAKE_SBDFO(makePCISegmentFromNode(node),
makePCIBusFromNode(node),
makePCIDeviceFromNode(node),
@@ -572,6 +575,56 @@ static u8 fam10GetNumCoresOnNode(u8 node, cNorthBridge *nb)
/***************************************************************************//**
*
+ * static u8
+ * fam15GetNumCoresOnNode(u8 node, cNorthBridge *nb)
+ *
+ * Description:
+ * Return the number of cores (1 based count) on node.
+ *
+ * Parameters:
+ * @param[in] node = the node that will be examined
+ * @param[in] *nb = this northbridge
+ * @return = the number of cores
+ *
+ *
+ */
+static u8 fam15GetNumCoresOnNode(u8 node, cNorthBridge *nb)
+{
+ u32 temp, leveling, cores;
+ u8 i;
+
+ ASSERT((node < nb->maxNodes));
+ /* Read CmpCap [7:0] */
+ AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
+ makePCIBusFromNode(node),
+ makePCIDeviceFromNode(node),
+ CPU_NB_FUNC_05,
+ REG_NB_CAPABILITY_5X84),
+ 7, 0, &temp);
+
+ /* bits[7:0] specify the cores */
+ temp = temp & 0xff;
+ cores = temp + 1;
+
+ /* Support Downcoring */
+ AmdPCIReadBits (MAKE_SBDFO(makePCISegmentFromNode(node),
+ makePCIBusFromNode(node),
+ makePCIDeviceFromNode(node),
+ CPU_NB_FUNC_03,
+ REG_NB_DOWNCORE_3X190),
+ 31, 0, &leveling);
+ for (i=0; i<cores; i++)
+ {
+ if (leveling & ((u32) 1 << i))
+ {
+ temp--;
+ }
+ }
+ return (u8)(temp+1);
+}
+
+/***************************************************************************//**
+ *
* static void
* setTotalNodesAndCores(u8 node, u8 totalNodes, u8 totalCores, cNorthBridge *nb)
*
@@ -850,6 +903,69 @@ static BOOL fam10IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
/***************************************************************************//**
*
+ * static BOOL
+ * fam15IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
+ *
+ * Description:
+ * Get node capability and update the minimum supported system capability.
+ * Return whether the current configuration exceeds the capability.
+ *
+ * Parameters:
+ * @param[in] node = the node
+ * @param[in,out] *pDat = sysMpCap (updated) and NodesDiscovered
+ * @param[in] *nb = this northbridge
+ * @return true: system is capable of current config.
+ * false: system is not capable of current config.
+ *
+ * ---------------------------------------------------------------------------------------
+ */
+static BOOL fam15IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
+{
+#ifndef HT_BUILD_NC_ONLY
+ u32 temp;
+ u8 maxNodes;
+
+ ASSERT(node < nb->maxNodes);
+
+ AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
+ makePCIBusFromNode(node),
+ makePCIDeviceFromNode(node),
+ CPU_NB_FUNC_03,
+ REG_NB_CAPABILITY_3XE8),
+ 18, 16, &temp);
+
+ if (temp != 0)
+ {
+ maxNodes = (1 << (~temp & 0x3)); /* That is, 1, 2, 4, or 8 */
+ }
+ else
+ {
+ /* Check if CPU package is dual node */
+ AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
+ makePCIBusFromNode(node),
+ makePCIDeviceFromNode(node),
+ CPU_NB_FUNC_03,
+ REG_NB_CAPABILITY_3XE8),
+ 29, 29, &temp);
+ if (temp)
+ maxNodes = 4;
+ else
+ maxNodes = 8;
+ }
+
+ if (pDat->sysMpCap > maxNodes)
+ {
+ pDat->sysMpCap = maxNodes;
+ }
+ /* Note since sysMpCap is one based and NodesDiscovered is zero based, equal is false */
+ return (pDat->sysMpCap > pDat->NodesDiscovered);
+#else
+ return 1;
+#endif
+}
+
+/***************************************************************************//**
+ *
* static void
* fam0fStopLink(u8 currentNode, u8 currentLink, cNorthBridge *nb)
*
@@ -2064,6 +2180,49 @@ void newNorthBridge(u8 node, cNorthBridge *nb)
u32 match;
u32 extFam, baseFam, model;
+ cNorthBridge fam15 =
+ {
+#ifdef HT_BUILD_NC_ONLY
+ 8,
+ 1,
+ 12,
+#else
+ 8,
+ 8,
+ 64,
+#endif /* HT_BUILD_NC_ONLY*/
+ writeRoutingTable,
+ writeNodeID,
+ readDefLnk,
+ enableRoutingTables,
+ verifyLinkIsCoherent,
+ readTrueLinkFailStatus,
+ readToken,
+ writeToken,
+ fam15GetNumCoresOnNode,
+ setTotalNodesAndCores,
+ limitNodes,
+ writeFullRoutingTable,
+ isCompatible,
+ fam15IsCapable,
+ (void (*)(u8, u8, cNorthBridge*))commonVoid,
+ (BOOL (*)(u8, u8, sMainData*, cNorthBridge*))commonReturnFalse,
+ readSbLink,
+ verifyLinkIsNonCoherent,
+ ht3SetCFGAddrMap,
+ convertBitsToWidth,
+ convertWidthToBits,
+ fam10NorthBridgeFreqMask,
+ gatherLinkData,
+ setLinkData,
+ ht3WriteTrafficDistribution,
+ fam10BufferOptimizations,
+ 0x00000001,
+ 0x00000200,
+ 18,
+ 0x00000f06
+ };
+
cNorthBridge fam10 =
{
#ifdef HT_BUILD_NC_ONLY
@@ -2171,8 +2330,14 @@ void newNorthBridge(u8 node, cNorthBridge *nb)
7, 4, &model);
match = (u32)((baseFam << 8) | extFam);
- /* Test each in turn looking for a match. Init the struct if found */
- if (match == fam10.compatibleKey)
+ /* Test each in turn looking for a match.
+ * Initialize the struct if found.
+ */
+ if (match == fam15.compatibleKey)
+ {
+ Amdmemcpy((void *)nb, (const void *)&fam15, (u32) sizeof(cNorthBridge));
+ }
+ else if (match == fam10.compatibleKey)
{
Amdmemcpy((void *)nb, (const void *)&fam10, (u32) sizeof(cNorthBridge));
}
diff --git a/src/northbridge/amd/amdht/ht_wrapper.c b/src/northbridge/amd/amdht/ht_wrapper.c
index 3bc236ed49..1f38b0c032 100644
--- a/src/northbridge/amd/amdht/ht_wrapper.c
+++ b/src/northbridge/amd/amdht/ht_wrapper.c
@@ -170,16 +170,22 @@ void amd_ht_fixup(struct sys_info *sysinfo) {
printk(BIOS_DEBUG, "amd_ht_fixup()\n");
if (IS_ENABLED(CONFIG_CPU_AMD_MODEL_10XXX)) {
uint8_t rev_gte_d = 0;
+ uint8_t fam15h = 0;
uint8_t dual_node = 0;
uint32_t f3xe8;
uint32_t family;
uint32_t model;
family = model = cpuid_eax(0x80000001);
- model = ((model & 0xf0000) >> 16) | ((model & 0xf0) >> 4);
+ model = ((model & 0xf0000) >> 12) | ((model & 0xf0) >> 4);
+ family = ((family & 0xf00000) >> 16) | ((family & 0xf00) >> 8);
- if (model >= 0x8)
- /* Revision D or later */
+ if (family >= 0x6f)
+ /* Family 15h or later */
+ fam15h = 1;
+
+ if ((model >= 0x8) || fam15h)
+ /* Family 10h Revision D or later */
rev_gte_d = 1;
if (rev_gte_d) {
@@ -191,7 +197,8 @@ void amd_ht_fixup(struct sys_info *sysinfo) {
if (dual_node) {
/* Each G34 processor contains a defective HT link.
- * See the BKDG Rev 3.62 section 2.7.1.5 for details.
+ * See the Family 10h BKDG Rev 3.62 section 2.7.1.5 for details
+ * For Family 15h see the BKDG Rev. 3.14 section 2.12.1.5 for details.
*/
uint8_t node;
uint8_t node_count = get_nodes();
@@ -201,46 +208,46 @@ void amd_ht_fixup(struct sys_info *sysinfo) {
uint8_t internal_node_number = ((f3xe8 & 0xc0000000) >> 30);
printk(BIOS_DEBUG, "amd_ht_fixup(): node %d (internal node ID %d): disabling defective HT link\n", node, internal_node_number);
if (internal_node_number == 0) {
- uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), 0xd8) & 0x1;
+ uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x98:0xd8) & 0x1;
if (package_link_3_connected) {
/* Set WidthIn and WidthOut to 0 */
- dword = pci_read_config32(NODE_PCI(node, 0), 0xc4);
+ dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x84:0xc4);
dword &= ~0x77000000;
- pci_write_config32(NODE_PCI(node, 0), 0xc4, dword);
+ pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x84:0xc4, dword);
/* Set Ganged to 1 */
- dword = pci_read_config32(NODE_PCI(node, 0), 0x178);
+ dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x170:0x178);
dword |= 0x00000001;
- pci_write_config32(NODE_PCI(node, 0), 0x178, dword);
+ pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x170:0x178, dword);
} else {
/* Set ConnDly to 1 */
dword = pci_read_config32(NODE_PCI(node, 0), 0x16c);
dword |= 0x00000100;
pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
/* Set TransOff and EndOfChain to 1 */
- dword = pci_read_config32(NODE_PCI(node, 4), 0xc4);
+ dword = pci_read_config32(NODE_PCI(node, 4), (fam15h)?0x84:0xc4);
dword |= 0x000000c0;
- pci_write_config32(NODE_PCI(node, 4), 0xc4, dword);
+ pci_write_config32(NODE_PCI(node, 4), (fam15h)?0x84:0xc4, dword);
}
} else if (internal_node_number == 1) {
- uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), 0xb8) & 0x1;
+ uint8_t package_link_3_connected = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0xf8:0xb8) & 0x1;
if (package_link_3_connected) {
/* Set WidthIn and WidthOut to 0 */
- dword = pci_read_config32(NODE_PCI(node, 0), 0xa4);
+ dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0xe4:0xa4);
dword &= ~0x77000000;
- pci_write_config32(NODE_PCI(node, 0), 0xa4, dword);
+ pci_write_config32(NODE_PCI(node, 0), (fam15h)?0xe4:0xa4, dword);
/* Set Ganged to 1 */
- dword = pci_read_config32(NODE_PCI(node, 0), 0x174);
+ dword = pci_read_config32(NODE_PCI(node, 0), (fam15h)?0x18c:0x174);
dword |= 0x00000001;
- pci_write_config32(NODE_PCI(node, 0), 0x174, dword);
+ pci_write_config32(NODE_PCI(node, 0), (fam15h)?0x18c:0x174, dword);
} else {
/* Set ConnDly to 1 */
dword = pci_read_config32(NODE_PCI(node, 0), 0x16c);
dword |= 0x00000100;
pci_write_config32(NODE_PCI(node, 0), 0x16c, dword);
/* Set TransOff and EndOfChain to 1 */
- dword = pci_read_config32(NODE_PCI(node, 4), 0xa4);
+ dword = pci_read_config32(NODE_PCI(node, 4), (fam15h)?0xe4:0xa4);
dword |= 0x000000c0;
- pci_write_config32(NODE_PCI(node, 4), 0xa4, dword);
+ pci_write_config32(NODE_PCI(node, 4), (fam15h)?0xe4:0xa4, dword);
}
}
}