reduce warnings in MCP55 and Fam10 code
[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         switch(value) {
1113         case 1: return 16;
1114         case 0: return 8;
1115         case 5: return 4;
1116         case 4: return 2;
1117         default: STOP_HERE; /*  This is an error internal condition */
1118         }
1119         return 0; // shut up GCC.
1120 }
1121
1122 /**----------------------------------------------------------------------------------------
1123  *
1124  * u8
1125  * convertWidthToBits(u8 value, cNorthBridge *nb)
1126  *
1127  *  Description:
1128  *      Translate a desired width setting to the bits to set in the register field
1129  *
1130  *  Parameters:
1131  *      @param[in]  u8  value     = The width
1132  *      @param[in]  cNorthBridge *nb = this northbridge
1133  *      @param[out] u8  results   = The bits for the register
1134  *
1135  * ---------------------------------------------------------------------------------------
1136  */
1137 u8 convertWidthToBits(u8 value, cNorthBridge *nb)
1138 {
1139         switch (value) {
1140         case 16: return 1;
1141         case  8: return 0;
1142         case  4: return 5;
1143         case  2: return 4;
1144         default: STOP_HERE; /*  This is an internal error condition */
1145         }
1146         return 0; // shut up GCC
1147 }
1148
1149 /**----------------------------------------------------------------------------------------
1150  *
1151  * u16
1152  * ht1NorthBridgeFreqMask(u8 NodeID, cNorthBridge *nb)
1153  *
1154  *  Description:
1155  *      Return a mask that eliminates HT frequencies that cannot be used due to a slow
1156  *      northbridge frequency.
1157  *
1158  *  Parameters:
1159  *      @param[in]  u8  node      = Result could (later) be for a specific node
1160  *      @param[in]  cNorthBridge *nb = this northbridge
1161  *      @param[out] u16 results   = Frequency mask
1162  *
1163  * ---------------------------------------------------------------------------------------
1164  */
1165 u16 ht1NorthBridgeFreqMask(u8 node, cNorthBridge *nb)
1166 {
1167         /* only up to HT1 speeds */
1168         return (HT_FREQUENCY_LIMIT_HT1_ONLY);
1169 }
1170
1171 /**----------------------------------------------------------------------------------------
1172  *
1173  * u16
1174  * fam10NorthBridgeFreqMask(u8 NodeID, cNorthBridge *nb)
1175  *
1176  *  Description:
1177  *      Return a mask that eliminates HT frequencies that cannot be used due to a slow
1178  *      northbridge frequency.
1179  *
1180  *  Parameters:
1181  *      @param[in]  u8    node     = Result could (later) be for a specific node
1182  *      @param[in]  cNorthBridge *nb  = this northbridge
1183  *      @param[out] u16   results  = Frequency mask
1184  *
1185  * ---------------------------------------------------------------------------------------
1186  */
1187 u16 fam10NorthBridgeFreqMask(u8 node, cNorthBridge *nb)
1188 {
1189         u8 nbCOF;
1190         u16 supported;
1191
1192         nbCOF = getMinNbCOF();
1193         /*
1194          * nbCOF is minimum northbridge speed in hundreds of MHz.
1195          * HT can not go faster than the minimum speed of the northbridge.
1196          */
1197         if ((nbCOF >= 6) && (nbCOF <= 26))
1198         {
1199                 /* Convert frequency to bit and all less significant bits,
1200                  * by setting next power of 2 and subtracting 1.
1201                  */
1202                 supported = ((u16)1 << ((nbCOF >> 1) + 2)) - 1;
1203         }
1204         else if (nbCOF > 26)
1205         {
1206                 supported = HT_FREQUENCY_LIMIT_2600M;
1207         }
1208         /* unlikely cases, but include as a defensive measure, also avoid trick above */
1209         else if (nbCOF == 4)
1210         {
1211                 supported = HT_FREQUENCY_LIMIT_400M;
1212         }
1213         else if (nbCOF == 2)
1214         {
1215                 supported = HT_FREQUENCY_LIMIT_200M;
1216         }
1217         else
1218         {
1219                 STOP_HERE;
1220                 supported = HT_FREQUENCY_LIMIT_200M;
1221         }
1222
1223         return (fixEarlySampleFreqCapability(supported));
1224 }
1225
1226 /**----------------------------------------------------------------------------------------
1227  *
1228  * void
1229  * gatherLinkData(sMainData *pDat, cNorthBridge *nb)
1230  *
1231  *  Description:
1232  *       For all discovered links, populate the port list with the frequency and width
1233  *       capabilities.
1234  *
1235  *  Parameters:
1236  *      @param[in,out] sMainData*  pDat = our global state, port list
1237  *      @param[in]     cNorthBridge *nb = this northbridge
1238  *
1239  * ---------------------------------------------------------------------------------------
1240  */
1241 void gatherLinkData(sMainData *pDat, cNorthBridge *nb)
1242 {
1243         u8 i;
1244         SBDFO linkBase;
1245         u32 temp;
1246
1247         for (i = 0; i < pDat->TotalLinks*2; i++)
1248         {
1249                 if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU)
1250                 {
1251                         linkBase = makeLinkBase(pDat->PortList[i].NodeID, pDat->PortList[i].Link);
1252
1253                         pDat->PortList[i].Pointer = linkBase;
1254
1255                         AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 22, 20, &temp);
1256                         pDat->PortList[i].PrvWidthOutCap = convertBitsToWidth((u8)temp, pDat->nb);
1257
1258                         AmdPCIReadBits(linkBase + HTHOST_LINK_CONTROL_REG, 18, 16, &temp);
1259                         pDat->PortList[i].PrvWidthInCap = convertBitsToWidth((u8)temp, pDat->nb);
1260
1261                         AmdPCIReadBits(linkBase + HTHOST_FREQ_REV_REG, 31, 16, &temp);
1262                         pDat->PortList[i].PrvFrequencyCap = (u16)temp & 0x7FFF
1263                                 & nb->northBridgeFreqMask(pDat->PortList[i].NodeID, pDat->nb); /*  Mask off bit 15, reserved value */
1264                 }
1265                 else
1266                 {
1267                         linkBase = pDat->PortList[i].Pointer;
1268                         if (pDat->PortList[i].Link == 1)
1269                          linkBase += HTSLAVE_LINK01_OFFSET;
1270
1271                         AmdPCIReadBits(linkBase + HTSLAVE_LINK_CONTROL_0_REG, 22, 20, &temp);
1272                         pDat->PortList[i].PrvWidthOutCap = convertBitsToWidth((u8)temp, pDat->nb);
1273
1274                         AmdPCIReadBits(linkBase + HTSLAVE_LINK_CONTROL_0_REG, 18, 16, &temp);
1275                         pDat->PortList[i].PrvWidthInCap = convertBitsToWidth((u8)temp, pDat->nb);
1276
1277                         AmdPCIReadBits(linkBase + HTSLAVE_FREQ_REV_0_REG, 31, 16, &temp);
1278                         pDat->PortList[i].PrvFrequencyCap = (u16)temp;
1279
1280                         if (pDat->HtBlock->AMD_CB_DeviceCapOverride)
1281                         {
1282                                 linkBase &= 0xFFFFF000;
1283                                 AmdPCIRead(linkBase, &temp);
1284
1285                                 pDat->HtBlock->AMD_CB_DeviceCapOverride(
1286                                         pDat->PortList[i].NodeID,
1287                                         pDat->PortList[i].HostLink,
1288                                         pDat->PortList[i].HostDepth,
1289                                         (u8)SBDFO_SEG(pDat->PortList[i].Pointer),
1290                                         (u8)SBDFO_BUS(pDat->PortList[i].Pointer),
1291                                         (u8)SBDFO_DEV(pDat->PortList[i].Pointer),
1292                                         temp,
1293                                         pDat->PortList[i].Link,
1294                                         &(pDat->PortList[i].PrvWidthInCap),
1295                                         &(pDat->PortList[i].PrvWidthOutCap),
1296                                         &(pDat->PortList[i].PrvFrequencyCap));
1297                         }
1298                 }
1299         }
1300 }
1301
1302 /**----------------------------------------------------------------------------------------
1303  *
1304  * void
1305  * setLinkData(sMainData *pDat, cNorthBridge *nb)
1306  *
1307  *  Description:
1308  *       Change the hardware state for all links according to the now optimized data in the
1309  *       port list data structure.
1310  *
1311  *  Parameters:
1312  *        @param[in]        sMainData*    pDat           = our global state, port list
1313  *        @param[in]        cNorthBridge *nb   = this northbridge
1314  *
1315  * ---------------------------------------------------------------------------------------
1316  */
1317 void setLinkData(sMainData *pDat, cNorthBridge *nb)
1318 {
1319         u8 i;
1320         SBDFO linkBase;
1321         u32 temp, widthin, widthout, bits;
1322
1323         for (i = 0; i < pDat->TotalLinks*2; i++)
1324         {
1325
1326                 ASSERT(pDat->PortList[i&0xFE].SelWidthOut == pDat->PortList[(i&0xFE)+1].SelWidthIn);
1327                 ASSERT(pDat->PortList[i&0xFE].SelWidthIn == pDat->PortList[(i&0xFE)+1].SelWidthOut);
1328                 ASSERT(pDat->PortList[i&0xFE].SelFrequency == pDat->PortList[(i&0xFE)+1].SelFrequency);
1329
1330                 if (pDat->PortList[i].SelRegang)
1331                 {
1332                         ASSERT(pDat->PortList[i].Type == PORTLIST_TYPE_CPU);
1333                         ASSERT(pDat->PortList[i].Link < 4);
1334                         temp = 1;
1335                         AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID),
1336                                         makePCIBusFromNode(pDat->PortList[i].NodeID),
1337                                         makePCIDeviceFromNode(pDat->PortList[i].NodeID),
1338                                         CPU_HTNB_FUNC_00,
1339                                         REG_HT_LINK_EXT_CONTROL0_0X170 + 4*pDat->PortList[i].Link),
1340                                         0, 0, &temp);
1341                 }
1342
1343                 if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU)
1344                 {
1345                         if (pDat->HtBlock->AMD_CB_OverrideCpuPort)
1346                                 pDat->HtBlock->AMD_CB_OverrideCpuPort(pDat->PortList[i].NodeID,
1347                                                 pDat->PortList[i].Link,
1348                                                 &(pDat->PortList[i].SelWidthIn),
1349                                                 &(pDat->PortList[i].SelWidthOut),
1350                                                 &(pDat->PortList[i].SelFrequency));
1351                 }
1352                 else
1353                 {
1354                         if (pDat->HtBlock->AMD_CB_OverrideDevicePort)
1355                                 pDat->HtBlock->AMD_CB_OverrideDevicePort(pDat->PortList[i].NodeID,
1356                                                         pDat->PortList[i].HostLink,
1357                                                         pDat->PortList[i].HostDepth,
1358                                                         pDat->PortList[i].Link,
1359                                                         &(pDat->PortList[i].SelWidthIn),
1360                                                         &(pDat->PortList[i].SelWidthOut),
1361                                                         &(pDat->PortList[i].SelFrequency));
1362                 }
1363
1364                 linkBase = pDat->PortList[i].Pointer;
1365                 if ((pDat->PortList[i].Type == PORTLIST_TYPE_IO) && (pDat->PortList[i].Link == 1))
1366                         linkBase += HTSLAVE_LINK01_OFFSET;
1367
1368                 /* Some IO devices don't work properly when setting widths, so write them in a single operation,
1369                  * rather than individually.
1370                  */
1371                 widthout = convertWidthToBits(pDat->PortList[i].SelWidthOut, pDat->nb);
1372                 ASSERT(widthout == 1 || widthout == 0 || widthout == 5 || widthout == 4);
1373                 widthin = convertWidthToBits(pDat->PortList[i].SelWidthIn, pDat->nb);
1374                 ASSERT(widthin == 1 || widthin == 0 || widthin == 5 || widthin == 4);
1375
1376                 temp = (widthin & 7) | ((widthout & 7) << 4);
1377                 setHtControlRegisterBits(linkBase + HTHOST_LINK_CONTROL_REG, 31, 24, &temp);
1378
1379                 temp = pDat->PortList[i].SelFrequency;
1380                 if (pDat->PortList[i].Type == PORTLIST_TYPE_CPU)
1381                 {
1382                         ASSERT((temp >= HT_FREQUENCY_600M && temp <= HT_FREQUENCY_2600M)
1383                                 || (temp == HT_FREQUENCY_200M) || (temp == HT_FREQUENCY_400M));
1384                         AmdPCIWriteBits(linkBase + HTHOST_FREQ_REV_REG, 11, 8, &temp);
1385                         if (temp > HT_FREQUENCY_1000M) /*  Gen1 = 200Mhz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz */
1386                         {
1387                                 /* Enable  for Gen3 frequencies */
1388                                 temp = 1;
1389                         }
1390                         else
1391                         {
1392                                 /* Disable  for Gen1 frequencies */
1393                                 temp = 0;
1394                         }
1395                                 /* HT3 retry mode enable / disable */
1396                                 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID),
1397                                                         makePCIBusFromNode(pDat->PortList[i].NodeID),
1398                                                         makePCIDeviceFromNode(pDat->PortList[i].NodeID),
1399                                                         CPU_HTNB_FUNC_00,
1400                                                         REG_HT_LINK_RETRY0_0X130 + 4*pDat->PortList[i].Link),
1401                                                         0, 0, &temp);
1402                                 /* and Scrambling enable / disable */
1403                                 AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID),
1404                                                 makePCIBusFromNode(pDat->PortList[i].NodeID),
1405                                                 makePCIDeviceFromNode(pDat->PortList[i].NodeID),
1406                                                 CPU_HTNB_FUNC_00,
1407                                                 REG_HT_LINK_EXT_CONTROL0_0X170 + 4*pDat->PortList[i].Link),
1408                                                 3, 3, &temp);
1409                 }
1410                 else
1411                 {
1412                         SBDFO currentPtr;
1413                         BOOL isFound;
1414
1415                         ASSERT(temp <= HT_FREQUENCY_2600M);
1416                         /* Write the frequency setting */
1417                         AmdPCIWriteBits(linkBase + HTSLAVE_FREQ_REV_0_REG, 11, 8, &temp);
1418
1419                         /* Handle additional HT3 frequency requirements, if needed,
1420                          * or clear them if switching down to ht1 on a warm reset.
1421                          * Gen1 = 200Mhz -> 1000MHz, Gen3 = 1200MHz -> 2600MHz
1422                          *
1423                          * Even though we assert if debugging, we need to check that the capability was found
1424                          * always, since this is an unknown hardware device, also we are taking
1425                          * unqualified frequency from the call backs
1426                          * (could be trying to do ht3 on an ht1 IO device).
1427                          */
1428
1429                         if (temp > HT_FREQUENCY_1000M)
1430                         {
1431                                 /* Enabling features if gen 3 */
1432                                 bits = 1;
1433                         }
1434                         else
1435                         {
1436                                 /* Disabling features if gen 1 */
1437                                 bits = 0;
1438                         }
1439
1440                         /* Retry Enable */
1441                         isFound = FALSE;
1442                         currentPtr = linkBase & (u32)0xFFFFF000; /* Set PCI Offset to 0 */
1443                         do
1444                         {
1445                                 AmdPCIFindNextCap(&currentPtr);
1446                                 if (currentPtr != ILLEGAL_SBDFO)
1447                                 {
1448                                         AmdPCIRead(currentPtr, &temp);
1449                                         /* HyperTransport Retry Capability? */
1450                                         if (IS_HT_RETRY_CAPABILITY(temp))
1451                                         {
1452                                                 ASSERT(pDat->PortList[i].Link < 2);
1453                                                 AmdPCIWriteBits(currentPtr + HTRETRY_CONTROL_REG,
1454                                                                 pDat->PortList[i].Link*16,
1455                                                                 pDat->PortList[i].Link*16,
1456                                                                 &bits);
1457                                                 isFound = TRUE;
1458                                         }
1459                                 /* Some other capability, keep looking */
1460                                 }
1461                                 else
1462                                 {
1463                                         /* If we are turning it off, that may mean the device was only ht1 capable,
1464                                          * so don't complain that we can't do it.
1465                                          */
1466                                         if (bits != 0)
1467                                         {
1468                                                 if (pDat->HtBlock->AMD_CB_EventNotify)
1469                                                 {
1470                                                         sHtEventOptRequiredCap evt;
1471                                                         evt.eSize = sizeof(sHtEventOptRequiredCap);
1472                                                         evt.node = pDat->PortList[i].NodeID;
1473                                                         evt.link = pDat->PortList[i].HostLink;
1474                                                         evt.depth = pDat->PortList[i].HostDepth;
1475
1476                                                         pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_WARNING,
1477                                                                                 HT_EVENT_OPT_REQUIRED_CAP_RETRY,
1478                                                                                 (u8 *)&evt);
1479                                                 }
1480                                                 STOP_HERE;
1481                                         }
1482                                         isFound = TRUE;
1483                                 }
1484                         } while (!isFound);
1485
1486                         /* Scrambling enable */
1487                         isFound = FALSE;
1488                         currentPtr = linkBase & (u32)0xFFFFF000; /* Set PCI Offset to 0 */
1489                         do
1490                         {
1491                                 AmdPCIFindNextCap(&currentPtr);
1492                                 if (currentPtr != ILLEGAL_SBDFO)
1493                                 {
1494                                         AmdPCIRead(currentPtr, &temp);
1495                                         /* HyperTransport Gen3 Capability? */
1496                                         if (IS_HT_GEN3_CAPABILITY(temp))
1497                                         {
1498                                                 ASSERT(pDat->PortList[i].Link < 2);
1499                                                 AmdPCIWriteBits((currentPtr +
1500                                                         HTGEN3_LINK_TRAINING_0_REG +
1501                                                         pDat->PortList[i].Link*HTGEN3_LINK01_OFFSET),
1502                                                         3, 3, &bits);
1503                                                 isFound = TRUE;
1504                                         }
1505                                         /* Some other capability, keep looking */
1506                                         }
1507                                         else
1508                                         {
1509                                         /* If we are turning it off, that may mean the device was only ht1 capable,
1510                                          * so don't complain that we can't do it.
1511                                          */
1512                                         if (bits != 0)
1513                                         {
1514                                                 if (pDat->HtBlock->AMD_CB_EventNotify)
1515                                                 {
1516                                                         sHtEventOptRequiredCap evt;
1517                                                         evt.eSize = sizeof(sHtEventOptRequiredCap);
1518                                                         evt.node = pDat->PortList[i].NodeID;
1519                                                         evt.link = pDat->PortList[i].HostLink;
1520                                                         evt.depth = pDat->PortList[i].HostDepth;
1521
1522                                                         pDat->HtBlock->AMD_CB_EventNotify(HT_EVENT_CLASS_WARNING,
1523                                                                                 HT_EVENT_OPT_REQUIRED_CAP_GEN3,
1524                                                                                 (u8 *)&evt);
1525                                                 }
1526                                                 STOP_HERE;
1527                                         }
1528                                         isFound = TRUE;
1529                                 }
1530                         } while (!isFound);
1531                 }
1532         }
1533 }
1534
1535 /**----------------------------------------------------------------------------------------
1536  *
1537  * void
1538  * fam0fWriteHTLinkCmdBufferAlloc(u8 node, u8 link, u8 req, u8 preq, u8 rsp, u8 prb)
1539  *
1540  *  Description:
1541  *      Set the command buffer allocations in the buffer count register for the node and link.
1542  *      The command buffer settings in the low 16 bits are the same on both
1543  *      family 10h and family 0fh northbridges.
1544  *
1545  *  Parameters:
1546  *      @param[in]  u8 node = The node to set allocations on
1547  *      @param[in]  u8 link = the link to set allocations on
1548  *      @param[in]  u8 req  = non-posted Request Command Buffers
1549  *      @param[in]  u8 preq = Posted Request Command Buffers
1550  *      @param[in]  u8 rsp  = Response Command Buffers
1551  *      @param[in]  u8 prb  = Probe Command Buffers
1552  *
1553  * ---------------------------------------------------------------------------------------
1554  */
1555 static void fam0fWriteHTLinkCmdBufferAlloc(u8 node, u8 link, u8 req, u8 preq, u8 rsp, u8 prb)
1556 {
1557         u32 temp;
1558         SBDFO currentPtr;
1559
1560         currentPtr = makeLinkBase(node, link);
1561         currentPtr += HTHOST_BUFFER_COUNT_REG;
1562
1563         /* non-posted Request Command Buffers */
1564         temp = req;
1565         AmdPCIWriteBits(currentPtr, 3, 0, &temp);
1566         /* Posted Request Command Buffers */
1567         temp = preq;
1568         AmdPCIWriteBits(currentPtr, 7, 4, &temp);
1569         /* Response Command Buffers */
1570         temp = rsp;
1571         AmdPCIWriteBits(currentPtr, 11, 8, &temp);
1572         /* Probe Command Buffers */
1573         temp = prb;
1574         AmdPCIWriteBits(currentPtr, 15, 12, &temp);
1575 }
1576
1577 /**----------------------------------------------------------------------------------------
1578  *
1579  * void
1580  * fam0fWriteHTLinkDatBufferAlloc(u8 node, u8 link, u8 reqD, u8 preqD, u8 rspD)
1581  *
1582  *  Description:
1583  *       Set the data buffer allocations in the buffer count register for the node and link.
1584  *       The command buffer settings in the high 16 bits are not the same on both
1585  *       family 10h and family 0fh northbridges.
1586  *
1587  *  Parameters:
1588  *      @param[in] u8 node  = The node to set allocations on
1589  *      @param[in] u8 link  = the link to set allocations on
1590  *      @param[in] u8 reqD  = non-posted Request Data Buffers
1591  *      @param[in] u8 preqD = Posted Request Data Buffers
1592  *      @param[in] u8 rspD  = Response Data Buffers
1593  *
1594  * ---------------------------------------------------------------------------------------
1595  */
1596 static void fam0fWriteHTLinkDatBufferAlloc(u8 node, u8 link, u8 reqD, u8 preqD, u8 rspD)
1597 {
1598         u32 temp;
1599         SBDFO currentPtr;
1600
1601         currentPtr = makeLinkBase(node, link);
1602         currentPtr += HTHOST_BUFFER_COUNT_REG;
1603
1604         /* Request Data Buffers */
1605         temp = reqD;
1606         AmdPCIWriteBits(currentPtr, 18, 16, &temp);
1607         /* Posted Request Data Buffers */
1608         temp = preqD;
1609         AmdPCIWriteBits(currentPtr, 22, 20, &temp);
1610         /* Response Data Buffers */
1611         temp = rspD;
1612         AmdPCIWriteBits(currentPtr, 26, 24, &temp);
1613 }
1614
1615 /**----------------------------------------------------------------------------------------
1616  *
1617  * void
1618  * ht3WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb)
1619  *
1620  *  Description:
1621  *       Set the traffic distribution register for the links provided.
1622  *
1623  *  Parameters:
1624  *      @param[in] u32 links01   = coherent links from node 0 to 1
1625  *      @param[in] u32 links10   = coherent links from node 1 to 0
1626  *      @param[in] cNorthBridge* nb = this northbridge
1627  *
1628  * ---------------------------------------------------------------------------------------
1629  */
1630 void ht3WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb)
1631 {
1632 #ifndef HT_BUILD_NC_ONLY
1633         u32 temp;
1634
1635         /* Node 0 */
1636         /* DstLnk */
1637         AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(0),
1638                         makePCIBusFromNode(0),
1639                         makePCIDeviceFromNode(0),
1640                         CPU_HTNB_FUNC_00,
1641                         REG_HT_TRAFFIC_DIST_0X164),
1642                         23, 16, &links01);
1643         /* DstNode = 1, cHTPrbDistEn=1, cHTRspDistEn=1, cHTReqDistEn=1 */
1644         temp = 0x0107;
1645         AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(0),
1646                         makePCIBusFromNode(0),
1647                         makePCIDeviceFromNode(0),
1648                         CPU_HTNB_FUNC_00,
1649                         REG_HT_TRAFFIC_DIST_0X164),
1650                         15, 0, &temp);
1651
1652         /* Node 1 */
1653         /* DstLnk */
1654         AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(1),
1655                         makePCIBusFromNode(1),
1656                         makePCIDeviceFromNode(1),
1657                         CPU_HTNB_FUNC_00,
1658                         REG_HT_TRAFFIC_DIST_0X164),
1659                         23, 16, &links10);
1660         /* DstNode = 0, cHTPrbDistEn=1, cHTRspDistEn=1, cHTReqDistEn=1 */
1661         temp = 0x0007;
1662         AmdPCIWriteBits(MAKE_SBDFO(makePCISegmentFromNode(1),
1663                         makePCIBusFromNode(1),
1664                         makePCIDeviceFromNode(1),
1665                         CPU_HTNB_FUNC_00,
1666                         REG_HT_TRAFFIC_DIST_0X164),
1667                         15, 0, &temp);
1668 #endif /* HT_BUILD_NC_ONLY */
1669 }
1670
1671 /**----------------------------------------------------------------------------------------
1672  *
1673  * void
1674  * ht1WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb)
1675  *
1676  *  Description:
1677  *       Traffic distribution is more complex in this case as the routing table must be
1678  *       adjusted to use one link for requests and the other for responses.  Also,
1679  *       perform the buffer tunings on the links required for this config.
1680  *
1681  *  Parameters:
1682  *      @param[in]  u32  links01  = coherent links from node 0 to 1
1683  *      @param[in]  u32  links01  = coherent links from node 1 to 0
1684  *      @param[in]  cNorthBridge* nb = this northbridge
1685  *
1686  * ---------------------------------------------------------------------------------------
1687  */
1688 void ht1WriteTrafficDistribution(u32 links01, u32 links10, cNorthBridge *nb)
1689 {
1690 #ifndef HT_BUILD_NC_ONLY
1691         u32 route01, route10;
1692         u8 req0, req1, rsp0, rsp1, nclink;
1693
1694         /*
1695          * Get the current request route for 0->1 and 1->0.  This will indicate which of the links
1696          * in links01 are connected to which links in links10.  Since we have to route to distribute
1697          * traffic, we need to know that.       The link used by htinit will become the request, probe link.
1698          * the other link will be used for responses.
1699          */
1700
1701         /* Get the routes, and hang on to them, we will write them back updated. */
1702         AmdPCIRead(MAKE_SBDFO(makePCISegmentFromNode(0),
1703                                 makePCIBusFromNode(0),
1704                                 makePCIDeviceFromNode(0),
1705                                 CPU_HTNB_FUNC_00,
1706                                 REG_ROUTE1_0X44),
1707                                 &route01);
1708         AmdPCIRead(MAKE_SBDFO(makePCISegmentFromNode(1),
1709                                 makePCIBusFromNode(1),
1710                                 makePCIDeviceFromNode(1),
1711                                 CPU_HTNB_FUNC_00,
1712                                 REG_ROUTE0_0X40),
1713                                 &route10);
1714
1715         /* Convert the request routes to a link number.  Note "0xE" is ht1 nb specific.
1716          * Find the response link numbers.
1717         */
1718         ASSERT((route01 & 0xE) && (route10 & 0xE));    /* no route! error! */
1719         req0 = (u8)AmdBitScanReverse((route01 & 0xE)) - 1;
1720         req1 = (u8)AmdBitScanReverse((route10 & 0xE)) - 1;
1721         /* Now, find the other link for the responses */
1722         rsp0 = (u8)AmdBitScanReverse((links01 & ~((u32)1 << req0)));
1723         rsp1 = (u8)AmdBitScanReverse((links10 & ~((u32)1 << req1)));
1724
1725         /* ht1 nb restriction, must have exactly two links */
1726         ASSERT(((((links01 & ~((u32)1 << req0)) & ~((u32)1 << rsp0))) == 0)
1727                 && ((((links10 & ~((u32)1 << req1)) & ~((u32)1 << rsp1))) == 0));
1728
1729         route01 = (route01 & ~0x0E00) | ((u32)0x0100<<(rsp0 + 1));
1730         route10 = (route10 & ~0x0E00) | ((u32)0x0100<<(rsp1 + 1));
1731
1732         AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(0),
1733                                 makePCIBusFromNode(0),
1734                                 makePCIDeviceFromNode(0),
1735                                 CPU_HTNB_FUNC_00,
1736                                 REG_ROUTE1_0X44),
1737                                 &route01);
1738
1739         AmdPCIWrite(MAKE_SBDFO(makePCISegmentFromNode(1),
1740                                 makePCIBusFromNode(1),
1741                                 makePCIDeviceFromNode(1),
1742                                 CPU_HTNB_FUNC_00,
1743                                 REG_ROUTE0_0X40),
1744                                 &route10);
1745
1746         /* While we otherwise do buffer tunings elsewhere, for the dual cHT DP case with
1747          * ht1 northbridges like family 0Fh, do the tunings here where we have all the
1748          * link and route info at hand and don't need to recalculate it.
1749          */
1750
1751         /* Node 0, Request / Probe Link (note family F only has links < 4) */
1752         fam0fWriteHTLinkCmdBufferAlloc(0, req0, 6, 3, 1, 6);
1753         fam0fWriteHTLinkDatBufferAlloc(0, req0, 4, 3, 1);
1754         /* Node 0, Response Link (note family F only has links < 4) */
1755         fam0fWriteHTLinkCmdBufferAlloc(0, rsp0, 1, 0, 15, 0);
1756         fam0fWriteHTLinkDatBufferAlloc(0, rsp0, 1, 1, 6);
1757         /* Node 1, Request / Probe Link (note family F only has links < 4) */
1758         fam0fWriteHTLinkCmdBufferAlloc(1, req1, 6, 3, 1, 6);
1759         fam0fWriteHTLinkDatBufferAlloc(1, req1, 4, 3, 1);
1760         /* Node 1, Response Link (note family F only has links < 4) */
1761         fam0fWriteHTLinkCmdBufferAlloc(1, rsp1, 1, 0, 15, 0);
1762         fam0fWriteHTLinkDatBufferAlloc(1, rsp1, 1, 1, 6);
1763
1764         /* Node 0, is the third link non-coherent? */
1765         nclink = (u8)AmdBitScanReverse(((u8)0x07 & ~((u32)1 << req0) & ~((u32)1 << rsp0)));
1766         if (nb->verifyLinkIsNonCoherent(0, nclink, nb))
1767         {
1768                 fam0fWriteHTLinkCmdBufferAlloc(0, nclink, 6, 5, 2, 0);
1769         }
1770
1771         /* Node 1, is the third link non-coherent? */
1772         nclink = (u8)AmdBitScanReverse(((u8)0x07 & ~((u32)1 << req1) & ~((u32)1 << rsp1)));
1773         if (nb->verifyLinkIsNonCoherent(1, nclink, nb))
1774         {
1775                 fam0fWriteHTLinkCmdBufferAlloc(1, nclink, 6, 5, 2, 0);
1776         }
1777 #endif /* HT_BUILD_NC_ONLY */
1778 }
1779
1780 /**----------------------------------------------------------------------------------------
1781  *
1782  * void
1783  * fam0fBufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
1784  *
1785  *  Description:
1786  *       Buffer tunings are inherently northbridge specific. Check for specific configs
1787  *       which require adjustments and apply any standard workarounds to this node.
1788  *
1789  *  Parameters:
1790  *      @param[in]  u8  node      = the node to
1791  *      @param[in]  sMainData *pDat  = coherent links from node 0 to 1
1792  *      @param[in]  cNorthBridge* nb = this northbridge
1793  *
1794  * ---------------------------------------------------------------------------------------
1795  */
1796 void fam0fBufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
1797 {
1798 #ifndef HT_BUILD_NC_ONLY
1799         u8 i;
1800         u32 temp;
1801         SBDFO currentPtr;
1802
1803         ASSERT(node < nb->maxNodes);
1804
1805         /* Fix the FIFO pointer register before changing speeds */
1806         currentPtr = MAKE_SBDFO(makePCISegmentFromNode(node),
1807                                 makePCIBusFromNode(node),
1808                                 makePCIDeviceFromNode(node),
1809                                 CPU_NB_FUNC_03,
1810                                 REG_NB_FIFOPTR_3XDC);
1811         for (i=0; i < nb->maxLinks; i++)
1812         {
1813                 temp = 0;
1814                 if (nb->verifyLinkIsCoherent(node, i, nb))
1815                 {
1816                         temp = 0x26;
1817                         ASSERT(i<3);
1818                         AmdPCIWriteBits(currentPtr, 8*i + 5, 8*i, &temp);
1819                 }
1820                 else
1821                 {
1822                         if (nb->verifyLinkIsNonCoherent(node, i, nb))
1823                         {
1824                                 temp = 0x25;
1825                                 ASSERT(i<3);
1826                                 AmdPCIWriteBits(currentPtr, 8*i + 5, 8*i, &temp);
1827                         }
1828                 }
1829         }
1830         /*
1831          * 8P Buffer tuning.
1832          * Either apply the BKDG tunings or, if applicable, apply the more restrictive errata 153
1833          * workaround.
1834          * If 8 nodes, Check this node for 'inner' or 'outer'.
1835          * Tune each link based on coherent or non-coherent
1836          */
1837         if (pDat->NodesDiscovered >= 6)
1838         {
1839                 u8 j;
1840                 BOOL isOuter;
1841                 BOOL isErrata153;
1842
1843                 /* This is for family 0Fh, so assuming dual core max then 7 or 8 nodes are required
1844                  * to be in the situation of 14 or more cores.   We checked nodes above, cross check
1845                  * that the number of cores is 14 or more. We want both 14 cores with at least 7 or 8 nodes
1846                  * not one condition alone, to apply the errata 153 workaround.  Otherwise, 7 or 8 rev F
1847                  * nodes use the BKDG tuning.
1848                  */
1849
1850                 isErrata153 = 0;
1851
1852                 AmdPCIReadBits (MAKE_SBDFO(makePCISegmentFromNode(0),
1853                                         makePCIBusFromNode(0),
1854                                         makePCIDeviceFromNode(0),
1855                                         CPU_HTNB_FUNC_00,
1856                                         REG_NODE_ID_0X60),
1857                                         19, 16, &temp);
1858
1859                 if (temp >= 14)
1860                 {
1861                         /* Check whether we need to do errata 153 tuning or BKDG tuning.
1862                          * Errata 153 applies to JH-1, JH-2 and older.  It is fixed in JH-3
1863                          * (and, one assumes, from there on).
1864                          */
1865                         for (i=0; i < (pDat->NodesDiscovered +1); i++)
1866                         {
1867                                 AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(i),
1868                                                 makePCIBusFromNode(i),
1869                                                 makePCIDeviceFromNode(i),
1870                                                 CPU_NB_FUNC_03,
1871                                                 REG_NB_CPUID_3XFC),
1872                                                 7, 0, &temp);
1873                                 if (((u8)temp & ~0x40) < 0x13)
1874                                 {
1875                                         isErrata153 = 1;
1876                                         break;
1877                                 }
1878                         }
1879                 }
1880
1881                 for (i=0; i < CPU_ADDR_NUM_CONFIG_MAPS; i++)
1882                 {
1883                         isOuter = FALSE;
1884                         /* Check for outer node by scanning the config maps on node 0 for one
1885                          * which is assigned to this node.
1886                          */
1887                         currentPtr = MAKE_SBDFO(makePCISegmentFromNode(0),
1888                                                 makePCIBusFromNode(0),
1889                                                 makePCIDeviceFromNode(0),
1890                                                 CPU_ADDR_FUNC_01,
1891                                                 REG_ADDR_CONFIG_MAP0_1XE0 + (4 * i));
1892                         AmdPCIReadBits (currentPtr, 1, 0, &temp);
1893                         /* Make sure this config map is valid, if it is it will be enabled for read/write */
1894                         if (temp == 3)
1895                         {
1896                                 /* It's valid, get the node (that node is an outer node) */
1897                                 AmdPCIReadBits (currentPtr, 6, 4, &temp);
1898                                 /* Is the node we're working on now? */
1899                                 if (node == (u8)temp)
1900                                 {
1901                                         /* This is an outer node.       Tune it appropriately. */
1902                                         for (j=0; j < nb->maxLinks; j++)
1903                                         {
1904                                                 if (isErrata153)
1905                                                 {
1906                                                         if (nb->verifyLinkIsCoherent(node, j, nb))
1907                                                         {
1908                                                                 fam0fWriteHTLinkCmdBufferAlloc(node, j, 1, 1, 6, 4);
1909                                                         }
1910                                                         else
1911                                                         {
1912                                                                 if (nb->verifyLinkIsNonCoherent(node, j, nb))
1913                                                                 {
1914                                                                         fam0fWriteHTLinkCmdBufferAlloc(node, j, 5, 4, 1, 0);
1915                                                                 }
1916                                                         }
1917                                                 }
1918                                                 else
1919                                                 {
1920                                                         if (nb->verifyLinkIsCoherent(node, j, nb))
1921                                                         {
1922                                                                 fam0fWriteHTLinkCmdBufferAlloc(node, j, 1, 1, 8, 5);
1923                                                         }
1924                                                 }
1925                                         }
1926                                         /*
1927                                          * SRI to XBAR Buffer Counts are correct for outer node at power on defaults.
1928                                          */
1929                                         isOuter = TRUE;
1930                                         break;
1931                                 }
1932                         }
1933                         /* We fill config maps in ascending order, so if we didn't use this one, we're done. */
1934                         else break;
1935                 }
1936                 if (!isOuter)
1937                 {
1938                         if (isErrata153)
1939                         {
1940                                 /* Tuning for inner node coherent links */
1941                                 for (j=0; j < nb->maxLinks; j++)
1942                                 {
1943                                         if (nb->verifyLinkIsCoherent(node, j, nb))
1944                                         {
1945                                                 fam0fWriteHTLinkCmdBufferAlloc(node, j, 2, 1, 5, 4);
1946                                         }
1947
1948                                 }
1949                                 /* SRI to XBAR Buffer Count for inner nodes, zero DReq and DPReq */
1950                                 temp = 0;
1951                                 AmdPCIWriteBits (MAKE_SBDFO(makePCISegmentFromNode(node),
1952                                                         makePCIBusFromNode(node),
1953                                                         makePCIDeviceFromNode(node),
1954                                                         CPU_NB_FUNC_03,
1955                                                         REG_NB_SRI_XBAR_BUF_3X70),
1956                                                         31, 28, &temp);
1957                         }
1958                 }
1959
1960                 /*
1961                  * Tune MCT to XBAR Buffer Count the same an all nodes, 2 Probes, 5 Response
1962                  */
1963                 if (isErrata153)
1964                 {
1965                         temp = 0x25;
1966                         AmdPCIWriteBits (MAKE_SBDFO(makePCISegmentFromNode(node),
1967                                                 makePCIBusFromNode(node),
1968                                                 makePCIDeviceFromNode(node),
1969                                                 CPU_NB_FUNC_03,
1970                                                 REG_NB_MCT_XBAR_BUF_3X78),
1971                                                 14, 8, &temp);
1972                 }
1973         }
1974 #endif /* HT_BUILD_NC_ONLY */
1975 }
1976
1977 /**----------------------------------------------------------------------------------------
1978  *
1979  * void
1980  * fam10BufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
1981  *
1982  *  Description:
1983  *       Buffer tunings are inherently northbridge specific. Check for specific configs
1984  *       which require adjustments and apply any standard workarounds to this node.
1985  *
1986  *  Parameters:
1987  *      @param[in] u8 node       = the node to tune
1988  *      @param[in] sMainData *pDat  = global state
1989  *      @param[in] cNorthBridge* nb = this northbridge
1990  *
1991  * ---------------------------------------------------------------------------------------
1992  */
1993 void fam10BufferOptimizations(u8 node, sMainData *pDat, cNorthBridge *nb)
1994 {
1995         u32 temp;
1996         SBDFO currentPtr;
1997         u8 i;
1998
1999         ASSERT(node < nb->maxNodes);
2000
2001         /*
2002          * Link to XCS Token Count Tuning
2003          *
2004          * For each active link that we reganged (so this unfortunately can't go into the PCI reg
2005          * table), we have to switch the Link to XCS Token Counts to the ganged state.
2006          * We do this here for the non-uma case, which is to write the values that would have
2007          * been power on defaults if the link was ganged at cold reset.
2008          */
2009         for (i = 0; i < pDat->TotalLinks*2; i++)
2010         {
2011                 if ((pDat->PortList[i].NodeID == node) && (pDat->PortList[i].Type == PORTLIST_TYPE_CPU))
2012                 {
2013                         /* If the link is greater than 4, this is a sublink 1, so it is not reganged. */
2014                         if (pDat->PortList[i].Link < 4)
2015                         {
2016                                 currentPtr = MAKE_SBDFO(makePCISegmentFromNode(node),
2017                                                 makePCIBusFromNode(node),
2018                                                 makePCIDeviceFromNode(node),
2019                                                 CPU_NB_FUNC_03,
2020                                                 REG_NB_LINK_XCS_TOKEN0_3X148 + 4*pDat->PortList[i].Link);
2021                                 if (pDat->PortList[i].SelRegang)
2022                                 {
2023                                         /* Handle all the regang Token count adjustments */
2024
2025                                         /* Sublink 0: [Probe0tok] = 2 [Rsp0tok] = 2 [PReq0tok] = 2 [Req0tok] = 2 */
2026                                         temp = 0xAA;
2027                                         AmdPCIWriteBits(currentPtr, 7, 0, &temp);
2028                                         /* Sublink 1: [Probe1tok] = 0 [Rsp1tok] = 0 [PReq1tok] = 0 [Req1tok] = 0 */
2029                                         temp = 0;
2030                                         AmdPCIWriteBits(currentPtr, 23, 16, &temp);
2031                                         /* [FreeTok] = 3 */
2032                                         temp = 3;
2033                                         AmdPCIWriteBits(currentPtr, 15, 14, &temp);
2034                                 }
2035                                 else
2036                                 {
2037                                         /* Read the regang bit in hardware */
2038                                         AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(pDat->PortList[i].NodeID),
2039                                                         makePCIBusFromNode(pDat->PortList[i].NodeID),
2040                                                         makePCIDeviceFromNode(pDat->PortList[i].NodeID),
2041                                                         CPU_HTNB_FUNC_00,
2042                                                         REG_HT_LINK_EXT_CONTROL0_0X170 + 4*pDat->PortList[i].Link),
2043                                                         0, 0, &temp);
2044                                         if (temp == 1)
2045                                         {
2046                                                 /* handle a minor adjustment for stapped ganged links.   If SelRegang is false we
2047                                                  * didn't do the regang, so if the bit is on then it's hardware strapped.
2048                                                  */
2049
2050                                                 /* [FreeTok] = 3 */
2051                                                 temp = 3;
2052                                                 AmdPCIWriteBits(currentPtr, 15, 14, &temp);
2053                                         }
2054                                 }
2055                         }
2056                 }
2057         }
2058 }
2059
2060 /*
2061  * North Bridge 'constructor'.
2062  *
2063  */
2064
2065 /**----------------------------------------------------------------------------------------
2066  *
2067  * void
2068  * newNorthBridge(u8 node, cNorthBridge *nb)
2069  *
2070  *  Description:
2071  *       Construct a new northbridge.  This routine encapsulates knowledge of how to tell
2072  *       significant differences between families of supported northbridges and what routines
2073  *       can be used in common and which are unique.  A fully populated northbridge interface
2074  *       is provided by nb.
2075  *
2076  *  Parameters:
2077  *        @param[in]        node          u8             = create a northbridge interface for this node.
2078  *        @param[out]       cNorthBridge* nb             = the caller's northbridge structure to initialize.
2079  *
2080  * ---------------------------------------------------------------------------------------
2081  */
2082 void newNorthBridge(u8 node, cNorthBridge *nb)
2083 {
2084         u32 match;
2085         u32 extFam, baseFam, model;
2086
2087         cNorthBridge fam10 =
2088         {
2089 #ifdef HT_BUILD_NC_ONLY
2090                 8,
2091                 1,
2092                 12,
2093 #else
2094                 8,
2095                 8,
2096                 64,
2097 #endif /* HT_BUILD_NC_ONLY*/
2098                 writeRoutingTable,
2099                 writeNodeID,
2100                 readDefLnk,
2101                 enableRoutingTables,
2102                 verifyLinkIsCoherent,
2103                 readTrueLinkFailStatus,
2104                 readToken,
2105                 writeToken,
2106                 fam10GetNumCoresOnNode,
2107                 setTotalNodesAndCores,
2108                 limitNodes,
2109                 writeFullRoutingTable,
2110                 isCompatible,
2111                 fam10IsCapable,
2112                 (void (*)(u8, u8, cNorthBridge*))commonVoid,
2113                 (BOOL (*)(u8, u8, sMainData*, cNorthBridge*))commonReturnFalse,
2114                 readSbLink,
2115                 verifyLinkIsNonCoherent,
2116                 ht3SetCFGAddrMap,
2117                 convertBitsToWidth,
2118                 convertWidthToBits,
2119                 fam10NorthBridgeFreqMask,
2120                 gatherLinkData,
2121                 setLinkData,
2122                 ht3WriteTrafficDistribution,
2123                 fam10BufferOptimizations,
2124                 0x00000001,
2125                 0x00000200,
2126                 18,
2127                 0x00000f01
2128         };
2129
2130         cNorthBridge fam0f =
2131         {
2132 #ifdef HT_BUILD_NC_ONLY
2133                 3,
2134                 1,
2135                 12,
2136 #else
2137                 3,
2138                 8,
2139                 32,
2140 #endif /* HT_BUILD_NC_ONLY*/
2141                 writeRoutingTable,
2142                 writeNodeID,
2143                 readDefLnk,
2144                 enableRoutingTables,
2145                 verifyLinkIsCoherent,
2146                 readTrueLinkFailStatus,
2147                 readToken,
2148                 writeToken,
2149                 fam0FGetNumCoresOnNode,
2150                 setTotalNodesAndCores,
2151                 limitNodes,
2152                 writeFullRoutingTable,
2153                 isCompatible,
2154                 fam0fIsCapable,
2155                 fam0fStopLink,
2156                 (BOOL (*)(u8, u8, sMainData*, cNorthBridge*))commonReturnFalse,
2157                 readSbLink,
2158                 verifyLinkIsNonCoherent,
2159                 ht1SetCFGAddrMap,
2160                 convertBitsToWidth,
2161                 convertWidthToBits,
2162                 ht1NorthBridgeFreqMask,
2163                 gatherLinkData,
2164                 setLinkData,
2165                 ht1WriteTrafficDistribution,
2166                 fam0fBufferOptimizations,
2167                 0x00000001,
2168                 0x00000100,
2169                 16,
2170                 0x00000f00
2171         };
2172
2173         /* Start with enough of the key to identify the northbridge interface */
2174         AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
2175                         makePCIBusFromNode(node),
2176                         makePCIDeviceFromNode(node),
2177                         CPU_NB_FUNC_03,
2178                         REG_NB_CPUID_3XFC),
2179                         27, 20, &extFam);
2180         AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
2181                         makePCIBusFromNode(node),
2182                         makePCIDeviceFromNode(node),
2183                         CPU_NB_FUNC_03,
2184                         REG_NB_CPUID_3XFC),
2185                         11, 8, &baseFam);
2186         AmdPCIReadBits(MAKE_SBDFO(makePCISegmentFromNode(node),
2187                         makePCIBusFromNode(node),
2188                         makePCIDeviceFromNode(node),
2189                         CPU_NB_FUNC_03,
2190                         REG_NB_CPUID_3XFC),
2191                         7, 4, &model);
2192         match = (u32)((baseFam << 8) | extFam);
2193
2194         /* Test each in turn looking for a match.       Init the struct if found */
2195         if (match == fam10.compatibleKey)
2196         {
2197                 Amdmemcpy((void *)nb, (const void *)&fam10, (u32) sizeof(cNorthBridge));
2198         }
2199         else
2200         {
2201                 if (match == fam0f.compatibleKey)
2202                 {
2203                         Amdmemcpy((void *)nb, (const void *)&fam0f, (u32) sizeof(cNorthBridge));
2204                 }
2205                 else
2206                 {
2207                 STOP_HERE;
2208                 }
2209         }
2210
2211         /* Update the initial limited key to the real one, which may include other matching info */
2212         nb->compatibleKey = makeKey(node);
2213 }
2214