1 /** @file
2   This file contains functions that read the SPD data for each DIMM slot over
3   the SMBus interface.
4   This file is SampleCode for Intel SA PEI Policy initialization.
5 
6   Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
7 
8   SPDX-License-Identifier: BSD-2-Clause-Patent
9 **/
10 
11 #include "PeiSaPolicyLibrary.h"
12 #include "MrcInterface.h"
13 
14 #define RTC_INDEX_REGISTER        (0x70)
15 #define RTC_TARGET_REGISTER       (0x71)
16 
17 #define RTC_INDEX_MASK            (0x7F)
18 #define RTC_BANK_SIZE             (0x80)
19 
20 #define RTC_SECONDS               (0x00)
21 #define RTC_MINUTES               (0x02)
22 #define RTC_HOURS                 (0x04)
main(int argc,char * argv[])23 #define RTC_DAY_OF_MONTH          (0x07)
24 #define RTC_MONTH                 (0x08)
25 #define RTC_YEAR                  (0x09)
26 #define CMOS_REGA                 (0x0A)
27 #define CMOS_REGB                 (0x0B)
28 #define CMOS_REGC                 (0x0C)
29 #define CMOS_REGD                 (0x0D)
30 
31 #define RTC_UPDATE_IN_PROGRESS    (0x80)
32 #define RTC_HOLD                  (0x80)
33 #define RTC_MODE_24HOUR           (0x02)
34 #define RTC_CLOCK_DIVIDER         (0x20)
35 #define RTC_RATE_SELECT           (0x06)
36 
37 #define BCD2BINARY(A)             (((((A) >> 4) & 0xF) * 10) + ((A) & 0xF))
38 #define CENTURY_OFFSET            (2000)
39 
40 /**
41   Read the SPD data over the SMBus, at the given SmBus SPD address and copy the data to the data structure.
42   The SPD data locations read is controlled by the current boot mode.
43 
44   @param[in] BootMode           - The current MRC boot mode.
45   @param[in] Address            - SPD SmBus address offset.
46   @param[in] Buffer             - Buffer that contains the data read from the SPD.
47   @param[in] SpdDdr3Table       - Indicates which SPD bytes to read.
48   @param[in] SpdDdr3TableSize   - Size of SpdDdr3Table in bytes.
49   @param[in] SpdDdr4Table       - Indicates which SPD bytes to read.
50   @param[in] SpdDdr4TableSize   - Size of SpdDdr4Table in bytes.
51   @param[in] SpdLpddrTable      - Indicates which SPD bytes to read.
52   @param[in] SpdLpddrTableSize  - Size of SpdLpddrTable in bytes.
53 
54   @retval TRUE if the read is successful, otherwise FALSE on error.
55 **/
56 BOOLEAN
57 GetSpdData (
58   IN SPD_BOOT_MODE BootMode,
59   IN UINT8         Address,
60   IN OUT   UINT8   *Buffer,
61   IN UINT8         *SpdDdr3Table,
62   IN UINT32        SpdDdr3TableSize,
63   IN UINT8         *SpdDdr4Table,
64   IN UINT32        SpdDdr4TableSize,
65   IN UINT8         *SpdLpddrTable,
66   IN UINT32        SpdLpddrTableSize
67   );
68 
69 /**
70   Output a string to the debug stream/device.
71 
72   @param[in] String     - The string to output.
73 **/
74 VOID
75 SaDebugPrint (
76   VOID   *String
77   );
78 
79 /**
80   Calculate the PCI device address for the given Bus/Device/Function/Offset.
81 
82   @param[in] Bus      - PCI bus
83   @param[in] Device   - PCI device
84   @param[in] Function - PCI function
85   @param[in] Offset   - Offset
86 
87   @retval The PCI device address.
88 **/
89 UINT32
90 GetPciDeviceAddress (
91   IN const UINT8 Bus,
92   IN const UINT8 Device,
93   IN const UINT8 Function,
94   IN const UINT8 Offset
95   );
96 
97 /**
98   Calculate the PCIE device address for the given Bus/Device/Function/Offset.
99 
100   @param[in] Bus      - PCI bus
101   @param[in] Device   - PCI device
102   @param[in] Function - PCI function
103   @param[in] Offset   - Offset
104 
105    The PCIE device address.
106 
107   @retval The PCIe device address
108 **/
109 UINT32
110 GetPcieDeviceAddress (
111   IN const UINT8 Bus,
112   IN const UINT8 Device,
113   IN const UINT8 Function,
114   IN const UINT8 Offset
115   );
116 
117 /**
118   Read specific RTC/CMOS RAM
119 
120   @param[in] Location        Point to RTC/CMOS RAM offset for read
121 
122   @retval The data of specific location in RTC/CMOS RAM.
123 **/
124 UINT8
125 PeiRtcRead (
126   IN const UINT8 Location
127   );
128 
129 /**
130   Returns the current time, as determined by reading the Real Time Clock (RTC) on the platform.
131   Since RTC time is stored in BCD, convert each value to binary.
132 
133   @param[out] Seconds       - The current second (0-59).
134   @param[out] Minutes       - The current minute (0-59).
135   @param[out] Hours         - The current hour (0-23).
136   @param[out] DayOfMonth    - The current day of the month (1-31).
137   @param[out] Month         - The current month (1-12).
138   @param[out] Year          - The current year (2000-2099).
139 **/
140 VOID
141 GetRtcTime (
142   OUT UINT8  *const Seconds,
143   OUT UINT8  *const Minutes,
144   OUT UINT8  *const Hours,
145   OUT UINT8  *const DayOfMonth,
146   OUT UINT8  *const Month,
147   OUT UINT16 *const Year
148   );
149 
150 /**
151   Gets CPU current time.
152 
153   @param[in] GlobalData - Pointer to global MRC data struct.
154 
155   @retval The current CPU time in milliseconds.
156 **/
157 UINT64
158 GetCpuTime (
159   IN VOID     *GlobalData
160   );
161 
162 /**
163   Sets the specified number of memory words, a word at a time, at the
164   specified destination.
165 
166   @param[in, out] Dest     - Destination pointer.
167   @param[in]      NumWords - The number of dwords to set.
168   @param[in]      Value    - The value to set.
169 
170   @retval Pointer to the buffer.
171 **/
172 VOID *
173 SetMemWord (
174   IN OUT VOID     *Dest,
175   IN UINTN        NumWords,
176   IN const UINT16 Value
177   );
178 
179 /**
180   Sets the specified number of memory dwords, a dword at a time, at the
181   specified destination.
182 
183   @param[in, out] Dest      - Destination pointer.
184   @param[in]      NumDwords - The number of dwords to set.
185   @param[in]      Value     - The value to set.
186 
187   @retval Pointer to the buffer.
188 **/
189 VOID *
190 SetMemDword (
191   IN OUT VOID     *Dest,
192   IN UINT32       NumDwords,
193   IN const UINT32 Value
194   );
195 
196 /**
197   Read 64 bits from the Memory Mapped I/O space.
198   Use MMX instruction for atomic access, because some MC registers have side effect.
199 
200   @param[in] Address - Memory mapped I/O address.
201 **/
202 UINT64
203 SaMmioRead64 (
204   IN  UINTN Address
205   );
206 
207 /**
208   Write 64 bits to the Memory Mapped I/O space.
209   Use MMX instruction for atomic access, because some MC registers have side effect.
210 
211   @param[in] Address - Memory mapped I/O address.
212   @param[in] Value   - The value to write.
213 **/
214 UINT64
215 SaMmioWrite64 (
216   IN UINTN Address,
217   IN UINT64 Value
218   );
219 
220 /**
221   Intel Silicon View Technology check point interface based on IO port reading
222 
223   @param CheckPoint        Check point AH value.
224                            AH = 0x10:  End of MRC State
225                            AH = 0x20:  End of DXE State
226                            AH = 0x30:  Ready to boot before INT-19h or UEFI boot
227                            AH = 0x40:  After OS booting, need a timer SMI trigger to implement (TBD)
228 
229   @param PortReading       IO port reading address used for breakpoints
230 **/
231 VOID
232 EFIAPI
233 IsvtCheckPoint (
234   IN UINT32          CheckPoint,
235   IN UINT32          PortReading
236   );
237 
238 /**
239   Gets the current memory voltage (VDD).
240 
241   @param[in] GlobalData - Pointer to global MRC data struct.
242   @param[in] DefaultVdd - Default Vdd for the given platform.
243 
244   @retval The current memory voltage (VDD), in millivolts. 0 means platform default.
245 **/
246 UINT32
247 GetMemoryVdd (
248   IN VOID     *GlobalData,
249   IN UINT32   DefaultVdd
250   );
251 
252 /**
253   Sets the memory voltage (VDD) to the specified value.
254 
255   @param[in] GlobalData - Pointer to global MRC data struct.
256   @param[in] DefaultVdd - Default Vdd for the given platform.
257   @param[in] Voltage    - The new memory voltage to set.
258 
259   @retval The actual memory voltage (VDD), in millivolts, that is closest to what the caller passed in.
260 **/
261 UINT32
262 SetMemoryVdd (
263   IN VOID     *GlobalData,
264   IN UINT32   DefaultVdd,
265   IN UINT32   Voltage
266   );
267 
268 /**
269   Check point that is called at various points in the MRC.
270 
271   @param[in] GlobalData - MRC global data.
272   @param[in] Command    - OEM command.
273   @param[in] Pointer    - Command specific data.
274 
275   @retval MrcStatus value.
276 **/
277 UINT32
278 CheckPoint (
279   VOID   *GlobalData,
280   UINT32 Command,
281   VOID   *Pointer
282   );
283 
284 /**
285   Typically used to display to the I/O port 80h.
286 
287   @param[in] GlobalData         - Mrc Global Data
288   @param[in] DisplayDebugNumber - the number to display on port 80.
289 
290   @retval Nothing.
291 **/
292 VOID
293 DebugHook (
294   VOID          *GlobalData,
295   UINT16        DisplayDebugNumber
296   );
297 
298 /**
299   Hook to take any action after returning from MrcStartMemoryConfiguration()
300   and prior to taking any action regarding MrcStatus.  Pre-populated with issuing
301   Intel Silicon View Technology (ISVT) checkpoint 0x01.
302 
303   @param[in] GlobalData         - Mrc Global Data
304   @param[in] MrcStatus          - Mrc status variable
305 **/
306 VOID
307 ReturnFromSmc (
308   VOID          *GlobalData,
309   UINT32        MrcStatus
310   );
311 
312 /**
313   Assert or deassert DRAM_RESET# pin; this is used in JEDEC Reset.
314 
315   @param[in] PciEBaseAddress  - PCI express base address.
316   @param[in] ResetValue       - desired value of DRAM_RESET#. 1 - reset deasserted, 0 - reset asserted.
317 **/
318 VOID
319 SaDramReset (
320   IN UINT32 PciEBaseAddress,
321   IN UINT32 ResetValue
322   );
323 
324