blob: ac7d393b240079fef70bb3031f8010f8ada36866 [file] [log] [blame]
Marc Jones8ae8c882007-12-19 01:32:08 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Marc Jones8ae8c882007-12-19 01:32:08 +00003 *
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Marc Jones8ae8c882007-12-19 01:32:08 +000014 */
15
16
17/*----------------------------------------------------------------------------
18 * MODULES USED
19 *
20 *----------------------------------------------------------------------------
21 */
22
23#undef FILECODE
24#define FILECODE 0xF002
25#include "h3finit.h"
26#include "h3ffeat.h"
27#include "h3ncmn.h"
28#include "AsPsNb.h"
29
30
31/*----------------------------------------------------------------------------
32 * DEFINITIONS AND MACROS
33 *
34 *----------------------------------------------------------------------------
35 */
36
37/* CPU Northbridge Functions */
38#define CPU_HTNB_FUNC_00 0
39#define CPU_HTNB_FUNC_04 4
40#define CPU_ADDR_FUNC_01 1
41#define CPU_NB_FUNC_03 3
Timothy Pearson730a0432015-10-16 13:51:51 -050042#define CPU_NB_FUNC_05 5
Marc Jones8ae8c882007-12-19 01:32:08 +000043
44/* Function 0 registers */
45#define REG_ROUTE0_0X40 0x40
46#define REG_ROUTE1_0X44 0x44
47#define REG_NODE_ID_0X60 0x60
48#define REG_UNIT_ID_0X64 0x64
49#define REG_LINK_TRANS_CONTROL_0X68 0x68
50#define REG_LINK_INIT_CONTROL_0X6C 0x6C
51#define REG_HT_CAP_BASE_0X80 0x80
52#define REG_HT_LINK_RETRY0_0X130 0x130
53#define REG_HT_TRAFFIC_DIST_0X164 0x164
54#define REG_HT_LINK_EXT_CONTROL0_0X170 0x170
55
56#define HT_CONTROL_CLEAR_CRC (~(3 << 8))
57
58/* Function 1 registers */
59#define REG_ADDR_CONFIG_MAP0_1XE0 0xE0
60#define CPU_ADDR_NUM_CONFIG_MAPS 4
61
62/* Function 3 registers */
63#define REG_NB_SRI_XBAR_BUF_3X70 0x70
64#define REG_NB_MCT_XBAR_BUF_3X78 0x78
65#define REG_NB_FIFOPTR_3XDC 0xDC
66#define REG_NB_CAPABILITY_3XE8 0xE8
67#define REG_NB_CPUID_3XFC 0xFC
68#define REG_NB_LINK_XCS_TOKEN0_3X148 0x148
69#define REG_NB_DOWNCORE_3X190 0x190
Timothy Pearson730a0432015-10-16 13:51:51 -050070#define REG_NB_CAPABILITY_5X84 0x84
Marc Jones8ae8c882007-12-19 01:32:08 +000071
72/* Function 4 registers */
73
74
75/*----------------------------------------------------------------------------
76 * TYPEDEFS AND STRUCTURES
77 *
78 *----------------------------------------------------------------------------
79 */
80/*----------------------------------------------------------------------------
81 * PROTOTYPES OF LOCAL FUNCTIONS
82 *
83 *----------------------------------------------------------------------------
84 */
85
86/***************************************************************************
87 *** FAMILY/NORTHBRIDGE SPECIFIC FUNCTIONS ***
88 ***************************************************************************/
89
Martin Rothf4cb4122015-01-06 10:27:39 -070090/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +000091 *
92 * SBDFO
93 * makeLinkBase(u8 currentNode, u8 currentLink)
94 *
95 * Description:
96 * Private to northbridge implementation. Return the HT Host capability base
97 * PCI config address for a link.
98 *
99 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700100 * @param[in] node = the node this link is on
101 * @param[in] link = the link
Marc Jones8ae8c882007-12-19 01:32:08 +0000102 *
Martin Rothf4cb4122015-01-06 10:27:39 -0700103 *****************************************************************************/
Marc Jones8ae8c882007-12-19 01:32:08 +0000104static SBDFO makeLinkBase(u8 node, u8 link)
105{
106 SBDFO linkBase;
107
108 /* With rev F can not be called with a 4th link or with the sublinks */
109 if (link < 4)
110 linkBase = MAKE_SBDFO(makePCISegmentFromNode(node),
111 makePCIBusFromNode(node),
112 makePCIDeviceFromNode(node),
113 CPU_HTNB_FUNC_00,
114 REG_HT_CAP_BASE_0X80 + link*HT_HOST_CAP_SIZE);
115 else
116 linkBase = MAKE_SBDFO(makePCISegmentFromNode(node),
117 makePCIBusFromNode(node),
118 makePCIDeviceFromNode(node),
119 CPU_HTNB_FUNC_04,
120 REG_HT_CAP_BASE_0X80 + (link-4)*HT_HOST_CAP_SIZE);
121 return linkBase;
122}
123
Martin Rothf4cb4122015-01-06 10:27:39 -0700124/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000125 *
126 * void
127 * setHtControlRegisterBits(SBDFO reg, u8 hiBit, u8 loBit, u32 *pValue)
128 *
129 * Description:
130 * Private to northbridge implementation. Provide a common routine for accessing the
131 * HT Link Control registers (84, a4, c4, e4), to enforce not clearing the
132 * HT CRC error bits. Replaces direct use of AmdPCIWriteBits().
133 * NOTE: This routine is called for IO Devices as well as CPUs!
134 *
135 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700136 * @param[in] reg = the PCI config address the control register
137 * @param[in] hiBit = the high bit number
138 * @param[in] loBit = the low bit number
139 * @param[in] pValue = the value to write to that bit range. Bit 0 => loBit.
Marc Jones8ae8c882007-12-19 01:32:08 +0000140 *
Martin Rothf4cb4122015-01-06 10:27:39 -0700141 *****************************************************************************/
Marc Jones8ae8c882007-12-19 01:32:08 +0000142static void setHtControlRegisterBits(SBDFO reg, u8 hiBit, u8 loBit, u32 *pValue)
143{
144 u32 temp, mask;
145
146 ASSERT((hiBit < 32) && (loBit < 32) && (hiBit >= loBit) && ((reg & 0x3) == 0));
147 ASSERT((hiBit < 8) || (loBit > 9));
148
149 /* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */
150 if ((hiBit-loBit) != 31)
151 mask = (((u32)1 << (hiBit-loBit+1))-1);
152 else
153 mask = (u32)0xFFFFFFFF;
154
155 AmdPCIRead(reg, &temp);
156 temp &= ~(mask << loBit);
157 temp |= (*pValue & mask) << loBit;
158 temp &= (u32)HT_CONTROL_CLEAR_CRC;
159 AmdPCIWrite(reg, &temp);
160}
161
Martin Rothf4cb4122015-01-06 10:27:39 -0700162/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000163 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000164 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +0000165 * writeRoutingTable(u8 node, u8 target, u8 Link, cNorthBridge *nb)
166 *
167 * Description:
168 * This routine will modify the routing tables on the
169 * SourceNode to cause it to route both request and response traffic to the
170 * targetNode through the specified Link.
171 *
172 * NOTE: This routine is to be used for early discovery and initialization. The
173 * final routing tables must be loaded some other way because this
174 * routine does not address the issue of probes, or independent request
175 * response paths.
176 *
177 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700178 * @param[in] node = the node that will have it's routing tables modified.
179 * @param[in] target = For routing to node target
180 * @param[in] link = Link from node to target
181 * @param[in] *nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +0000182 *
Martin Rothf4cb4122015-01-06 10:27:39 -0700183 *****************************************************************************/
Marc Jones8ae8c882007-12-19 01:32:08 +0000184
Stefan Reinauer30634322010-04-09 13:35:03 +0000185static void writeRoutingTable(u8 node, u8 target, u8 link, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000186{
187#ifndef HT_BUILD_NC_ONLY
188 u32 temp = (nb->selfRouteResponseMask | nb->selfRouteRequestMask) << (link + 1);
189 ASSERT((node < nb->maxNodes) && (target < nb->maxNodes) && (link < nb->maxLinks));
190 AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(node),
191 makePCIBusFromNode(node),
192 makePCIDeviceFromNode(node),
193 CPU_HTNB_FUNC_00,
194 REG_ROUTE0_0X40 + target*4),
195 &temp);
196#else
197 STOP_HERE;
198#endif
199}
200
Martin Rothf4cb4122015-01-06 10:27:39 -0700201/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000202 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000203 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +0000204 * writeNodeID(u8 node, u8 nodeID, cNorthBridge *nb)
205 *
206 * Description:
207 * Modifies the NodeID register on the target node
208 *
209 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700210 * @param[in] node = the node that will have its NodeID altered.
211 * @param[in] nodeID = the new value for NodeID
212 * @param[in] *nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +0000213 *
Martin Rothf4cb4122015-01-06 10:27:39 -0700214 *****************************************************************************/
Marc Jones8ae8c882007-12-19 01:32:08 +0000215
Stefan Reinauer30634322010-04-09 13:35:03 +0000216static void writeNodeID(u8 node, u8 nodeID, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000217{
218 u32 temp = nodeID;
219 ASSERT((node < nb->maxNodes) && (nodeID < nb->maxNodes));
220 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(node),
221 makePCIBusFromNode(node),
222 makePCIDeviceFromNode(node),
223 CPU_HTNB_FUNC_00,
224 REG_NODE_ID_0X60),
225 2, 0, &temp);
226}
227
Martin Rothf4cb4122015-01-06 10:27:39 -0700228/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000229 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000230 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +0000231 * readDefLnk(u8 node, cNorthBridge *nb)
232 *
233 * Description:
234 * Read the DefLnk (the source link of the current packet)
235 * from node
236 *
237 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700238 * @param[in] node = the node that will have its NodeID altered.
239 * @param[in] *nb = this northbridge
240 * @return The HyperTransport link where the request to
Marc Jones8ae8c882007-12-19 01:32:08 +0000241 * read the default link came from. Since this
242 * code is running on the BSP, this should be the link
243 * pointing back towards the BSP.
244 *
Martin Rothf4cb4122015-01-06 10:27:39 -0700245 *****************************************************************************/
Marc Jones8ae8c882007-12-19 01:32:08 +0000246
Stefan Reinauer30634322010-04-09 13:35:03 +0000247static u8 readDefLnk(u8 node, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000248{
249 u32 deflink = 0;
250 SBDFO licr;
251 u32 temp;
252
253 licr = MAKE_SBDFO(makePCISegmentFromNode(node),
254 makePCIBusFromNode(node),
255 makePCIDeviceFromNode(node),
256 CPU_HTNB_FUNC_00,
257 REG_LINK_INIT_CONTROL_0X6C);
258
259 ASSERT((node < nb->maxNodes));
260 AmdPCIReadBits(licr, 3, 2, &deflink);
261 AmdPCIReadBits(licr, 8, 8, &temp); /* on rev F, this bit is reserved == 0 */
262 deflink |= temp << 2;
263 return (u8)deflink;
264}
265
Martin Rothf4cb4122015-01-06 10:27:39 -0700266/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000267 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000268 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +0000269 * enableRoutingTables(u8 node, cNorthBridge *nb)
270 *
271 * Description:
272 * Turns routing tables on for a given node
273 *
274 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700275 * @param[in] node = the node that will have it's routing tables enabled
276 * @param[in] *nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +0000277 *
Martin Rothf4cb4122015-01-06 10:27:39 -0700278 *****************************************************************************/
Marc Jones8ae8c882007-12-19 01:32:08 +0000279
Stefan Reinauer30634322010-04-09 13:35:03 +0000280static void enableRoutingTables(u8 node, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000281{
282 u32 temp = 0;
283 ASSERT((node < nb->maxNodes));
284 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(node),
285 makePCIBusFromNode(node),
286 makePCIDeviceFromNode(node),
287 CPU_HTNB_FUNC_00,
288 REG_LINK_INIT_CONTROL_0X6C),
289 0, 0, &temp);
290}
291
292
Martin Rothf4cb4122015-01-06 10:27:39 -0700293/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000294 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000295 * static BOOL
Marc Jones8ae8c882007-12-19 01:32:08 +0000296 * verifyLinkIsCoherent(u8 node, u8 Link, cNorthBridge *nbk)
297 *
298 * Description:
299 * Verify that the link is coherent, connected, and ready
300 *
301 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700302 * @param[in] node = the node that will be examined
303 * @param[in] link = the link on that Node to examine
304 * @param[in] *nb = this northbridge
305 * @return true - The link has the following status
Marc Jones8ae8c882007-12-19 01:32:08 +0000306 * linkCon=1, Link is connected
307 * InitComplete=1, Link initialization is complete
308 * NC=0, Link is coherent
309 * UniP-cLDT=0, Link is not Uniprocessor cLDT
310 * LinkConPend=0 Link connection is not pending
311 * false- The link has some other status
312 *
Martin Rothf4cb4122015-01-06 10:27:39 -0700313 *****************************************************************************/
Marc Jones8ae8c882007-12-19 01:32:08 +0000314
Stefan Reinauer30634322010-04-09 13:35:03 +0000315static BOOL verifyLinkIsCoherent(u8 node, u8 link, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000316{
317#ifndef HT_BUILD_NC_ONLY
318
319 u32 linkType;
320 SBDFO linkBase;
321
322 ASSERT((node < nb->maxNodes) && (link < nb->maxLinks));
323
324 linkBase = makeLinkBase(node, link);
325
Marc Jonesaee07962008-07-16 21:09:31 +0000326 /* FN0_98/A4/C4 = LDT Type Register */
Marc Jones8ae8c882007-12-19 01:32:08 +0000327 AmdPCIRead(linkBase + HTHOST_LINK_TYPE_REG, &linkType);
328
Marc Jonesaee07962008-07-16 21:09:31 +0000329 /* Verify LinkCon=1, InitComplete=1, NC=0, UniP-cLDT=0, LinkConPend=0 */
Marc Jones8ae8c882007-12-19 01:32:08 +0000330 return (linkType & HTHOST_TYPE_MASK) == HTHOST_TYPE_COHERENT;
331#else
332 return 0;
333#endif /* HT_BUILD_NC_ONLY */
334}
335
Martin Rothf4cb4122015-01-06 10:27:39 -0700336/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000337 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000338 * static bool
Marc Jones8ae8c882007-12-19 01:32:08 +0000339 * readTrueLinkFailStatus(u8 node, u8 link, sMainData *pDat, cNorthBridge *nb)
340 *
341 * Description:
342 * Return the LinkFailed status AFTER an attempt is made to clear the bit.
343 * Also, call event notify if a Hardware Fault caused a synch flood on a previous boot.
344 *
345 * The table below summarizes correct responses of this routine.
346 * Family before after unconnected Notify? return
347 * 0F 0 0 0 No 0
348 * 0F 1 0 0 Yes 0
349 * 0F 1 1 X No 1
350 * 10 0 0 0 No 0
351 * 10 1 0 0 Yes 0
352 * 10 1 0 3 No 1
353 *
354 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700355 * @param[in] node = the node that will be examined
356 * @param[in] link = the link on that node to examine
357 * @param[in] *pDat = access to call back routine
358 * @param[in] *nb = this northbridge
359 * @return true - the link is not connected or has hard error
360 * false- if the link is connected
Marc Jones8ae8c882007-12-19 01:32:08 +0000361 *
Martin Rothf4cb4122015-01-06 10:27:39 -0700362 *****************************************************************************/
363
Stefan Reinauer30634322010-04-09 13:35:03 +0000364static BOOL readTrueLinkFailStatus(u8 node, u8 link, sMainData *pDat, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000365{
366 u32 before, after, unconnected, crc;
367 SBDFO linkBase;
368
369 ASSERT((node < nb->maxNodes) && (link < nb->maxLinks));
370
371 linkBase = makeLinkBase(node, link);
372
373 /* Save the CRC status before doing anything else.
374 * Read, Clear, the Re-read the error bits in the Link Control Register
375 * FN0_84/A4/C4[4] = LinkFail bit
376 * and the connection status, TransOff and EndOfChain
377 */
378 AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 9, 8, &crc);
379 AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 4, 4, &before);
380 setHtControlRegisterBits(linkBase + HTHOST_LINK_CONTROL_REG, 4, 4, &before);
381 AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 4, 4, &after);
382 AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 7, 6, &unconnected);
383
384 if (before != after)
385 {
386 if (!unconnected)
387 {
388 if (crc != 0)
389 {
390 /* A synch flood occurred due to HT CRC */
391 if (pDat->HtBlock->AMD_CB_EventNotify)
392 {
393 /* Pass the node and link on which the generic synch flood event occurred. */
Marc Jones212486e2008-07-17 19:50:37 +0000394 sHtEventHWHtCrc evt;
395 evt.eSize = sizeof(sHtEventHWHtCrc);
396 evt.node = node;
397 evt.link = link;
398 evt.laneMask = (uint8)crc;
Marc Jones8ae8c882007-12-19 01:32:08 +0000399
400 pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_HW_FAULT,
401 HT_EVENT_HW_HTCRC,
402 (u8 *)&evt);
403 }
404 }
405 else
406 {
407 /* Some synch flood occurred */
408 if (pDat->HtBlock->AMD_CB_EventNotify)
409 {
410 /* Pass the node and link on which the generic synch flood event occurred. */
Marc Jones212486e2008-07-17 19:50:37 +0000411 sHtEventHWSynchFlood evt;
412 evt.eSize = sizeof(sHtEventHWSynchFlood);
413 evt.node = node;
414 evt.link = link;
Marc Jones8ae8c882007-12-19 01:32:08 +0000415
416 pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_HW_FAULT,
417 HT_EVENT_HW_SYNCHFLOOD,
418 (u8 *)&evt);
419 }
420 }
421 }
422 }
423 return ((after != 0) || unconnected);
424}
425
426
Martin Rothf4cb4122015-01-06 10:27:39 -0700427/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000428 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000429 * static u8
Marc Jones8ae8c882007-12-19 01:32:08 +0000430 * readToken(u8 node, cNorthBridge *nb)
431 *
432 * Description:
433 * Read the token stored in the scratchpad register
434 * NOTE: The location used to store the token is arbitrary. The only
435 * requirement is that the location warm resets to zero, and that
436 * using it will have no ill-effects during HyperTransport initialization.
437 *
438 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700439 * @param[in] node = the node that will be examined
440 * @param[in] *nb = this northbridge
441 * @return the Token read from the node
Marc Jones8ae8c882007-12-19 01:32:08 +0000442 *
Martin Rothf4cb4122015-01-06 10:27:39 -0700443 *****************************************************************************/
Stefan Reinauer30634322010-04-09 13:35:03 +0000444static u8 readToken(u8 node, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000445{
446 u32 temp;
447
448 ASSERT((node < nb->maxNodes));
449 /* Use CpuCnt as a scratch register */
450 /* Limiting use to 4 bits makes code GH to rev F compatible. */
451 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
452 makePCIBusFromNode(node),
453 makePCIDeviceFromNode(node),
454 CPU_HTNB_FUNC_00,
455 REG_NODE_ID_0X60),
456 19, 16, &temp);
457
458 return (u8)temp;
459}
460
461
Martin Rothf4cb4122015-01-06 10:27:39 -0700462/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000463 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000464 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +0000465 * writeToken(u8 node, u8 Value, cNorthBridge *nb)
466 *
467 * Description:
468 * Write the token stored in the scratchpad register
469 * NOTE: The location used to store the token is arbitrary. The only
470 * requirement is that the location warm resets to zero, and that
471 * using it will have no ill-effects during HyperTransport initialization.
472 * Limiting use to 4 bits makes code GH to rev F compatible.
473 *
474 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700475 * @param[in] node = the node that will be examined
476 * @param value
477 * @param[in] *nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +0000478 *
Martin Rothf4cb4122015-01-06 10:27:39 -0700479 *****************************************************************************/
Stefan Reinauer30634322010-04-09 13:35:03 +0000480static void writeToken(u8 node, u8 value, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000481{
482 u32 temp = value;
483 ASSERT((node < nb->maxNodes));
484 /* Use CpuCnt as a scratch register */
485 /* Limiting use to 4 bits makes code GH to rev F compatible. */
486 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(node),
487 makePCIBusFromNode(node),
488 makePCIDeviceFromNode(node),
489 CPU_HTNB_FUNC_00,
490 REG_NODE_ID_0X60),
491 19, 16, &temp);
492}
493
Martin Rothf4cb4122015-01-06 10:27:39 -0700494/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000495 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000496 * static u8
Marc Jones8ae8c882007-12-19 01:32:08 +0000497 * fam0FGetNumCoresOnNode(u8 node, cNorthBridge *nb)
498 *
499 * Description:
500 * Return the number of cores (1 based count) on node.
501 *
502 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700503 * @param[in] node = the node that will be examined
504 * @param[in] *nb = this northbridge
505 * @return = the number of cores
Marc Jones8ae8c882007-12-19 01:32:08 +0000506 *
507 * ---------------------------------------------------------------------------------------
508 */
Stefan Reinauer30634322010-04-09 13:35:03 +0000509static u8 fam0FGetNumCoresOnNode(u8 node, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000510{
511 u32 temp;
512
513 ASSERT((node < nb->maxNodes));
514 /* Read CmpCap */
515 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
516 makePCIBusFromNode(node),
517 makePCIDeviceFromNode(node),
518 CPU_NB_FUNC_03,
519 REG_NB_CAPABILITY_3XE8),
520 13, 12, &temp);
521
522 /* and add one */
523 return (u8)(temp+1);
524}
525
Martin Rothf4cb4122015-01-06 10:27:39 -0700526/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000527 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000528 * static u8
Marc Jones8ae8c882007-12-19 01:32:08 +0000529 * fam10GetNumCoresOnNode(u8 node, cNorthBridge *nb)
530 *
531 * Description:
532 * Return the number of cores (1 based count) on node.
533 *
534 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700535 * @param[in] node = the node that will be examined
536 * @param[in] *nb = this northbridge
537 * @return = the number of cores
Marc Jones8ae8c882007-12-19 01:32:08 +0000538 *
Martin Rothf4cb4122015-01-06 10:27:39 -0700539 *
Marc Jones8ae8c882007-12-19 01:32:08 +0000540 */
Stefan Reinauer30634322010-04-09 13:35:03 +0000541static u8 fam10GetNumCoresOnNode(u8 node, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000542{
543 u32 temp, leveling, cores;
544 u8 i;
545
546 ASSERT((node < nb->maxNodes));
Zheng Bao23ffe8b2010-08-05 06:12:16 +0000547 /* Read CmpCap [2][1:0] */
Marc Jones8ae8c882007-12-19 01:32:08 +0000548 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
549 makePCIBusFromNode(node),
550 makePCIDeviceFromNode(node),
551 CPU_NB_FUNC_03,
552 REG_NB_CAPABILITY_3XE8),
Zheng Bao23ffe8b2010-08-05 06:12:16 +0000553 15, 12, &temp);
Marc Jones8ae8c882007-12-19 01:32:08 +0000554
Zheng Bao23ffe8b2010-08-05 06:12:16 +0000555 /* bits[15,13,12] specify the cores */
Zheng Baob18f9b02011-04-19 06:40:56 +0000556 temp = ((temp & 8) >> 1) + (temp & 3);
557 cores = temp + 1;
Timothy Pearson730a0432015-10-16 13:51:51 -0500558
559 /* Support Downcoring */
Marc Jones8ae8c882007-12-19 01:32:08 +0000560 AmdPCIReadBits (MAKE_SBDFO(makePCISegmentFromNode(node),
561 makePCIBusFromNode(node),
562 makePCIDeviceFromNode(node),
563 CPU_NB_FUNC_03,
564 REG_NB_DOWNCORE_3X190),
565 3, 0, &leveling);
566 for (i=0; i<cores; i++)
567 {
568 if (leveling & ((u32) 1 << i))
569 {
570 temp--;
571 }
572 }
573 return (u8)(temp+1);
574}
575
Martin Rothf4cb4122015-01-06 10:27:39 -0700576/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000577 *
Timothy Pearson730a0432015-10-16 13:51:51 -0500578 * static u8
579 * fam15GetNumCoresOnNode(u8 node, cNorthBridge *nb)
580 *
581 * Description:
582 * Return the number of cores (1 based count) on node.
583 *
584 * Parameters:
585 * @param[in] node = the node that will be examined
586 * @param[in] *nb = this northbridge
587 * @return = the number of cores
588 *
589 *
590 */
591static u8 fam15GetNumCoresOnNode(u8 node, cNorthBridge *nb)
592{
593 u32 temp, leveling, cores;
594 u8 i;
595
596 ASSERT((node < nb->maxNodes));
597 /* Read CmpCap [7:0] */
598 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
599 makePCIBusFromNode(node),
600 makePCIDeviceFromNode(node),
601 CPU_NB_FUNC_05,
602 REG_NB_CAPABILITY_5X84),
603 7, 0, &temp);
604
605 /* bits[7:0] specify the cores */
606 temp = temp & 0xff;
607 cores = temp + 1;
608
609 /* Support Downcoring */
610 AmdPCIReadBits (MAKE_SBDFO(makePCISegmentFromNode(node),
611 makePCIBusFromNode(node),
612 makePCIDeviceFromNode(node),
613 CPU_NB_FUNC_03,
614 REG_NB_DOWNCORE_3X190),
615 31, 0, &leveling);
616 for (i=0; i<cores; i++)
617 {
618 if (leveling & ((u32) 1 << i))
619 {
620 temp--;
621 }
622 }
623 return (u8)(temp+1);
624}
625
626/***************************************************************************//**
627 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000628 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +0000629 * setTotalNodesAndCores(u8 node, u8 totalNodes, u8 totalCores, cNorthBridge *nb)
630 *
631 * Description:
632 * Write the total number of cores and nodes to the node
633 *
634 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700635 * @param[in] node = the node that will be examined
636 * @param[in] totalNodes = the total number of nodes
637 * @param[in] totalCores = the total number of cores
638 * @param[in] *nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +0000639 *
640 * ---------------------------------------------------------------------------------------
641 */
Stefan Reinauer30634322010-04-09 13:35:03 +0000642static void setTotalNodesAndCores(u8 node, u8 totalNodes, u8 totalCores, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000643{
644 SBDFO nodeIDReg;
645 u32 temp;
646
647 ASSERT((node < nb->maxNodes) && (totalNodes <= nb->maxNodes));
648 nodeIDReg = MAKE_SBDFO(makePCISegmentFromNode(node),
649 makePCIBusFromNode(node),
650 makePCIDeviceFromNode(node),
651 CPU_HTNB_FUNC_00,
652 REG_NODE_ID_0X60);
653
654 temp = totalCores-1;
655 /* Rely on max number of nodes:cores for rev F and GH to make
656 * this code work, even though we write reserved bit 20 on rev F it will be
657 * zero in that case.
658 */
659 AmdPCIWriteBits(nodeIDReg, 20, 16, &temp);
660 temp = totalNodes-1;
661 AmdPCIWriteBits(nodeIDReg, 6, 4, &temp);
662}
663
Martin Rothf4cb4122015-01-06 10:27:39 -0700664/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000665 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000666 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +0000667 * limitNodes(u8 node, cNorthBridge *nb)
668 *
669 * Description:
670 * Limit coherent config accesses to cpus as indicated by nodecnt.
671 *
672 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700673 * @param[in] node = the node that will be examined
674 * @param[in] *nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +0000675 *
676 * ---------------------------------------------------------------------------------------
677 */
Stefan Reinauer30634322010-04-09 13:35:03 +0000678static void limitNodes(u8 node, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000679{
680 u32 temp = 1;
681 ASSERT((node < nb->maxNodes));
682 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(node),
683 makePCIBusFromNode(node),
684 makePCIDeviceFromNode(node),
685 CPU_HTNB_FUNC_00,
686 REG_LINK_TRANS_CONTROL_0X68),
687 15, 15, &temp);
688}
689
Martin Rothf4cb4122015-01-06 10:27:39 -0700690/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000691 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000692 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +0000693 * writeFullRoutingTable(u8 node, u8 target, u8 reqLink, u8 rspLink, u32 BClinks, cNorthBridge *nb)
694 *
695 * Description:
696 * Write the routing table entry for node to target, using the request link, response
697 * link, and broadcast links provided.
698 *
699 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700700 * @param[in] node = the node that will be examined
701 * @param[in] target = the target node for these routes
702 * @param[in] reqLink = the link for requests to target
703 * @param[in] rspLink = the link for responses to target
704 * @param[in] bClinks = the broadcast links
705 * @param[in] *nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +0000706 *
707 * ---------------------------------------------------------------------------------------
708 */
Stefan Reinauer30634322010-04-09 13:35:03 +0000709static void writeFullRoutingTable(u8 node, u8 target, u8 reqLink, u8 rspLink, u32 bClinks, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000710{
711#ifndef HT_BUILD_NC_ONLY
712 u32 value = 0;
713
714 ASSERT((node < nb->maxNodes) && (target < nb->maxNodes));
715 if (reqLink == ROUTETOSELF)
716 value |= nb->selfRouteRequestMask;
717 else
718 value |= nb->selfRouteRequestMask << (reqLink+1);
719
720 if (rspLink == ROUTETOSELF)
721 value |= nb->selfRouteResponseMask;
722 else
723 value |= nb->selfRouteResponseMask << (rspLink+1);
724
725 /* Allow us to accept a Broadcast ourselves, then set broadcasts for routes */
726 value |= (u32)1 << nb->broadcastSelfBit;
727 value |= (u32)bClinks << (nb->broadcastSelfBit + 1);
728
729 AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(node),
730 makePCIBusFromNode(node),
731 makePCIDeviceFromNode(node),
732 CPU_HTNB_FUNC_00,
733 REG_ROUTE0_0X40 + target*4), &value);
734#else
735 STOP_HERE;
736#endif /* HT_BUILD_NC_ONLY */
737}
738
Martin Rothf4cb4122015-01-06 10:27:39 -0700739/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000740 *
741 * static u32
742 * makeKey(u8 currentNode)
743 *
744 * Description:
745 * Private routine to northbridge code.
746 * Determine whether a node is compatible with the discovered configuration so
747 * far. Currently, that means the family, extended family of the new node are the
748 * same as the BSP's.
749 *
750 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700751 * @param[in] node = the node
752 * @return = the key value
Marc Jones8ae8c882007-12-19 01:32:08 +0000753 *
754 * ---------------------------------------------------------------------------------------
755 */
756static u32 makeKey(u8 node)
757{
758 u32 extFam, baseFam;
759 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
760 makePCIBusFromNode(node),
761 makePCIDeviceFromNode(node),
762 CPU_NB_FUNC_03,
763 REG_NB_CPUID_3XFC),
764 27, 20, &extFam);
765 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
766 makePCIBusFromNode(node),
767 makePCIDeviceFromNode(node),
768 CPU_NB_FUNC_03,
769 REG_NB_CPUID_3XFC),
770 11, 8, &baseFam);
771 return ((u32)(baseFam << 8) | extFam);
772}
773
774
Martin Rothf4cb4122015-01-06 10:27:39 -0700775/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000776 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000777 * static BOOL
Marc Jones8ae8c882007-12-19 01:32:08 +0000778 * isCompatible(u8 currentNode, cNorthBridge *nb)
779 *
780 * Description:
781 * Determine whether a node is compatible with the discovered configuration so
782 * far. Currently, that means the family, extended family of the new node are the
783 * same as the BSP's.
784 *
785 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700786 * @param[in] node = the node
787 * @param[in] *nb = this northbridge
788 * @return = true: the new is compatible, false: it is not
Marc Jones8ae8c882007-12-19 01:32:08 +0000789 *
790 * ---------------------------------------------------------------------------------------
791 */
Stefan Reinauer30634322010-04-09 13:35:03 +0000792static BOOL isCompatible(u8 node, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000793{
794 return (makeKey(node) == nb->compatibleKey);
795}
796
Martin Rothf4cb4122015-01-06 10:27:39 -0700797/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000798 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000799 * static BOOL
Marc Jones8ae8c882007-12-19 01:32:08 +0000800 * fam0fIsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
801 *
802 * Description:
803 * Get node capability and update the minimum supported system capability.
804 * Return whether the current configuration exceeds the capability.
805 *
806 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700807 * @param[in] node = the node
808 * @param[in,out] *pDat = sysMpCap (updated) and NodesDiscovered
809 * @param[in] *nb = this northbridge
810 * @return true: system is capable of current config.
Marc Jones8ae8c882007-12-19 01:32:08 +0000811 * false: system is not capable of current config.
812 *
813 * ---------------------------------------------------------------------------------------
814 */
Stefan Reinauer30634322010-04-09 13:35:03 +0000815static BOOL fam0fIsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000816{
817#ifndef HT_BUILD_NC_ONLY
818 u32 temp;
819 u8 maxNodes;
820
821 ASSERT(node < nb->maxNodes);
822
823 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
824 makePCIBusFromNode(node),
825 makePCIDeviceFromNode(node),
826 CPU_NB_FUNC_03,
827 REG_NB_CAPABILITY_3XE8),
828 2, 1, &temp);
829 if (temp > 1)
830 {
831 maxNodes = 8;
832 } else {
833 if (temp == 1)
834 {
835 maxNodes = 2;
836 } else {
837 maxNodes = 1;
838 }
839 }
840 if (pDat->sysMpCap > maxNodes)
841 {
842 pDat->sysMpCap = maxNodes;
843 }
844 /* Note since sysMpCap is one based and NodesDiscovered is zero based, equal is false */
845 return (pDat->sysMpCap > pDat->NodesDiscovered);
846#else
847 return 1;
848#endif
849}
850
Martin Rothf4cb4122015-01-06 10:27:39 -0700851/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000852 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000853 * static BOOL
Marc Jones8ae8c882007-12-19 01:32:08 +0000854 * fam10IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
855 *
856 * Description:
857 * Get node capability and update the minimum supported system capability.
858 * Return whether the current configuration exceeds the capability.
859 *
860 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700861 * @param[in] node = the node
862 * @param[in,out] *pDat = sysMpCap (updated) and NodesDiscovered
863 * @param[in] *nb = this northbridge
864 * @return true: system is capable of current config.
Marc Jones8ae8c882007-12-19 01:32:08 +0000865 * false: system is not capable of current config.
866 *
867 * ---------------------------------------------------------------------------------------
868 */
Stefan Reinauer30634322010-04-09 13:35:03 +0000869static BOOL fam10IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000870{
871#ifndef HT_BUILD_NC_ONLY
872 u32 temp;
873 u8 maxNodes;
874
875 ASSERT(node < nb->maxNodes);
876
877 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
878 makePCIBusFromNode(node),
879 makePCIDeviceFromNode(node),
880 CPU_NB_FUNC_03,
881 REG_NB_CAPABILITY_3XE8),
882 18, 16, &temp);
883
884 if (temp != 0)
885 {
886 maxNodes = (1 << (~temp & 0x3)); /* That is, 1, 2, 4, or 8 */
887 }
888 else
889 {
890 maxNodes = 8;
891 }
892
893 if (pDat->sysMpCap > maxNodes)
894 {
895 pDat->sysMpCap = maxNodes;
896 }
897 /* Note since sysMpCap is one based and NodesDiscovered is zero based, equal is false */
898 return (pDat->sysMpCap > pDat->NodesDiscovered);
899#else
900 return 1;
901#endif
902}
903
Martin Rothf4cb4122015-01-06 10:27:39 -0700904/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000905 *
Timothy Pearson730a0432015-10-16 13:51:51 -0500906 * static BOOL
907 * fam15IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
908 *
909 * Description:
910 * Get node capability and update the minimum supported system capability.
911 * Return whether the current configuration exceeds the capability.
912 *
913 * Parameters:
914 * @param[in] node = the node
915 * @param[in,out] *pDat = sysMpCap (updated) and NodesDiscovered
916 * @param[in] *nb = this northbridge
917 * @return true: system is capable of current config.
918 * false: system is not capable of current config.
919 *
920 * ---------------------------------------------------------------------------------------
921 */
922static BOOL fam15IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
923{
924#ifndef HT_BUILD_NC_ONLY
925 u32 temp;
926 u8 maxNodes;
927
928 ASSERT(node < nb->maxNodes);
929
930 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
931 makePCIBusFromNode(node),
932 makePCIDeviceFromNode(node),
933 CPU_NB_FUNC_03,
934 REG_NB_CAPABILITY_3XE8),
935 18, 16, &temp);
936
937 if (temp != 0)
938 {
939 maxNodes = (1 << (~temp & 0x3)); /* That is, 1, 2, 4, or 8 */
940 }
941 else
942 {
943 /* Check if CPU package is dual node */
944 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
945 makePCIBusFromNode(node),
946 makePCIDeviceFromNode(node),
947 CPU_NB_FUNC_03,
948 REG_NB_CAPABILITY_3XE8),
949 29, 29, &temp);
950 if (temp)
951 maxNodes = 4;
952 else
953 maxNodes = 8;
954 }
955
956 if (pDat->sysMpCap > maxNodes)
957 {
958 pDat->sysMpCap = maxNodes;
959 }
960 /* Note since sysMpCap is one based and NodesDiscovered is zero based, equal is false */
961 return (pDat->sysMpCap > pDat->NodesDiscovered);
962#else
963 return 1;
964#endif
965}
966
967/***************************************************************************//**
968 *
Stefan Reinauer30634322010-04-09 13:35:03 +0000969 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +0000970 * fam0fStopLink(u8 currentNode, u8 currentLink, cNorthBridge *nb)
971 *
972 * Description:
973 * Disable a cHT link on node by setting F0x[E4, C4, A4, 84][TransOff, EndOfChain]=1
974 *
975 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -0700976 * @param[in] node = the node this link is on
977 * @param[in] link = the link to stop
978 * @param[in] *nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +0000979 *
980 * ---------------------------------------------------------------------------------------
981 */
Stefan Reinauer30634322010-04-09 13:35:03 +0000982static void fam0fStopLink(u8 node, u8 link, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +0000983{
984#ifndef HT_BUILD_NC_ONLY
985 u32 temp;
986 SBDFO linkBase;
987
988 ASSERT((node < nb->maxNodes) && (link < nb->maxLinks));
989
990 linkBase = makeLinkBase(node, link);
991
992 /* Set TransOff, EndOfChain */
993 temp = 3;
994 setHtControlRegisterBits(linkBase + HTHOST_LINK_CONTROL_REG, 7, 6, &temp);
995#endif
996}
997
Martin Rothf4cb4122015-01-06 10:27:39 -0700998/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +0000999 *
Stefan Reinauer30634322010-04-09 13:35:03 +00001000 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +00001001 * commonVoid()
1002 *
1003 * Description:
1004 * Nothing.
1005 *
1006 * Parameters:
1007 * None.
1008 *
1009 * ---------------------------------------------------------------------------------------
1010 */
Stefan Reinauer30634322010-04-09 13:35:03 +00001011static void commonVoid(void)
Marc Jones8ae8c882007-12-19 01:32:08 +00001012{
1013}
1014
Martin Rothf4cb4122015-01-06 10:27:39 -07001015/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001016 *
Stefan Reinauer30634322010-04-09 13:35:03 +00001017 * static BOOL
Marc Jones8ae8c882007-12-19 01:32:08 +00001018 * commonReturnFalse()
1019 *
1020 * Description:
1021 * Return False.
1022 *
1023 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001024 * @return = false
1025 *
Marc Jones8ae8c882007-12-19 01:32:08 +00001026 */
Stefan Reinauer30634322010-04-09 13:35:03 +00001027static BOOL commonReturnFalse(void)
Marc Jones8ae8c882007-12-19 01:32:08 +00001028{
1029 return 0;
1030}
1031
1032/***************************************************************************
1033 *** Non-coherent init code ***
1034 *** Northbridge access routines ***
1035 ***************************************************************************/
1036
Martin Rothf4cb4122015-01-06 10:27:39 -07001037/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001038 *
Stefan Reinauer30634322010-04-09 13:35:03 +00001039 * static u8
Marc Jones8ae8c882007-12-19 01:32:08 +00001040 * readSbLink(cNorthBridge *nb)
1041 *
1042 * Description:
1043 * Return the link to the Southbridge
1044 *
1045 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001046 * @param[in] *nb = this northbridge
1047 * @return the link to the southbridge
Marc Jones8ae8c882007-12-19 01:32:08 +00001048 *
1049 * ---------------------------------------------------------------------------------------
1050 */
Stefan Reinauer30634322010-04-09 13:35:03 +00001051static u8 readSbLink(cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00001052{
1053 u32 temp;
1054 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(0),
1055 makePCIBusFromNode(0),
1056 makePCIDeviceFromNode(0),
1057 CPU_HTNB_FUNC_00,
1058 REG_UNIT_ID_0X64),
1059 10, 8, &temp);
1060 return (u8)temp;
1061}
1062
Martin Rothf4cb4122015-01-06 10:27:39 -07001063/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001064 *
Stefan Reinauer30634322010-04-09 13:35:03 +00001065 * static BOOL
Marc Jones8ae8c882007-12-19 01:32:08 +00001066 * verifyLinkIsNonCoherent(u8 node, u8 link, cNorthBridge *nb)
1067 *
1068 * Description:
1069 * Verify that the link is non-coherent, connected, and ready
1070 *
1071 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001072 * @param[in] node = the node that will be examined
1073 * @param[in] link = the Link on that node to examine
1074 * @param[in] *nb = this northbridge
1075 * @return = true - The link has the following status
Marc Jones8ae8c882007-12-19 01:32:08 +00001076 * LinkCon=1, Link is connected
1077 * InitComplete=1,Link initilization is complete
1078 * NC=1, Link is coherent
1079 * UniP-cLDT=0, Link is not Uniprocessor cLDT
1080 * LinkConPend=0 Link connection is not pending
1081 * false- The link has some other status
1082 *
1083 * ---------------------------------------------------------------------------------------
1084 */
Stefan Reinauer30634322010-04-09 13:35:03 +00001085static BOOL verifyLinkIsNonCoherent(u8 node, u8 link, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00001086{
1087 u32 linkType;
1088 SBDFO linkBase;
1089
1090 ASSERT((node < nb->maxNodes) && (link < nb->maxLinks));
1091
1092 linkBase = makeLinkBase(node, link);
1093
1094 /* FN0_98/A4/C4 = LDT Type Register */
1095 AmdPCIRead(linkBase + HTHOST_LINK_TYPE_REG, &linkType);
1096
1097 /* Verify linkCon=1, InitComplete=1, NC=0, UniP-cLDT=0, LinkConPend=0 */
1098 return (linkType & HTHOST_TYPE_MASK) == HTHOST_TYPE_NONCOHERENT;
1099}
1100
Martin Rothf4cb4122015-01-06 10:27:39 -07001101/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001102 *
Stefan Reinauer30634322010-04-09 13:35:03 +00001103 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +00001104 * ht3SetCFGAddrMap(u8 cfgMapIndex, u8 secBus, u8 subBus, u8 targetNode, u8 targetLink, sMainData *pDat, cNorthBridge *nb)
1105 *
1106 * Description:
1107 * Configure and enable config access to a non-coherent chain for the given bus range.
1108 *
1109 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001110 * @param[in] cfgMapIndex = the map entry to set
1111 * @param[in] secBus = The secondary bus number to use
1112 * @param[in] subBus = The subordinate bus number to use
1113 * @param[in] targetNode = The node that shall be the recipient of the traffic
1114 * @param[in] targetLink = The link that shall be the recipient of the traffic
1115 * @param[in] pDat = our global state
1116 * @param[in] *nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +00001117 *
1118 * ---------------------------------------------------------------------------------------
1119 */
Stefan Reinauer30634322010-04-09 13:35:03 +00001120static void ht3SetCFGAddrMap(u8 cfgMapIndex, u8 secBus, u8 subBus, u8 targetNode, u8 targetLink, sMainData *pDat, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00001121{
1122 u8 curNode;
1123 SBDFO linkBase;
1124 u32 temp;
1125
1126 linkBase = makeLinkBase(targetNode, targetLink);
1127
1128 ASSERT(secBus <= subBus);
1129 temp = secBus;
1130 AmdPCIWriteBits(linkBase + HTHOST_ISOC_REG, 15, 8, &temp);
1131
1132 /* For target link, note that rev F uses bits 9:8 and only with GH is bit 10
1133 * set to indicate a sublink. For node, we are currently not supporting Extended
1134 * routing tables.
1135 */
1136 temp = ((u32)subBus << 24) + ((u32)secBus << 16) + ((u32)targetLink << 8)
1137 + ((u32)targetNode << 4) + (u32)3;
1138 for (curNode = 0; curNode < pDat->NodesDiscovered+1; curNode++)
1139 AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(curNode),
1140 makePCIBusFromNode(curNode),
1141 makePCIDeviceFromNode(curNode),
1142 CPU_ADDR_FUNC_01,
1143 REG_ADDR_CONFIG_MAP0_1XE0 + 4*cfgMapIndex),
1144 &temp);
1145}
1146
Martin Rothf4cb4122015-01-06 10:27:39 -07001147/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001148 *
Stefan Reinauer26afd182010-04-02 22:31:35 +00001149 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +00001150 * ht1SetCFGAddrMap(u8 cfgMapIndex, u8 secBus, u8 subBus, u8 targetNode, u8 targetLink, sMainData *pDat, cNorthBridge *nb)
1151 *
1152 * Description:
1153 * Configure and enable config access to a non-coherent chain for the given bus range.
1154 *
1155 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001156 * @param[in] cfgMapIndex = the map entry to set
1157 * @param[in] secBus = The secondary bus number to use
1158 * @param[in] subBus = The subordinate bus number to use
1159 * @param[in] targetNode = The node that shall be the recipient of the traffic
1160 * @param[in] targetLink = The link that shall be the recipient of the traffic
1161 * @param[in] pDat = our global state
1162 * @param[in] *nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +00001163 *
Martin Rothf4cb4122015-01-06 10:27:39 -07001164 ******************************************************************************/
Stefan Reinauer26afd182010-04-02 22:31:35 +00001165static void ht1SetCFGAddrMap(u8 cfgMapIndex, u8 secBus, u8 subBus, u8 targetNode, u8 targetLink, sMainData *pDat, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00001166{
1167 u8 curNode;
1168 SBDFO linkBase;
1169 u32 temp;
1170
1171 linkBase = makeLinkBase(targetNode, targetLink);
1172
1173 ASSERT(secBus <= subBus);
1174 temp = secBus;
1175 AmdPCIWriteBits(linkBase + HTHOST_ISOC_REG, 15, 8, &temp);
1176
1177 temp = subBus;
1178 AmdPCIWriteBits(linkBase + HTHOST_ISOC_REG, 23, 16, &temp);
1179
1180 /* For target link, note that rev F uses bits 9:8 and only with GH is bit 10
1181 * set to indicate a sublink. For node, we are currently not supporting Extended
1182 * routing tables.
1183 */
1184 temp = ((u32)subBus << 24) + ((u32)secBus << 16) + ((u32)targetLink << 8)
1185 + ((u32)targetNode << 4) + (u32)3;
1186 for (curNode = 0; curNode < pDat->NodesDiscovered+1; curNode++)
1187 AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(curNode),
1188 makePCIBusFromNode(curNode),
1189 makePCIDeviceFromNode(curNode),
1190 CPU_ADDR_FUNC_01,
1191 REG_ADDR_CONFIG_MAP0_1XE0 + 4*cfgMapIndex),
1192 &temp);
1193}
1194
1195/***************************************************************************
1196 *** Link Optimization ***
1197 ***************************************************************************/
1198
Martin Rothf4cb4122015-01-06 10:27:39 -07001199/**
Stefan Reinauer30634322010-04-09 13:35:03 +00001200 * static u8
Marc Jones8ae8c882007-12-19 01:32:08 +00001201 * convertBitsToWidth(u8 value, cNorthBridge *nb)
1202 *
1203 * Description:
1204 * Given the bits set in the register field, return the width it represents
1205 *
1206 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001207 * @param[in] value = The bits for the register
1208 * @param[in] *nb = this northbridge
1209 * @return The width
Marc Jones8ae8c882007-12-19 01:32:08 +00001210 *
Martin Rothf4cb4122015-01-06 10:27:39 -07001211 ******************************************************************************/
Stefan Reinauer30634322010-04-09 13:35:03 +00001212static u8 convertBitsToWidth(u8 value, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00001213{
Stefan Reinauer8b547b12010-03-30 09:56:35 +00001214 switch(value) {
1215 case 1: return 16;
1216 case 0: return 8;
1217 case 5: return 4;
1218 case 4: return 2;
1219 default: STOP_HERE; /* This is an error internal condition */
Marc Jones8ae8c882007-12-19 01:32:08 +00001220 }
Stefan Reinauer8b547b12010-03-30 09:56:35 +00001221 return 0; // shut up GCC.
Marc Jones8ae8c882007-12-19 01:32:08 +00001222}
1223
Martin Rothf4cb4122015-01-06 10:27:39 -07001224/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001225 *
Stefan Reinauer30634322010-04-09 13:35:03 +00001226 * static u8
Marc Jones8ae8c882007-12-19 01:32:08 +00001227 * convertWidthToBits(u8 value, cNorthBridge *nb)
1228 *
1229 * Description:
1230 * Translate a desired width setting to the bits to set in the register field
1231 *
1232 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001233 * @param[in] value = The width
1234 * @param[in] *nb = this northbridge
1235 * @return The bits for the register
Marc Jones8ae8c882007-12-19 01:32:08 +00001236 *
Martin Rothf4cb4122015-01-06 10:27:39 -07001237 ******************************************************************************/
Stefan Reinauer30634322010-04-09 13:35:03 +00001238static u8 convertWidthToBits(u8 value, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00001239{
Stefan Reinauer8b547b12010-03-30 09:56:35 +00001240 switch (value) {
1241 case 16: return 1;
1242 case 8: return 0;
1243 case 4: return 5;
1244 case 2: return 4;
1245 default: STOP_HERE; /* This is an internal error condition */
Marc Jones8ae8c882007-12-19 01:32:08 +00001246 }
Stefan Reinauer8b547b12010-03-30 09:56:35 +00001247 return 0; // shut up GCC
Marc Jones8ae8c882007-12-19 01:32:08 +00001248}
1249
Martin Rothf4cb4122015-01-06 10:27:39 -07001250/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001251 *
Stefan Reinauer30634322010-04-09 13:35:03 +00001252 * static u16
Marc Jones8ae8c882007-12-19 01:32:08 +00001253 * ht1NorthBridgeFreqMask(u8 NodeID, cNorthBridge *nb)
1254 *
1255 * Description:
1256 * Return a mask that eliminates HT frequencies that cannot be used due to a slow
1257 * northbridge frequency.
1258 *
1259 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001260 * @param[in] node = Result could (later) be for a specific node
1261 * @param[in] *nb = this northbridge
1262 * @return Frequency mask
Marc Jones8ae8c882007-12-19 01:32:08 +00001263 *
Martin Rothf4cb4122015-01-06 10:27:39 -07001264 ******************************************************************************/
Stefan Reinauer30634322010-04-09 13:35:03 +00001265static u16 ht1NorthBridgeFreqMask(u8 node, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00001266{
1267 /* only up to HT1 speeds */
1268 return (HT_FREQUENCY_LIMIT_HT1_ONLY);
1269}
1270
Martin Rothf4cb4122015-01-06 10:27:39 -07001271/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001272 *
Stefan Reinauer30634322010-04-09 13:35:03 +00001273 * static u16
Marc Jones8ae8c882007-12-19 01:32:08 +00001274 * fam10NorthBridgeFreqMask(u8 NodeID, cNorthBridge *nb)
1275 *
1276 * Description:
1277 * Return a mask that eliminates HT frequencies that cannot be used due to a slow
1278 * northbridge frequency.
1279 *
1280 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001281 * @param[in] node = Result could (later) be for a specific node
1282 * @param[in] *nb = this northbridge
1283 * @return = Frequency mask
Marc Jones8ae8c882007-12-19 01:32:08 +00001284 *
Martin Rothf4cb4122015-01-06 10:27:39 -07001285 ******************************************************************************/
Stefan Reinauer30634322010-04-09 13:35:03 +00001286static u16 fam10NorthBridgeFreqMask(u8 node, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00001287{
1288 u8 nbCOF;
1289 u16 supported;
1290
1291 nbCOF = getMinNbCOF();
1292 /*
1293 * nbCOF is minimum northbridge speed in hundreds of MHz.
1294 * HT can not go faster than the minimum speed of the northbridge.
1295 */
1296 if ((nbCOF >= 6) && (nbCOF <= 26))
1297 {
1298 /* Convert frequency to bit and all less significant bits,
1299 * by setting next power of 2 and subtracting 1.
1300 */
1301 supported = ((u16)1 << ((nbCOF >> 1) + 2)) - 1;
1302 }
1303 else if (nbCOF > 26)
1304 {
1305 supported = HT_FREQUENCY_LIMIT_2600M;
1306 }
1307 /* unlikely cases, but include as a defensive measure, also avoid trick above */
1308 else if (nbCOF == 4)
1309 {
1310 supported = HT_FREQUENCY_LIMIT_400M;
1311 }
1312 else if (nbCOF == 2)
1313 {
1314 supported = HT_FREQUENCY_LIMIT_200M;
1315 }
1316 else
1317 {
1318 STOP_HERE;
1319 supported = HT_FREQUENCY_LIMIT_200M;
1320 }
1321
1322 return (fixEarlySampleFreqCapability(supported));
1323}
1324
Martin Rothf4cb4122015-01-06 10:27:39 -07001325/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001326 *
Stefan Reinauer30634322010-04-09 13:35:03 +00001327 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +00001328 * gatherLinkData(sMainData *pDat, cNorthBridge *nb)
1329 *
1330 * Description:
1331 * For all discovered links, populate the port list with the frequency and width
1332 * capabilities.
1333 *
1334 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001335 * @param[in,out] pDat = our global state, port list
1336 * @param[in] *nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +00001337 *
Martin Rothf4cb4122015-01-06 10:27:39 -07001338 ******************************************************************************/
Stefan Reinauer30634322010-04-09 13:35:03 +00001339static void gatherLinkData(sMainData *pDat, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00001340{
1341 u8 i;
1342 SBDFO linkBase;
1343 u32 temp;
1344
1345 for (i = 0; i < pDat->TotalLinks*2; i++)
1346 {
1347 if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU)
1348 {
1349 linkBase = makeLinkBase(pDat->PortList[i].NodeID, pDat->PortList[i].Link);
1350
1351 pDat->PortList[i].Pointer = linkBase;
1352
1353 AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 22, 20, &temp);
1354 pDat->PortList[i].PrvWidthOutCap = convertBitsToWidth((u8)temp, pDat->nb);
1355
1356 AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 18, 16, &temp);
1357 pDat->PortList[i].PrvWidthInCap = convertBitsToWidth((u8)temp, pDat->nb);
1358
1359 AmdPCIReadBits(linkBase + HTHOST_FREQ_REV_REG, 31, 16, &temp);
1360 pDat->PortList[i].PrvFrequencyCap = (u16)temp & 0x7FFF
Marc Jonesaee07962008-07-16 21:09:31 +00001361 & nb->northBridgeFreqMask(pDat->PortList[i].NodeID, pDat->nb); /* Mask off bit 15, reserved value */
Marc Jones8ae8c882007-12-19 01:32:08 +00001362 }
1363 else
1364 {
1365 linkBase = pDat->PortList[i].Pointer;
1366 if (pDat->PortList[i].Link == 1)
1367 linkBase += HTSLAVE_LINK01_OFFSET;
1368
1369 AmdPCIReadBits(linkBase + HTSLAVE_LINK_CONTROL_0_REG, 22, 20, &temp);
1370 pDat->PortList[i].PrvWidthOutCap = convertBitsToWidth((u8)temp, pDat->nb);
1371
1372 AmdPCIReadBits(linkBase + HTSLAVE_LINK_CONTROL_0_REG, 18, 16, &temp);
1373 pDat->PortList[i].PrvWidthInCap = convertBitsToWidth((u8)temp, pDat->nb);
1374
1375 AmdPCIReadBits(linkBase + HTSLAVE_FREQ_REV_0_REG, 31, 16, &temp);
1376 pDat->PortList[i].PrvFrequencyCap = (u16)temp;
1377
1378 if (pDat->HtBlock->AMD_CB_DeviceCapOverride)
1379 {
1380 linkBase &= 0xFFFFF000;
1381 AmdPCIRead(linkBase, &temp);
1382
1383 pDat->HtBlock->AMD_CB_DeviceCapOverride(
1384 pDat->PortList[i].NodeID,
1385 pDat->PortList[i].HostLink,
1386 pDat->PortList[i].HostDepth,
1387 (u8)SBDFO_SEG(pDat->PortList[i].Pointer),
1388 (u8)SBDFO_BUS(pDat->PortList[i].Pointer),
1389 (u8)SBDFO_DEV(pDat->PortList[i].Pointer),
1390 temp,
1391 pDat->PortList[i].Link,
1392 &(pDat->PortList[i].PrvWidthInCap),
1393 &(pDat->PortList[i].PrvWidthOutCap),
1394 &(pDat->PortList[i].PrvFrequencyCap));
1395 }
1396 }
1397 }
1398}
1399
Martin Rothf4cb4122015-01-06 10:27:39 -07001400/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001401 *
Stefan Reinauer30634322010-04-09 13:35:03 +00001402 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +00001403 * setLinkData(sMainData *pDat, cNorthBridge *nb)
1404 *
1405 * Description:
1406 * Change the hardware state for all links according to the now optimized data in the
1407 * port list data structure.
1408 *
1409 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001410 * @param[in] pDat = our global state, port list
1411 * @param[in] *nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +00001412 *
Martin Rothf4cb4122015-01-06 10:27:39 -07001413 ******************************************************************************/
Stefan Reinauer30634322010-04-09 13:35:03 +00001414static void setLinkData(sMainData *pDat, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00001415{
1416 u8 i;
1417 SBDFO linkBase;
1418 u32 temp, widthin, widthout, bits;
1419
1420 for (i = 0; i < pDat->TotalLinks*2; i++)
1421 {
1422
1423 ASSERT(pDat->PortList[i&0xFE].SelWidthOut == pDat->PortList[(i&0xFE)+1].SelWidthIn);
1424 ASSERT(pDat->PortList[i&0xFE].SelWidthIn == pDat->PortList[(i&0xFE)+1].SelWidthOut);
1425 ASSERT(pDat->PortList[i&0xFE].SelFrequency == pDat->PortList[(i&0xFE)+1].SelFrequency);
1426
1427 if (pDat->PortList[i].SelRegang)
1428 {
1429 ASSERT(pDat->PortList[i].Type == PORTLIST_TYPE_CPU);
1430 ASSERT(pDat->PortList[i].Link < 4);
1431 temp = 1;
1432 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID),
1433 makePCIBusFromNode(pDat->PortList[i].NodeID),
1434 makePCIDeviceFromNode(pDat->PortList[i].NodeID),
1435 CPU_HTNB_FUNC_00,
1436 REG_HT_LINK_EXT_CONTROL0_0X170 + 4*pDat->PortList[i].Link),
1437 0, 0, &temp);
1438 }
1439
1440 if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU)
1441 {
1442 if (pDat->HtBlock->AMD_CB_OverrideCpuPort)
1443 pDat->HtBlock->AMD_CB_OverrideCpuPort(pDat->PortList[i].NodeID,
1444 pDat->PortList[i].Link,
1445 &(pDat->PortList[i].SelWidthIn),
1446 &(pDat->PortList[i].SelWidthOut),
1447 &(pDat->PortList[i].SelFrequency));
1448 }
1449 else
1450 {
1451 if (pDat->HtBlock->AMD_CB_OverrideDevicePort)
1452 pDat->HtBlock->AMD_CB_OverrideDevicePort(pDat->PortList[i].NodeID,
1453 pDat->PortList[i].HostLink,
1454 pDat->PortList[i].HostDepth,
1455 pDat->PortList[i].Link,
1456 &(pDat->PortList[i].SelWidthIn),
1457 &(pDat->PortList[i].SelWidthOut),
1458 &(pDat->PortList[i].SelFrequency));
1459 }
1460
1461 linkBase = pDat->PortList[i].Pointer;
1462 if ((pDat->PortList[i].Type == PORTLIST_TYPE_IO) && (pDat->PortList[i].Link == 1))
1463 linkBase += HTSLAVE_LINK01_OFFSET;
1464
1465 /* Some IO devices don't work properly when setting widths, so write them in a single operation,
1466 * rather than individually.
1467 */
1468 widthout = convertWidthToBits(pDat->PortList[i].SelWidthOut, pDat->nb);
1469 ASSERT(widthout == 1 || widthout == 0 || widthout == 5 || widthout == 4);
1470 widthin = convertWidthToBits(pDat->PortList[i].SelWidthIn, pDat->nb);
1471 ASSERT(widthin == 1 || widthin == 0 || widthin == 5 || widthin == 4);
1472
1473 temp = (widthin & 7) | ((widthout & 7) << 4);
1474 setHtControlRegisterBits(linkBase + HTHOST_LINK_CONTROL_REG, 31, 24, &temp);
1475
1476 temp = pDat->PortList[i].SelFrequency;
1477 if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU)
1478 {
1479 ASSERT((temp >= HT_FREQUENCY_600M && temp <= HT_FREQUENCY_2600M)
1480 || (temp == HT_FREQUENCY_200M) || (temp == HT_FREQUENCY_400M));
1481 AmdPCIWriteBits(linkBase + HTHOST_FREQ_REV_REG, 11, 8, &temp);
Elyes HAOUAS0f92f632014-07-27 19:37:31 +02001482 if (temp > HT_FREQUENCY_1000M) /* Gen1 = 200MHz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz */
Marc Jones8ae8c882007-12-19 01:32:08 +00001483 {
1484 /* Enable for Gen3 frequencies */
1485 temp = 1;
1486 }
1487 else
1488 {
1489 /* Disable for Gen1 frequencies */
1490 temp = 0;
1491 }
1492 /* HT3 retry mode enable / disable */
1493 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID),
1494 makePCIBusFromNode(pDat->PortList[i].NodeID),
1495 makePCIDeviceFromNode(pDat->PortList[i].NodeID),
1496 CPU_HTNB_FUNC_00,
1497 REG_HT_LINK_RETRY0_0X130 + 4*pDat->PortList[i].Link),
1498 0, 0, &temp);
1499 /* and Scrambling enable / disable */
1500 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID),
1501 makePCIBusFromNode(pDat->PortList[i].NodeID),
1502 makePCIDeviceFromNode(pDat->PortList[i].NodeID),
1503 CPU_HTNB_FUNC_00,
1504 REG_HT_LINK_EXT_CONTROL0_0X170 + 4*pDat->PortList[i].Link),
1505 3, 3, &temp);
1506 }
1507 else
1508 {
1509 SBDFO currentPtr;
1510 BOOL isFound;
1511
1512 ASSERT(temp <= HT_FREQUENCY_2600M);
1513 /* Write the frequency setting */
1514 AmdPCIWriteBits(linkBase + HTSLAVE_FREQ_REV_0_REG, 11, 8, &temp);
1515
1516 /* Handle additional HT3 frequency requirements, if needed,
1517 * or clear them if switching down to ht1 on a warm reset.
Elyes HAOUAS0f92f632014-07-27 19:37:31 +02001518 * Gen1 = 200MHz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz
Marc Jones8ae8c882007-12-19 01:32:08 +00001519 *
1520 * Even though we assert if debugging, we need to check that the capability was found
1521 * always, since this is an unknown hardware device, also we are taking
1522 * unqualified frequency from the call backs
1523 * (could be trying to do ht3 on an ht1 IO device).
1524 */
1525
1526 if (temp > HT_FREQUENCY_1000M)
1527 {
1528 /* Enabling features if gen 3 */
1529 bits = 1;
1530 }
1531 else
1532 {
1533 /* Disabling features if gen 1 */
1534 bits = 0;
1535 }
1536
1537 /* Retry Enable */
1538 isFound = FALSE;
1539 currentPtr = linkBase & (u32)0xFFFFF000; /* Set PCI Offset to 0 */
1540 do
1541 {
1542 AmdPCIFindNextCap(&currentPtr);
1543 if (currentPtr != ILLEGAL_SBDFO)
1544 {
1545 AmdPCIRead(currentPtr, &temp);
1546 /* HyperTransport Retry Capability? */
1547 if (IS_HT_RETRY_CAPABILITY(temp))
1548 {
1549 ASSERT(pDat->PortList[i].Link < 2);
1550 AmdPCIWriteBits(currentPtr + HTRETRY_CONTROL_REG,
1551 pDat->PortList[i].Link*16,
1552 pDat->PortList[i].Link*16,
1553 &bits);
1554 isFound = TRUE;
1555 }
1556 /* Some other capability, keep looking */
1557 }
1558 else
1559 {
1560 /* If we are turning it off, that may mean the device was only ht1 capable,
1561 * so don't complain that we can't do it.
1562 */
1563 if (bits != 0)
1564 {
1565 if (pDat->HtBlock->AMD_CB_EventNotify)
1566 {
Marc Jones212486e2008-07-17 19:50:37 +00001567 sHtEventOptRequiredCap evt;
1568 evt.eSize = sizeof(sHtEventOptRequiredCap);
1569 evt.node = pDat->PortList[i].NodeID;
1570 evt.link = pDat->PortList[i].HostLink;
1571 evt.depth = pDat->PortList[i].HostDepth;
Marc Jones8ae8c882007-12-19 01:32:08 +00001572
1573 pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_WARNING,
1574 HT_EVENT_OPT_REQUIRED_CAP_RETRY,
1575 (u8 *)&evt);
1576 }
1577 STOP_HERE;
1578 }
1579 isFound = TRUE;
1580 }
1581 } while (!isFound);
1582
1583 /* Scrambling enable */
1584 isFound = FALSE;
1585 currentPtr = linkBase & (u32)0xFFFFF000; /* Set PCI Offset to 0 */
1586 do
1587 {
1588 AmdPCIFindNextCap(&currentPtr);
1589 if (currentPtr != ILLEGAL_SBDFO)
1590 {
1591 AmdPCIRead(currentPtr, &temp);
1592 /* HyperTransport Gen3 Capability? */
1593 if (IS_HT_GEN3_CAPABILITY(temp))
1594 {
1595 ASSERT(pDat->PortList[i].Link < 2);
1596 AmdPCIWriteBits((currentPtr +
1597 HTGEN3_LINK_TRAINING_0_REG +
1598 pDat->PortList[i].Link*HTGEN3_LINK01_OFFSET),
1599 3, 3, &bits);
1600 isFound = TRUE;
1601 }
1602 /* Some other capability, keep looking */
1603 }
1604 else
1605 {
1606 /* If we are turning it off, that may mean the device was only ht1 capable,
1607 * so don't complain that we can't do it.
1608 */
1609 if (bits != 0)
1610 {
1611 if (pDat->HtBlock->AMD_CB_EventNotify)
1612 {
Marc Jones212486e2008-07-17 19:50:37 +00001613 sHtEventOptRequiredCap evt;
1614 evt.eSize = sizeof(sHtEventOptRequiredCap);
1615 evt.node = pDat->PortList[i].NodeID;
1616 evt.link = pDat->PortList[i].HostLink;
1617 evt.depth = pDat->PortList[i].HostDepth;
Marc Jones8ae8c882007-12-19 01:32:08 +00001618
1619 pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_WARNING,
1620 HT_EVENT_OPT_REQUIRED_CAP_GEN3,
1621 (u8 *)&evt);
1622 }
1623 STOP_HERE;
1624 }
1625 isFound = TRUE;
1626 }
1627 } while (!isFound);
1628 }
1629 }
1630}
1631
Martin Rothf4cb4122015-01-06 10:27:39 -07001632/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001633 *
1634 * void
1635 * fam0fWriteHTLinkCmdBufferAlloc(u8 node, u8 link, u8 req, u8 preq, u8 rsp, u8 prb)
1636 *
1637 * Description:
1638 * Set the command buffer allocations in the buffer count register for the node and link.
1639 * The command buffer settings in the low 16 bits are the same on both
1640 * family 10h and family 0fh northbridges.
1641 *
1642 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001643 * @param[in] node = The node to set allocations on
1644 * @param[in] link = the link to set allocations on
1645 * @param[in] req = non-posted Request Command Buffers
1646 * @param[in] preq = Posted Request Command Buffers
1647 * @param[in] rsp = Response Command Buffers
1648 * @param[in] prb = Probe Command Buffers
Marc Jones8ae8c882007-12-19 01:32:08 +00001649 *
Martin Rothf4cb4122015-01-06 10:27:39 -07001650 ******************************************************************************/
Xavi Drudis Ferrane660f042010-08-17 06:12:59 +00001651#ifndef HT_BUILD_NC_ONLY
1652
Marc Jones8ae8c882007-12-19 01:32:08 +00001653static void fam0fWriteHTLinkCmdBufferAlloc(u8 node, u8 link, u8 req, u8 preq, u8 rsp, u8 prb)
1654{
1655 u32 temp;
1656 SBDFO currentPtr;
1657
1658 currentPtr = makeLinkBase(node, link);
1659 currentPtr += HTHOST_BUFFER_COUNT_REG;
1660
1661 /* non-posted Request Command Buffers */
1662 temp = req;
1663 AmdPCIWriteBits(currentPtr, 3, 0, &temp);
1664 /* Posted Request Command Buffers */
1665 temp = preq;
1666 AmdPCIWriteBits(currentPtr, 7, 4, &temp);
1667 /* Response Command Buffers */
1668 temp = rsp;
1669 AmdPCIWriteBits(currentPtr, 11, 8, &temp);
1670 /* Probe Command Buffers */
1671 temp = prb;
1672 AmdPCIWriteBits(currentPtr, 15, 12, &temp);
1673}
Xavi Drudis Ferrane660f042010-08-17 06:12:59 +00001674#endif /* HT_BUILD_NC_ONLY */
Marc Jones8ae8c882007-12-19 01:32:08 +00001675
Martin Rothf4cb4122015-01-06 10:27:39 -07001676/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001677 *
1678 * void
1679 * fam0fWriteHTLinkDatBufferAlloc(u8 node, u8 link, u8 reqD, u8 preqD, u8 rspD)
1680 *
1681 * Description:
1682 * Set the data buffer allocations in the buffer count register for the node and link.
1683 * The command buffer settings in the high 16 bits are not the same on both
1684 * family 10h and family 0fh northbridges.
1685 *
1686 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001687 * @param[in] node = The node to set allocations on
1688 * @param[in] link = the link to set allocations on
1689 * @param[in] reqD = non-posted Request Data Buffers
1690 * @param[in] preqD = Posted Request Data Buffers
1691 * @param[in] rspD = Response Data Buffers
Marc Jones8ae8c882007-12-19 01:32:08 +00001692 *
Martin Rothf4cb4122015-01-06 10:27:39 -07001693 ******************************************************************************/
Xavi Drudis Ferrane660f042010-08-17 06:12:59 +00001694#ifndef HT_BUILD_NC_ONLY
1695
Marc Jones8ae8c882007-12-19 01:32:08 +00001696static void fam0fWriteHTLinkDatBufferAlloc(u8 node, u8 link, u8 reqD, u8 preqD, u8 rspD)
1697{
1698 u32 temp;
1699 SBDFO currentPtr;
1700
1701 currentPtr = makeLinkBase(node, link);
1702 currentPtr += HTHOST_BUFFER_COUNT_REG;
1703
1704 /* Request Data Buffers */
1705 temp = reqD;
1706 AmdPCIWriteBits(currentPtr, 18, 16, &temp);
1707 /* Posted Request Data Buffers */
1708 temp = preqD;
1709 AmdPCIWriteBits(currentPtr, 22, 20, &temp);
1710 /* Response Data Buffers */
1711 temp = rspD;
1712 AmdPCIWriteBits(currentPtr, 26, 24, &temp);
1713}
Xavi Drudis Ferrane660f042010-08-17 06:12:59 +00001714#endif /* HT_BUILD_NC_ONLY */
Marc Jones8ae8c882007-12-19 01:32:08 +00001715
Martin Rothf4cb4122015-01-06 10:27:39 -07001716/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001717 *
Stefan Reinauer30634322010-04-09 13:35:03 +00001718 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +00001719 * ht3WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb)
1720 *
1721 * Description:
1722 * Set the traffic distribution register for the links provided.
1723 *
1724 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001725 * @param[in] links01 = coherent links from node 0 to 1
1726 * @param[in] links10 = coherent links from node 1 to 0
1727 * @param[in] nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +00001728 *
Martin Rothf4cb4122015-01-06 10:27:39 -07001729 ******************************************************************************/
Stefan Reinauer30634322010-04-09 13:35:03 +00001730static void ht3WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00001731{
1732#ifndef HT_BUILD_NC_ONLY
1733 u32 temp;
1734
1735 /* Node 0 */
1736 /* DstLnk */
1737 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(0),
1738 makePCIBusFromNode(0),
1739 makePCIDeviceFromNode(0),
1740 CPU_HTNB_FUNC_00,
1741 REG_HT_TRAFFIC_DIST_0X164),
1742 23, 16, &links01);
1743 /* DstNode = 1, cHTPrbDistEn=1, cHTRspDistEn=1, cHTReqDistEn=1 */
1744 temp = 0x0107;
1745 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(0),
1746 makePCIBusFromNode(0),
1747 makePCIDeviceFromNode(0),
1748 CPU_HTNB_FUNC_00,
1749 REG_HT_TRAFFIC_DIST_0X164),
1750 15, 0, &temp);
1751
1752 /* Node 1 */
1753 /* DstLnk */
1754 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(1),
1755 makePCIBusFromNode(1),
1756 makePCIDeviceFromNode(1),
1757 CPU_HTNB_FUNC_00,
1758 REG_HT_TRAFFIC_DIST_0X164),
1759 23, 16, &links10);
1760 /* DstNode = 0, cHTPrbDistEn=1, cHTRspDistEn=1, cHTReqDistEn=1 */
1761 temp = 0x0007;
1762 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(1),
1763 makePCIBusFromNode(1),
1764 makePCIDeviceFromNode(1),
1765 CPU_HTNB_FUNC_00,
1766 REG_HT_TRAFFIC_DIST_0X164),
1767 15, 0, &temp);
1768#endif /* HT_BUILD_NC_ONLY */
1769}
1770
Martin Rothf4cb4122015-01-06 10:27:39 -07001771/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001772 *
Stefan Reinauer30634322010-04-09 13:35:03 +00001773 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +00001774 * ht1WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb)
1775 *
1776 * Description:
1777 * Traffic distribution is more complex in this case as the routing table must be
1778 * adjusted to use one link for requests and the other for responses. Also,
1779 * perform the buffer tunings on the links required for this config.
1780 *
1781 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001782 * @param[in] links01 = coherent links from node 0 to 1
1783 * @param[in] links10 = coherent links from node 1 to 0
1784 * @param[in] nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +00001785 *
Martin Rothf4cb4122015-01-06 10:27:39 -07001786 ******************************************************************************/
Stefan Reinauer30634322010-04-09 13:35:03 +00001787static void ht1WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00001788{
1789#ifndef HT_BUILD_NC_ONLY
1790 u32 route01, route10;
1791 u8 req0, req1, rsp0, rsp1, nclink;
1792
1793 /*
1794 * Get the current request route for 0->1 and 1->0. This will indicate which of the links
1795 * in links01 are connected to which links in links10. Since we have to route to distribute
1796 * traffic, we need to know that. The link used by htinit will become the request, probe link.
1797 * the other link will be used for responses.
1798 */
1799
1800 /* Get the routes, and hang on to them, we will write them back updated. */
1801 AmdPCIRead(MAKE_SBDFO(makePCISegmentFromNode(0),
1802 makePCIBusFromNode(0),
1803 makePCIDeviceFromNode(0),
1804 CPU_HTNB_FUNC_00,
1805 REG_ROUTE1_0X44),
1806 &route01);
1807 AmdPCIRead(MAKE_SBDFO(makePCISegmentFromNode(1),
1808 makePCIBusFromNode(1),
1809 makePCIDeviceFromNode(1),
1810 CPU_HTNB_FUNC_00,
1811 REG_ROUTE0_0X40),
1812 &route10);
1813
1814 /* Convert the request routes to a link number. Note "0xE" is ht1 nb specific.
1815 * Find the response link numbers.
1816 */
1817 ASSERT((route01 & 0xE) && (route10 & 0xE)); /* no route! error! */
1818 req0 = (u8)AmdBitScanReverse((route01 & 0xE)) - 1;
1819 req1 = (u8)AmdBitScanReverse((route10 & 0xE)) - 1;
1820 /* Now, find the other link for the responses */
1821 rsp0 = (u8)AmdBitScanReverse((links01 & ~((u32)1 << req0)));
1822 rsp1 = (u8)AmdBitScanReverse((links10 & ~((u32)1 << req1)));
1823
1824 /* ht1 nb restriction, must have exactly two links */
1825 ASSERT(((((links01 & ~((u32)1 << req0)) & ~((u32)1 << rsp0))) == 0)
1826 && ((((links10 & ~((u32)1 << req1)) & ~((u32)1 << rsp1))) == 0));
1827
1828 route01 = (route01 & ~0x0E00) | ((u32)0x0100<<(rsp0 + 1));
1829 route10 = (route10 & ~0x0E00) | ((u32)0x0100<<(rsp1 + 1));
1830
1831 AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(0),
1832 makePCIBusFromNode(0),
1833 makePCIDeviceFromNode(0),
1834 CPU_HTNB_FUNC_00,
1835 REG_ROUTE1_0X44),
1836 &route01);
1837
1838 AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(1),
1839 makePCIBusFromNode(1),
1840 makePCIDeviceFromNode(1),
1841 CPU_HTNB_FUNC_00,
1842 REG_ROUTE0_0X40),
1843 &route10);
1844
1845 /* While we otherwise do buffer tunings elsewhere, for the dual cHT DP case with
1846 * ht1 northbridges like family 0Fh, do the tunings here where we have all the
1847 * link and route info at hand and don't need to recalculate it.
1848 */
1849
1850 /* Node 0, Request / Probe Link (note family F only has links < 4) */
1851 fam0fWriteHTLinkCmdBufferAlloc(0, req0, 6, 3, 1, 6);
1852 fam0fWriteHTLinkDatBufferAlloc(0, req0, 4, 3, 1);
1853 /* Node 0, Response Link (note family F only has links < 4) */
1854 fam0fWriteHTLinkCmdBufferAlloc(0, rsp0, 1, 0, 15, 0);
1855 fam0fWriteHTLinkDatBufferAlloc(0, rsp0, 1, 1, 6);
1856 /* Node 1, Request / Probe Link (note family F only has links < 4) */
1857 fam0fWriteHTLinkCmdBufferAlloc(1, req1, 6, 3, 1, 6);
1858 fam0fWriteHTLinkDatBufferAlloc(1, req1, 4, 3, 1);
1859 /* Node 1, Response Link (note family F only has links < 4) */
1860 fam0fWriteHTLinkCmdBufferAlloc(1, rsp1, 1, 0, 15, 0);
1861 fam0fWriteHTLinkDatBufferAlloc(1, rsp1, 1, 1, 6);
1862
1863 /* Node 0, is the third link non-coherent? */
1864 nclink = (u8)AmdBitScanReverse(((u8)0x07 & ~((u32)1 << req0) & ~((u32)1 << rsp0)));
1865 if (nb->verifyLinkIsNonCoherent(0, nclink, nb))
1866 {
1867 fam0fWriteHTLinkCmdBufferAlloc(0, nclink, 6, 5, 2, 0);
1868 }
1869
1870 /* Node 1, is the third link non-coherent? */
1871 nclink = (u8)AmdBitScanReverse(((u8)0x07 & ~((u32)1 << req1) & ~((u32)1 << rsp1)));
1872 if (nb->verifyLinkIsNonCoherent(1, nclink, nb))
1873 {
1874 fam0fWriteHTLinkCmdBufferAlloc(1, nclink, 6, 5, 2, 0);
1875 }
1876#endif /* HT_BUILD_NC_ONLY */
1877}
1878
Martin Rothf4cb4122015-01-06 10:27:39 -07001879/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00001880 *
Stefan Reinauer30634322010-04-09 13:35:03 +00001881 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +00001882 * fam0fBufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
1883 *
1884 * Description:
1885 * Buffer tunings are inherently northbridge specific. Check for specific configs
1886 * which require adjustments and apply any standard workarounds to this node.
1887 *
1888 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07001889 * @param[in] node = the node to
1890 * @param[in] *pDat = coherent links from node 0 to 1
1891 * @param[in] nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +00001892 *
Martin Rothf4cb4122015-01-06 10:27:39 -07001893 ******************************************************************************/
Stefan Reinauer30634322010-04-09 13:35:03 +00001894static void fam0fBufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00001895{
1896#ifndef HT_BUILD_NC_ONLY
1897 u8 i;
1898 u32 temp;
1899 SBDFO currentPtr;
1900
1901 ASSERT(node < nb->maxNodes);
1902
1903 /* Fix the FIFO pointer register before changing speeds */
1904 currentPtr = MAKE_SBDFO(makePCISegmentFromNode(node),
1905 makePCIBusFromNode(node),
1906 makePCIDeviceFromNode(node),
1907 CPU_NB_FUNC_03,
1908 REG_NB_FIFOPTR_3XDC);
1909 for (i=0; i < nb->maxLinks; i++)
1910 {
1911 temp = 0;
1912 if (nb->verifyLinkIsCoherent(node, i, nb))
1913 {
1914 temp = 0x26;
1915 ASSERT(i<3);
1916 AmdPCIWriteBits(currentPtr, 8*i + 5, 8*i, &temp);
1917 }
1918 else
1919 {
1920 if (nb->verifyLinkIsNonCoherent(node, i, nb))
1921 {
1922 temp = 0x25;
1923 ASSERT(i<3);
1924 AmdPCIWriteBits(currentPtr, 8*i + 5, 8*i, &temp);
1925 }
1926 }
1927 }
1928 /*
1929 * 8P Buffer tuning.
1930 * Either apply the BKDG tunings or, if applicable, apply the more restrictive errata 153
1931 * workaround.
1932 * If 8 nodes, Check this node for 'inner' or 'outer'.
1933 * Tune each link based on coherent or non-coherent
1934 */
1935 if (pDat->NodesDiscovered >= 6)
1936 {
1937 u8 j;
1938 BOOL isOuter;
1939 BOOL isErrata153;
1940
1941 /* This is for family 0Fh, so assuming dual core max then 7 or 8 nodes are required
1942 * to be in the situation of 14 or more cores. We checked nodes above, cross check
1943 * that the number of cores is 14 or more. We want both 14 cores with at least 7 or 8 nodes
1944 * not one condition alone, to apply the errata 153 workaround. Otherwise, 7 or 8 rev F
1945 * nodes use the BKDG tuning.
1946 */
1947
1948 isErrata153 = 0;
1949
1950 AmdPCIReadBits (MAKE_SBDFO(makePCISegmentFromNode(0),
1951 makePCIBusFromNode(0),
1952 makePCIDeviceFromNode(0),
1953 CPU_HTNB_FUNC_00,
1954 REG_NODE_ID_0X60),
1955 19, 16, &temp);
1956
1957 if (temp >= 14)
1958 {
1959 /* Check whether we need to do errata 153 tuning or BKDG tuning.
1960 * Errata 153 applies to JH-1, JH-2 and older. It is fixed in JH-3
1961 * (and, one assumes, from there on).
1962 */
1963 for (i=0; i < (pDat->NodesDiscovered +1); i++)
1964 {
1965 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(i),
1966 makePCIBusFromNode(i),
1967 makePCIDeviceFromNode(i),
1968 CPU_NB_FUNC_03,
1969 REG_NB_CPUID_3XFC),
1970 7, 0, &temp);
1971 if (((u8)temp & ~0x40) < 0x13)
1972 {
1973 isErrata153 = 1;
1974 break;
1975 }
1976 }
1977 }
1978
1979 for (i=0; i < CPU_ADDR_NUM_CONFIG_MAPS; i++)
1980 {
1981 isOuter = FALSE;
1982 /* Check for outer node by scanning the config maps on node 0 for one
1983 * which is assigned to this node.
1984 */
1985 currentPtr = MAKE_SBDFO(makePCISegmentFromNode(0),
1986 makePCIBusFromNode(0),
1987 makePCIDeviceFromNode(0),
1988 CPU_ADDR_FUNC_01,
1989 REG_ADDR_CONFIG_MAP0_1XE0 + (4 * i));
1990 AmdPCIReadBits (currentPtr, 1, 0, &temp);
1991 /* Make sure this config map is valid, if it is it will be enabled for read/write */
1992 if (temp == 3)
1993 {
1994 /* It's valid, get the node (that node is an outer node) */
1995 AmdPCIReadBits (currentPtr, 6, 4, &temp);
1996 /* Is the node we're working on now? */
1997 if (node == (u8)temp)
1998 {
1999 /* This is an outer node. Tune it appropriately. */
2000 for (j=0; j < nb->maxLinks; j++)
2001 {
2002 if (isErrata153)
2003 {
2004 if (nb->verifyLinkIsCoherent(node, j, nb))
2005 {
2006 fam0fWriteHTLinkCmdBufferAlloc(node, j, 1, 1, 6, 4);
2007 }
2008 else
2009 {
2010 if (nb->verifyLinkIsNonCoherent(node, j, nb))
2011 {
2012 fam0fWriteHTLinkCmdBufferAlloc(node, j, 5, 4, 1, 0);
2013 }
2014 }
2015 }
2016 else
2017 {
2018 if (nb->verifyLinkIsCoherent(node, j, nb))
2019 {
2020 fam0fWriteHTLinkCmdBufferAlloc(node, j, 1, 1, 8, 5);
2021 }
2022 }
2023 }
2024 /*
2025 * SRI to XBAR Buffer Counts are correct for outer node at power on defaults.
2026 */
2027 isOuter = TRUE;
2028 break;
2029 }
2030 }
2031 /* We fill config maps in ascending order, so if we didn't use this one, we're done. */
2032 else break;
2033 }
2034 if (!isOuter)
2035 {
2036 if (isErrata153)
2037 {
2038 /* Tuning for inner node coherent links */
2039 for (j=0; j < nb->maxLinks; j++)
2040 {
2041 if (nb->verifyLinkIsCoherent(node, j, nb))
2042 {
2043 fam0fWriteHTLinkCmdBufferAlloc(node, j, 2, 1, 5, 4);
2044 }
2045
2046 }
2047 /* SRI to XBAR Buffer Count for inner nodes, zero DReq and DPReq */
2048 temp = 0;
2049 AmdPCIWriteBits (MAKE_SBDFO(makePCISegmentFromNode(node),
2050 makePCIBusFromNode(node),
2051 makePCIDeviceFromNode(node),
2052 CPU_NB_FUNC_03,
2053 REG_NB_SRI_XBAR_BUF_3X70),
2054 31, 28, &temp);
2055 }
2056 }
2057
2058 /*
2059 * Tune MCT to XBAR Buffer Count the same an all nodes, 2 Probes, 5 Response
2060 */
2061 if (isErrata153)
2062 {
2063 temp = 0x25;
2064 AmdPCIWriteBits (MAKE_SBDFO(makePCISegmentFromNode(node),
2065 makePCIBusFromNode(node),
2066 makePCIDeviceFromNode(node),
2067 CPU_NB_FUNC_03,
2068 REG_NB_MCT_XBAR_BUF_3X78),
2069 14, 8, &temp);
2070 }
2071 }
2072#endif /* HT_BUILD_NC_ONLY */
2073}
2074
Martin Rothf4cb4122015-01-06 10:27:39 -07002075/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00002076 *
Stefan Reinauer30634322010-04-09 13:35:03 +00002077 * static void
Marc Jones8ae8c882007-12-19 01:32:08 +00002078 * fam10BufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
2079 *
2080 * Description:
2081 * Buffer tunings are inherently northbridge specific. Check for specific configs
2082 * which require adjustments and apply any standard workarounds to this node.
2083 *
2084 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07002085 * @param[in] node = the node to tune
2086 * @param[in] *pDat = global state
2087 * @param[in] nb = this northbridge
Marc Jones8ae8c882007-12-19 01:32:08 +00002088 *
Martin Rothf4cb4122015-01-06 10:27:39 -07002089 ******************************************************************************/
Stefan Reinauer30634322010-04-09 13:35:03 +00002090static void fam10BufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
Marc Jones8ae8c882007-12-19 01:32:08 +00002091{
2092 u32 temp;
2093 SBDFO currentPtr;
2094 u8 i;
2095
2096 ASSERT(node < nb->maxNodes);
2097
2098 /*
2099 * Link to XCS Token Count Tuning
2100 *
2101 * For each active link that we reganged (so this unfortunately can't go into the PCI reg
2102 * table), we have to switch the Link to XCS Token Counts to the ganged state.
2103 * We do this here for the non-uma case, which is to write the values that would have
2104 * been power on defaults if the link was ganged at cold reset.
2105 */
2106 for (i = 0; i < pDat->TotalLinks*2; i++)
2107 {
2108 if ((pDat->PortList[i].NodeID == node) && (pDat->PortList[i].Type == PORTLIST_TYPE_CPU))
2109 {
2110 /* If the link is greater than 4, this is a sublink 1, so it is not reganged. */
2111 if (pDat->PortList[i].Link < 4)
2112 {
2113 currentPtr = MAKE_SBDFO(makePCISegmentFromNode(node),
2114 makePCIBusFromNode(node),
2115 makePCIDeviceFromNode(node),
2116 CPU_NB_FUNC_03,
2117 REG_NB_LINK_XCS_TOKEN0_3X148 + 4*pDat->PortList[i].Link);
2118 if (pDat->PortList[i].SelRegang)
2119 {
2120 /* Handle all the regang Token count adjustments */
2121
2122 /* Sublink 0: [Probe0tok] = 2 [Rsp0tok] = 2 [PReq0tok] = 2 [Req0tok] = 2 */
2123 temp = 0xAA;
2124 AmdPCIWriteBits(currentPtr, 7, 0, &temp);
2125 /* Sublink 1: [Probe1tok] = 0 [Rsp1tok] = 0 [PReq1tok] = 0 [Req1tok] = 0 */
2126 temp = 0;
2127 AmdPCIWriteBits(currentPtr, 23, 16, &temp);
2128 /* [FreeTok] = 3 */
2129 temp = 3;
2130 AmdPCIWriteBits(currentPtr, 15, 14, &temp);
2131 }
2132 else
2133 {
2134 /* Read the regang bit in hardware */
2135 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID),
2136 makePCIBusFromNode(pDat->PortList[i].NodeID),
2137 makePCIDeviceFromNode(pDat->PortList[i].NodeID),
2138 CPU_HTNB_FUNC_00,
2139 REG_HT_LINK_EXT_CONTROL0_0X170 + 4*pDat->PortList[i].Link),
2140 0, 0, &temp);
2141 if (temp == 1)
2142 {
2143 /* handle a minor adjustment for stapped ganged links. If SelRegang is false we
2144 * didn't do the regang, so if the bit is on then it's hardware strapped.
2145 */
2146
2147 /* [FreeTok] = 3 */
2148 temp = 3;
2149 AmdPCIWriteBits(currentPtr, 15, 14, &temp);
2150 }
2151 }
2152 }
2153 }
2154 }
2155}
2156
2157/*
2158 * North Bridge 'constructor'.
2159 *
2160 */
2161
Martin Rothf4cb4122015-01-06 10:27:39 -07002162/***************************************************************************//**
Marc Jones8ae8c882007-12-19 01:32:08 +00002163 *
2164 * void
2165 * newNorthBridge(u8 node, cNorthBridge *nb)
2166 *
2167 * Description:
2168 * Construct a new northbridge. This routine encapsulates knowledge of how to tell
2169 * significant differences between families of supported northbridges and what routines
2170 * can be used in common and which are unique. A fully populated northbridge interface
2171 * is provided by nb.
2172 *
2173 * Parameters:
Martin Rothf4cb4122015-01-06 10:27:39 -07002174 * @param node
2175 * @param[out] nb = the caller's northbridge structure to initialize.
Marc Jones8ae8c882007-12-19 01:32:08 +00002176 *
Martin Rothf4cb4122015-01-06 10:27:39 -07002177 ******************************************************************************/
Marc Jones8ae8c882007-12-19 01:32:08 +00002178void newNorthBridge(u8 node, cNorthBridge *nb)
2179{
2180 u32 match;
2181 u32 extFam, baseFam, model;
2182
Timothy Pearson730a0432015-10-16 13:51:51 -05002183 cNorthBridge fam15 =
2184 {
2185#ifdef HT_BUILD_NC_ONLY
2186 8,
2187 1,
2188 12,
2189#else
2190 8,
2191 8,
2192 64,
2193#endif /* HT_BUILD_NC_ONLY*/
2194 writeRoutingTable,
2195 writeNodeID,
2196 readDefLnk,
2197 enableRoutingTables,
2198 verifyLinkIsCoherent,
2199 readTrueLinkFailStatus,
2200 readToken,
2201 writeToken,
2202 fam15GetNumCoresOnNode,
2203 setTotalNodesAndCores,
2204 limitNodes,
2205 writeFullRoutingTable,
2206 isCompatible,
2207 fam15IsCapable,
2208 (void (*)(u8, u8, cNorthBridge*))commonVoid,
2209 (BOOL (*)(u8, u8, sMainData*, cNorthBridge*))commonReturnFalse,
2210 readSbLink,
2211 verifyLinkIsNonCoherent,
2212 ht3SetCFGAddrMap,
2213 convertBitsToWidth,
2214 convertWidthToBits,
2215 fam10NorthBridgeFreqMask,
2216 gatherLinkData,
2217 setLinkData,
2218 ht3WriteTrafficDistribution,
2219 fam10BufferOptimizations,
2220 0x00000001,
2221 0x00000200,
2222 18,
2223 0x00000f06
2224 };
2225
Marc Jones8ae8c882007-12-19 01:32:08 +00002226 cNorthBridge fam10 =
2227 {
2228#ifdef HT_BUILD_NC_ONLY
2229 8,
2230 1,
2231 12,
2232#else
2233 8,
2234 8,
2235 64,
2236#endif /* HT_BUILD_NC_ONLY*/
2237 writeRoutingTable,
2238 writeNodeID,
2239 readDefLnk,
2240 enableRoutingTables,
2241 verifyLinkIsCoherent,
2242 readTrueLinkFailStatus,
2243 readToken,
2244 writeToken,
2245 fam10GetNumCoresOnNode,
2246 setTotalNodesAndCores,
2247 limitNodes,
2248 writeFullRoutingTable,
2249 isCompatible,
2250 fam10IsCapable,
2251 (void (*)(u8, u8, cNorthBridge*))commonVoid,
2252 (BOOL (*)(u8, u8, sMainData*, cNorthBridge*))commonReturnFalse,
2253 readSbLink,
2254 verifyLinkIsNonCoherent,
2255 ht3SetCFGAddrMap,
2256 convertBitsToWidth,
2257 convertWidthToBits,
2258 fam10NorthBridgeFreqMask,
2259 gatherLinkData,
2260 setLinkData,
2261 ht3WriteTrafficDistribution,
2262 fam10BufferOptimizations,
2263 0x00000001,
2264 0x00000200,
2265 18,
2266 0x00000f01
2267 };
2268
2269 cNorthBridge fam0f =
2270 {
2271#ifdef HT_BUILD_NC_ONLY
2272 3,
2273 1,
2274 12,
2275#else
2276 3,
2277 8,
2278 32,
2279#endif /* HT_BUILD_NC_ONLY*/
2280 writeRoutingTable,
2281 writeNodeID,
2282 readDefLnk,
2283 enableRoutingTables,
2284 verifyLinkIsCoherent,
2285 readTrueLinkFailStatus,
2286 readToken,
2287 writeToken,
2288 fam0FGetNumCoresOnNode,
2289 setTotalNodesAndCores,
2290 limitNodes,
2291 writeFullRoutingTable,
2292 isCompatible,
2293 fam0fIsCapable,
2294 fam0fStopLink,
2295 (BOOL (*)(u8, u8, sMainData*, cNorthBridge*))commonReturnFalse,
2296 readSbLink,
2297 verifyLinkIsNonCoherent,
2298 ht1SetCFGAddrMap,
2299 convertBitsToWidth,
2300 convertWidthToBits,
2301 ht1NorthBridgeFreqMask,
2302 gatherLinkData,
2303 setLinkData,
2304 ht1WriteTrafficDistribution,
2305 fam0fBufferOptimizations,
2306 0x00000001,
2307 0x00000100,
2308 16,
2309 0x00000f00
2310 };
2311
2312 /* Start with enough of the key to identify the northbridge interface */
2313 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
2314 makePCIBusFromNode(node),
2315 makePCIDeviceFromNode(node),
2316 CPU_NB_FUNC_03,
2317 REG_NB_CPUID_3XFC),
2318 27, 20, &extFam);
2319 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
2320 makePCIBusFromNode(node),
2321 makePCIDeviceFromNode(node),
2322 CPU_NB_FUNC_03,
2323 REG_NB_CPUID_3XFC),
2324 11, 8, &baseFam);
2325 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
2326 makePCIBusFromNode(node),
2327 makePCIDeviceFromNode(node),
2328 CPU_NB_FUNC_03,
2329 REG_NB_CPUID_3XFC),
2330 7, 4, &model);
2331 match = (u32)((baseFam << 8) | extFam);
2332
Timothy Pearson730a0432015-10-16 13:51:51 -05002333 /* Test each in turn looking for a match.
2334 * Initialize the struct if found.
2335 */
2336 if (match == fam15.compatibleKey)
2337 {
2338 Amdmemcpy((void *)nb, (const void *)&fam15, (u32) sizeof(cNorthBridge));
2339 }
2340 else if (match == fam10.compatibleKey)
Marc Jones8ae8c882007-12-19 01:32:08 +00002341 {
2342 Amdmemcpy((void *)nb, (const void *)&fam10, (u32) sizeof(cNorthBridge));
2343 }
2344 else
2345 {
2346 if (match == fam0f.compatibleKey)
2347 {
2348 Amdmemcpy((void *)nb, (const void *)&fam0f, (u32) sizeof(cNorthBridge));
2349 }
2350 else
2351 {
2352 STOP_HERE;
2353 }
2354 }
2355
2356 /* Update the initial limited key to the real one, which may include other matching info */
2357 nb->compatibleKey = makeKey(node);
2358}