52f8645e8d2edafebc2b1ce702716343e8037f08
[coreboot.git] / src / northbridge / amd / amdht / AsPsNb.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  *----------------------------------------------------------------------------
23  *                              MODULES USED
24  *
25  *----------------------------------------------------------------------------
26  */
27 #undef FILECODE
28 #define FILECODE 0xCCCC
29 #include "comlib.h"
30 #include "AsPsDefs.h"
31 #include "AsPsNb.h"
32
33
34 /*----------------------------------------------------------------------------
35  *                      PROTOTYPES OF LOCAL FUNCTIONS
36  *
37  *----------------------------------------------------------------------------
38  */
39 u8 getNumOfNodeNb(void);
40 u8 translateNodeIdToDeviceIdNb(u8 nodeId);
41
42
43 /*----------------------------------------------------------------------------
44  * FUNCTION: getMinNbCOF
45  * INPUT: None
46  * OUTPUT: minNbCOF (in multiple of half of CLKIN, 100MHz)
47  * DESCRIPTION:
48  * This function returns the minimum possible NbCOF (in 100MHz)
49  * for the system .
50  * This function can be run on any core and is used by the HT & Memory init code
51  * in Phase 1.
52  * ----------------------------------------------------------------------------
53  */
54 u8 getMinNbCOF(void)
55 {
56         u8 numOfNode, i, j, deviceId, nbDid, nbFid, nextNbFid;
57         u32 dtemp;
58
59         nbDid = 0;
60         nbFid = 0;
61
62         /* get number of node in the system */
63         numOfNode = getNumOfNodeNb();
64
65         /* go through each node for the minimum NbCOF (in multiple of CLKIN/2) */
66         for(i=0; i < numOfNode; i++)
67         {
68                 /* stub function for APIC ID virtualization for large MP system later */
69                 deviceId = translateNodeIdToDeviceIdNb(i);
70
71                 /* read all P-state spec registers for NbDid=1 */
72                 for(j=0; j < 5; j++)
73                 {
74                         AmdPCIRead(MAKE_SBDFO(0,0,deviceId,FN_4,PS_SPEC_REG+(j*PCI_REG_LEN)), &dtemp); /*F4x1E0 + j*4 */
75                         /* get NbDid */
76                         if(dtemp & NB_DID_MASK)
77                                 nbDid = 1;
78                 }
79                 /* if F3x1FC[NbCofVidUpdate]=0, NbFid =  default value */
80                 AmdPCIRead(MAKE_SBDFO(0,0,deviceId,FN_3,PRCT_INFO), &dtemp); /*F3x1FC*/
81                 if(!(dtemp & NB_CV_UPDATE)) /* F3x1FC[NbCofVidUpdated]=0, use default VID */
82                 {
83                         AmdPCIRead(MAKE_SBDFO(0,0,deviceId,FN_3,CPTC0), &dtemp); /*F3xD4*/
84                         nextNbFid = (u8) (dtemp & BIT_MASK_5);
85                         if(nbDid)
86                                 nextNbFid = (u8) (nextNbFid >> 1);
87                 }
88                 else
89                 {
90                         /* check PVI/SPI */
91                         AmdPCIRead(MAKE_SBDFO(0,0,deviceId,FN_3,PW_CTL_MISC), &dtemp); /*F3xA0*/
92                         if(dtemp & PVI_MODE) /* PVI */
93                         {
94                                 AmdPCIRead(MAKE_SBDFO(0,0,deviceId,FN_3,PRCT_INFO), &dtemp); /*F3x1FC*/
95                                 nextNbFid = (u8) (dtemp >> UNI_NB_FID_BIT);
96                                 nextNbFid &= BIT_MASK_5;
97                                 /* if(nbDid)
98                                         nextNbFid = nextNbFid  >> 1; */
99                         }
100                         else /* SVI */
101                         {
102                                 AmdPCIRead(MAKE_SBDFO(0,0,deviceId,FN_3,PRCT_INFO), &dtemp); /*F3x1FC*/
103                                 nextNbFid = (u8) ((dtemp >> UNI_NB_FID_BIT) & BIT_MASK_5);
104                                 nextNbFid = (u8) (nextNbFid + ((dtemp >> SPLT_NB_FID_OFFSET) & BIT_MASK_3));
105                                 /* if(nbDid)
106                                         nextNbFid = nextNbFid >> 1; */
107                         }
108                 }
109                 if( i == 0)
110                         nbFid = nextNbFid;
111                 else if( nbFid > nextNbFid )
112                 nbFid = nextNbFid;
113         }
114
115         /* add the base and convert to 100MHz divide by 2 if DID=1 */
116         if(nbDid)
117                 nbFid = (u8) (nbFid + 4);
118         else
119                 nbFid = (u8) ((nbFid + 4) << 1);
120         return nbFid;
121 }
122
123 u8 getNumOfNodeNb(void)
124 {
125         u32 dtemp;
126
127         AmdPCIRead(MAKE_SBDFO(0,0,24,0,0x60), &dtemp);
128         dtemp = (dtemp >> 4) & BIT_MASK_3;
129         dtemp++;
130         return (u8)dtemp;
131 }
132
133 /*----------------------------------------------------------------------------
134  * FUNCTION: translateNodeIdToDeviceId
135  * INPUT: u8 nodeId - node ID of the node
136  * OUTPUT: u8 - PCI device ID of the node
137  * DESCRIPTION:
138  * This function return the PCI device ID for PCI access using node ID.
139  * This function may need to chnage node ID to device ID in big MP systems.
140  * ----------------------------------------------------------------------------
141  */
142 u8 translateNodeIdToDeviceIdNb(u8 nodeId)
143 {
144         return (u8) (nodeId+PCI_DEV_BASE);
145 }