b153eef71ec834ddb01f636305b5d53f33f60480
[coreboot.git] / src / northbridge / amd / amdmct / mct_ddr3 / mutilc_d.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2010 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 /* This file contains functions for common utility functions */
21
22 /*
23  *-----------------------------------------------------------------------------
24  *              MODULES USED
25  *
26  *-----------------------------------------------------------------------------
27  */
28
29 /*
30  *-----------------------------------------------------------------------------
31  *              EXPORTED FUNCTIONS
32  *
33  *-----------------------------------------------------------------------------
34  */
35
36 static void AmdMemPCIReadBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue)
37 {
38         /* ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0); */
39
40         AmdMemPCIRead(loc, pValue);
41         *pValue = *pValue >> lowbit;  /* Shift */
42
43         /* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */
44         if ((highbit-lowbit) != 31)
45                 *pValue &= (((u32)1 << (highbit-lowbit+1))-1);
46 }
47
48 static void AmdMemPCIWriteBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue)
49 {
50         u32 temp, mask;
51
52         /* ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0); */
53
54         /* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */
55         if ((highbit-lowbit) != 31)
56                 mask = (((u32)1 << (highbit-lowbit+1))-1);
57         else
58                 mask = (u32)0xFFFFFFFF;
59
60         AmdMemPCIRead(loc, &temp);
61         temp &= ~(mask << lowbit);
62         temp |= (*pValue & mask) << lowbit;
63         AmdMemPCIWrite(loc, &temp);
64 }
65
66 /*-----------------------------------------------------------------------------
67  * uint 32
68  * u32 bitTestSet(u32 csMask,u32 tempD)
69  *
70  * Description:
71  *     This routine sets a bit in a u32
72  *
73  * Parameters:
74  *     IN        csMask = Target value in which the bit will be set
75  *     IN        tempD     =  Bit that will be set
76  *     OUT    value     =  Target value with the bit set
77  *-----------------------------------------------------------------------------
78  */
79 static u32 bitTestSet(u32 csMask,u32 tempD)
80 {
81         u32 localTemp;
82         /* ASSERT(tempD < 32); */
83         localTemp = 1;
84         csMask |= localTemp << tempD;
85         return csMask;
86 }
87
88 /*-----------------------------------------------------------------------------
89  * uint 32
90  * u32 bitTestReset(u32 csMask,u32 tempD)
91  *
92  * Description:
93  *     This routine re-sets a bit in a u32
94  *
95  * Parameters:
96  *     IN        csMask = Target value in which the bit will be re-set
97  *     IN        tempD     =  Bit that will be re-set
98  *     OUT    value     =  Target value with the bit re-set
99  *-----------------------------------------------------------------------------
100  */
101 static u32 bitTestReset(u32 csMask,u32 tempD)
102 {
103         u32 temp, localTemp;
104         /* ASSERT(tempD < 32); */
105         localTemp = 1;
106         temp = localTemp << tempD;
107         temp = ~temp;
108         csMask &= temp;
109         return csMask;
110 }
111
112 /*-----------------------------------------------------------------------------
113  * uint 32
114  *  u32 get_Bits(DCTStruct *DCTData, u8 DCT, u8 Node, u8 func, u16 offset,
115  *                 u8 low, u8 high)
116  *
117  * Description:
118  *     This routine Gets the PCT bits from the specidfied Node, DCT and PCI address
119  *
120  * Parameters:
121  *   IN  OUT *DCTData - Pointer to buffer with information about each DCT
122  *     IN        DCT - DCT number
123  *              - 1 indicates DCT 1
124  *              - 0 indicates DCT 0
125  *              - 2 both DCTs
126  *          Node - Node number
127  *          Func - PCI Function number
128  *          Offset - PCI register number
129  *          Low - Low bit of the bit field
130  *          High - High bit of the bit field
131  *
132  *     OUT    value     =  Value read from PCI space
133  *-----------------------------------------------------------------------------
134  */
135 static u32 get_Bits(sDCTStruct *pDCTData,
136                 u8 dct, u8 node, u8 func,
137                 u16 offset, u8 low, u8 high)
138 {
139         u32 temp;
140         /* ASSERT(node < MAX_NODES); */
141         if (dct == BOTH_DCTS)
142         {
143                 /* Registers exist on DCT0 only */
144                 AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
145         }
146         else
147         {
148                 if (dct == 1)
149                 {
150                         /* Write to dct 1 */
151                         offset += 0x100;
152                         AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
153                 }
154                 else
155                 {
156                         /* Write to dct 0 */
157                         AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
158                 }
159         }
160         return temp;
161 }
162
163 /*-----------------------------------------------------------------------------
164  * uint 32
165  *  void set_Bits(DCTStruct *DCTData,u8 DCT,u8 Node,u8 func, u16 offset,
166  *                u8 low, u8 high, u32 value)
167  *
168  * Description:
169  *     This routine Sets the PCT bits from the specidfied Node, DCT and PCI address
170  *
171  * Parameters:
172  *   IN  OUT *DCTData - Pointer to buffer with information about each DCT
173  *     IN        DCT - DCT number
174  *              - 1 indicates DCT 1
175  *              - 0 indicates DCT 0
176  *              - 2 both DCTs
177  *          Node - Node number
178  *          Func - PCI Function number
179  *          Offset - PCI register number
180  *          Low - Low bit of the bit field
181  *          High - High bit of the bit field
182  *
183  *     OUT
184  *-----------------------------------------------------------------------------
185  */
186 static void set_Bits(sDCTStruct *pDCTData,
187                 u8 dct, u8 node, u8 func,
188                 u16 offset, u8 low, u8 high, u32 value)
189 {
190         u32 temp;
191         temp = value;
192
193         if (dct == BOTH_DCTS)
194         {
195                 /* Registers exist on DCT0 only */
196                 AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
197         }
198         else
199         {
200                 if (dct == 1)
201                 {
202                         /* Write to dct 1 */
203                         offset += 0x100;
204                         AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
205                 }
206                 else
207                 {
208                         /* Write to dct 0 */
209                         AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
210                 }
211         }
212 }
213
214 /*-------------------------------------------------
215  * uint 32
216  *  u32 get_ADD_DCT_Bits(DCTStruct *DCTData,u8 DCT,u8 Node,u8 func,
217  *                         u16 offset,u8 low, u8 high)
218  *
219  * Description:
220  *     This routine gets the Additional PCT register from Function 2 by specidfied
221  *   Node, DCT and PCI address
222  *
223  * Parameters:
224  *   IN  OUT *DCTData - Pointer to buffer with information about each DCT
225  *     IN        DCT - DCT number
226  *              - 1 indicates DCT 1
227  *              - 0 indicates DCT 0
228  *              - 2 both DCTs
229  *          Node - Node number
230  *          Func - PCI Function number
231  *          Offset - Additional PCI register number
232  *          Low - Low bit of the bit field
233  *          High - High bit of the bit field
234  *
235  *     OUT
236  *-------------------------------------------------
237  */
238 static u32 get_ADD_DCT_Bits(sDCTStruct *pDCTData,
239                 u8 dct, u8 node, u8 func,
240                 u16 offset, u8 low, u8 high)
241 {
242         u32 tempD;
243         tempD = offset;
244         tempD = bitTestReset(tempD,DctAccessWrite);
245         set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG,
246                 PCI_MIN_LOW, PCI_MAX_HIGH, offset);
247         while ((get_Bits(pDCTData,dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG,
248                         DctAccessDone, DctAccessDone)) == 0);
249         return (get_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_PORT_REG,
250                         low, high));
251 }
252
253 /*-------------------------------------------------
254  * uint 32
255  *  void set_DCT_ADDR_Bits(DCTStruct *DCTData, u8 DCT,u8 Node,u8 func,
256  *                         u16 offset,u8 low, u8 high, u32 value)
257  *
258  * Description:
259  *     This routine sets the Additional PCT register from Function 2 by specidfied
260  *   Node, DCT and PCI address
261  *
262  * Parameters:
263  *   IN  OUT *DCTData - Pointer to buffer with information about each DCT
264  *     IN        DCT - DCT number
265  *              - 1 indicates DCT 1
266  *              - 0 indicates DCT 0
267  *              - 2 both DCTs
268  *          Node - Node number
269  *          Func - PCI Function number
270  *          Offset - Additional PCI register number
271  *          Low - Low bit of the bit field
272  *          High - High bit of the bit field
273  *
274  *     OUT
275  *-------------------------------------------------
276  */
277 static void set_DCT_ADDR_Bits(sDCTStruct *pDCTData,
278                 u8 dct, u8 node, u8 func,
279                 u16 offset, u8 low, u8 high, u32 value)
280 {
281         u32 tempD;
282
283         set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG,
284                 PCI_MIN_LOW, PCI_MAX_HIGH, offset);
285         while ((get_Bits(pDCTData,dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG,
286                         DctAccessDone, DctAccessDone)) == 0);
287
288         set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_PORT_REG,
289                 low, high, value);
290         tempD = offset;
291         tempD = bitTestSet(tempD,DctAccessWrite);
292         set_Bits(pDCTData, dct, node, FUN_DCT,DRAM_CONTROLLER_ADD_DATA_OFFSET_REG,
293                 PCI_MIN_LOW, PCI_MAX_HIGH, tempD);
294         while ((get_Bits(pDCTData,dct, pDCTData->NodeId, FUN_DCT,
295                         DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, DctAccessDone,
296                         DctAccessDone)) == 0);
297 }
298
299 /*-------------------------------------------------
300  * uint 32
301  * BOOL bitTest(u32 value, u8 bitLoc)
302  *
303  * Description:
304  *     This routine tests the value to determine if the bitLoc is set
305  *
306  * Parameters:
307  *     IN        Value - value to be tested
308  *          bitLoc - bit location to be tested
309  *     OUT    TRUE - bit is set
310  *          FALSE - bit is clear
311  *-------------------------------------------------
312  */
313 static BOOL bitTest(u32 value, u8 bitLoc)
314 {
315         u32 tempD, compD;
316         tempD = value;
317         compD = 0;
318         compD = bitTestSet(compD,bitLoc);
319         tempD &= compD;
320         if (compD == tempD)
321         {
322                 return TRUE;
323         }
324         else
325         {
326                 return FALSE;
327         }
328 }