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