3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
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.
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.
21 PPI for reading SPD modules on DIMMs.
29 #include "Platformearlyinit.h"
31 #define DIMM_SOCKETS 4 // Total number of DIMM sockets allowed on
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
43 IN EFI_PEI_SERVICES
**PeiServices
,
44 IN PEI_PLATFORM_DIMM_PPI
*This
,
46 OUT PEI_PLATFORM_DIMM_STATE
*State
52 IN EFI_PEI_SERVICES
**PeiServices
,
53 IN PEI_PLATFORM_DIMM_PPI
*This
,
55 IN PEI_PLATFORM_DIMM_STATE
*State
61 IN EFI_PEI_SERVICES
**PeiServices
,
62 IN PEI_PLATFORM_DIMM_PPI
*This
,
69 static PEI_PLATFORM_DIMM_PPI mGchDimmPpi
= {
78 static EFI_PEI_PPI_DESCRIPTOR mPpiPlatformDimm
= {
79 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
80 &gPeiPlatformDimmPpiGuid
,
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
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
100 @retval EFI_SUCCESS The function completed successfully.
106 IN EFI_PEI_SERVICES
**PeiServices
,
107 IN PEI_PLATFORM_DIMM_PPI
*This
,
109 OUT PEI_PLATFORM_DIMM_STATE
*State
115 PEI_ASSERT (PeiServices
, (Dimm
< This
->DimmSockets
));
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.
130 if (EFI_ERROR (Status
)) {
137 // BUGBUG: Update to check platform variable when it is available
147 This function updates the state of a single DIMM.
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.
154 @retval EFI_SUCCESS The function completed successfully.
155 @retval EFI_UNSUPPORTED The function is not supported.
161 IN EFI_PEI_SERVICES
**PeiServices
,
162 IN PEI_PLATFORM_DIMM_PPI
*This
,
164 IN PEI_PLATFORM_DIMM_STATE
*State
167 return EFI_UNSUPPORTED
;
171 This function reads SPD information from a DIMM.
173 PeiServices PEI services table pointer
175 Dimm DIMM to read from
176 Offset Offset in DIMM
177 Count Number of bytes
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
184 @retval EFI_TIMEOUT Time out trying to read the SPD module.
185 @retval EFI_INVALID_PARAMETER A parameter was outside the legal limits.
191 IN EFI_PEI_SERVICES
**PeiServices
,
192 IN PEI_PLATFORM_DIMM_PPI
*This
,
200 PEI_SMBUS_PPI
*Smbus
;
203 EFI_SMBUS_DEVICE_ADDRESS SlaveAddress
;
204 EFI_SMBUS_DEVICE_COMMAND Command
;
207 Status
= (**PeiServices
).LocatePpi (
209 &gPeiSmbusPpiGuid
, // GUID
211 NULL
, // EFI_PEI_PPI_DESCRIPTOR
214 ASSERT_PEI_ERROR (PeiServices
, Status
);
218 SlaveAddress
.SmbusDeviceAddress
= SMBUS_ADDR_CH_A_1
>> 1;
221 SlaveAddress
.SmbusDeviceAddress
= SMBUS_ADDR_CH_A_2
>> 1;
224 SlaveAddress
.SmbusDeviceAddress
= SMBUS_ADDR_CH_B_1
>> 1;
227 SlaveAddress
.SmbusDeviceAddress
= SMBUS_ADDR_CH_B_2
>> 1;
230 return EFI_INVALID_PARAMETER
;
236 // read the first serveral bytes to speed up following reading
238 for (Index1
= 0; Index1
< Index
; Index1
++) {
240 Command
= Offset
+ Index1
;
241 Status
= Smbus
->Execute (
251 if (EFI_ERROR(Status
)) {
258 // Now collect all the remaining bytes on 4 bytes block
260 for (; Index
< Count
; Index
+= 2) {
261 Command
= Index
+ Offset
;
263 Status
= Smbus
->Execute (
273 if (EFI_ERROR(Status
)) {
278 Command
= Index
+ Offset
;
280 Status
= Smbus
->Execute (
290 if (EFI_ERROR(Status
)) {
298 This function initializes the PEIM. It simply installs the DIMM PPI.
300 @param FfsHeader Not used by this function
301 @param PeiServices Pointer to PEI services table
303 @retval EFI_SUCCESS The function completed successfully.
309 IN EFI_PEI_SERVICES
**PeiServices
,
310 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor
,
316 Status
= (**PeiServices
).InstallPpi (
320 ASSERT_PEI_ERROR (PeiServices
, Status
);