Clean up AMD FAM10 HT variable initialization. The structure init is cleaner, avoid...
[coreboot.git] / src / northbridge / amd / amdht / h3ncmn.c
1 /*
2  * This file is part of the coreboot project.
3  *
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  */
108 static 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  */
147 static 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
191 void 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
223 void 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
255 u8 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
289 void 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
325 BOOL 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
336         /*  FN0_98/A4/C4 = LDT Type Register */
337         AmdPCIRead(linkBase + HTHOST_LINK_TYPE_REG, &linkType);
338
339         /*  Verify LinkCon=1, InitComplete=1, NC=0, UniP-cLDT=0, LinkConPend=0 */
340         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  */
374 BOOL 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. */
404                                         sHtEventHWHtCrc evt;
405                                         evt.eSize = sizeof(sHtEventHWHtCrc);
406                                         evt.node = node;
407                                         evt.link = link;
408                                         evt.laneMask = (uint8)crc;
409
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. */
421                                         sHtEventHWSynchFlood evt;
422                                         evt.eSize = sizeof(sHtEventHWSynchFlood);
423                                         evt.node = node;
424                                         evt.link = link;
425
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  */
455 u8 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  */
491 void 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  */
520 u8 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  */
552 u8 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  */
600 void 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  */
636 void 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  */
667 void 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  */
714 static 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  */
750 BOOL 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  */
773 BOOL 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  */
827 BOOL 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  */
877 void 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  */
906 void 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  */
922 BOOL 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  */
946 u8 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  */
980 BOOL 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  */
1015 void  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  */
1061 void 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  */
1110 u8 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         }
1121         STOP_HERE; /*  This is an error internal condition */
1122 }
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  */
1139 u8 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         }
1150         STOP_HERE; /*  This is an internal error condition */
1151 }
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  */
1169 u16 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  */
1191 u16 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  */
1245 void 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
1267                                 & nb->northBridgeFreqMask(pDat->PortList[i].NodeID, pDat->nb); /*  Mask off bit 15, reserved value */
1268                 }
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  */
1321 void 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);
1389                         if (temp > HT_FREQUENCY_1000M) /*  Gen1 = 200Mhz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz */
1390                         {
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                                                 {
1474                                                         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;
1479
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                                                 {
1520                                                         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;
1525
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  */
1559 static 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  */
1600 static 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  */
1634 void 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  */
1692 void 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  */
1800 void 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  */
1997 void 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  */
2086 void 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