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