diff options
Diffstat (limited to 'src/northbridge/amd/amdht')
-rw-r--r-- | src/northbridge/amd/amdht/h3ncmn.c | 171 | ||||
-rw-r--r-- | src/northbridge/amd/amdht/ht_wrapper.c | 43 |
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); } } } |