blob: 5b038a3a5860646f0043e25dba98af67bd04384c [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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20
21/*----------------------------------------------------------------------------
22 * MODULES USED
23 *
24 *----------------------------------------------------------------------------
25 */
26
27#undef FILECODE
28#define FILECODE 0xF002
29#include "h3finit.h"
30#include "h3ffeat.h"
31#include "h3ncmn.h"
32#include "AsPsNb.h"
33
34
35/*----------------------------------------------------------------------------
36 * DEFINITIONS AND MACROS
37 *
38 *----------------------------------------------------------------------------
39 */
40
41/* CPU Northbridge Functions */
42#define CPU_HTNB_FUNC_00 0
43#define CPU_HTNB_FUNC_04 4
44#define CPU_ADDR_FUNC_01 1
45#define CPU_NB_FUNC_03 3
46
47/* Function 0 registers */
48#define REG_ROUTE0_0X40 0x40
49#define REG_ROUTE1_0X44 0x44
50#define REG_NODE_ID_0X60 0x60
51#define REG_UNIT_ID_0X64 0x64
52#define REG_LINK_TRANS_CONTROL_0X68 0x68
53#define REG_LINK_INIT_CONTROL_0X6C 0x6C
54#define REG_HT_CAP_BASE_0X80 0x80
55#define REG_HT_LINK_RETRY0_0X130 0x130
56#define REG_HT_TRAFFIC_DIST_0X164 0x164
57#define REG_HT_LINK_EXT_CONTROL0_0X170 0x170
58
59#define HT_CONTROL_CLEAR_CRC (~(3 << 8))
60
61/* Function 1 registers */
62#define REG_ADDR_CONFIG_MAP0_1XE0 0xE0
63#define CPU_ADDR_NUM_CONFIG_MAPS 4
64
65/* Function 3 registers */
66#define REG_NB_SRI_XBAR_BUF_3X70 0x70
67#define REG_NB_MCT_XBAR_BUF_3X78 0x78
68#define REG_NB_FIFOPTR_3XDC 0xDC
69#define REG_NB_CAPABILITY_3XE8 0xE8
70#define REG_NB_CPUID_3XFC 0xFC
71#define REG_NB_LINK_XCS_TOKEN0_3X148 0x148
72#define REG_NB_DOWNCORE_3X190 0x190
73
74/* Function 4 registers */
75
76
77/*----------------------------------------------------------------------------
78 * TYPEDEFS AND STRUCTURES
79 *
80 *----------------------------------------------------------------------------
81 */
82/*----------------------------------------------------------------------------
83 * PROTOTYPES OF LOCAL FUNCTIONS
84 *
85 *----------------------------------------------------------------------------
86 */
87
88/***************************************************************************
89 *** FAMILY/NORTHBRIDGE SPECIFIC FUNCTIONS ***
90 ***************************************************************************/
91
92/**----------------------------------------------------------------------------------------
93 *
94 * SBDFO
95 * makeLinkBase(u8 currentNode, u8 currentLink)
96 *
97 * Description:
98 * Private to northbridge implementation. Return the HT Host capability base
99 * PCI config address for a link.
100 *
101 * Parameters:
102 * @param[in] u8 node = the node this link is on
103 * @param[in] u8 link = the link
104 * @param[out] SBDFO result = the pci config address
105 *
106 * ---------------------------------------------------------------------------------------
107 */
108static SBDFO makeLinkBase(u8 node, u8 link)
109{
110 SBDFO linkBase;
111
112 /* With rev F can not be called with a 4th link or with the sublinks */
113 if (link < 4)
114 linkBase = MAKE_SBDFO(makePCISegmentFromNode(node),
115 makePCIBusFromNode(node),
116 makePCIDeviceFromNode(node),
117 CPU_HTNB_FUNC_00,
118 REG_HT_CAP_BASE_0X80 + link*HT_HOST_CAP_SIZE);
119 else
120 linkBase = MAKE_SBDFO(makePCISegmentFromNode(node),
121 makePCIBusFromNode(node),
122 makePCIDeviceFromNode(node),
123 CPU_HTNB_FUNC_04,
124 REG_HT_CAP_BASE_0X80 + (link-4)*HT_HOST_CAP_SIZE);
125 return linkBase;
126}
127
128/**----------------------------------------------------------------------------------------
129 *
130 * void
131 * setHtControlRegisterBits(SBDFO reg, u8 hiBit, u8 loBit, u32 *pValue)
132 *
133 * Description:
134 * Private to northbridge implementation. Provide a common routine for accessing the
135 * HT Link Control registers (84, a4, c4, e4), to enforce not clearing the
136 * HT CRC error bits. Replaces direct use of AmdPCIWriteBits().
137 * NOTE: This routine is called for IO Devices as well as CPUs!
138 *
139 * Parameters:
140 * @param[in] SBDFO reg = the PCI config address the control register
141 * @param[in] u8 hiBit = the high bit number
142 * @param[in] u8 loBit = the low bit number
143 * @param[in] u8 pValue = the value to write to that bit range. Bit 0 => loBit.
144 *
145 * ---------------------------------------------------------------------------------------
146 */
147static void setHtControlRegisterBits(SBDFO reg, u8 hiBit, u8 loBit, u32 *pValue)
148{
149 u32 temp, mask;
150
151 ASSERT((hiBit < 32) && (loBit < 32) && (hiBit >= loBit) && ((reg & 0x3) == 0));
152 ASSERT((hiBit < 8) || (loBit > 9));
153
154 /* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */
155 if ((hiBit-loBit) != 31)
156 mask = (((u32)1 << (hiBit-loBit+1))-1);
157 else
158 mask = (u32)0xFFFFFFFF;
159
160 AmdPCIRead(reg, &temp);
161 temp &= ~(mask << loBit);
162 temp |= (*pValue & mask) << loBit;
163 temp &= (u32)HT_CONTROL_CLEAR_CRC;
164 AmdPCIWrite(reg, &temp);
165}
166
167/**----------------------------------------------------------------------------------------
168 *
169 * void
170 * writeRoutingTable(u8 node, u8 target, u8 Link, cNorthBridge *nb)
171 *
172 * Description:
173 * This routine will modify the routing tables on the
174 * SourceNode to cause it to route both request and response traffic to the
175 * targetNode through the specified Link.
176 *
177 * NOTE: This routine is to be used for early discovery and initialization. The
178 * final routing tables must be loaded some other way because this
179 * routine does not address the issue of probes, or independent request
180 * response paths.
181 *
182 * Parameters:
183 * @param[in] u8 node = the node that will have it's routing tables modified.
184 * @param[in] u8 target = For routing to node target
185 * @param[in] u8 Link = Link from node to target
186 * @param[in] cNorthBridge *nb = this northbridge
187 *
188 * ---------------------------------------------------------------------------------------
189 */
190
191void writeRoutingTable(u8 node, u8 target, u8 link, cNorthBridge *nb)
192{
193#ifndef HT_BUILD_NC_ONLY
194 u32 temp = (nb->selfRouteResponseMask | nb->selfRouteRequestMask) << (link + 1);
195 ASSERT((node < nb->maxNodes) && (target < nb->maxNodes) && (link < nb->maxLinks));
196 AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(node),
197 makePCIBusFromNode(node),
198 makePCIDeviceFromNode(node),
199 CPU_HTNB_FUNC_00,
200 REG_ROUTE0_0X40 + target*4),
201 &temp);
202#else
203 STOP_HERE;
204#endif
205}
206
207/**----------------------------------------------------------------------------------------
208 *
209 * void
210 * writeNodeID(u8 node, u8 nodeID, cNorthBridge *nb)
211 *
212 * Description:
213 * Modifies the NodeID register on the target node
214 *
215 * Parameters:
216 * @param[in] u8 node = the node that will have its NodeID altered.
217 * @param[in] u8 nodeID = the new value for NodeID
218 * @param[in] cNorthBridge *nb = this northbridge
219 *
220 * ---------------------------------------------------------------------------------------
221 */
222
223void writeNodeID(u8 node, u8 nodeID, cNorthBridge *nb)
224{
225 u32 temp = nodeID;
226 ASSERT((node < nb->maxNodes) && (nodeID < nb->maxNodes));
227 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(node),
228 makePCIBusFromNode(node),
229 makePCIDeviceFromNode(node),
230 CPU_HTNB_FUNC_00,
231 REG_NODE_ID_0X60),
232 2, 0, &temp);
233}
234
235/**----------------------------------------------------------------------------------------
236 *
237 * void
238 * readDefLnk(u8 node, cNorthBridge *nb)
239 *
240 * Description:
241 * Read the DefLnk (the source link of the current packet)
242 * from node
243 *
244 * Parameters:
245 * @param[in] u8 node = the node that will have its NodeID altered.
246 * @param[in] cNorthBridge *nb = this northbridge
247 * @param[out] u8 result = The HyperTransport link where the request to
248 * read the default link came from. Since this
249 * code is running on the BSP, this should be the link
250 * pointing back towards the BSP.
251 *
252 * ---------------------------------------------------------------------------------------
253 */
254
255u8 readDefLnk(u8 node, cNorthBridge *nb)
256{
257 u32 deflink = 0;
258 SBDFO licr;
259 u32 temp;
260
261 licr = MAKE_SBDFO(makePCISegmentFromNode(node),
262 makePCIBusFromNode(node),
263 makePCIDeviceFromNode(node),
264 CPU_HTNB_FUNC_00,
265 REG_LINK_INIT_CONTROL_0X6C);
266
267 ASSERT((node < nb->maxNodes));
268 AmdPCIReadBits(licr, 3, 2, &deflink);
269 AmdPCIReadBits(licr, 8, 8, &temp); /* on rev F, this bit is reserved == 0 */
270 deflink |= temp << 2;
271 return (u8)deflink;
272}
273
274/**----------------------------------------------------------------------------------------
275 *
276 * void
277 * enableRoutingTables(u8 node, cNorthBridge *nb)
278 *
279 * Description:
280 * Turns routing tables on for a given node
281 *
282 * Parameters:
283 * @param[in] u8 node = the node that will have it's routing tables enabled
284 * @param[in] cNorthBridge *nb = this northbridge
285 *
286 * ---------------------------------------------------------------------------------------
287 */
288
289void enableRoutingTables(u8 node, cNorthBridge *nb)
290{
291 u32 temp = 0;
292 ASSERT((node < nb->maxNodes));
293 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(node),
294 makePCIBusFromNode(node),
295 makePCIDeviceFromNode(node),
296 CPU_HTNB_FUNC_00,
297 REG_LINK_INIT_CONTROL_0X6C),
298 0, 0, &temp);
299}
300
301
302/**----------------------------------------------------------------------------------------
303 *
304 * void
305 * verifyLinkIsCoherent(u8 node, u8 Link, cNorthBridge *nbk)
306 *
307 * Description:
308 * Verify that the link is coherent, connected, and ready
309 *
310 * Parameters:
311 * @param[in] u8 node = the node that will be examined
312 * @param[in] u8 link = the link on that Node to examine
313 * @param[in] cNorthBridge *nb = this northbridge
314 * @param[out] u8 result = true - The link has the following status
315 * linkCon=1, Link is connected
316 * InitComplete=1, Link initialization is complete
317 * NC=0, Link is coherent
318 * UniP-cLDT=0, Link is not Uniprocessor cLDT
319 * LinkConPend=0 Link connection is not pending
320 * false- The link has some other status
321 *
322 * ---------------------------------------------------------------------------------------
323 */
324
325BOOL verifyLinkIsCoherent(u8 node, u8 link, cNorthBridge *nb)
326{
327#ifndef HT_BUILD_NC_ONLY
328
329 u32 linkType;
330 SBDFO linkBase;
331
332 ASSERT((node < nb->maxNodes) && (link < nb->maxLinks));
333
334 linkBase = makeLinkBase(node, link);
335
Marc Jonesaee07962008-07-16 21:09:31 +0000336 /* FN0_98/A4/C4 = LDT Type Register */
Marc Jones8ae8c882007-12-19 01:32:08 +0000337 AmdPCIRead(linkBase + HTHOST_LINK_TYPE_REG, &linkType);
338
Marc Jonesaee07962008-07-16 21:09:31 +0000339 /* Verify LinkCon=1, InitComplete=1, NC=0, UniP-cLDT=0, LinkConPend=0 */
Marc Jones8ae8c882007-12-19 01:32:08 +0000340 return (linkType & HTHOST_TYPE_MASK) == HTHOST_TYPE_COHERENT;
341#else
342 return 0;
343#endif /* HT_BUILD_NC_ONLY */
344}
345
346/**----------------------------------------------------------------------------------------
347 *
348 * bool
349 * readTrueLinkFailStatus(u8 node, u8 link, sMainData *pDat, cNorthBridge *nb)
350 *
351 * Description:
352 * Return the LinkFailed status AFTER an attempt is made to clear the bit.
353 * Also, call event notify if a Hardware Fault caused a synch flood on a previous boot.
354 *
355 * The table below summarizes correct responses of this routine.
356 * Family before after unconnected Notify? return
357 * 0F 0 0 0 No 0
358 * 0F 1 0 0 Yes 0
359 * 0F 1 1 X No 1
360 * 10 0 0 0 No 0
361 * 10 1 0 0 Yes 0
362 * 10 1 0 3 No 1
363 *
364 * Parameters:
365 * @param[in] u8 node = the node that will be examined
366 * @param[in] u8 link = the link on that node to examine
367 * @param[in] u8 sMainData = access to call back routine
368 * @param[in] cNorthBridge *nb = this northbridge
369 * @param[out] u8 result = true - the link is not connected or has hard error
370 * false- if the link is connected
371 *
372 * ---------------------------------------------------------------------------------------
373 */
374BOOL readTrueLinkFailStatus(u8 node, u8 link, sMainData *pDat, cNorthBridge *nb)
375{
376 u32 before, after, unconnected, crc;
377 SBDFO linkBase;
378
379 ASSERT((node < nb->maxNodes) && (link < nb->maxLinks));
380
381 linkBase = makeLinkBase(node, link);
382
383 /* Save the CRC status before doing anything else.
384 * Read, Clear, the Re-read the error bits in the Link Control Register
385 * FN0_84/A4/C4[4] = LinkFail bit
386 * and the connection status, TransOff and EndOfChain
387 */
388 AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 9, 8, &crc);
389 AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 4, 4, &before);
390 setHtControlRegisterBits(linkBase + HTHOST_LINK_CONTROL_REG, 4, 4, &before);
391 AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 4, 4, &after);
392 AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 7, 6, &unconnected);
393
394 if (before != after)
395 {
396 if (!unconnected)
397 {
398 if (crc != 0)
399 {
400 /* A synch flood occurred due to HT CRC */
401 if (pDat->HtBlock->AMD_CB_EventNotify)
402 {
403 /* Pass the node and link on which the generic synch flood event occurred. */
Marc Jones212486e2008-07-17 19:50:37 +0000404 sHtEventHWHtCrc evt;
405 evt.eSize = sizeof(sHtEventHWHtCrc);
406 evt.node = node;
407 evt.link = link;
408 evt.laneMask = (uint8)crc;
Marc Jones8ae8c882007-12-19 01:32:08 +0000409
410 pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_HW_FAULT,
411 HT_EVENT_HW_HTCRC,
412 (u8 *)&evt);
413 }
414 }
415 else
416 {
417 /* Some synch flood occurred */
418 if (pDat->HtBlock->AMD_CB_EventNotify)
419 {
420 /* Pass the node and link on which the generic synch flood event occurred. */
Marc Jones212486e2008-07-17 19:50:37 +0000421 sHtEventHWSynchFlood evt;
422 evt.eSize = sizeof(sHtEventHWSynchFlood);
423 evt.node = node;
424 evt.link = link;
Marc Jones8ae8c882007-12-19 01:32:08 +0000425
426 pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_HW_FAULT,
427 HT_EVENT_HW_SYNCHFLOOD,
428 (u8 *)&evt);
429 }
430 }
431 }
432 }
433 return ((after != 0) || unconnected);
434}
435
436
437/**----------------------------------------------------------------------------------------
438 *
439 * u8
440 * readToken(u8 node, cNorthBridge *nb)
441 *
442 * Description:
443 * Read the token stored in the scratchpad register
444 * NOTE: The location used to store the token is arbitrary. The only
445 * requirement is that the location warm resets to zero, and that
446 * using it will have no ill-effects during HyperTransport initialization.
447 *
448 * Parameters:
449 * @param[in] u8 node = the node that will be examined
450 * @param[in] cNorthBridge *nb = this northbridge
451 * @param[out] u8 result = the Token read from the node
452 *
453 * ---------------------------------------------------------------------------------------
454 */
455u8 readToken(u8 node, cNorthBridge *nb)
456{
457 u32 temp;
458
459 ASSERT((node < nb->maxNodes));
460 /* Use CpuCnt as a scratch register */
461 /* Limiting use to 4 bits makes code GH to rev F compatible. */
462 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
463 makePCIBusFromNode(node),
464 makePCIDeviceFromNode(node),
465 CPU_HTNB_FUNC_00,
466 REG_NODE_ID_0X60),
467 19, 16, &temp);
468
469 return (u8)temp;
470}
471
472
473/**----------------------------------------------------------------------------------------
474 *
475 * void
476 * writeToken(u8 node, u8 Value, cNorthBridge *nb)
477 *
478 * Description:
479 * Write the token stored in the scratchpad register
480 * NOTE: The location used to store the token is arbitrary. The only
481 * requirement is that the location warm resets to zero, and that
482 * using it will have no ill-effects during HyperTransport initialization.
483 * Limiting use to 4 bits makes code GH to rev F compatible.
484 *
485 * Parameters:
486 * @param[in] u8 node = the node that will be examined
487 * @param[in] cNorthBridge *nb = this northbridge
488 *
489 * ---------------------------------------------------------------------------------------
490 */
491void writeToken(u8 node, u8 value, cNorthBridge *nb)
492{
493 u32 temp = value;
494 ASSERT((node < nb->maxNodes));
495 /* Use CpuCnt as a scratch register */
496 /* Limiting use to 4 bits makes code GH to rev F compatible. */
497 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(node),
498 makePCIBusFromNode(node),
499 makePCIDeviceFromNode(node),
500 CPU_HTNB_FUNC_00,
501 REG_NODE_ID_0X60),
502 19, 16, &temp);
503}
504
505/**----------------------------------------------------------------------------------------
506 *
507 * u8
508 * fam0FGetNumCoresOnNode(u8 node, cNorthBridge *nb)
509 *
510 * Description:
511 * Return the number of cores (1 based count) on node.
512 *
513 * Parameters:
514 * @param[in] u8 node = the node that will be examined
515 * @param[in] cNorthBridge *nb = this northbridge
516 * @param[out] u8 result = the number of cores
517 *
518 * ---------------------------------------------------------------------------------------
519 */
520u8 fam0FGetNumCoresOnNode(u8 node, cNorthBridge *nb)
521{
522 u32 temp;
523
524 ASSERT((node < nb->maxNodes));
525 /* Read CmpCap */
526 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
527 makePCIBusFromNode(node),
528 makePCIDeviceFromNode(node),
529 CPU_NB_FUNC_03,
530 REG_NB_CAPABILITY_3XE8),
531 13, 12, &temp);
532
533 /* and add one */
534 return (u8)(temp+1);
535}
536
537/**----------------------------------------------------------------------------------------
538 *
539 * u8
540 * fam10GetNumCoresOnNode(u8 node, cNorthBridge *nb)
541 *
542 * Description:
543 * Return the number of cores (1 based count) on node.
544 *
545 * Parameters:
546 * @param[in] u8 node = the node that will be examined
547 * @param[in] cNorthBridge *nb = this northbridge
548 * @param[out] u8 result = the number of cores
549 *
550 * ---------------------------------------------------------------------------------------
551 */
552u8 fam10GetNumCoresOnNode(u8 node, cNorthBridge *nb)
553{
554 u32 temp, leveling, cores;
555 u8 i;
556
557 ASSERT((node < nb->maxNodes));
558 /* Read CmpCap */
559 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
560 makePCIBusFromNode(node),
561 makePCIDeviceFromNode(node),
562 CPU_NB_FUNC_03,
563 REG_NB_CAPABILITY_3XE8),
564 13, 12, &temp);
565
566 /* Support Downcoring */
567 cores = temp + 1;
568 AmdPCIReadBits (MAKE_SBDFO(makePCISegmentFromNode(node),
569 makePCIBusFromNode(node),
570 makePCIDeviceFromNode(node),
571 CPU_NB_FUNC_03,
572 REG_NB_DOWNCORE_3X190),
573 3, 0, &leveling);
574 for (i=0; i<cores; i++)
575 {
576 if (leveling & ((u32) 1 << i))
577 {
578 temp--;
579 }
580 }
581 return (u8)(temp+1);
582}
583
584/**----------------------------------------------------------------------------------------
585 *
586 * void
587 * setTotalNodesAndCores(u8 node, u8 totalNodes, u8 totalCores, cNorthBridge *nb)
588 *
589 * Description:
590 * Write the total number of cores and nodes to the node
591 *
592 * Parameters:
593 * @param[in] u8 node = the node that will be examined
594 * @param[in] u8 totalNodes = the total number of nodes
595 * @param[in] u8 totalCores = the total number of cores
596 * @param[in] cNorthBridge *nb = this northbridge
597 *
598 * ---------------------------------------------------------------------------------------
599 */
600void setTotalNodesAndCores(u8 node, u8 totalNodes, u8 totalCores, cNorthBridge *nb)
601{
602 SBDFO nodeIDReg;
603 u32 temp;
604
605 ASSERT((node < nb->maxNodes) && (totalNodes <= nb->maxNodes));
606 nodeIDReg = MAKE_SBDFO(makePCISegmentFromNode(node),
607 makePCIBusFromNode(node),
608 makePCIDeviceFromNode(node),
609 CPU_HTNB_FUNC_00,
610 REG_NODE_ID_0X60);
611
612 temp = totalCores-1;
613 /* Rely on max number of nodes:cores for rev F and GH to make
614 * this code work, even though we write reserved bit 20 on rev F it will be
615 * zero in that case.
616 */
617 AmdPCIWriteBits(nodeIDReg, 20, 16, &temp);
618 temp = totalNodes-1;
619 AmdPCIWriteBits(nodeIDReg, 6, 4, &temp);
620}
621
622/**----------------------------------------------------------------------------------------
623 *
624 * void
625 * limitNodes(u8 node, cNorthBridge *nb)
626 *
627 * Description:
628 * Limit coherent config accesses to cpus as indicated by nodecnt.
629 *
630 * Parameters:
631 * @param[in] u8 node = the node that will be examined
632 * @param[in] cNorthBridge *nb = this northbridge
633 *
634 * ---------------------------------------------------------------------------------------
635 */
636void limitNodes(u8 node, cNorthBridge *nb)
637{
638 u32 temp = 1;
639 ASSERT((node < nb->maxNodes));
640 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(node),
641 makePCIBusFromNode(node),
642 makePCIDeviceFromNode(node),
643 CPU_HTNB_FUNC_00,
644 REG_LINK_TRANS_CONTROL_0X68),
645 15, 15, &temp);
646}
647
648/**----------------------------------------------------------------------------------------
649 *
650 * void
651 * writeFullRoutingTable(u8 node, u8 target, u8 reqLink, u8 rspLink, u32 BClinks, cNorthBridge *nb)
652 *
653 * Description:
654 * Write the routing table entry for node to target, using the request link, response
655 * link, and broadcast links provided.
656 *
657 * Parameters:
658 * @param[in] u8 node = the node that will be examined
659 * @param[in] u8 target = the target node for these routes
660 * @param[in] u8 reqLink = the link for requests to target
661 * @param[in] u8 rspLink = the link for responses to target
662 * @param[in] u32 bClinks = the broadcast links
663 * @param[in] cNorthBridge *nb = this northbridge
664 *
665 * ---------------------------------------------------------------------------------------
666 */
667void writeFullRoutingTable(u8 node, u8 target, u8 reqLink, u8 rspLink, u32 bClinks, cNorthBridge *nb)
668{
669#ifndef HT_BUILD_NC_ONLY
670 u32 value = 0;
671
672 ASSERT((node < nb->maxNodes) && (target < nb->maxNodes));
673 if (reqLink == ROUTETOSELF)
674 value |= nb->selfRouteRequestMask;
675 else
676 value |= nb->selfRouteRequestMask << (reqLink+1);
677
678 if (rspLink == ROUTETOSELF)
679 value |= nb->selfRouteResponseMask;
680 else
681 value |= nb->selfRouteResponseMask << (rspLink+1);
682
683 /* Allow us to accept a Broadcast ourselves, then set broadcasts for routes */
684 value |= (u32)1 << nb->broadcastSelfBit;
685 value |= (u32)bClinks << (nb->broadcastSelfBit + 1);
686
687 AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(node),
688 makePCIBusFromNode(node),
689 makePCIDeviceFromNode(node),
690 CPU_HTNB_FUNC_00,
691 REG_ROUTE0_0X40 + target*4), &value);
692#else
693 STOP_HERE;
694#endif /* HT_BUILD_NC_ONLY */
695}
696
697/**----------------------------------------------------------------------------------------
698 *
699 * static u32
700 * makeKey(u8 currentNode)
701 *
702 * Description:
703 * Private routine to northbridge code.
704 * Determine whether a node is compatible with the discovered configuration so
705 * far. Currently, that means the family, extended family of the new node are the
706 * same as the BSP's.
707 *
708 * Parameters:
709 * @param[in] u8 node = the node
710 * @param[out] u32 result = the key value
711 *
712 * ---------------------------------------------------------------------------------------
713 */
714static u32 makeKey(u8 node)
715{
716 u32 extFam, baseFam;
717 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
718 makePCIBusFromNode(node),
719 makePCIDeviceFromNode(node),
720 CPU_NB_FUNC_03,
721 REG_NB_CPUID_3XFC),
722 27, 20, &extFam);
723 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
724 makePCIBusFromNode(node),
725 makePCIDeviceFromNode(node),
726 CPU_NB_FUNC_03,
727 REG_NB_CPUID_3XFC),
728 11, 8, &baseFam);
729 return ((u32)(baseFam << 8) | extFam);
730}
731
732
733/**----------------------------------------------------------------------------------------
734 *
735 * BOOL
736 * isCompatible(u8 currentNode, cNorthBridge *nb)
737 *
738 * Description:
739 * Determine whether a node is compatible with the discovered configuration so
740 * far. Currently, that means the family, extended family of the new node are the
741 * same as the BSP's.
742 *
743 * Parameters:
744 * @param[in] u8 node = the node
745 * @param[in] cNorthBridge *nb = this northbridge
746 * @param[out] BOOL result = true: the new is compatible, false: it is not
747 *
748 * ---------------------------------------------------------------------------------------
749 */
750BOOL isCompatible(u8 node, cNorthBridge *nb)
751{
752 return (makeKey(node) == nb->compatibleKey);
753}
754
755/**----------------------------------------------------------------------------------------
756 *
757 * BOOL
758 * fam0fIsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
759 *
760 * Description:
761 * Get node capability and update the minimum supported system capability.
762 * Return whether the current configuration exceeds the capability.
763 *
764 * Parameters:
765 * @param[in] u8 node = the node
766 * @param[in,out] sMainData *pDat = sysMpCap (updated) and NodesDiscovered
767 * @param[in] cNorthBridge *nb = this northbridge
768 * @param[out] BOOL result = true: system is capable of current config.
769 * false: system is not capable of current config.
770 *
771 * ---------------------------------------------------------------------------------------
772 */
773BOOL fam0fIsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
774{
775#ifndef HT_BUILD_NC_ONLY
776 u32 temp;
777 u8 maxNodes;
778
779 ASSERT(node < nb->maxNodes);
780
781 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
782 makePCIBusFromNode(node),
783 makePCIDeviceFromNode(node),
784 CPU_NB_FUNC_03,
785 REG_NB_CAPABILITY_3XE8),
786 2, 1, &temp);
787 if (temp > 1)
788 {
789 maxNodes = 8;
790 } else {
791 if (temp == 1)
792 {
793 maxNodes = 2;
794 } else {
795 maxNodes = 1;
796 }
797 }
798 if (pDat->sysMpCap > maxNodes)
799 {
800 pDat->sysMpCap = maxNodes;
801 }
802 /* Note since sysMpCap is one based and NodesDiscovered is zero based, equal is false */
803 return (pDat->sysMpCap > pDat->NodesDiscovered);
804#else
805 return 1;
806#endif
807}
808
809/**----------------------------------------------------------------------------------------
810 *
811 * BOOL
812 * fam10IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
813 *
814 * Description:
815 * Get node capability and update the minimum supported system capability.
816 * Return whether the current configuration exceeds the capability.
817 *
818 * Parameters:
819 * @param[in] u8 node = the node
820 * @param[in,out] sMainData *pDat = sysMpCap (updated) and NodesDiscovered
821 * @param[in] cNorthBridge *nb = this northbridge
822 * @param[out] BOOL result = true: system is capable of current config.
823 * false: system is not capable of current config.
824 *
825 * ---------------------------------------------------------------------------------------
826 */
827BOOL fam10IsCapable(u8 node, sMainData *pDat, cNorthBridge *nb)
828{
829#ifndef HT_BUILD_NC_ONLY
830 u32 temp;
831 u8 maxNodes;
832
833 ASSERT(node < nb->maxNodes);
834
835 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
836 makePCIBusFromNode(node),
837 makePCIDeviceFromNode(node),
838 CPU_NB_FUNC_03,
839 REG_NB_CAPABILITY_3XE8),
840 18, 16, &temp);
841
842 if (temp != 0)
843 {
844 maxNodes = (1 << (~temp & 0x3)); /* That is, 1, 2, 4, or 8 */
845 }
846 else
847 {
848 maxNodes = 8;
849 }
850
851 if (pDat->sysMpCap > maxNodes)
852 {
853 pDat->sysMpCap = maxNodes;
854 }
855 /* Note since sysMpCap is one based and NodesDiscovered is zero based, equal is false */
856 return (pDat->sysMpCap > pDat->NodesDiscovered);
857#else
858 return 1;
859#endif
860}
861
862/**----------------------------------------------------------------------------------------
863 *
864 * void
865 * fam0fStopLink(u8 currentNode, u8 currentLink, cNorthBridge *nb)
866 *
867 * Description:
868 * Disable a cHT link on node by setting F0x[E4, C4, A4, 84][TransOff, EndOfChain]=1
869 *
870 * Parameters:
871 * @param[in] u8 node = the node this link is on
872 * @param[in] u8 link = the link to stop
873 * @param[in] cNorthBridge *nb = this northbridge
874 *
875 * ---------------------------------------------------------------------------------------
876 */
877void fam0fStopLink(u8 node, u8 link, cNorthBridge *nb)
878{
879#ifndef HT_BUILD_NC_ONLY
880 u32 temp;
881 SBDFO linkBase;
882
883 ASSERT((node < nb->maxNodes) && (link < nb->maxLinks));
884
885 linkBase = makeLinkBase(node, link);
886
887 /* Set TransOff, EndOfChain */
888 temp = 3;
889 setHtControlRegisterBits(linkBase + HTHOST_LINK_CONTROL_REG, 7, 6, &temp);
890#endif
891}
892
893/**----------------------------------------------------------------------------------------
894 *
895 * void
896 * commonVoid()
897 *
898 * Description:
899 * Nothing.
900 *
901 * Parameters:
902 * None.
903 *
904 * ---------------------------------------------------------------------------------------
905 */
906void commonVoid()
907{
908}
909
910/**----------------------------------------------------------------------------------------
911 *
912 * BOOL
913 * commonReturnFalse()
914 *
915 * Description:
916 * Return False.
917 *
918 * Parameters:
919 * @param[out] BOOL result = false
920 * ---------------------------------------------------------------------------------------
921 */
922BOOL commonReturnFalse()
923{
924 return 0;
925}
926
927/***************************************************************************
928 *** Non-coherent init code ***
929 *** Northbridge access routines ***
930 ***************************************************************************/
931
932/**----------------------------------------------------------------------------------------
933 *
934 * u8
935 * readSbLink(cNorthBridge *nb)
936 *
937 * Description:
938 * Return the link to the Southbridge
939 *
940 * Parameters:
941 * @param[in] cNorthBridge *nb = this northbridge
942 * @param[out] u8 results = the link to the southbridge
943 *
944 * ---------------------------------------------------------------------------------------
945 */
946u8 readSbLink(cNorthBridge *nb)
947{
948 u32 temp;
949 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(0),
950 makePCIBusFromNode(0),
951 makePCIDeviceFromNode(0),
952 CPU_HTNB_FUNC_00,
953 REG_UNIT_ID_0X64),
954 10, 8, &temp);
955 return (u8)temp;
956}
957
958/**----------------------------------------------------------------------------------------
959 *
960 * BOOL
961 * verifyLinkIsNonCoherent(u8 node, u8 link, cNorthBridge *nb)
962 *
963 * Description:
964 * Verify that the link is non-coherent, connected, and ready
965 *
966 * Parameters:
967 * @param[in] u8 node = the node that will be examined
968 * @param[in] u8 link = the Link on that node to examine
969 * @param[in] cNorthBridge *nb = this northbridge
970 * @param[out] u8 results = true - The link has the following status
971 * LinkCon=1, Link is connected
972 * InitComplete=1,Link initilization is complete
973 * NC=1, Link is coherent
974 * UniP-cLDT=0, Link is not Uniprocessor cLDT
975 * LinkConPend=0 Link connection is not pending
976 * false- The link has some other status
977 *
978 * ---------------------------------------------------------------------------------------
979 */
980BOOL verifyLinkIsNonCoherent(u8 node, u8 link, cNorthBridge *nb)
981{
982 u32 linkType;
983 SBDFO linkBase;
984
985 ASSERT((node < nb->maxNodes) && (link < nb->maxLinks));
986
987 linkBase = makeLinkBase(node, link);
988
989 /* FN0_98/A4/C4 = LDT Type Register */
990 AmdPCIRead(linkBase + HTHOST_LINK_TYPE_REG, &linkType);
991
992 /* Verify linkCon=1, InitComplete=1, NC=0, UniP-cLDT=0, LinkConPend=0 */
993 return (linkType & HTHOST_TYPE_MASK) == HTHOST_TYPE_NONCOHERENT;
994}
995
996/**----------------------------------------------------------------------------------------
997 *
998 * void
999 * ht3SetCFGAddrMap(u8 cfgMapIndex, u8 secBus, u8 subBus, u8 targetNode, u8 targetLink, sMainData *pDat, cNorthBridge *nb)
1000 *
1001 * Description:
1002 * Configure and enable config access to a non-coherent chain for the given bus range.
1003 *
1004 * Parameters:
1005 * @param[in] u8 cfgRouteIndex = the map entry to set
1006 * @param[in] u8 secBus = The secondary bus number to use
1007 * @param[in] u8 subBus = The subordinate bus number to use
1008 * @param[in] u8 targetNode = The node that shall be the recipient of the traffic
1009 * @param[in] u8 targetLink = The link that shall be the recipient of the traffic
1010 * @param[in] sMainData* pDat = our global state
1011 * @param[in] cNorthBridge *nb = this northbridge
1012 *
1013 * ---------------------------------------------------------------------------------------
1014 */
1015void ht3SetCFGAddrMap(u8 cfgMapIndex, u8 secBus, u8 subBus, u8 targetNode, u8 targetLink, sMainData *pDat, cNorthBridge *nb)
1016{
1017 u8 curNode;
1018 SBDFO linkBase;
1019 u32 temp;
1020
1021 linkBase = makeLinkBase(targetNode, targetLink);
1022
1023 ASSERT(secBus <= subBus);
1024 temp = secBus;
1025 AmdPCIWriteBits(linkBase + HTHOST_ISOC_REG, 15, 8, &temp);
1026
1027 /* For target link, note that rev F uses bits 9:8 and only with GH is bit 10
1028 * set to indicate a sublink. For node, we are currently not supporting Extended
1029 * routing tables.
1030 */
1031 temp = ((u32)subBus << 24) + ((u32)secBus << 16) + ((u32)targetLink << 8)
1032 + ((u32)targetNode << 4) + (u32)3;
1033 for (curNode = 0; curNode < pDat->NodesDiscovered+1; curNode++)
1034 AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(curNode),
1035 makePCIBusFromNode(curNode),
1036 makePCIDeviceFromNode(curNode),
1037 CPU_ADDR_FUNC_01,
1038 REG_ADDR_CONFIG_MAP0_1XE0 + 4*cfgMapIndex),
1039 &temp);
1040}
1041
1042/**----------------------------------------------------------------------------------------
1043 *
1044 * void
1045 * ht1SetCFGAddrMap(u8 cfgMapIndex, u8 secBus, u8 subBus, u8 targetNode, u8 targetLink, sMainData *pDat, cNorthBridge *nb)
1046 *
1047 * Description:
1048 * Configure and enable config access to a non-coherent chain for the given bus range.
1049 *
1050 * Parameters:
1051 * @param[in] u8 cfgMapIndex = the map entry to set
1052 * @param[in] u8 secBus = The secondary bus number to use
1053 * @param[in] u8 subBus = The subordinate bus number to use
1054 * @param[in] u8 targetNode = The node that shall be the recipient of the traffic
1055 * @param[in] u8 targetLink = The link that shall be the recipient of the traffic
1056 * @param[in] sMainData* pDat = our global state
1057 * @param[in] cNorthBridge *nb = this northbridge
1058 *
1059 * ---------------------------------------------------------------------------------------
1060 */
1061void ht1SetCFGAddrMap(u8 cfgMapIndex, u8 secBus, u8 subBus, u8 targetNode, u8 targetLink, sMainData *pDat, cNorthBridge *nb)
1062{
1063 u8 curNode;
1064 SBDFO linkBase;
1065 u32 temp;
1066
1067 linkBase = makeLinkBase(targetNode, targetLink);
1068
1069 ASSERT(secBus <= subBus);
1070 temp = secBus;
1071 AmdPCIWriteBits(linkBase + HTHOST_ISOC_REG, 15, 8, &temp);
1072
1073 temp = subBus;
1074 AmdPCIWriteBits(linkBase + HTHOST_ISOC_REG, 23, 16, &temp);
1075
1076 /* For target link, note that rev F uses bits 9:8 and only with GH is bit 10
1077 * set to indicate a sublink. For node, we are currently not supporting Extended
1078 * routing tables.
1079 */
1080 temp = ((u32)subBus << 24) + ((u32)secBus << 16) + ((u32)targetLink << 8)
1081 + ((u32)targetNode << 4) + (u32)3;
1082 for (curNode = 0; curNode < pDat->NodesDiscovered+1; curNode++)
1083 AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(curNode),
1084 makePCIBusFromNode(curNode),
1085 makePCIDeviceFromNode(curNode),
1086 CPU_ADDR_FUNC_01,
1087 REG_ADDR_CONFIG_MAP0_1XE0 + 4*cfgMapIndex),
1088 &temp);
1089}
1090
1091/***************************************************************************
1092 *** Link Optimization ***
1093 ***************************************************************************/
1094
1095/**----------------------------------------------------------------------------------------
1096 *
1097 * u8
1098 * convertBitsToWidth(u8 value, cNorthBridge *nb)
1099 *
1100 * Description:
1101 * Given the bits set in the register field, return the width it represents
1102 *
1103 * Parameters:
1104 * @param[in] u8 value = The bits for the register
1105 * @param[in] cNorthBridge *nb = this northbridge
1106 * @param[out] u8 results = The width
1107 *
1108 * ---------------------------------------------------------------------------------------
1109 */
1110u8 convertBitsToWidth(u8 value, cNorthBridge *nb)
1111{
1112 if (value == 1) {
1113 return 16;
1114 } else if (value == 0) {
1115 return 8;
1116 } else if (value == 5) {
1117 return 4;
1118 } else if (value == 4) {
1119 return 2;
1120 }
Marc Jonesaee07962008-07-16 21:09:31 +00001121 STOP_HERE; /* This is an error internal condition */
Marc Jones8ae8c882007-12-19 01:32:08 +00001122}
1123
1124/**----------------------------------------------------------------------------------------
1125 *
1126 * u8
1127 * convertWidthToBits(u8 value, cNorthBridge *nb)
1128 *
1129 * Description:
1130 * Translate a desired width setting to the bits to set in the register field
1131 *
1132 * Parameters:
1133 * @param[in] u8 value = The width
1134 * @param[in] cNorthBridge *nb = this northbridge
1135 * @param[out] u8 results = The bits for the register
1136 *
1137 * ---------------------------------------------------------------------------------------
1138 */
1139u8 convertWidthToBits(u8 value, cNorthBridge *nb)
1140{
1141 if (value == 16) {
1142 return 1;
1143 } else if (value == 8) {
1144 return 0;
1145 } else if (value == 4) {
1146 return 5;
1147 } else if (value == 2) {
1148 return 4;
1149 }
Marc Jonesaee07962008-07-16 21:09:31 +00001150 STOP_HERE; /* This is an internal error condition */
Marc Jones8ae8c882007-12-19 01:32:08 +00001151}
1152
1153/**----------------------------------------------------------------------------------------
1154 *
1155 * u16
1156 * ht1NorthBridgeFreqMask(u8 NodeID, cNorthBridge *nb)
1157 *
1158 * Description:
1159 * Return a mask that eliminates HT frequencies that cannot be used due to a slow
1160 * northbridge frequency.
1161 *
1162 * Parameters:
1163 * @param[in] u8 node = Result could (later) be for a specific node
1164 * @param[in] cNorthBridge *nb = this northbridge
1165 * @param[out] u16 results = Frequency mask
1166 *
1167 * ---------------------------------------------------------------------------------------
1168 */
1169u16 ht1NorthBridgeFreqMask(u8 node, cNorthBridge *nb)
1170{
1171 /* only up to HT1 speeds */
1172 return (HT_FREQUENCY_LIMIT_HT1_ONLY);
1173}
1174
1175/**----------------------------------------------------------------------------------------
1176 *
1177 * u16
1178 * fam10NorthBridgeFreqMask(u8 NodeID, cNorthBridge *nb)
1179 *
1180 * Description:
1181 * Return a mask that eliminates HT frequencies that cannot be used due to a slow
1182 * northbridge frequency.
1183 *
1184 * Parameters:
1185 * @param[in] u8 node = Result could (later) be for a specific node
1186 * @param[in] cNorthBridge *nb = this northbridge
1187 * @param[out] u16 results = Frequency mask
1188 *
1189 * ---------------------------------------------------------------------------------------
1190 */
1191u16 fam10NorthBridgeFreqMask(u8 node, cNorthBridge *nb)
1192{
1193 u8 nbCOF;
1194 u16 supported;
1195
1196 nbCOF = getMinNbCOF();
1197 /*
1198 * nbCOF is minimum northbridge speed in hundreds of MHz.
1199 * HT can not go faster than the minimum speed of the northbridge.
1200 */
1201 if ((nbCOF >= 6) && (nbCOF <= 26))
1202 {
1203 /* Convert frequency to bit and all less significant bits,
1204 * by setting next power of 2 and subtracting 1.
1205 */
1206 supported = ((u16)1 << ((nbCOF >> 1) + 2)) - 1;
1207 }
1208 else if (nbCOF > 26)
1209 {
1210 supported = HT_FREQUENCY_LIMIT_2600M;
1211 }
1212 /* unlikely cases, but include as a defensive measure, also avoid trick above */
1213 else if (nbCOF == 4)
1214 {
1215 supported = HT_FREQUENCY_LIMIT_400M;
1216 }
1217 else if (nbCOF == 2)
1218 {
1219 supported = HT_FREQUENCY_LIMIT_200M;
1220 }
1221 else
1222 {
1223 STOP_HERE;
1224 supported = HT_FREQUENCY_LIMIT_200M;
1225 }
1226
1227 return (fixEarlySampleFreqCapability(supported));
1228}
1229
1230/**----------------------------------------------------------------------------------------
1231 *
1232 * void
1233 * gatherLinkData(sMainData *pDat, cNorthBridge *nb)
1234 *
1235 * Description:
1236 * For all discovered links, populate the port list with the frequency and width
1237 * capabilities.
1238 *
1239 * Parameters:
1240 * @param[in,out] sMainData* pDat = our global state, port list
1241 * @param[in] cNorthBridge *nb = this northbridge
1242 *
1243 * ---------------------------------------------------------------------------------------
1244 */
1245void gatherLinkData(sMainData *pDat, cNorthBridge *nb)
1246{
1247 u8 i;
1248 SBDFO linkBase;
1249 u32 temp;
1250
1251 for (i = 0; i < pDat->TotalLinks*2; i++)
1252 {
1253 if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU)
1254 {
1255 linkBase = makeLinkBase(pDat->PortList[i].NodeID, pDat->PortList[i].Link);
1256
1257 pDat->PortList[i].Pointer = linkBase;
1258
1259 AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 22, 20, &temp);
1260 pDat->PortList[i].PrvWidthOutCap = convertBitsToWidth((u8)temp, pDat->nb);
1261
1262 AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 18, 16, &temp);
1263 pDat->PortList[i].PrvWidthInCap = convertBitsToWidth((u8)temp, pDat->nb);
1264
1265 AmdPCIReadBits(linkBase + HTHOST_FREQ_REV_REG, 31, 16, &temp);
1266 pDat->PortList[i].PrvFrequencyCap = (u16)temp & 0x7FFF
Marc Jonesaee07962008-07-16 21:09:31 +00001267 & nb->northBridgeFreqMask(pDat->PortList[i].NodeID, pDat->nb); /* Mask off bit 15, reserved value */
Marc Jones8ae8c882007-12-19 01:32:08 +00001268 }
1269 else
1270 {
1271 linkBase = pDat->PortList[i].Pointer;
1272 if (pDat->PortList[i].Link == 1)
1273 linkBase += HTSLAVE_LINK01_OFFSET;
1274
1275 AmdPCIReadBits(linkBase + HTSLAVE_LINK_CONTROL_0_REG, 22, 20, &temp);
1276 pDat->PortList[i].PrvWidthOutCap = convertBitsToWidth((u8)temp, pDat->nb);
1277
1278 AmdPCIReadBits(linkBase + HTSLAVE_LINK_CONTROL_0_REG, 18, 16, &temp);
1279 pDat->PortList[i].PrvWidthInCap = convertBitsToWidth((u8)temp, pDat->nb);
1280
1281 AmdPCIReadBits(linkBase + HTSLAVE_FREQ_REV_0_REG, 31, 16, &temp);
1282 pDat->PortList[i].PrvFrequencyCap = (u16)temp;
1283
1284 if (pDat->HtBlock->AMD_CB_DeviceCapOverride)
1285 {
1286 linkBase &= 0xFFFFF000;
1287 AmdPCIRead(linkBase, &temp);
1288
1289 pDat->HtBlock->AMD_CB_DeviceCapOverride(
1290 pDat->PortList[i].NodeID,
1291 pDat->PortList[i].HostLink,
1292 pDat->PortList[i].HostDepth,
1293 (u8)SBDFO_SEG(pDat->PortList[i].Pointer),
1294 (u8)SBDFO_BUS(pDat->PortList[i].Pointer),
1295 (u8)SBDFO_DEV(pDat->PortList[i].Pointer),
1296 temp,
1297 pDat->PortList[i].Link,
1298 &(pDat->PortList[i].PrvWidthInCap),
1299 &(pDat->PortList[i].PrvWidthOutCap),
1300 &(pDat->PortList[i].PrvFrequencyCap));
1301 }
1302 }
1303 }
1304}
1305
1306/**----------------------------------------------------------------------------------------
1307 *
1308 * void
1309 * setLinkData(sMainData *pDat, cNorthBridge *nb)
1310 *
1311 * Description:
1312 * Change the hardware state for all links according to the now optimized data in the
1313 * port list data structure.
1314 *
1315 * Parameters:
1316 * @param[in] sMainData* pDat = our global state, port list
1317 * @param[in] cNorthBridge *nb = this northbridge
1318 *
1319 * ---------------------------------------------------------------------------------------
1320 */
1321void setLinkData(sMainData *pDat, cNorthBridge *nb)
1322{
1323 u8 i;
1324 SBDFO linkBase;
1325 u32 temp, widthin, widthout, bits;
1326
1327 for (i = 0; i < pDat->TotalLinks*2; i++)
1328 {
1329
1330 ASSERT(pDat->PortList[i&0xFE].SelWidthOut == pDat->PortList[(i&0xFE)+1].SelWidthIn);
1331 ASSERT(pDat->PortList[i&0xFE].SelWidthIn == pDat->PortList[(i&0xFE)+1].SelWidthOut);
1332 ASSERT(pDat->PortList[i&0xFE].SelFrequency == pDat->PortList[(i&0xFE)+1].SelFrequency);
1333
1334 if (pDat->PortList[i].SelRegang)
1335 {
1336 ASSERT(pDat->PortList[i].Type == PORTLIST_TYPE_CPU);
1337 ASSERT(pDat->PortList[i].Link < 4);
1338 temp = 1;
1339 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID),
1340 makePCIBusFromNode(pDat->PortList[i].NodeID),
1341 makePCIDeviceFromNode(pDat->PortList[i].NodeID),
1342 CPU_HTNB_FUNC_00,
1343 REG_HT_LINK_EXT_CONTROL0_0X170 + 4*pDat->PortList[i].Link),
1344 0, 0, &temp);
1345 }
1346
1347 if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU)
1348 {
1349 if (pDat->HtBlock->AMD_CB_OverrideCpuPort)
1350 pDat->HtBlock->AMD_CB_OverrideCpuPort(pDat->PortList[i].NodeID,
1351 pDat->PortList[i].Link,
1352 &(pDat->PortList[i].SelWidthIn),
1353 &(pDat->PortList[i].SelWidthOut),
1354 &(pDat->PortList[i].SelFrequency));
1355 }
1356 else
1357 {
1358 if (pDat->HtBlock->AMD_CB_OverrideDevicePort)
1359 pDat->HtBlock->AMD_CB_OverrideDevicePort(pDat->PortList[i].NodeID,
1360 pDat->PortList[i].HostLink,
1361 pDat->PortList[i].HostDepth,
1362 pDat->PortList[i].Link,
1363 &(pDat->PortList[i].SelWidthIn),
1364 &(pDat->PortList[i].SelWidthOut),
1365 &(pDat->PortList[i].SelFrequency));
1366 }
1367
1368 linkBase = pDat->PortList[i].Pointer;
1369 if ((pDat->PortList[i].Type == PORTLIST_TYPE_IO) && (pDat->PortList[i].Link == 1))
1370 linkBase += HTSLAVE_LINK01_OFFSET;
1371
1372 /* Some IO devices don't work properly when setting widths, so write them in a single operation,
1373 * rather than individually.
1374 */
1375 widthout = convertWidthToBits(pDat->PortList[i].SelWidthOut, pDat->nb);
1376 ASSERT(widthout == 1 || widthout == 0 || widthout == 5 || widthout == 4);
1377 widthin = convertWidthToBits(pDat->PortList[i].SelWidthIn, pDat->nb);
1378 ASSERT(widthin == 1 || widthin == 0 || widthin == 5 || widthin == 4);
1379
1380 temp = (widthin & 7) | ((widthout & 7) << 4);
1381 setHtControlRegisterBits(linkBase + HTHOST_LINK_CONTROL_REG, 31, 24, &temp);
1382
1383 temp = pDat->PortList[i].SelFrequency;
1384 if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU)
1385 {
1386 ASSERT((temp >= HT_FREQUENCY_600M && temp <= HT_FREQUENCY_2600M)
1387 || (temp == HT_FREQUENCY_200M) || (temp == HT_FREQUENCY_400M));
1388 AmdPCIWriteBits(linkBase + HTHOST_FREQ_REV_REG, 11, 8, &temp);
Marc Jonesaee07962008-07-16 21:09:31 +00001389 if (temp > HT_FREQUENCY_1000M) /* Gen1 = 200Mhz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz */
Marc Jones8ae8c882007-12-19 01:32:08 +00001390 {
1391 /* Enable for Gen3 frequencies */
1392 temp = 1;
1393 }
1394 else
1395 {
1396 /* Disable for Gen1 frequencies */
1397 temp = 0;
1398 }
1399 /* HT3 retry mode enable / disable */
1400 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID),
1401 makePCIBusFromNode(pDat->PortList[i].NodeID),
1402 makePCIDeviceFromNode(pDat->PortList[i].NodeID),
1403 CPU_HTNB_FUNC_00,
1404 REG_HT_LINK_RETRY0_0X130 + 4*pDat->PortList[i].Link),
1405 0, 0, &temp);
1406 /* and Scrambling enable / disable */
1407 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID),
1408 makePCIBusFromNode(pDat->PortList[i].NodeID),
1409 makePCIDeviceFromNode(pDat->PortList[i].NodeID),
1410 CPU_HTNB_FUNC_00,
1411 REG_HT_LINK_EXT_CONTROL0_0X170 + 4*pDat->PortList[i].Link),
1412 3, 3, &temp);
1413 }
1414 else
1415 {
1416 SBDFO currentPtr;
1417 BOOL isFound;
1418
1419 ASSERT(temp <= HT_FREQUENCY_2600M);
1420 /* Write the frequency setting */
1421 AmdPCIWriteBits(linkBase + HTSLAVE_FREQ_REV_0_REG, 11, 8, &temp);
1422
1423 /* Handle additional HT3 frequency requirements, if needed,
1424 * or clear them if switching down to ht1 on a warm reset.
1425 * Gen1 = 200Mhz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz
1426 *
1427 * Even though we assert if debugging, we need to check that the capability was found
1428 * always, since this is an unknown hardware device, also we are taking
1429 * unqualified frequency from the call backs
1430 * (could be trying to do ht3 on an ht1 IO device).
1431 */
1432
1433 if (temp > HT_FREQUENCY_1000M)
1434 {
1435 /* Enabling features if gen 3 */
1436 bits = 1;
1437 }
1438 else
1439 {
1440 /* Disabling features if gen 1 */
1441 bits = 0;
1442 }
1443
1444 /* Retry Enable */
1445 isFound = FALSE;
1446 currentPtr = linkBase & (u32)0xFFFFF000; /* Set PCI Offset to 0 */
1447 do
1448 {
1449 AmdPCIFindNextCap(&currentPtr);
1450 if (currentPtr != ILLEGAL_SBDFO)
1451 {
1452 AmdPCIRead(currentPtr, &temp);
1453 /* HyperTransport Retry Capability? */
1454 if (IS_HT_RETRY_CAPABILITY(temp))
1455 {
1456 ASSERT(pDat->PortList[i].Link < 2);
1457 AmdPCIWriteBits(currentPtr + HTRETRY_CONTROL_REG,
1458 pDat->PortList[i].Link*16,
1459 pDat->PortList[i].Link*16,
1460 &bits);
1461 isFound = TRUE;
1462 }
1463 /* Some other capability, keep looking */
1464 }
1465 else
1466 {
1467 /* If we are turning it off, that may mean the device was only ht1 capable,
1468 * so don't complain that we can't do it.
1469 */
1470 if (bits != 0)
1471 {
1472 if (pDat->HtBlock->AMD_CB_EventNotify)
1473 {
Marc Jones212486e2008-07-17 19:50:37 +00001474 sHtEventOptRequiredCap evt;
1475 evt.eSize = sizeof(sHtEventOptRequiredCap);
1476 evt.node = pDat->PortList[i].NodeID;
1477 evt.link = pDat->PortList[i].HostLink;
1478 evt.depth = pDat->PortList[i].HostDepth;
Marc Jones8ae8c882007-12-19 01:32:08 +00001479
1480 pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_WARNING,
1481 HT_EVENT_OPT_REQUIRED_CAP_RETRY,
1482 (u8 *)&evt);
1483 }
1484 STOP_HERE;
1485 }
1486 isFound = TRUE;
1487 }
1488 } while (!isFound);
1489
1490 /* Scrambling enable */
1491 isFound = FALSE;
1492 currentPtr = linkBase & (u32)0xFFFFF000; /* Set PCI Offset to 0 */
1493 do
1494 {
1495 AmdPCIFindNextCap(&currentPtr);
1496 if (currentPtr != ILLEGAL_SBDFO)
1497 {
1498 AmdPCIRead(currentPtr, &temp);
1499 /* HyperTransport Gen3 Capability? */
1500 if (IS_HT_GEN3_CAPABILITY(temp))
1501 {
1502 ASSERT(pDat->PortList[i].Link < 2);
1503 AmdPCIWriteBits((currentPtr +
1504 HTGEN3_LINK_TRAINING_0_REG +
1505 pDat->PortList[i].Link*HTGEN3_LINK01_OFFSET),
1506 3, 3, &bits);
1507 isFound = TRUE;
1508 }
1509 /* Some other capability, keep looking */
1510 }
1511 else
1512 {
1513 /* If we are turning it off, that may mean the device was only ht1 capable,
1514 * so don't complain that we can't do it.
1515 */
1516 if (bits != 0)
1517 {
1518 if (pDat->HtBlock->AMD_CB_EventNotify)
1519 {
Marc Jones212486e2008-07-17 19:50:37 +00001520 sHtEventOptRequiredCap evt;
1521 evt.eSize = sizeof(sHtEventOptRequiredCap);
1522 evt.node = pDat->PortList[i].NodeID;
1523 evt.link = pDat->PortList[i].HostLink;
1524 evt.depth = pDat->PortList[i].HostDepth;
Marc Jones8ae8c882007-12-19 01:32:08 +00001525
1526 pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_WARNING,
1527 HT_EVENT_OPT_REQUIRED_CAP_GEN3,
1528 (u8 *)&evt);
1529 }
1530 STOP_HERE;
1531 }
1532 isFound = TRUE;
1533 }
1534 } while (!isFound);
1535 }
1536 }
1537}
1538
1539/**----------------------------------------------------------------------------------------
1540 *
1541 * void
1542 * fam0fWriteHTLinkCmdBufferAlloc(u8 node, u8 link, u8 req, u8 preq, u8 rsp, u8 prb)
1543 *
1544 * Description:
1545 * Set the command buffer allocations in the buffer count register for the node and link.
1546 * The command buffer settings in the low 16 bits are the same on both
1547 * family 10h and family 0fh northbridges.
1548 *
1549 * Parameters:
1550 * @param[in] u8 node = The node to set allocations on
1551 * @param[in] u8 link = the link to set allocations on
1552 * @param[in] u8 req = non-posted Request Command Buffers
1553 * @param[in] u8 preq = Posted Request Command Buffers
1554 * @param[in] u8 rsp = Response Command Buffers
1555 * @param[in] u8 prb = Probe Command Buffers
1556 *
1557 * ---------------------------------------------------------------------------------------
1558 */
1559static void fam0fWriteHTLinkCmdBufferAlloc(u8 node, u8 link, u8 req, u8 preq, u8 rsp, u8 prb)
1560{
1561 u32 temp;
1562 SBDFO currentPtr;
1563
1564 currentPtr = makeLinkBase(node, link);
1565 currentPtr += HTHOST_BUFFER_COUNT_REG;
1566
1567 /* non-posted Request Command Buffers */
1568 temp = req;
1569 AmdPCIWriteBits(currentPtr, 3, 0, &temp);
1570 /* Posted Request Command Buffers */
1571 temp = preq;
1572 AmdPCIWriteBits(currentPtr, 7, 4, &temp);
1573 /* Response Command Buffers */
1574 temp = rsp;
1575 AmdPCIWriteBits(currentPtr, 11, 8, &temp);
1576 /* Probe Command Buffers */
1577 temp = prb;
1578 AmdPCIWriteBits(currentPtr, 15, 12, &temp);
1579}
1580
1581/**----------------------------------------------------------------------------------------
1582 *
1583 * void
1584 * fam0fWriteHTLinkDatBufferAlloc(u8 node, u8 link, u8 reqD, u8 preqD, u8 rspD)
1585 *
1586 * Description:
1587 * Set the data buffer allocations in the buffer count register for the node and link.
1588 * The command buffer settings in the high 16 bits are not the same on both
1589 * family 10h and family 0fh northbridges.
1590 *
1591 * Parameters:
1592 * @param[in] u8 node = The node to set allocations on
1593 * @param[in] u8 link = the link to set allocations on
1594 * @param[in] u8 reqD = non-posted Request Data Buffers
1595 * @param[in] u8 preqD = Posted Request Data Buffers
1596 * @param[in] u8 rspD = Response Data Buffers
1597 *
1598 * ---------------------------------------------------------------------------------------
1599 */
1600static void fam0fWriteHTLinkDatBufferAlloc(u8 node, u8 link, u8 reqD, u8 preqD, u8 rspD)
1601{
1602 u32 temp;
1603 SBDFO currentPtr;
1604
1605 currentPtr = makeLinkBase(node, link);
1606 currentPtr += HTHOST_BUFFER_COUNT_REG;
1607
1608 /* Request Data Buffers */
1609 temp = reqD;
1610 AmdPCIWriteBits(currentPtr, 18, 16, &temp);
1611 /* Posted Request Data Buffers */
1612 temp = preqD;
1613 AmdPCIWriteBits(currentPtr, 22, 20, &temp);
1614 /* Response Data Buffers */
1615 temp = rspD;
1616 AmdPCIWriteBits(currentPtr, 26, 24, &temp);
1617}
1618
1619/**----------------------------------------------------------------------------------------
1620 *
1621 * void
1622 * ht3WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb)
1623 *
1624 * Description:
1625 * Set the traffic distribution register for the links provided.
1626 *
1627 * Parameters:
1628 * @param[in] u32 links01 = coherent links from node 0 to 1
1629 * @param[in] u32 links10 = coherent links from node 1 to 0
1630 * @param[in] cNorthBridge* nb = this northbridge
1631 *
1632 * ---------------------------------------------------------------------------------------
1633 */
1634void ht3WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb)
1635{
1636#ifndef HT_BUILD_NC_ONLY
1637 u32 temp;
1638
1639 /* Node 0 */
1640 /* DstLnk */
1641 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(0),
1642 makePCIBusFromNode(0),
1643 makePCIDeviceFromNode(0),
1644 CPU_HTNB_FUNC_00,
1645 REG_HT_TRAFFIC_DIST_0X164),
1646 23, 16, &links01);
1647 /* DstNode = 1, cHTPrbDistEn=1, cHTRspDistEn=1, cHTReqDistEn=1 */
1648 temp = 0x0107;
1649 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(0),
1650 makePCIBusFromNode(0),
1651 makePCIDeviceFromNode(0),
1652 CPU_HTNB_FUNC_00,
1653 REG_HT_TRAFFIC_DIST_0X164),
1654 15, 0, &temp);
1655
1656 /* Node 1 */
1657 /* DstLnk */
1658 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(1),
1659 makePCIBusFromNode(1),
1660 makePCIDeviceFromNode(1),
1661 CPU_HTNB_FUNC_00,
1662 REG_HT_TRAFFIC_DIST_0X164),
1663 23, 16, &links10);
1664 /* DstNode = 0, cHTPrbDistEn=1, cHTRspDistEn=1, cHTReqDistEn=1 */
1665 temp = 0x0007;
1666 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(1),
1667 makePCIBusFromNode(1),
1668 makePCIDeviceFromNode(1),
1669 CPU_HTNB_FUNC_00,
1670 REG_HT_TRAFFIC_DIST_0X164),
1671 15, 0, &temp);
1672#endif /* HT_BUILD_NC_ONLY */
1673}
1674
1675/**----------------------------------------------------------------------------------------
1676 *
1677 * void
1678 * ht1WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb)
1679 *
1680 * Description:
1681 * Traffic distribution is more complex in this case as the routing table must be
1682 * adjusted to use one link for requests and the other for responses. Also,
1683 * perform the buffer tunings on the links required for this config.
1684 *
1685 * Parameters:
1686 * @param[in] u32 links01 = coherent links from node 0 to 1
1687 * @param[in] u32 links01 = coherent links from node 1 to 0
1688 * @param[in] cNorthBridge* nb = this northbridge
1689 *
1690 * ---------------------------------------------------------------------------------------
1691 */
1692void ht1WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb)
1693{
1694#ifndef HT_BUILD_NC_ONLY
1695 u32 route01, route10;
1696 u8 req0, req1, rsp0, rsp1, nclink;
1697
1698 /*
1699 * Get the current request route for 0->1 and 1->0. This will indicate which of the links
1700 * in links01 are connected to which links in links10. Since we have to route to distribute
1701 * traffic, we need to know that. The link used by htinit will become the request, probe link.
1702 * the other link will be used for responses.
1703 */
1704
1705 /* Get the routes, and hang on to them, we will write them back updated. */
1706 AmdPCIRead(MAKE_SBDFO(makePCISegmentFromNode(0),
1707 makePCIBusFromNode(0),
1708 makePCIDeviceFromNode(0),
1709 CPU_HTNB_FUNC_00,
1710 REG_ROUTE1_0X44),
1711 &route01);
1712 AmdPCIRead(MAKE_SBDFO(makePCISegmentFromNode(1),
1713 makePCIBusFromNode(1),
1714 makePCIDeviceFromNode(1),
1715 CPU_HTNB_FUNC_00,
1716 REG_ROUTE0_0X40),
1717 &route10);
1718
1719 /* Convert the request routes to a link number. Note "0xE" is ht1 nb specific.
1720 * Find the response link numbers.
1721 */
1722 ASSERT((route01 & 0xE) && (route10 & 0xE)); /* no route! error! */
1723 req0 = (u8)AmdBitScanReverse((route01 & 0xE)) - 1;
1724 req1 = (u8)AmdBitScanReverse((route10 & 0xE)) - 1;
1725 /* Now, find the other link for the responses */
1726 rsp0 = (u8)AmdBitScanReverse((links01 & ~((u32)1 << req0)));
1727 rsp1 = (u8)AmdBitScanReverse((links10 & ~((u32)1 << req1)));
1728
1729 /* ht1 nb restriction, must have exactly two links */
1730 ASSERT(((((links01 & ~((u32)1 << req0)) & ~((u32)1 << rsp0))) == 0)
1731 && ((((links10 & ~((u32)1 << req1)) & ~((u32)1 << rsp1))) == 0));
1732
1733 route01 = (route01 & ~0x0E00) | ((u32)0x0100<<(rsp0 + 1));
1734 route10 = (route10 & ~0x0E00) | ((u32)0x0100<<(rsp1 + 1));
1735
1736 AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(0),
1737 makePCIBusFromNode(0),
1738 makePCIDeviceFromNode(0),
1739 CPU_HTNB_FUNC_00,
1740 REG_ROUTE1_0X44),
1741 &route01);
1742
1743 AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(1),
1744 makePCIBusFromNode(1),
1745 makePCIDeviceFromNode(1),
1746 CPU_HTNB_FUNC_00,
1747 REG_ROUTE0_0X40),
1748 &route10);
1749
1750 /* While we otherwise do buffer tunings elsewhere, for the dual cHT DP case with
1751 * ht1 northbridges like family 0Fh, do the tunings here where we have all the
1752 * link and route info at hand and don't need to recalculate it.
1753 */
1754
1755 /* Node 0, Request / Probe Link (note family F only has links < 4) */
1756 fam0fWriteHTLinkCmdBufferAlloc(0, req0, 6, 3, 1, 6);
1757 fam0fWriteHTLinkDatBufferAlloc(0, req0, 4, 3, 1);
1758 /* Node 0, Response Link (note family F only has links < 4) */
1759 fam0fWriteHTLinkCmdBufferAlloc(0, rsp0, 1, 0, 15, 0);
1760 fam0fWriteHTLinkDatBufferAlloc(0, rsp0, 1, 1, 6);
1761 /* Node 1, Request / Probe Link (note family F only has links < 4) */
1762 fam0fWriteHTLinkCmdBufferAlloc(1, req1, 6, 3, 1, 6);
1763 fam0fWriteHTLinkDatBufferAlloc(1, req1, 4, 3, 1);
1764 /* Node 1, Response Link (note family F only has links < 4) */
1765 fam0fWriteHTLinkCmdBufferAlloc(1, rsp1, 1, 0, 15, 0);
1766 fam0fWriteHTLinkDatBufferAlloc(1, rsp1, 1, 1, 6);
1767
1768 /* Node 0, is the third link non-coherent? */
1769 nclink = (u8)AmdBitScanReverse(((u8)0x07 & ~((u32)1 << req0) & ~((u32)1 << rsp0)));
1770 if (nb->verifyLinkIsNonCoherent(0, nclink, nb))
1771 {
1772 fam0fWriteHTLinkCmdBufferAlloc(0, nclink, 6, 5, 2, 0);
1773 }
1774
1775 /* Node 1, is the third link non-coherent? */
1776 nclink = (u8)AmdBitScanReverse(((u8)0x07 & ~((u32)1 << req1) & ~((u32)1 << rsp1)));
1777 if (nb->verifyLinkIsNonCoherent(1, nclink, nb))
1778 {
1779 fam0fWriteHTLinkCmdBufferAlloc(1, nclink, 6, 5, 2, 0);
1780 }
1781#endif /* HT_BUILD_NC_ONLY */
1782}
1783
1784/**----------------------------------------------------------------------------------------
1785 *
1786 * void
1787 * fam0fBufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
1788 *
1789 * Description:
1790 * Buffer tunings are inherently northbridge specific. Check for specific configs
1791 * which require adjustments and apply any standard workarounds to this node.
1792 *
1793 * Parameters:
1794 * @param[in] u8 node = the node to
1795 * @param[in] sMainData *pDat = coherent links from node 0 to 1
1796 * @param[in] cNorthBridge* nb = this northbridge
1797 *
1798 * ---------------------------------------------------------------------------------------
1799 */
1800void fam0fBufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
1801{
1802#ifndef HT_BUILD_NC_ONLY
1803 u8 i;
1804 u32 temp;
1805 SBDFO currentPtr;
1806
1807 ASSERT(node < nb->maxNodes);
1808
1809 /* Fix the FIFO pointer register before changing speeds */
1810 currentPtr = MAKE_SBDFO(makePCISegmentFromNode(node),
1811 makePCIBusFromNode(node),
1812 makePCIDeviceFromNode(node),
1813 CPU_NB_FUNC_03,
1814 REG_NB_FIFOPTR_3XDC);
1815 for (i=0; i < nb->maxLinks; i++)
1816 {
1817 temp = 0;
1818 if (nb->verifyLinkIsCoherent(node, i, nb))
1819 {
1820 temp = 0x26;
1821 ASSERT(i<3);
1822 AmdPCIWriteBits(currentPtr, 8*i + 5, 8*i, &temp);
1823 }
1824 else
1825 {
1826 if (nb->verifyLinkIsNonCoherent(node, i, nb))
1827 {
1828 temp = 0x25;
1829 ASSERT(i<3);
1830 AmdPCIWriteBits(currentPtr, 8*i + 5, 8*i, &temp);
1831 }
1832 }
1833 }
1834 /*
1835 * 8P Buffer tuning.
1836 * Either apply the BKDG tunings or, if applicable, apply the more restrictive errata 153
1837 * workaround.
1838 * If 8 nodes, Check this node for 'inner' or 'outer'.
1839 * Tune each link based on coherent or non-coherent
1840 */
1841 if (pDat->NodesDiscovered >= 6)
1842 {
1843 u8 j;
1844 BOOL isOuter;
1845 BOOL isErrata153;
1846
1847 /* This is for family 0Fh, so assuming dual core max then 7 or 8 nodes are required
1848 * to be in the situation of 14 or more cores. We checked nodes above, cross check
1849 * that the number of cores is 14 or more. We want both 14 cores with at least 7 or 8 nodes
1850 * not one condition alone, to apply the errata 153 workaround. Otherwise, 7 or 8 rev F
1851 * nodes use the BKDG tuning.
1852 */
1853
1854 isErrata153 = 0;
1855
1856 AmdPCIReadBits (MAKE_SBDFO(makePCISegmentFromNode(0),
1857 makePCIBusFromNode(0),
1858 makePCIDeviceFromNode(0),
1859 CPU_HTNB_FUNC_00,
1860 REG_NODE_ID_0X60),
1861 19, 16, &temp);
1862
1863 if (temp >= 14)
1864 {
1865 /* Check whether we need to do errata 153 tuning or BKDG tuning.
1866 * Errata 153 applies to JH-1, JH-2 and older. It is fixed in JH-3
1867 * (and, one assumes, from there on).
1868 */
1869 for (i=0; i < (pDat->NodesDiscovered +1); i++)
1870 {
1871 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(i),
1872 makePCIBusFromNode(i),
1873 makePCIDeviceFromNode(i),
1874 CPU_NB_FUNC_03,
1875 REG_NB_CPUID_3XFC),
1876 7, 0, &temp);
1877 if (((u8)temp & ~0x40) < 0x13)
1878 {
1879 isErrata153 = 1;
1880 break;
1881 }
1882 }
1883 }
1884
1885 for (i=0; i < CPU_ADDR_NUM_CONFIG_MAPS; i++)
1886 {
1887 isOuter = FALSE;
1888 /* Check for outer node by scanning the config maps on node 0 for one
1889 * which is assigned to this node.
1890 */
1891 currentPtr = MAKE_SBDFO(makePCISegmentFromNode(0),
1892 makePCIBusFromNode(0),
1893 makePCIDeviceFromNode(0),
1894 CPU_ADDR_FUNC_01,
1895 REG_ADDR_CONFIG_MAP0_1XE0 + (4 * i));
1896 AmdPCIReadBits (currentPtr, 1, 0, &temp);
1897 /* Make sure this config map is valid, if it is it will be enabled for read/write */
1898 if (temp == 3)
1899 {
1900 /* It's valid, get the node (that node is an outer node) */
1901 AmdPCIReadBits (currentPtr, 6, 4, &temp);
1902 /* Is the node we're working on now? */
1903 if (node == (u8)temp)
1904 {
1905 /* This is an outer node. Tune it appropriately. */
1906 for (j=0; j < nb->maxLinks; j++)
1907 {
1908 if (isErrata153)
1909 {
1910 if (nb->verifyLinkIsCoherent(node, j, nb))
1911 {
1912 fam0fWriteHTLinkCmdBufferAlloc(node, j, 1, 1, 6, 4);
1913 }
1914 else
1915 {
1916 if (nb->verifyLinkIsNonCoherent(node, j, nb))
1917 {
1918 fam0fWriteHTLinkCmdBufferAlloc(node, j, 5, 4, 1, 0);
1919 }
1920 }
1921 }
1922 else
1923 {
1924 if (nb->verifyLinkIsCoherent(node, j, nb))
1925 {
1926 fam0fWriteHTLinkCmdBufferAlloc(node, j, 1, 1, 8, 5);
1927 }
1928 }
1929 }
1930 /*
1931 * SRI to XBAR Buffer Counts are correct for outer node at power on defaults.
1932 */
1933 isOuter = TRUE;
1934 break;
1935 }
1936 }
1937 /* We fill config maps in ascending order, so if we didn't use this one, we're done. */
1938 else break;
1939 }
1940 if (!isOuter)
1941 {
1942 if (isErrata153)
1943 {
1944 /* Tuning for inner node coherent links */
1945 for (j=0; j < nb->maxLinks; j++)
1946 {
1947 if (nb->verifyLinkIsCoherent(node, j, nb))
1948 {
1949 fam0fWriteHTLinkCmdBufferAlloc(node, j, 2, 1, 5, 4);
1950 }
1951
1952 }
1953 /* SRI to XBAR Buffer Count for inner nodes, zero DReq and DPReq */
1954 temp = 0;
1955 AmdPCIWriteBits (MAKE_SBDFO(makePCISegmentFromNode(node),
1956 makePCIBusFromNode(node),
1957 makePCIDeviceFromNode(node),
1958 CPU_NB_FUNC_03,
1959 REG_NB_SRI_XBAR_BUF_3X70),
1960 31, 28, &temp);
1961 }
1962 }
1963
1964 /*
1965 * Tune MCT to XBAR Buffer Count the same an all nodes, 2 Probes, 5 Response
1966 */
1967 if (isErrata153)
1968 {
1969 temp = 0x25;
1970 AmdPCIWriteBits (MAKE_SBDFO(makePCISegmentFromNode(node),
1971 makePCIBusFromNode(node),
1972 makePCIDeviceFromNode(node),
1973 CPU_NB_FUNC_03,
1974 REG_NB_MCT_XBAR_BUF_3X78),
1975 14, 8, &temp);
1976 }
1977 }
1978#endif /* HT_BUILD_NC_ONLY */
1979}
1980
1981/**----------------------------------------------------------------------------------------
1982 *
1983 * void
1984 * fam10BufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
1985 *
1986 * Description:
1987 * Buffer tunings are inherently northbridge specific. Check for specific configs
1988 * which require adjustments and apply any standard workarounds to this node.
1989 *
1990 * Parameters:
1991 * @param[in] u8 node = the node to tune
1992 * @param[in] sMainData *pDat = global state
1993 * @param[in] cNorthBridge* nb = this northbridge
1994 *
1995 * ---------------------------------------------------------------------------------------
1996 */
1997void fam10BufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
1998{
1999 u32 temp;
2000 SBDFO currentPtr;
2001 u8 i;
2002
2003 ASSERT(node < nb->maxNodes);
2004
2005 /*
2006 * Link to XCS Token Count Tuning
2007 *
2008 * For each active link that we reganged (so this unfortunately can't go into the PCI reg
2009 * table), we have to switch the Link to XCS Token Counts to the ganged state.
2010 * We do this here for the non-uma case, which is to write the values that would have
2011 * been power on defaults if the link was ganged at cold reset.
2012 */
2013 for (i = 0; i < pDat->TotalLinks*2; i++)
2014 {
2015 if ((pDat->PortList[i].NodeID == node) && (pDat->PortList[i].Type == PORTLIST_TYPE_CPU))
2016 {
2017 /* If the link is greater than 4, this is a sublink 1, so it is not reganged. */
2018 if (pDat->PortList[i].Link < 4)
2019 {
2020 currentPtr = MAKE_SBDFO(makePCISegmentFromNode(node),
2021 makePCIBusFromNode(node),
2022 makePCIDeviceFromNode(node),
2023 CPU_NB_FUNC_03,
2024 REG_NB_LINK_XCS_TOKEN0_3X148 + 4*pDat->PortList[i].Link);
2025 if (pDat->PortList[i].SelRegang)
2026 {
2027 /* Handle all the regang Token count adjustments */
2028
2029 /* Sublink 0: [Probe0tok] = 2 [Rsp0tok] = 2 [PReq0tok] = 2 [Req0tok] = 2 */
2030 temp = 0xAA;
2031 AmdPCIWriteBits(currentPtr, 7, 0, &temp);
2032 /* Sublink 1: [Probe1tok] = 0 [Rsp1tok] = 0 [PReq1tok] = 0 [Req1tok] = 0 */
2033 temp = 0;
2034 AmdPCIWriteBits(currentPtr, 23, 16, &temp);
2035 /* [FreeTok] = 3 */
2036 temp = 3;
2037 AmdPCIWriteBits(currentPtr, 15, 14, &temp);
2038 }
2039 else
2040 {
2041 /* Read the regang bit in hardware */
2042 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID),
2043 makePCIBusFromNode(pDat->PortList[i].NodeID),
2044 makePCIDeviceFromNode(pDat->PortList[i].NodeID),
2045 CPU_HTNB_FUNC_00,
2046 REG_HT_LINK_EXT_CONTROL0_0X170 + 4*pDat->PortList[i].Link),
2047 0, 0, &temp);
2048 if (temp == 1)
2049 {
2050 /* handle a minor adjustment for stapped ganged links. If SelRegang is false we
2051 * didn't do the regang, so if the bit is on then it's hardware strapped.
2052 */
2053
2054 /* [FreeTok] = 3 */
2055 temp = 3;
2056 AmdPCIWriteBits(currentPtr, 15, 14, &temp);
2057 }
2058 }
2059 }
2060 }
2061 }
2062}
2063
2064/*
2065 * North Bridge 'constructor'.
2066 *
2067 */
2068
2069/**----------------------------------------------------------------------------------------
2070 *
2071 * void
2072 * newNorthBridge(u8 node, cNorthBridge *nb)
2073 *
2074 * Description:
2075 * Construct a new northbridge. This routine encapsulates knowledge of how to tell
2076 * significant differences between families of supported northbridges and what routines
2077 * can be used in common and which are unique. A fully populated northbridge interface
2078 * is provided by nb.
2079 *
2080 * Parameters:
2081 * @param[in] node u8 = create a northbridge interface for this node.
2082 * @param[out] cNorthBridge* nb = the caller's northbridge structure to initialize.
2083 *
2084 * ---------------------------------------------------------------------------------------
2085 */
2086void newNorthBridge(u8 node, cNorthBridge *nb)
2087{
2088 u32 match;
2089 u32 extFam, baseFam, model;
2090
2091 cNorthBridge fam10 =
2092 {
2093#ifdef HT_BUILD_NC_ONLY
2094 8,
2095 1,
2096 12,
2097#else
2098 8,
2099 8,
2100 64,
2101#endif /* HT_BUILD_NC_ONLY*/
2102 writeRoutingTable,
2103 writeNodeID,
2104 readDefLnk,
2105 enableRoutingTables,
2106 verifyLinkIsCoherent,
2107 readTrueLinkFailStatus,
2108 readToken,
2109 writeToken,
2110 fam10GetNumCoresOnNode,
2111 setTotalNodesAndCores,
2112 limitNodes,
2113 writeFullRoutingTable,
2114 isCompatible,
2115 fam10IsCapable,
2116 (void (*)(u8, u8, cNorthBridge*))commonVoid,
2117 (BOOL (*)(u8, u8, sMainData*, cNorthBridge*))commonReturnFalse,
2118 readSbLink,
2119 verifyLinkIsNonCoherent,
2120 ht3SetCFGAddrMap,
2121 convertBitsToWidth,
2122 convertWidthToBits,
2123 fam10NorthBridgeFreqMask,
2124 gatherLinkData,
2125 setLinkData,
2126 ht3WriteTrafficDistribution,
2127 fam10BufferOptimizations,
2128 0x00000001,
2129 0x00000200,
2130 18,
2131 0x00000f01
2132 };
2133
2134 cNorthBridge fam0f =
2135 {
2136#ifdef HT_BUILD_NC_ONLY
2137 3,
2138 1,
2139 12,
2140#else
2141 3,
2142 8,
2143 32,
2144#endif /* HT_BUILD_NC_ONLY*/
2145 writeRoutingTable,
2146 writeNodeID,
2147 readDefLnk,
2148 enableRoutingTables,
2149 verifyLinkIsCoherent,
2150 readTrueLinkFailStatus,
2151 readToken,
2152 writeToken,
2153 fam0FGetNumCoresOnNode,
2154 setTotalNodesAndCores,
2155 limitNodes,
2156 writeFullRoutingTable,
2157 isCompatible,
2158 fam0fIsCapable,
2159 fam0fStopLink,
2160 (BOOL (*)(u8, u8, sMainData*, cNorthBridge*))commonReturnFalse,
2161 readSbLink,
2162 verifyLinkIsNonCoherent,
2163 ht1SetCFGAddrMap,
2164 convertBitsToWidth,
2165 convertWidthToBits,
2166 ht1NorthBridgeFreqMask,
2167 gatherLinkData,
2168 setLinkData,
2169 ht1WriteTrafficDistribution,
2170 fam0fBufferOptimizations,
2171 0x00000001,
2172 0x00000100,
2173 16,
2174 0x00000f00
2175 };
2176
2177 /* Start with enough of the key to identify the northbridge interface */
2178 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
2179 makePCIBusFromNode(node),
2180 makePCIDeviceFromNode(node),
2181 CPU_NB_FUNC_03,
2182 REG_NB_CPUID_3XFC),
2183 27, 20, &extFam);
2184 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
2185 makePCIBusFromNode(node),
2186 makePCIDeviceFromNode(node),
2187 CPU_NB_FUNC_03,
2188 REG_NB_CPUID_3XFC),
2189 11, 8, &baseFam);
2190 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
2191 makePCIBusFromNode(node),
2192 makePCIDeviceFromNode(node),
2193 CPU_NB_FUNC_03,
2194 REG_NB_CPUID_3XFC),
2195 7, 4, &model);
2196 match = (u32)((baseFam << 8) | extFam);
2197
2198 /* Test each in turn looking for a match. Init the struct if found */
2199 if (match == fam10.compatibleKey)
2200 {
2201 Amdmemcpy((void *)nb, (const void *)&fam10, (u32) sizeof(cNorthBridge));
2202 }
2203 else
2204 {
2205 if (match == fam0f.compatibleKey)
2206 {
2207 Amdmemcpy((void *)nb, (const void *)&fam0f, (u32) sizeof(cNorthBridge));
2208 }
2209 else
2210 {
2211 STOP_HERE;
2212 }
2213 }
2214
2215 /* Update the initial limited key to the real one, which may include other matching info */
2216 nb->compatibleKey = makeKey(node);
2217}
2218