blob: 18cad7eae70e817c0f780d2802c53eabd463c020 [file] [log] [blame]
Zheng Baoeb75f652010-04-23 17:32:48 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2010 Advanced Micro Devices, Inc.
Timothy Pearson730a0432015-10-16 13:51:51 -05005 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
Zheng Baoeb75f652010-04-23 17:32:48 +00006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Zheng Baoeb75f652010-04-23 17:32:48 +000015 */
16
17/* This file contains functions for common utility functions */
18
19/*
20 *-----------------------------------------------------------------------------
21 * MODULES USED
22 *
23 *-----------------------------------------------------------------------------
24 */
25
26/*
27 *-----------------------------------------------------------------------------
28 * EXPORTED FUNCTIONS
29 *
30 *-----------------------------------------------------------------------------
31 */
32
33static void AmdMemPCIReadBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue)
34{
35 /* ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0); */
36
37 AmdMemPCIRead(loc, pValue);
38 *pValue = *pValue >> lowbit; /* Shift */
39
40 /* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */
41 if ((highbit-lowbit) != 31)
42 *pValue &= (((u32)1 << (highbit-lowbit+1))-1);
43}
44
45static void AmdMemPCIWriteBits(SBDFO loc, u8 highbit, u8 lowbit, u32 *pValue)
46{
47 u32 temp, mask;
48
49 /* ASSERT(highbit < 32 && lowbit < 32 && highbit >= lowbit && (loc & 3) == 0); */
50
51 /* A 1<<32 == 1<<0 due to x86 SHL instruction, so skip if that is the case */
52 if ((highbit-lowbit) != 31)
53 mask = (((u32)1 << (highbit-lowbit+1))-1);
54 else
55 mask = (u32)0xFFFFFFFF;
56
57 AmdMemPCIRead(loc, &temp);
58 temp &= ~(mask << lowbit);
59 temp |= (*pValue & mask) << lowbit;
60 AmdMemPCIWrite(loc, &temp);
61}
62
63/*-----------------------------------------------------------------------------
Zheng Baoeb75f652010-04-23 17:32:48 +000064 * u32 bitTestSet(u32 csMask,u32 tempD)
65 *
66 * Description:
67 * This routine sets a bit in a u32
68 *
69 * Parameters:
70 * IN csMask = Target value in which the bit will be set
71 * IN tempD = Bit that will be set
72 * OUT value = Target value with the bit set
73 *-----------------------------------------------------------------------------
74 */
75static u32 bitTestSet(u32 csMask,u32 tempD)
76{
77 u32 localTemp;
78 /* ASSERT(tempD < 32); */
79 localTemp = 1;
80 csMask |= localTemp << tempD;
81 return csMask;
82}
83
84/*-----------------------------------------------------------------------------
Zheng Baoeb75f652010-04-23 17:32:48 +000085 * u32 bitTestReset(u32 csMask,u32 tempD)
86 *
87 * Description:
88 * This routine re-sets a bit in a u32
89 *
90 * Parameters:
91 * IN csMask = Target value in which the bit will be re-set
92 * IN tempD = Bit that will be re-set
93 * OUT value = Target value with the bit re-set
94 *-----------------------------------------------------------------------------
95 */
96static u32 bitTestReset(u32 csMask,u32 tempD)
97{
98 u32 temp, localTemp;
99 /* ASSERT(tempD < 32); */
100 localTemp = 1;
101 temp = localTemp << tempD;
102 temp = ~temp;
103 csMask &= temp;
104 return csMask;
105}
106
107/*-----------------------------------------------------------------------------
Zheng Baoeb75f652010-04-23 17:32:48 +0000108 * u32 get_Bits(DCTStruct *DCTData, u8 DCT, u8 Node, u8 func, u16 offset,
109 * u8 low, u8 high)
110 *
111 * Description:
Zheng Bao53b52f32010-10-09 07:18:50 +0000112 * This routine Gets the PCT bits from the specified Node, DCT and PCI address
Zheng Baoeb75f652010-04-23 17:32:48 +0000113 *
114 * Parameters:
115 * IN OUT *DCTData - Pointer to buffer with information about each DCT
116 * IN DCT - DCT number
117 * - 1 indicates DCT 1
118 * - 0 indicates DCT 0
119 * - 2 both DCTs
120 * Node - Node number
121 * Func - PCI Function number
122 * Offset - PCI register number
123 * Low - Low bit of the bit field
124 * High - High bit of the bit field
125 *
126 * OUT value = Value read from PCI space
127 *-----------------------------------------------------------------------------
128 */
129static u32 get_Bits(sDCTStruct *pDCTData,
130 u8 dct, u8 node, u8 func,
131 u16 offset, u8 low, u8 high)
132{
133 u32 temp;
Timothy Pearson730a0432015-10-16 13:51:51 -0500134 uint32_t dword;
135
Zheng Baoeb75f652010-04-23 17:32:48 +0000136 /* ASSERT(node < MAX_NODES); */
137 if (dct == BOTH_DCTS)
138 {
139 /* Registers exist on DCT0 only */
Timothy Pearson730a0432015-10-16 13:51:51 -0500140 if (is_fam15h())
141 {
142 /* Select DCT 0 */
143 AmdMemPCIRead(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
144 dword &= ~0x1;
145 AmdMemPCIWrite(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
146 }
147
Zheng Baoeb75f652010-04-23 17:32:48 +0000148 AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
149 }
150 else
151 {
Timothy Pearson730a0432015-10-16 13:51:51 -0500152 if (is_fam15h())
Zheng Baoeb75f652010-04-23 17:32:48 +0000153 {
Timothy Pearson730a0432015-10-16 13:51:51 -0500154 /* Select DCT */
155 AmdMemPCIRead(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
156 dword &= ~0x1;
157 dword |= (dct & 0x1);
158 AmdMemPCIWrite(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
159
160 /* Read from the selected DCT */
Zheng Baoeb75f652010-04-23 17:32:48 +0000161 AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
162 }
163 else
164 {
Timothy Pearson730a0432015-10-16 13:51:51 -0500165 if (dct == 1)
166 {
167 /* Read from dct 1 */
168 offset += 0x100;
169 AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
170 }
171 else
172 {
173 /* Read from dct 0 */
174 AmdMemPCIReadBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
175 }
Zheng Baoeb75f652010-04-23 17:32:48 +0000176 }
177 }
178 return temp;
179}
180
181/*-----------------------------------------------------------------------------
Zheng Baoeb75f652010-04-23 17:32:48 +0000182 * void set_Bits(DCTStruct *DCTData,u8 DCT,u8 Node,u8 func, u16 offset,
183 * u8 low, u8 high, u32 value)
184 *
185 * Description:
Zheng Bao53b52f32010-10-09 07:18:50 +0000186 * This routine Sets the PCT bits from the specified Node, DCT and PCI address
Zheng Baoeb75f652010-04-23 17:32:48 +0000187 *
188 * Parameters:
189 * IN OUT *DCTData - Pointer to buffer with information about each DCT
190 * IN DCT - DCT number
191 * - 1 indicates DCT 1
192 * - 0 indicates DCT 0
193 * - 2 both DCTs
194 * Node - Node number
195 * Func - PCI Function number
196 * Offset - PCI register number
197 * Low - Low bit of the bit field
198 * High - High bit of the bit field
199 *
200 * OUT
201 *-----------------------------------------------------------------------------
202 */
203static void set_Bits(sDCTStruct *pDCTData,
204 u8 dct, u8 node, u8 func,
205 u16 offset, u8 low, u8 high, u32 value)
206{
207 u32 temp;
Timothy Pearson730a0432015-10-16 13:51:51 -0500208 uint32_t dword;
209
Zheng Baoeb75f652010-04-23 17:32:48 +0000210 temp = value;
211
212 if (dct == BOTH_DCTS)
213 {
214 /* Registers exist on DCT0 only */
Timothy Pearson730a0432015-10-16 13:51:51 -0500215 if (is_fam15h())
216 {
217 /* Select DCT 0 */
218 AmdMemPCIRead(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
219 dword &= ~0x1;
220 AmdMemPCIWrite(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
221 }
222
Zheng Baoeb75f652010-04-23 17:32:48 +0000223 AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
224 }
225 else
226 {
Timothy Pearson730a0432015-10-16 13:51:51 -0500227 if (is_fam15h())
Zheng Baoeb75f652010-04-23 17:32:48 +0000228 {
Timothy Pearson730a0432015-10-16 13:51:51 -0500229 /* Select DCT */
230 AmdMemPCIRead(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
231 dword &= ~0x1;
232 dword |= (dct & 0x1);
233 AmdMemPCIWrite(MAKE_SBDFO(0,0,24+node,1,0x10c), &dword);
234
235 /* Write to the selected DCT */
Zheng Baoeb75f652010-04-23 17:32:48 +0000236 AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
237 }
238 else
239 {
Timothy Pearson730a0432015-10-16 13:51:51 -0500240 if (dct == 1)
241 {
242 /* Write to dct 1 */
243 offset += 0x100;
244 AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
245 }
246 else
247 {
248 /* Write to dct 0 */
249 AmdMemPCIWriteBits(MAKE_SBDFO(0,0,24+node,func,offset), high, low, &temp);
250 }
Zheng Baoeb75f652010-04-23 17:32:48 +0000251 }
252 }
253}
254
255/*-------------------------------------------------
Zheng Baoeb75f652010-04-23 17:32:48 +0000256 * u32 get_ADD_DCT_Bits(DCTStruct *DCTData,u8 DCT,u8 Node,u8 func,
257 * u16 offset,u8 low, u8 high)
258 *
259 * Description:
Zheng Bao53b52f32010-10-09 07:18:50 +0000260 * This routine gets the Additional PCT register from Function 2 by specified
Zheng Baoeb75f652010-04-23 17:32:48 +0000261 * Node, DCT and PCI address
262 *
263 * Parameters:
264 * IN OUT *DCTData - Pointer to buffer with information about each DCT
265 * IN DCT - DCT number
266 * - 1 indicates DCT 1
267 * - 0 indicates DCT 0
268 * - 2 both DCTs
269 * Node - Node number
270 * Func - PCI Function number
271 * Offset - Additional PCI register number
272 * Low - Low bit of the bit field
273 * High - High bit of the bit field
274 *
275 * OUT
276 *-------------------------------------------------
277 */
278static u32 get_ADD_DCT_Bits(sDCTStruct *pDCTData,
279 u8 dct, u8 node, u8 func,
280 u16 offset, u8 low, u8 high)
281{
282 u32 tempD;
283 tempD = offset;
284 tempD = bitTestReset(tempD,DctAccessWrite);
285 set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG,
286 PCI_MIN_LOW, PCI_MAX_HIGH, offset);
287 while ((get_Bits(pDCTData,dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG,
288 DctAccessDone, DctAccessDone)) == 0);
289 return (get_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_PORT_REG,
290 low, high));
291}
292
293/*-------------------------------------------------
Zheng Baoeb75f652010-04-23 17:32:48 +0000294 * void set_DCT_ADDR_Bits(DCTStruct *DCTData, u8 DCT,u8 Node,u8 func,
295 * u16 offset,u8 low, u8 high, u32 value)
296 *
297 * Description:
Zheng Bao53b52f32010-10-09 07:18:50 +0000298 * This routine sets the Additional PCT register from Function 2 by specified
Zheng Baoeb75f652010-04-23 17:32:48 +0000299 * Node, DCT and PCI address
300 *
301 * Parameters:
302 * IN OUT *DCTData - Pointer to buffer with information about each DCT
303 * IN DCT - DCT number
304 * - 1 indicates DCT 1
305 * - 0 indicates DCT 0
306 * - 2 both DCTs
307 * Node - Node number
308 * Func - PCI Function number
309 * Offset - Additional PCI register number
310 * Low - Low bit of the bit field
311 * High - High bit of the bit field
312 *
313 * OUT
314 *-------------------------------------------------
315 */
316static void set_DCT_ADDR_Bits(sDCTStruct *pDCTData,
317 u8 dct, u8 node, u8 func,
318 u16 offset, u8 low, u8 high, u32 value)
319{
320 u32 tempD;
321
322 set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG,
323 PCI_MIN_LOW, PCI_MAX_HIGH, offset);
324 while ((get_Bits(pDCTData,dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_OFFSET_REG,
325 DctAccessDone, DctAccessDone)) == 0);
326
327 set_Bits(pDCTData, dct, node, FUN_DCT, DRAM_CONTROLLER_ADD_DATA_PORT_REG,
328 low, high, value);
329 tempD = offset;
330 tempD = bitTestSet(tempD,DctAccessWrite);
331 set_Bits(pDCTData, dct, node, FUN_DCT,DRAM_CONTROLLER_ADD_DATA_OFFSET_REG,
332 PCI_MIN_LOW, PCI_MAX_HIGH, tempD);
333 while ((get_Bits(pDCTData,dct, pDCTData->NodeId, FUN_DCT,
334 DRAM_CONTROLLER_ADD_DATA_OFFSET_REG, DctAccessDone,
335 DctAccessDone)) == 0);
336}
337
338/*-------------------------------------------------
Zheng Baoeb75f652010-04-23 17:32:48 +0000339 * BOOL bitTest(u32 value, u8 bitLoc)
340 *
341 * Description:
342 * This routine tests the value to determine if the bitLoc is set
343 *
344 * Parameters:
345 * IN Value - value to be tested
346 * bitLoc - bit location to be tested
347 * OUT TRUE - bit is set
348 * FALSE - bit is clear
349 *-------------------------------------------------
350 */
351static BOOL bitTest(u32 value, u8 bitLoc)
352{
353 u32 tempD, compD;
354 tempD = value;
355 compD = 0;
356 compD = bitTestSet(compD,bitLoc);
357 tempD &= compD;
358 if (compD == tempD)
359 {
360 return TRUE;
361 }
362 else
363 {
364 return FALSE;
365 }
366}