]> git.proxmox.com Git - mirror_edk2.git/blame - Vlv2TbltDevicePkg/PlatformInitPei/Dimm.c
IntelFsp2WrapperPkg: Update gFspWrapperTokenSpaceGuid to gIntelFsp2WrapperTokenSpaceGuid.
[mirror_edk2.git] / Vlv2TbltDevicePkg / PlatformInitPei / Dimm.c
CommitLineData
3cbfba02
DW
1/** @file\r
2\r
3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>\r
4 \r\r
5 This program and the accompanying materials are licensed and made available under\r\r
6 the terms and conditions of the BSD License that accompanies this distribution. \r\r
7 The full text of the license may be found at \r\r
8 http://opensource.org/licenses/bsd-license.php. \r\r
9 \r\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r\r
12 \r\r
13\r
14Module Name:\r
15\r
16\r
17 Dimm.c\r
18\r
19Abstract:\r
20\r
21 PPI for reading SPD modules on DIMMs.\r
22\r
23--*/\r
24\r
25\r
26//\r
27// Header Files\r
28//\r
29#include "Platformearlyinit.h"\r
30\r
31#define DIMM_SOCKETS 4 // Total number of DIMM sockets allowed on\r
32 // the platform\r
33#define DIMM_SEGMENTS 1 // Total number of Segments Per DIMM.\r
34#define MEMORY_CHANNELS 2 // Total number of memory channels\r
35 // populated on the system board\r
36//\r
37// Prototypes\r
38//\r
39\r
40EFI_STATUS\r
41EFIAPI\r
42GetDimmState (\r
43 IN EFI_PEI_SERVICES **PeiServices,\r
44 IN PEI_PLATFORM_DIMM_PPI *This,\r
45 IN UINT8 Dimm,\r
46 OUT PEI_PLATFORM_DIMM_STATE *State\r
47 );\r
48\r
49EFI_STATUS\r
50EFIAPI\r
51SetDimmState (\r
52 IN EFI_PEI_SERVICES **PeiServices,\r
53 IN PEI_PLATFORM_DIMM_PPI *This,\r
54 IN UINT8 Dimm,\r
55 IN PEI_PLATFORM_DIMM_STATE *State\r
56 );\r
57\r
58EFI_STATUS\r
59EFIAPI\r
60ReadSpd (\r
61 IN EFI_PEI_SERVICES **PeiServices,\r
62 IN PEI_PLATFORM_DIMM_PPI *This,\r
63 IN UINT8 Dimm,\r
64 IN UINT8 Offset,\r
65 IN UINTN Count,\r
66 IN OUT UINT8 *Buffer\r
67 );\r
68\r
69static PEI_PLATFORM_DIMM_PPI mGchDimmPpi = {\r
70 DIMM_SOCKETS,\r
71 DIMM_SEGMENTS,\r
72 MEMORY_CHANNELS,\r
73 GetDimmState,\r
74 SetDimmState,\r
75 ReadSpd\r
76};\r
77\r
78static EFI_PEI_PPI_DESCRIPTOR mPpiPlatformDimm = {\r
79 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
80 &gPeiPlatformDimmPpiGuid,\r
81 &mGchDimmPpi\r
82};\r
83\r
84\r
85//\r
86// Functions\r
87//\r
88\r
89/**\r
90 This function returns the current state of a single DIMM. Present indicates\r
91 that the DIMM slot is physically populated. Disabled indicates that the DIMM\r
92 should not be used.\r
93\r
94 @param PeiServices PEI services table pointer\r
95 @param This PPI pointer\r
96 @param Dimm DIMM to read from\r
97 @param State Pointer to a return buffer to be updated with the current state\r
98 of the DIMM\r
99\r
100 @retval EFI_SUCCESS The function completed successfully.\r
101\r
102**/\r
103EFI_STATUS\r
104EFIAPI\r
105GetDimmState (\r
106 IN EFI_PEI_SERVICES **PeiServices,\r
107 IN PEI_PLATFORM_DIMM_PPI *This,\r
108 IN UINT8 Dimm,\r
109 OUT PEI_PLATFORM_DIMM_STATE *State\r
110 )\r
111{\r
112 EFI_STATUS Status;\r
113 UINT8 Buffer;\r
114\r
115 PEI_ASSERT (PeiServices, (Dimm < This->DimmSockets));\r
116\r
117 //\r
118 // A failure here does not necessarily mean that no DIMM is present.\r
119 // Read a single byte. All we care about is the return status.\r
120 //\r
121 Status = ReadSpd (\r
122 PeiServices,\r
123 This,\r
124 Dimm,\r
125 0,\r
126 1,\r
127 &Buffer\r
128 );\r
129\r
130 if (EFI_ERROR (Status)) {\r
131 State->Present = 0;\r
132 } else {\r
133 State->Present = 1;\r
134 }\r
135\r
136 //\r
137 // BUGBUG: Update to check platform variable when it is available\r
138 //\r
139 State->Disabled = 0;\r
140 State->Reserved = 0;\r
141\r
142 return EFI_SUCCESS;\r
143}\r
144\r
145/**\r
146\r
147 This function updates the state of a single DIMM.\r
148\r
149 @param PeiServices PEI services table pointer\r
150 @param This PPI pointer\r
151 @param Dimm DIMM to set state for\r
152 @param State Pointer to the state information to set.\r
153\r
154 @retval EFI_SUCCESS The function completed successfully.\r
155 @retval EFI_UNSUPPORTED The function is not supported.\r
156\r
157**/\r
158EFI_STATUS\r
159EFIAPI\r
160SetDimmState (\r
161 IN EFI_PEI_SERVICES **PeiServices,\r
162 IN PEI_PLATFORM_DIMM_PPI *This,\r
163 IN UINT8 Dimm,\r
164 IN PEI_PLATFORM_DIMM_STATE *State\r
165 )\r
166{\r
167 return EFI_UNSUPPORTED;\r
168}\r
169\r
170/**\r
171 This function reads SPD information from a DIMM.\r
172\r
173 PeiServices PEI services table pointer\r
174 This PPI pointer\r
175 Dimm DIMM to read from\r
176 Offset Offset in DIMM\r
177 Count Number of bytes\r
178 Buffer Return buffer\r
179\r
180 @param EFI_SUCCESS The function completed successfully.\r
181 @param EFI_DEVICE_ERROR The DIMM being accessed reported a device error,\r
182 does not have an SPD module, or is not installed in\r
183 the system.\r
184 @retval EFI_TIMEOUT Time out trying to read the SPD module.\r
185 @retval EFI_INVALID_PARAMETER A parameter was outside the legal limits.\r
186\r
187**/\r
188EFI_STATUS\r
189EFIAPI\r
190ReadSpd (\r
191 IN EFI_PEI_SERVICES **PeiServices,\r
192 IN PEI_PLATFORM_DIMM_PPI *This,\r
193 IN UINT8 Dimm,\r
194 IN UINT8 Offset,\r
195 IN UINTN Count,\r
196 IN OUT UINT8 *Buffer\r
197 )\r
198{\r
199 EFI_STATUS Status;\r
200 PEI_SMBUS_PPI *Smbus;\r
201 UINTN Index;\r
202 UINTN Index1;\r
203 EFI_SMBUS_DEVICE_ADDRESS SlaveAddress;\r
204 EFI_SMBUS_DEVICE_COMMAND Command;\r
205 UINTN Length;\r
206\r
207 Status = (**PeiServices).LocatePpi (\r
208 PeiServices,\r
209 &gPeiSmbusPpiGuid, // GUID\r
210 0, // INSTANCE\r
211 NULL, // EFI_PEI_PPI_DESCRIPTOR\r
212 &Smbus // PPI\r
213 );\r
214 ASSERT_PEI_ERROR (PeiServices, Status);\r
215\r
216 switch (Dimm) {\r
217 case 0:\r
218 SlaveAddress.SmbusDeviceAddress = SMBUS_ADDR_CH_A_1 >> 1;\r
219 break;\r
220 case 1:\r
221 SlaveAddress.SmbusDeviceAddress = SMBUS_ADDR_CH_A_2 >> 1;\r
222 break;\r
223 case 2:\r
224 SlaveAddress.SmbusDeviceAddress = SMBUS_ADDR_CH_B_1 >> 1;\r
225 break;\r
226 case 3:\r
227 SlaveAddress.SmbusDeviceAddress = SMBUS_ADDR_CH_B_2 >> 1;\r
228 break;\r
229 default:\r
230 return EFI_INVALID_PARAMETER;\r
231 }\r
232\r
233 Index = Count % 4;\r
234 if (Index != 0) {\r
235 //\r
236 // read the first serveral bytes to speed up following reading\r
237 //\r
238 for (Index1 = 0; Index1 < Index; Index1++) {\r
239 Length = 1;\r
240 Command = Offset + Index1;\r
241 Status = Smbus->Execute (\r
242 PeiServices,\r
243 Smbus,\r
244 SlaveAddress,\r
245 Command,\r
246 EfiSmbusReadByte,\r
247 FALSE,\r
248 &Length,\r
249 &Buffer[Index1]\r
250 );\r
251 if (EFI_ERROR(Status)) {\r
252 return Status;\r
253 }\r
254 }\r
255 }\r
256\r
257 //\r
258 // Now collect all the remaining bytes on 4 bytes block\r
259 //\r
260 for (; Index < Count; Index += 2) {\r
261 Command = Index + Offset;\r
262 Length = 2;\r
263 Status = Smbus->Execute (\r
264 PeiServices,\r
265 Smbus,\r
266 SlaveAddress,\r
267 Command,\r
268 EfiSmbusReadWord,\r
269 FALSE,\r
270 &Length,\r
271 &Buffer[Index]\r
272 );\r
273 if (EFI_ERROR(Status)) {\r
274 return Status;\r
275 }\r
276\r
277 Index += 2;\r
278 Command = Index + Offset;\r
279 Length = 2;\r
280 Status = Smbus->Execute (\r
281 PeiServices,\r
282 Smbus,\r
283 SlaveAddress,\r
284 Command,\r
285 EfiSmbusReadWord,\r
286 FALSE,\r
287 &Length,\r
288 &Buffer[Index]\r
289 );\r
290 if (EFI_ERROR(Status)) {\r
291 return Status;\r
292 }\r
293 }\r
294 return EFI_SUCCESS;\r
295}\r
296\r
297/**\r
298 This function initializes the PEIM. It simply installs the DIMM PPI.\r
299\r
300 @param FfsHeader Not used by this function\r
301 @param PeiServices Pointer to PEI services table\r
302\r
303 @retval EFI_SUCCESS The function completed successfully.\r
304\r
305**/\r
306EFI_STATUS\r
307EFIAPI\r
308PeimInitializeDimm (\r
309 IN EFI_PEI_SERVICES **PeiServices,\r
310 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
311 IN VOID *SmbusPpi\r
312 )\r
313{\r
314 EFI_STATUS Status;\r
315\r
316 Status = (**PeiServices).InstallPpi (\r
317 PeiServices,\r
318 &mPpiPlatformDimm\r
319 );\r
320 ASSERT_PEI_ERROR (PeiServices, Status);\r
321\r
322 return EFI_SUCCESS;\r
323}\r
324\r