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