AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / Mem / Main / mmOnlineSpare.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * mmOnlineSpare.c
6  *
7  * Main Memory Feature implementation file for Node Interleaving
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project: AGESA
11  * @e sub-project: (Mem/Main)
12  * @e \$Revision: 53955 $ @e \$Date: 2011-05-29 20:54:54 -0600 (Sun, 29 May 2011) $
13  *
14  **/
15 /*****************************************************************************
16 *
17 * Copyright (C) 2012 Advanced Micro Devices, Inc.
18 * All rights reserved.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions are met:
22 *     * Redistributions of source code must retain the above copyright
23 *       notice, this list of conditions and the following disclaimer.
24 *     * Redistributions in binary form must reproduce the above copyright
25 *       notice, this list of conditions and the following disclaimer in the
26 *       documentation and/or other materials provided with the distribution.
27 *     * Neither the name of Advanced Micro Devices, Inc. nor the names of
28 *       its contributors may be used to endorse or promote products derived
29 *       from this software without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
35 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *
42 * ***************************************************************************
43 *
44 */
45
46 /*
47  *----------------------------------------------------------------------------
48  *                                MODULES USED
49  *
50  *----------------------------------------------------------------------------
51  */
52
53
54 #include "AGESA.h"
55 #include "OptionMemory.h"
56 #include "mm.h"
57 #include "mn.h"
58 #include "Ids.h"
59 #include "Filecode.h"
60 CODE_GROUP (G2_PEI)
61 RDATA_GROUP (G2_PEI)
62
63 #define FILECODE PROC_MEM_MAIN_MMONLINESPARE_FILECODE
64 /*----------------------------------------------------------------------------
65  *                        PROTOTYPES OF LOCAL FUNCTIONS
66  *
67  *----------------------------------------------------------------------------
68  */
69 BOOLEAN
70 MemMOnlineSpare (
71   IN OUT   MEM_MAIN_DATA_BLOCK *MemMainPtr
72   );
73
74 /*-----------------------------------------------------------------------------
75 *                                EXPORTED FUNCTIONS
76 *
77 *-----------------------------------------------------------------------------
78 */
79
80 /* -----------------------------------------------------------------------------*/
81 /**
82  *
83  *  Check and enable online spare on all nodes.
84  *
85  *     @param[in,out]   *MemMainPtr   - Pointer to the MEM_MAIN_DATA_BLOCK
86  *
87  *     @return          TRUE -  No fatal error occurs.
88  *     @return          FALSE - Fatal error occurs.
89  */
90 BOOLEAN
91 MemMOnlineSpare (
92   IN OUT   MEM_MAIN_DATA_BLOCK *MemMainPtr
93   )
94 {
95   UINT8   Node;
96   BOOLEAN IsEnabled;
97   UINT8   FirstEnabledNode;
98   UINT32  BottomIO;
99   BOOLEAN RetVal;
100   MEM_NB_BLOCK  *NBPtr;
101   MEM_PARAMETER_STRUCT *RefPtr;
102
103   AGESA_TESTPOINT (TpProcMemOnlineSpareInit, &(MemMainPtr->MemPtr->StdHeader));
104   FirstEnabledNode = 0;
105   IsEnabled = FALSE;
106   RetVal = TRUE;
107   NBPtr = MemMainPtr->NBPtr;
108   RefPtr = NBPtr[BSP_DIE].RefPtr;
109
110   for (Node = 0; Node < MemMainPtr->DieCount; Node++) {
111     if (NBPtr[Node].FeatPtr->OnlineSpare (&NBPtr[Node])) {
112       if (!IsEnabled) {
113         // Record the first node that has spared dimm enabled
114         FirstEnabledNode = Node;
115         IsEnabled = TRUE;
116       }
117     }
118   }
119
120   if (IsEnabled) {
121     NBPtr[BSP_DIE].SharedPtr->CurrentNodeSysBase = 0;
122     BottomIO = (NBPtr[BSP_DIE].RefPtr->BottomIo & 0xF8) << 8;
123     // If the first node that has spared dimms does not have a system base smaller
124     // than bottomIO, then we don't need to reset the GStatus, as we don't need to
125     // remap memory hole.
126     if (NBPtr[FirstEnabledNode].MCTPtr->NodeSysBase < BottomIO) {
127       RefPtr->GStatus[GsbHWHole] = FALSE;
128       RefPtr->GStatus[GsbSpIntRemapHole] = FALSE;
129       RefPtr->GStatus[GsbSoftHole] = FALSE;
130       RefPtr->HoleBase = 0;
131     }
132
133     for (Node = 0; Node < MemMainPtr->DieCount; Node++) {
134       if (Node >= FirstEnabledNode) {
135         // Remap memory on nodes with node number larger than the first node that has spared dimms.
136         NBPtr[Node].MCTPtr->Status[SbHWHole] = FALSE;
137         NBPtr[Node].MCTPtr->Status[SbSWNodeHole] = FALSE;
138         NBPtr[Node].SetBitField (&NBPtr[Node], BFDctSelBaseAddr, 0);
139         NBPtr[Node].SetBitField (&NBPtr[Node], BFDctSelHiRngEn, 0);
140         NBPtr[Node].SetBitField (&NBPtr[Node], BFDctSelHi, 0);
141         NBPtr[Node].SetBitField (&NBPtr[Node], BFDctSelBaseOffset, 0);
142         NBPtr[Node].SetBitField (&NBPtr[Node], BFDramHoleAddrReg, 0);
143         NBPtr[Node].HtMemMapInit (&NBPtr[Node]);
144       } else {
145         // No change is needed in the memory map of this node.
146         // Need to adjust the current system base for other nodes processed later.
147         NBPtr[Node].SharedPtr->CurrentNodeSysBase = (NBPtr[Node].MCTPtr->NodeSysLimit + 1) & 0xFFFFFFF0;
148         // If the current node does not have the memory hole, then set DramHoleAddrReg to be 0.
149         // If memory hoisting is enabled later by other node, SyncAddrMapToAllNodes will set the base
150         // and DramMemHoistValid.
151         // Otherwise, do not change the register value, as we need to keep DramHoleOffset unchanged, as well
152         // DramHoleValid.
153         if (!NBPtr[Node].MCTPtr->Status[SbHWHole]) {
154           NBPtr[Node].SetBitField (&NBPtr[Node], BFDramHoleAddrReg, 0);
155         }
156       }
157     }
158
159     for (Node = 0; Node < MemMainPtr->DieCount; Node++) {
160       NBPtr[Node].SyncAddrMapToAllNodes (&NBPtr[Node]);
161       RetVal &= (BOOLEAN) (NBPtr[Node].MCTPtr->ErrCode < AGESA_FATAL);
162     }
163     NBPtr[BSP_DIE].CpuMemTyping (&NBPtr[BSP_DIE]);
164   }
165   return RetVal;
166 }