c8379ff16f969ec53e8eb9cf7b38f335318ed54c
[coreboot.git] / src / mainboard / amd / persimmon / BiosCallOuts.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2011 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 #include "agesawrapper.h"
21 #include "amdlib.h"
22 #include "dimmSpd.h"
23 #include "BiosCallOuts.h"
24 #include "heapManager.h"
25 #include "SB800.h"
26
27 STATIC BIOS_CALLOUT_STRUCT BiosCallouts[] =
28 {
29         {AGESA_ALLOCATE_BUFFER,
30          BiosAllocateBuffer
31         },
32
33         {AGESA_DEALLOCATE_BUFFER,
34          BiosDeallocateBuffer
35         },
36
37         {AGESA_DO_RESET,
38          BiosReset
39         },
40
41         {AGESA_LOCATE_BUFFER,
42          BiosLocateBuffer
43         },
44
45         {AGESA_READ_SPD,
46          BiosReadSpd
47         },
48
49         {AGESA_READ_SPD_RECOVERY,
50          BiosDefaultRet
51         },
52
53         {AGESA_RUNFUNC_ONAP,
54          BiosRunFuncOnAp
55         },
56
57         {AGESA_GNB_PCIE_SLOT_RESET,
58          BiosGnbPcieSlotReset
59         },
60
61         {AGESA_HOOKBEFORE_DRAM_INIT,
62          BiosHookBeforeDramInit
63         },
64
65         {AGESA_HOOKBEFORE_DRAM_INIT_RECOVERY,
66          BiosHookBeforeDramInitRecovery
67         },
68
69         {AGESA_HOOKBEFORE_DQS_TRAINING,
70          BiosHookBeforeDQSTraining
71         },
72
73         {AGESA_HOOKBEFORE_EXIT_SELF_REF,
74          BiosHookBeforeExitSelfRefresh
75         },
76 };
77
78 AGESA_STATUS GetBiosCallout (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
79 {
80         UINTN i;
81         AGESA_STATUS CalloutStatus;
82         UINTN CallOutCount = sizeof (BiosCallouts) / sizeof (BiosCallouts [0]);
83
84         CalloutStatus = AGESA_UNSUPPORTED;
85
86         for (i = 0; i < CallOutCount; i++) {
87                 if (BiosCallouts[i].CalloutName == Func) {
88                         CalloutStatus = BiosCallouts[i].CalloutPtr (Func, Data, ConfigPtr);
89                         return CalloutStatus;
90                 }
91         }
92
93         return CalloutStatus;
94 }
95
96 AGESA_STATUS BiosAllocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
97 {
98         UINT32                          AvailableHeapSize;
99         UINT8                           *BiosHeapBaseAddr;
100         UINT32                          CurrNodeOffset;
101         UINT32                          PrevNodeOffset;
102         UINT32                          FreedNodeOffset;
103         UINT32                          BestFitNodeOffset;
104         UINT32                          BestFitPrevNodeOffset;
105         UINT32                          NextFreeOffset;
106         BIOS_BUFFER_NODE        *CurrNodePtr;
107         BIOS_BUFFER_NODE        *FreedNodePtr;
108         BIOS_BUFFER_NODE        *BestFitNodePtr;
109         BIOS_BUFFER_NODE        *BestFitPrevNodePtr;
110         BIOS_BUFFER_NODE        *NextFreePtr;
111         BIOS_HEAP_MANAGER       *BiosHeapBasePtr;
112         AGESA_BUFFER_PARAMS *AllocParams;
113
114         AllocParams = ((AGESA_BUFFER_PARAMS *) ConfigPtr);
115         AllocParams->BufferPointer = NULL;
116
117         AvailableHeapSize = BIOS_HEAP_SIZE - sizeof (BIOS_HEAP_MANAGER);
118         BiosHeapBaseAddr = (UINT8 *) BIOS_HEAP_START_ADDRESS;
119         BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BIOS_HEAP_START_ADDRESS;
120
121         if (BiosHeapBasePtr->StartOfAllocatedNodes == 0) {
122                 /* First allocation */
123                 CurrNodeOffset = sizeof (BIOS_HEAP_MANAGER);
124                 CurrNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + CurrNodeOffset);
125                 CurrNodePtr->BufferHandle = AllocParams->BufferHandle;
126                 CurrNodePtr->BufferSize = AllocParams->BufferLength;
127                 CurrNodePtr->NextNodeOffset = 0;
128                 AllocParams->BufferPointer = (UINT8 *) CurrNodePtr + sizeof (BIOS_BUFFER_NODE);
129
130                 /* Update the remaining free space */
131                 FreedNodeOffset = CurrNodeOffset + CurrNodePtr->BufferSize + sizeof (BIOS_BUFFER_NODE);
132                 FreedNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + FreedNodeOffset);
133                 FreedNodePtr->BufferSize = AvailableHeapSize - sizeof (BIOS_BUFFER_NODE) - CurrNodePtr->BufferSize;
134                 FreedNodePtr->NextNodeOffset = 0;
135
136                 /* Update the offsets for Allocated and Freed nodes */
137                 BiosHeapBasePtr->StartOfAllocatedNodes = CurrNodeOffset;
138                 BiosHeapBasePtr->StartOfFreedNodes = FreedNodeOffset;
139         } else {
140                 /* Find out whether BufferHandle has been allocated on the heap. */
141                 /* If it has, return AGESA_BOUNDS_CHK */
142                 CurrNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
143                 CurrNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + CurrNodeOffset);
144
145                 while (CurrNodeOffset != 0) {
146                         CurrNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + CurrNodeOffset);
147                         if (CurrNodePtr->BufferHandle == AllocParams->BufferHandle) {
148                                 return AGESA_BOUNDS_CHK;
149                         }
150                         CurrNodeOffset = CurrNodePtr->NextNodeOffset;
151                         /* If BufferHandle has not been allocated on the heap, CurrNodePtr here points
152                          to the end of the allocated nodes list.
153                         */
154                 }
155                 /* Find the node that best fits the requested buffer size */
156                 FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes;
157                 PrevNodeOffset = FreedNodeOffset;
158                 BestFitNodeOffset = 0;
159                 BestFitPrevNodeOffset = 0;
160                 while (FreedNodeOffset != 0) {
161                         FreedNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + FreedNodeOffset);
162                         if (FreedNodePtr->BufferSize >= (AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE))) {
163                                 if (BestFitNodeOffset == 0) {
164                                         /* First node that fits the requested buffer size */
165                                         BestFitNodeOffset = FreedNodeOffset;
166                                         BestFitPrevNodeOffset = PrevNodeOffset;
167                                 } else {
168                                         /* Find out whether current node is a better fit than the previous nodes */
169                                         BestFitNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + BestFitNodeOffset);
170                                         if (BestFitNodePtr->BufferSize > FreedNodePtr->BufferSize) {
171                                                 BestFitNodeOffset = FreedNodeOffset;
172                                                 BestFitPrevNodeOffset = PrevNodeOffset;
173                                         }
174                                 }
175                         }
176                         PrevNodeOffset = FreedNodeOffset;
177                         FreedNodeOffset = FreedNodePtr->NextNodeOffset;
178                 } /* end of while loop */
179
180
181                 if (BestFitNodeOffset == 0) {
182                         /* If we could not find a node that fits the requested buffer */
183                         /* size, return AGESA_BOUNDS_CHK */
184                         return AGESA_BOUNDS_CHK;
185                 } else {
186                         BestFitNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + BestFitNodeOffset);
187                         BestFitPrevNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + BestFitPrevNodeOffset);
188
189                         /* If BestFitNode is larger than the requested buffer, fragment the node further */
190                         if (BestFitNodePtr->BufferSize > (AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE))) {
191                                 NextFreeOffset = BestFitNodeOffset + AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE);
192
193                                 NextFreePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + NextFreeOffset);
194                                 NextFreePtr->BufferSize = BestFitNodePtr->BufferSize - (AllocParams->BufferLength + sizeof (BIOS_BUFFER_NODE));
195                                 NextFreePtr->NextNodeOffset = BestFitNodePtr->NextNodeOffset;
196                         } else {
197                                 /* Otherwise, next free node is NextNodeOffset of BestFitNode */
198                                 NextFreeOffset = BestFitNodePtr->NextNodeOffset;
199                         }
200
201                         /* If BestFitNode is the first buffer in the list, then update
202                          StartOfFreedNodes to reflect the new free node
203                         */
204                         if (BestFitNodeOffset == BiosHeapBasePtr->StartOfFreedNodes) {
205                                 BiosHeapBasePtr->StartOfFreedNodes = NextFreeOffset;
206                         } else {
207                                 BestFitPrevNodePtr->NextNodeOffset = NextFreeOffset;
208                         }
209
210                         /* Add BestFitNode to the list of Allocated nodes */
211                         CurrNodePtr->NextNodeOffset = BestFitNodeOffset;
212                         BestFitNodePtr->BufferSize = AllocParams->BufferLength;
213                         BestFitNodePtr->BufferHandle = AllocParams->BufferHandle;
214                         BestFitNodePtr->NextNodeOffset = 0;
215
216                         /* Remove BestFitNode from list of Freed nodes */
217                         AllocParams->BufferPointer = (UINT8 *) BestFitNodePtr + sizeof (BIOS_BUFFER_NODE);
218                 }
219         }
220
221         return AGESA_SUCCESS;
222 }
223
224 AGESA_STATUS BiosDeallocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
225 {
226
227         UINT8                            *BiosHeapBaseAddr;
228         UINT32                          AllocNodeOffset;
229         UINT32                          PrevNodeOffset;
230         UINT32                          NextNodeOffset;
231         UINT32                          FreedNodeOffset;
232         UINT32                          EndNodeOffset;
233         BIOS_BUFFER_NODE         *AllocNodePtr;
234         BIOS_BUFFER_NODE         *PrevNodePtr;
235         BIOS_BUFFER_NODE         *FreedNodePtr;
236         BIOS_BUFFER_NODE         *NextNodePtr;
237         BIOS_HEAP_MANAGER       *BiosHeapBasePtr;
238         AGESA_BUFFER_PARAMS *AllocParams;
239
240         BiosHeapBaseAddr = (UINT8 *) BIOS_HEAP_START_ADDRESS;
241         BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BIOS_HEAP_START_ADDRESS;
242
243         AllocParams = (AGESA_BUFFER_PARAMS *) ConfigPtr;
244
245         /* Find target node to deallocate in list of allocated nodes.
246          Return AGESA_BOUNDS_CHK if the BufferHandle is not found
247         */
248         AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
249         AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
250         PrevNodeOffset = AllocNodeOffset;
251
252         while (AllocNodePtr->BufferHandle !=    AllocParams->BufferHandle) {
253                 if (AllocNodePtr->NextNodeOffset == 0) {
254                         return AGESA_BOUNDS_CHK;
255                 }
256                 PrevNodeOffset = AllocNodeOffset;
257                 AllocNodeOffset = AllocNodePtr->NextNodeOffset;
258                 AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
259         }
260
261         /* Remove target node from list of allocated nodes */
262         PrevNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + PrevNodeOffset);
263         PrevNodePtr->NextNodeOffset = AllocNodePtr->NextNodeOffset;
264
265         /* Zero out the buffer, and clear the BufferHandle */
266         LibAmdMemFill ((UINT8 *)AllocNodePtr + sizeof (BIOS_BUFFER_NODE), 0, AllocNodePtr->BufferSize, &(AllocParams->StdHeader));
267         AllocNodePtr->BufferHandle = 0;
268         AllocNodePtr->BufferSize += sizeof (BIOS_BUFFER_NODE);
269
270         /* Add deallocated node in order to the list of freed nodes */
271         FreedNodeOffset = BiosHeapBasePtr->StartOfFreedNodes;
272         FreedNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + FreedNodeOffset);
273
274         EndNodeOffset = AllocNodeOffset + AllocNodePtr->BufferSize;
275
276         if (AllocNodeOffset < FreedNodeOffset) {
277                 /* Add to the start of the freed list */
278                 if (EndNodeOffset == FreedNodeOffset) {
279                         /* If the freed node is adjacent to the first node in the list, concatenate both nodes */
280                         AllocNodePtr->BufferSize += FreedNodePtr->BufferSize;
281                         AllocNodePtr->NextNodeOffset = FreedNodePtr->NextNodeOffset;
282
283                         /* Clear the BufferSize and NextNodeOffset of the previous first node */
284                         FreedNodePtr->BufferSize = 0;
285                         FreedNodePtr->NextNodeOffset = 0;
286                 } else {
287                         /* Otherwise, add freed node to the start of the list
288                          Update NextNodeOffset and BufferSize to include the
289                          size of BIOS_BUFFER_NODE
290                         */
291                         AllocNodePtr->NextNodeOffset = FreedNodeOffset;
292                 }
293                 /* Update StartOfFreedNodes to the new first node */
294                 BiosHeapBasePtr->StartOfFreedNodes = AllocNodeOffset;
295         } else {
296                 /* Traverse list of freed nodes to find where the deallocated node
297                          should be place
298                 */
299                 NextNodeOffset = FreedNodeOffset;
300                 NextNodePtr = FreedNodePtr;
301                 while (AllocNodeOffset > NextNodeOffset) {
302                         PrevNodeOffset = NextNodeOffset;
303                         if (NextNodePtr->NextNodeOffset == 0) {
304                         break;
305                         }
306                         NextNodeOffset = NextNodePtr->NextNodeOffset;
307                         NextNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + NextNodeOffset);
308                 }
309
310                 /* If deallocated node is adjacent to the next node,
311                          concatenate both nodes
312                 */
313                 if (NextNodeOffset == EndNodeOffset) {
314                         NextNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + NextNodeOffset);
315                         AllocNodePtr->BufferSize += NextNodePtr->BufferSize;
316                         AllocNodePtr->NextNodeOffset = NextNodePtr->NextNodeOffset;
317
318                         NextNodePtr->BufferSize = 0;
319                         NextNodePtr->NextNodeOffset = 0;
320                 } else {
321                         /*AllocNodePtr->NextNodeOffset = FreedNodePtr->NextNodeOffset; */
322                         AllocNodePtr->NextNodeOffset = NextNodeOffset;
323                 }
324                 /* If deallocated node is adjacent to the previous node,
325                          concatenate both nodes
326                 */
327                 PrevNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + PrevNodeOffset);
328                 EndNodeOffset = PrevNodeOffset + PrevNodePtr->BufferSize;
329                 if (AllocNodeOffset == EndNodeOffset) {
330                         PrevNodePtr->NextNodeOffset = AllocNodePtr->NextNodeOffset;
331                         PrevNodePtr->BufferSize += AllocNodePtr->BufferSize;
332                         AllocNodePtr->BufferSize = 0;
333                         AllocNodePtr->NextNodeOffset = 0;
334                 } else {
335                         PrevNodePtr->NextNodeOffset = AllocNodeOffset;
336                 }
337         }
338         return AGESA_SUCCESS;
339 }
340
341 AGESA_STATUS BiosLocateBuffer (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
342 {
343         UINT32                          AllocNodeOffset;
344         UINT8                           *BiosHeapBaseAddr;
345         BIOS_BUFFER_NODE        *AllocNodePtr;
346         BIOS_HEAP_MANAGER       *BiosHeapBasePtr;
347         AGESA_BUFFER_PARAMS     *AllocParams;
348
349         AllocParams = (AGESA_BUFFER_PARAMS *) ConfigPtr;
350
351         BiosHeapBaseAddr = (UINT8 *) BIOS_HEAP_START_ADDRESS;
352         BiosHeapBasePtr = (BIOS_HEAP_MANAGER *) BIOS_HEAP_START_ADDRESS;
353
354         AllocNodeOffset = BiosHeapBasePtr->StartOfAllocatedNodes;
355         AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
356
357         while (AllocParams->BufferHandle != AllocNodePtr->BufferHandle) {
358                 if (AllocNodePtr->NextNodeOffset == 0) {
359                         AllocParams->BufferPointer = NULL;
360                         AllocParams->BufferLength = 0;
361                         return AGESA_BOUNDS_CHK;
362                 } else {
363                         AllocNodeOffset = AllocNodePtr->NextNodeOffset;
364                         AllocNodePtr = (BIOS_BUFFER_NODE *) (BiosHeapBaseAddr + AllocNodeOffset);
365                 }
366         }
367
368         AllocParams->BufferPointer = (UINT8 *) ((UINT8 *) AllocNodePtr + sizeof (BIOS_BUFFER_NODE));
369         AllocParams->BufferLength = AllocNodePtr->BufferSize;
370
371         return AGESA_SUCCESS;
372
373 }
374
375 AGESA_STATUS BiosRunFuncOnAp (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
376 {
377         AGESA_STATUS            Status;
378
379         Status = agesawrapper_amdlaterunaptask (Func, Data, ConfigPtr);
380         return Status;
381 }
382
383 AGESA_STATUS BiosReset (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
384 {
385         AGESA_STATUS            Status;
386         UINT8                            Value;
387         UINTN                            ResetType;
388         AMD_CONFIG_PARAMS        *StdHeader;
389
390         ResetType = Data;
391         StdHeader = ConfigPtr;
392
393         //
394         // Perform the RESET based upon the ResetType. In case of
395         // WARM_RESET_WHENVER and COLD_RESET_WHENEVER, the request will go to
396         // AmdResetManager. During the critical condition, where reset is required
397         // immediately, the reset will be invoked directly by writing 0x04 to port
398         // 0xCF9 (Reset Port).
399         //
400         switch (ResetType) {
401                 case WARM_RESET_WHENEVER:
402                 case COLD_RESET_WHENEVER:
403                 break;
404
405                 case WARM_RESET_IMMEDIATELY:
406                 case COLD_RESET_IMMEDIATELY:
407                         Value = 0x06;
408                         LibAmdIoWrite (AccessWidth8, 0xCf9, &Value, StdHeader);
409                 break;
410
411                 default:
412                 break;
413         }
414
415         Status = 0;
416         return Status;
417 }
418
419 AGESA_STATUS BiosReadSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
420 {
421         AGESA_STATUS Status;
422         Status = AmdMemoryReadSPD (Func, Data, (AGESA_READ_SPD_PARAMS *)ConfigPtr);
423
424         return Status;
425 }
426
427 AGESA_STATUS BiosDefaultRet (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
428 {
429         return AGESA_UNSUPPORTED;
430 }
431 /*      Call the host environment interface to provide a user hook opportunity. */
432 AGESA_STATUS BiosHookBeforeDQSTraining (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
433 {
434         return AGESA_SUCCESS;
435 }
436 /*      Call the host environment interface to provide a user hook opportunity. */
437 AGESA_STATUS BiosHookBeforeDramInit (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
438 {
439         AGESA_STATUS            Status;
440         UINTN                    FcnData;
441         MEM_DATA_STRUCT  *MemData;
442         UINT32                  AcpiMmioAddr;
443         UINT32                  GpioMmioAddr;
444         UINT8                    Data8;
445         UINT16                  Data16;
446         UINT8                    TempData8;
447
448         FcnData = Data;
449         MemData = ConfigPtr;
450
451         Status  = AGESA_SUCCESS;
452         /* Get SB MMIO Base (AcpiMmioAddr) */
453         WriteIo8 (0xCD6, 0x27);
454         Data8    = ReadIo8(0xCD7);
455         Data16  = Data8<<8;
456         WriteIo8 (0xCD6, 0x26);
457         Data8    = ReadIo8(0xCD7);
458         Data16  |= Data8;
459         AcpiMmioAddr = (UINT32)Data16 << 16;
460         GpioMmioAddr = AcpiMmioAddr + GPIO_BASE;
461
462         Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG178);
463         Data8 &= ~BIT5;
464         TempData8       = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG178);
465         TempData8 &= 0x03;
466         TempData8 |= Data8;
467         Write64Mem8(GpioMmioAddr+SB_GPIO_REG178, TempData8);
468
469         Data8 |= BIT2+BIT3;
470         Data8 &= ~BIT4;
471         TempData8       = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG178);
472         TempData8 &= 0x23;
473         TempData8 |= Data8;
474         Write64Mem8(GpioMmioAddr+SB_GPIO_REG178, TempData8);
475
476         Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG179);
477         Data8 &= ~BIT5;
478         TempData8       = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG179);
479         TempData8 &= 0x03;
480         TempData8 |= Data8;
481         Write64Mem8(GpioMmioAddr+SB_GPIO_REG179, TempData8);
482
483         Data8 |= BIT2+BIT3;
484         Data8 &= ~BIT4;
485         TempData8       = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG179);
486         TempData8 &= 0x23;
487         TempData8 |= Data8;
488         Write64Mem8(GpioMmioAddr+SB_GPIO_REG179, TempData8);
489
490         switch(MemData->ParameterListPtr->DDR3Voltage){
491         case VOLT1_35:
492                 Data8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG178);
493                 Data8 &= ~(UINT8)BIT6;
494                 Write64Mem8(GpioMmioAddr+SB_GPIO_REG178, Data8);
495                 Data8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG179);
496                 Data8 |= (UINT8)BIT6;
497                 Write64Mem8(GpioMmioAddr+SB_GPIO_REG179, Data8);
498                 break;
499         case VOLT1_25:
500                 Data8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG178);
501                 Data8 &= ~(UINT8)BIT6;
502                 Write64Mem8(GpioMmioAddr+SB_GPIO_REG178, Data8);
503                 Data8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG179);
504                 Data8 &= ~(UINT8)BIT6;
505                 Write64Mem8(GpioMmioAddr+SB_GPIO_REG179, Data8);
506                 break;
507         case VOLT1_5:
508         default:
509                 Data8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG178);
510                 Data8 |= (UINT8)BIT6;
511                 Write64Mem8(GpioMmioAddr+SB_GPIO_REG178, Data8);
512                 Data8 = Read64Mem8 (GpioMmioAddr+SB_GPIO_REG179);
513                 Data8 &= ~(UINT8)BIT6;
514                 Write64Mem8(GpioMmioAddr+SB_GPIO_REG179, Data8);
515         }
516         return Status;
517 }
518
519 /*      Call the host environment interface to provide a user hook opportunity. */
520 AGESA_STATUS BiosHookBeforeDramInitRecovery (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
521 {
522         return AGESA_SUCCESS;
523 }
524
525 /*      Call the host environment interface to provide a user hook opportunity. */
526 AGESA_STATUS BiosHookBeforeExitSelfRefresh (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
527 {
528         return AGESA_SUCCESS;
529 }
530 /* PCIE slot reset control */
531 AGESA_STATUS BiosGnbPcieSlotReset (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
532 {
533         AGESA_STATUS Status;
534         UINTN                                   FcnData;
535         PCIe_SLOT_RESET_INFO    *ResetInfo;
536
537         UINT32  GpioMmioAddr;
538         UINT32  AcpiMmioAddr;
539         UINT8    Data8;
540         UINT16  Data16;
541
542         FcnData = Data;
543         ResetInfo = ConfigPtr;
544         // Get SB800 MMIO Base (AcpiMmioAddr)
545         WriteIo8(0xCD6, 0x27);
546         Data8 = ReadIo8(0xCD7);
547         Data16=Data8<<8;
548         WriteIo8(0xCD6, 0x26);
549         Data8 = ReadIo8(0xCD7);
550         Data16|=Data8;
551         AcpiMmioAddr = (UINT32)Data16 << 16;
552         Status = AGESA_UNSUPPORTED;
553         GpioMmioAddr = AcpiMmioAddr + GPIO_BASE;
554         switch (ResetInfo->ResetId)
555         {
556         case 4:
557                 switch (ResetInfo->ResetControl) {
558                         case AssertSlotReset:
559                         Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG21);
560                         Data8 &= ~(UINT8)BIT6 ;
561                         Write64Mem8(GpioMmioAddr+SB_GPIO_REG21, Data8);  // MXM_GPIO0. GPIO21
562                         Status = AGESA_SUCCESS;
563                         break;
564                         case DeassertSlotReset:
565                         Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG21);
566                         Data8 |= BIT6 ;
567                         Write64Mem8 (GpioMmioAddr+SB_GPIO_REG21, Data8);                 // MXM_GPIO0. GPIO21
568                         Status = AGESA_SUCCESS;
569                         break;
570                 }
571                 break;
572         case 6:
573                 switch (ResetInfo->ResetControl) {
574                         case AssertSlotReset:
575                         Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG25);
576                         Data8 &= ~(UINT8)BIT6 ;
577                         Write64Mem8(GpioMmioAddr+SB_GPIO_REG25, Data8);  // PCIE_RST#_LAN, GPIO25
578                         Status = AGESA_SUCCESS;
579                         break;
580                         case DeassertSlotReset:
581                         Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG25);
582                         Data8 |= BIT6 ;
583                         Write64Mem8 (GpioMmioAddr+SB_GPIO_REG25, Data8);                 // PCIE_RST#_LAN, GPIO25
584                         Status = AGESA_SUCCESS;
585                         break;
586                 }
587                 break;
588         case 7:
589                 switch (ResetInfo->ResetControl) {
590                         case AssertSlotReset:
591                         Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG02);
592                         Data8 &= ~(UINT8)BIT6 ;
593                         Write64Mem8(GpioMmioAddr+SB_GPIO_REG02, Data8);  // MPCIE_RST0, GPIO02
594                         Status = AGESA_SUCCESS;
595                         break;
596                         case DeassertSlotReset:
597                         Data8 = Read64Mem8(GpioMmioAddr+SB_GPIO_REG25);
598                         Data8 |= BIT6 ;
599                         Write64Mem8 (GpioMmioAddr+SB_GPIO_REG02, Data8);                 // MPCIE_RST0, GPIO02
600                         Status = AGESA_SUCCESS;
601                         break;
602                 }
603                 break;
604         }
605         return  Status;
606 }