]> git.proxmox.com Git - mirror_edk2.git/blame - Vlv2TbltDevicePkg/PlatformInitPei/PchInitPeim.c
edk2: Reformat TianoCore Contribution Agreement 1.1
[mirror_edk2.git] / Vlv2TbltDevicePkg / PlatformInitPei / PchInitPeim.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
14\r
15Module Name:\r
16\r
17 PchInitPeim.c\r
18\r
19Abstract:\r
20\r
21 Do Early PCH platform initialization.\r
22\r
23\r
24--*/\r
25\r
26#include "PlatformEarlyInit.h"\r
27#include "Ppi/PchPlatformPolicy.h"\r
28#include "PchRegs.h"\r
29#include <Ppi/PchUsbPolicy.h>\r
30#include "Ppi/PchInit.h"\r
31#include <Library/PcdLib.h>\r
32\r
33EFI_GUID gPchPlatformPolicyPpiGuid = PCH_PLATFORM_POLICY_PPI_GUID;\r
34\r
35#define MC_PMSTS_OFFSET 0xC\r
36\r
37#define DEFAULT_BUS_INFO 0x2020\r
38\r
39\r
40#define PCI_LPC_BASE (0x8000F800)\r
41#define PCI_LPC_REG(x) (PCI_LPC_BASE + (x))\r
42#define PCIEX_BASE_ADDRESS 0xE0000000\r
43#define PciD31F0RegBase PCIEX_BASE_ADDRESS + (UINT32) (31 << 15)\r
44\r
45VOID\r
46PchPolicySetupInit (\r
47 IN CONST EFI_PEI_SERVICES **PeiServices,\r
48 IN SYSTEM_CONFIGURATION *SystemConfiguration\r
49 );\r
50\r
51VOID\r
52PchInitInterrupt (\r
53 IN SYSTEM_CONFIGURATION *SystemConfiguration\r
54 );\r
55\r
a27bdc05
JY
56EFI_STATUS\r
57InstallPeiPchUsbPolicy (\r
58 IN CONST EFI_PEI_SERVICES **PeiServices\r
59 );\r
60\r
3cbfba02
DW
61#ifndef __GNUC__\r
62#pragma warning (push)\r
63#pragma warning (disable : 4245)\r
64#pragma warning (pop)\r
65#endif\r
66\r
67UINT8\r
68ReadCmosBank1Byte (\r
69 IN UINT8 Address\r
70 )\r
71{\r
72 UINT8 Data;\r
73\r
74 IoWrite8(R_PCH_RTC_EXT_INDEX, Address);\r
75 Data = IoRead8 (R_PCH_RTC_EXT_TARGET);\r
76 return Data;\r
77}\r
78\r
79VOID\r
80WriteCmosBank1Byte (\r
81 IN UINT8 Address,\r
82 IN UINT8 Data\r
83 )\r
84{\r
85 IoWrite8(R_PCH_RTC_EXT_INDEX, Address);\r
86 IoWrite8(R_PCH_RTC_EXT_TARGET, Data);\r
87}\r
88\r
89/**\r
90 Turn off system if needed.\r
91\r
92 @param PeiServices Pointer to PEI Services\r
93 @param CpuIo Pointer to CPU I/O Protocol\r
94\r
95 @retval None.\r
96\r
97**/\r
98VOID\r
99CheckPowerOffNow (\r
100 VOID\r
101 )\r
102{\r
103 UINT16 Pm1Sts;\r
104\r
105 //\r
106 // Read and check the ACPI registers\r
107 //\r
108 Pm1Sts = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS);\r
109 if ((Pm1Sts & B_PCH_ACPI_PM1_STS_PWRBTN) == B_PCH_ACPI_PM1_STS_PWRBTN) {\r
110 IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS, B_PCH_ACPI_PM1_STS_PWRBTN);\r
111 IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, V_PCH_ACPI_PM1_CNT_S5);\r
112 IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, V_PCH_ACPI_PM1_CNT_S5 + B_PCH_ACPI_PM1_CNT_SLP_EN);\r
113\r
114 //\r
115 // Should not return\r
116 //\r
117 CpuDeadLoop();\r
118 }\r
119}\r
120\r
121VOID\r
122ClearPowerState (\r
123 IN SYSTEM_CONFIGURATION *SystemConfiguration\r
124 )\r
125{\r
126 UINT8 Data8;\r
127 UINT16 Data16;\r
128 UINT32 Data32;\r
129\r
130 //\r
131 // Check for PowerState option for AC power loss and program the chipset\r
132 //\r
133\r
134 //\r
135 // Clear PWROK (Set to Clear)\r
136 //\r
137 MmioOr32 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, B_PCH_PMC_GEN_PMCON_PWROK_FLR);\r
138\r
139 //\r
140 // Clear Power Failure Bit (Set to Clear)\r
141 //\r
142 // TODO: Check if it is OK to clear here\r
143 //\r
144\r
145 MmioOr32 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR);\r
146\r
147 //\r
148 // Clear the GPE and PM enable\r
149 //\r
150 IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_EN, (UINT16) 0x00);\r
151 IoWrite32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_GPE0a_EN, (UINT32) 0x00);\r
152\r
153 //\r
154 // Halt the TCO timer\r
155 //\r
156 Data16 = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_TCO_CNT);\r
157 Data16 |= B_PCH_TCO_CNT_TMR_HLT;\r
158 IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_TCO_CNT, Data16);\r
159\r
160 //\r
161 // if NMI_NOW_STS is set\r
162 // NMI NOW bit is "Write '1' to clear"\r
163 //\r
164 Data8 = MmioRead8(ILB_BASE_ADDRESS + R_PCH_ILB_GNMI);\r
165 if ((Data8 & B_PCH_ILB_GNMI_NMINS) == B_PCH_ILB_GNMI_NMINS) {\r
166 MmioOr8 (ILB_BASE_ADDRESS + R_PCH_ILB_GNMI, B_PCH_ILB_GNMI_NMIN);\r
167 }\r
168\r
169 //\r
170 // Before we clear the TO status bit here we need to save the results in a CMOS bit for later use.\r
171 //\r
172 Data32 = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_TCO_STS);\r
173 if ((Data32 & B_PCH_TCO_STS_SECOND_TO) == B_PCH_TCO_STS_SECOND_TO)\r
174 {\r
175#if (defined(HW_WATCHDOG_TIMER_SUPPORT) && (HW_WATCHDOG_TIMER_SUPPORT != 0))\r
176 WriteCmosBank1Byte (\r
177 EFI_CMOS_PERFORMANCE_FLAGS,\r
178 ReadCmosBank1Byte (EFI_CMOS_PERFORMANCE_FLAGS) | B_CMOS_TCO_WDT_RESET\r
179 );\r
180#endif\r
181 }\r
182}\r
183\r
184/*++\r
185\r
186 Clear any SMI status or wake status left over from boot.\r
187\r
188**/\r
189VOID\r
190ClearSmiAndWake (\r
191 VOID\r
192 )\r
193{\r
194 UINT16 Pm1Sts;\r
195 UINT32 Gpe0Sts;\r
196 UINT32 SmiSts;\r
197\r
198 //\r
199 // Read the ACPI registers\r
200 //\r
201 Pm1Sts = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS);\r
202 Gpe0Sts = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_GPE0a_STS);\r
203 SmiSts = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_SMI_STS);\r
204\r
205 //\r
206 // Register Wake up reason for S4. This information is used to notify\r
207 // WinXp of wake up reason because S4 wake up path doesn't keep SCI.\r
208 // This is important for Viiv(Quick resume) platform.\r
209 //\r
210\r
211 //\r
212 // First Clear CMOS S4 Wake up flag.\r
213 //\r
214 WriteCmosBank1Byte(CMOS_S4_WAKEUP_FLAG_ADDRESS, 0);\r
215\r
216 //\r
217 // Check wake up reason and set CMOS accordingly. Currently checks\r
218 // Power button, USB, PS/2.\r
219 // Note : PS/2 wake up is using GPI13 (IO_PME). This must be changed depending\r
220 // on board design.\r
221 //\r
222 if ((Pm1Sts & B_PCH_ACPI_PM1_STS_PWRBTN) || (Gpe0Sts & (B_PCH_ACPI_GPE0a_STS_CORE_GPIO | B_PCH_ACPI_GPE0a_STS_SUS_GPIO))) {\r
223 WriteCmosBank1Byte(CMOS_S4_WAKEUP_FLAG_ADDRESS, 1);\r
224 }\r
225\r
226 //\r
227 // Clear any SMI or wake state from the boot\r
228 //\r
229 Pm1Sts = (B_PCH_ACPI_PM1_STS_PRBTNOR | B_PCH_ACPI_PM1_STS_PWRBTN);\r
230\r
231 Gpe0Sts |=\r
232 (\r
233 B_PCH_ACPI_GPE0a_STS_CORE_GPIO |\r
234 B_PCH_ACPI_GPE0a_STS_SUS_GPIO |\r
235 B_PCH_ACPI_GPE0a_STS_PME_B0 |\r
236 B_PCH_ACPI_GPE0a_STS_BATLOW |\r
237 B_PCH_ACPI_GPE0a_STS_PCI_EXP |\r
238 B_PCH_ACPI_GPE0a_STS_GUNIT_SCI |\r
239 B_PCH_ACPI_GPE0a_STS_PUNIT_SCI |\r
240 B_PCH_ACPI_GPE0a_STS_SWGPE |\r
241 B_PCH_ACPI_GPE0a_STS_HOT_PLUG\r
242 );\r
243\r
244 SmiSts |=\r
245 (\r
246 B_PCH_SMI_STS_SMBUS |\r
247 B_PCH_SMI_STS_PERIODIC |\r
248 B_PCH_SMI_STS_TCO |\r
249 B_PCH_SMI_STS_SWSMI_TMR |\r
250 B_PCH_SMI_STS_APM |\r
251 B_PCH_SMI_STS_ON_SLP_EN |\r
252 B_PCH_SMI_STS_BIOS\r
253 );\r
254\r
255 //\r
256 // Write them back\r
257 //\r
258 IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS, Pm1Sts);\r
259 IoWrite32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_GPE0a_STS, Gpe0Sts);\r
260 IoWrite32 (ACPI_BASE_ADDRESS + R_PCH_SMI_STS, SmiSts);\r
261}\r
262\r
263/**\r
264 Issue PCI-E Secondary Bus Reset\r
265\r
266 @param Bus Bus number of the bridge\r
267 @param Dev Devices number of the bridge\r
268 @param Fun Function number of the bridge\r
269\r
270 @retval EFI_SUCCESS\r
271\r
272**/\r
273EFI_STATUS\r
274PcieSecondaryBusReset (\r
275 IN CONST EFI_PEI_SERVICES **PeiServices,\r
276 IN UINT8 Bus,\r
277 IN UINT8 Dev,\r
278 IN UINT8 Fun\r
279 )\r
280{\r
281 EFI_PEI_STALL_PPI *PeiStall;\r
282 EFI_STATUS Status;\r
283\r
284 Status = (**PeiServices).LocatePpi (\r
285 PeiServices,\r
286 &gEfiPeiStallPpiGuid,\r
287 0,\r
288 NULL,\r
289 (void **)&PeiStall\r
290 );\r
291 ASSERT_EFI_ERROR (Status);\r
292\r
293 //\r
294 // Issue secondary bus reset\r
295 //\r
296 MmPci16Or(0, Bus, Dev, Fun, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_PCI_BRIDGE_CONTROL_RESET_SECONDARY_BUS);\r
297\r
298 //\r
299 // Wait 1ms\r
300 //\r
301 PeiStall->Stall (PeiServices, PeiStall, 1000);\r
302\r
303\r
304 //\r
305 // Clear the reset bit\r
306 // Note: The PCIe spec suggests 100ms delay between clearing this bit and accessing\r
307 // the device's config space. Since we will not access the config space until we enter DXE\r
308 // we don't put delay expressly here.\r
309 //\r
310 MmPci16And(0, Bus, Dev, Fun, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, ~(EFI_PCI_BRIDGE_CONTROL_RESET_SECONDARY_BUS));\r
311\r
312 return EFI_SUCCESS;\r
313}\r
314\r
315/**\r
316 Provide hard reset PPI service.\r
317 To generate full hard reset, write 0x0E to ICH RESET_GENERATOR_PORT (0xCF9).\r
318\r
319 @param PeiServices General purpose services available to every PEIM.\r
320\r
321 @retval Not return System reset occured.\r
322 @retval EFI_DEVICE_ERROR Device error, could not reset the system.\r
323\r
324**/\r
325EFI_STATUS\r
326EFIAPI\r
327IchReset (\r
328 IN CONST EFI_PEI_SERVICES **PeiServices\r
329 )\r
330{\r
331 IoWrite8 (\r
332 R_PCH_RST_CNT,\r
333 V_PCH_RST_CNT_HARDSTARTSTATE\r
334 );\r
335\r
336 IoWrite8 (\r
337 R_PCH_RST_CNT,\r
338 V_PCH_RST_CNT_HARDRESET\r
339 );\r
340\r
341 //\r
342 // System reset occured, should never reach at this line.\r
343 //\r
344 ASSERT_EFI_ERROR (EFI_DEVICE_ERROR);\r
345 CpuDeadLoop();\r
346\r
347 return EFI_DEVICE_ERROR;\r
348}\r
349\r
350VOID\r
351PchPlatformLpcInit (\r
352 IN CONST EFI_PEI_SERVICES **PeiServices,\r
353 IN SYSTEM_CONFIGURATION *SystemConfiguration\r
354 )\r
355{\r
356 EFI_BOOT_MODE BootMode;\r
357 UINT8 Data8;\r
358 UINT16 Data16;\r
359\r
360 (*PeiServices)->GetBootMode(PeiServices, &BootMode);\r
361\r
362 if ((BootMode != BOOT_ON_S3_RESUME)) {\r
363\r
364 //\r
365 // Clear all pending SMI. On S3 clear power button enable so it wll not generate an SMI\r
366 //\r
367 ClearSmiAndWake ();\r
368 }\r
369\r
370 ClearPowerState (SystemConfiguration);\r
371\r
372 //\r
373 // Need to set and clear SET bit (RTC_REGB Bit 7) as requested by the ICH EDS\r
374 // early in POST after each power up directly after coin-cell battery insertion.\r
375 // This is to avoid the UIP bit (RTC_REGA Bit 7) from stuck at "1".\r
376 // The UIP bit status may be polled by software (i.e ME FW) during POST.\r
377 //\r
378 if (MmioRead8 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1) & B_PCH_PMC_GEN_PMCON_RTC_PWR_STS) {\r
379 //\r
380 // Set and clear SET bit in RTC_REGB\r
381 //\r
382 IoWrite8(R_PCH_RTC_INDEX, R_PCH_RTC_REGISTERB);\r
383 Data8 = IoRead8(R_PCH_RTC_TARGET);\r
384 Data8 |= B_PCH_RTC_REGISTERB_SET;\r
385 IoWrite8(R_PCH_RTC_TARGET, Data8);\r
386\r
387 IoWrite8(R_PCH_RTC_INDEX, R_PCH_RTC_REGISTERB);\r
388 Data8 &= (~B_PCH_RTC_REGISTERB_SET);\r
389 IoWrite8(R_PCH_RTC_TARGET, Data8);\r
390\r
391 //\r
392 // Clear the UIP bit in RTC_REGA\r
393 //\r
394 IoWrite8(R_PCH_RTC_INDEX, R_PCH_RTC_REGISTERA);\r
395 IoWrite8(R_PCH_RTC_TARGET, 0x00);\r
396 }\r
397\r
398 //\r
399 // Disable SERR NMI and IOCHK# NMI in port 61\r
400 //\r
401 Data8 = IoRead8 (R_PCH_NMI_SC);\r
402 IoWrite8(R_PCH_NMI_SC, (UINT8) (Data8 | B_PCH_NMI_SC_PCI_SERR_EN | B_PCH_NMI_SC_IOCHK_NMI_EN));\r
403\r
404 //\r
405 // Enable Bus Master, I/O, Mem, and SERR on LPC bridge\r
406 //\r
407 Data16 = PchLpcPciCfg16 (R_PCH_LPC_COMMAND);\r
408 MmioWrite16 (\r
409 MmPciAddress (0,\r
410 DEFAULT_PCI_BUS_NUMBER_PCH,\r
411 PCI_DEVICE_NUMBER_PCH_LPC,\r
412 PCI_FUNCTION_NUMBER_PCH_LPC,\r
413 R_PCH_LPC_COMMAND\r
414 ),\r
415 (Data16 |\r
416 B_PCH_LPC_COMMAND_IOSE |\r
417 B_PCH_LPC_COMMAND_MSE |\r
418 B_PCH_LPC_COMMAND_BME |\r
419 B_PCH_LPC_COMMAND_SERR_EN)\r
420 );\r
421\r
422 //\r
423 // Set Stretch S4 to 1-2s per marketing request.\r
424 // Note: This register is powered by RTC well.\r
425 //\r
426 MmioAndThenOr8 (\r
427 PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1 ,\r
428 (UINT8) (~B_PCH_PMC_GEN_PMCON_SLP_S4_MAW),\r
429 (UINT8) (B_PCH_PMC_GEN_PMCON_SLP_S4_ASE | V_PCH_PMC_GEN_PMCON_SLP_S4_MAW_4S)\r
430 );\r
431\r
432}\r
433\r
434#define V_PCH_ILB_IRQE_UARTIRQEN_IRQ3 BIT3 // UART IRQ3 Enable\r
435\r
436VOID\r
437UARTInit (\r
438 IN SYSTEM_CONFIGURATION *SystemConfiguration\r
439 )\r
440{\r
441 if (0) { // for fix cr4 issue\r
442 //\r
443 // Program and enable PMC Base.\r
444 //\r
445 IoWrite32 (0xCF8, PCI_LPC_REG(R_PCH_LPC_PMC_BASE));\r
446 IoWrite32 (0xCFC, (PMC_BASE_ADDRESS | B_PCH_LPC_PMC_BASE_EN));\r
447\r
448 if( (SystemConfiguration->PcuUart1 == 1) &&\r
449 (SystemConfiguration->LpssHsuart0Enabled == 0)){\r
450 //\r
451 // Enable COM1 for debug message output.\r
452 //\r
453 MmioOr32 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1, BIT24);\r
454\r
455 //\r
456 //Enable internal UART3 port(COM1)\r
457 //\r
458 MmioOr8 (ILB_BASE_ADDRESS + R_PCH_ILB_IRQE, (UINT8) V_PCH_ILB_IRQE_UARTIRQEN_IRQ3);\r
459 MmioOr32 (IO_BASE_ADDRESS + 0x0520, 0x01); // UART3_RXD-L\r
460 MmioOr32 (IO_BASE_ADDRESS + 0x0530, 0x01); // UART3_TXD-0\r
461 MmioOr8 (PciD31F0RegBase + R_PCH_LPC_UART_CTRL, (UINT8) B_PCH_LPC_UART_CTRL_COM1_EN);\r
462 } else {\r
463 //\r
464 //Disable UART3(COM1)\r
465 //\r
466 MmioAnd8 (ILB_BASE_ADDRESS + R_PCH_ILB_IRQE, (UINT8) ~V_PCH_ILB_IRQE_UARTIRQEN_IRQ3);\r
467 MmioAnd32 (IO_BASE_ADDRESS + 0x0520, ~(UINT32)0x07);\r
468 MmioAnd32 (IO_BASE_ADDRESS + 0x0530, ~(UINT32)0x07);\r
469 MmioAnd8 (PciD31F0RegBase + R_PCH_LPC_UART_CTRL, (UINT8) ~B_PCH_LPC_UART_CTRL_COM1_EN);\r
470\r
471\r
472 if (SystemConfiguration->LpssHsuart0Enabled == 1){\r
473 //\r
474 //Valleyview BIOS Specification Vol2,17.2\r
475