]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.c
QuarkSocPkg: IntelQNCLib: remove set but unused variables
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / Library / IntelQNCLib / IntelQNCLib.c
CommitLineData
9b6bbcdb
MK
1/** @file\r
2Lib function for Pei QNC.\r
3\r
4Copyright (c) 2013-2015 Intel Corporation.\r
5\r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15#include "CommonHeader.h"\r
16\r
17/**\r
18 This function provides the necessary SOC initialization\r
19 before MRC running. It sets RCBA, GPIO, PMBASE\r
20 and some parts of SOC through SOC message method.\r
21 If the function cannot complete it'll ASSERT().\r
22**/\r
23VOID\r
24EFIAPI\r
25PeiQNCPreMemInit (\r
26 VOID\r
27 )\r
28{\r
29 UINT32 RegValue;\r
30\r
31 // QNCPortWrite(Port#, Offset, Value)\r
32\r
33 //\r
34 // Set the fixed PRI Status encodings config.\r
35 //\r
36 QNCPortWrite (\r
37 QUARK_NC_MEMORY_ARBITER_SB_PORT_ID,\r
38 QUARK_NC_MEMORY_ARBITER_REG_ASTATUS,\r
39 QNC_FIXED_CONFIG_ASTATUS\r
40 );\r
41\r
42 // Sideband register write to Remote Management Unit\r
43 QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QNC_MSG_TMPM_REG_PMBA, (BIT31 | PcdGet16 (PcdPmbaIoBaseAddress)));\r
44\r
45 // Configurable I/O address in iLB (legacy block)\r
46\r
47 LpcPciCfg32 (R_QNC_LPC_SMBUS_BASE) = BIT31 | PcdGet16 (PcdSmbaIoBaseAddress);\r
48 LpcPciCfg32 (R_QNC_LPC_GBA_BASE) = BIT31 | PcdGet16 (PcdGbaIoBaseAddress);\r
49 LpcPciCfg32 (R_QNC_LPC_PM1BLK) = BIT31 | PcdGet16 (PcdPm1blkIoBaseAddress);\r
50 LpcPciCfg32 (R_QNC_LPC_GPE0BLK) = BIT31 | PcdGet16 (PcdGpe0blkIoBaseAddress);\r
51 LpcPciCfg32 (R_QNC_LPC_WDTBA) = BIT31 | PcdGet16 (PcdWdtbaIoBaseAddress);\r
52\r
53 //\r
54 // Program RCBA Base Address\r
55 //\r
56 LpcPciCfg32AndThenOr (R_QNC_LPC_RCBA, (~B_QNC_LPC_RCBA_MASK), (((UINT32)(PcdGet64 (PcdRcbaMmioBaseAddress))) | B_QNC_LPC_RCBA_EN));\r
57\r
58 //\r
59 // Program Memory Manager fixed config values.\r
60 //\r
61\r
62 RegValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_BTHCTRL);\r
63 RegValue &= ~(DRAM_NON_HOST_RQ_LIMIT_MASK);\r
64 RegValue |= (V_DRAM_NON_HOST_RQ_LIMIT << DRAM_NON_HOST_RQ_LIMIT_BP);\r
65 QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_BTHCTRL, RegValue);\r
66\r
67 //\r
68 // Program iCLK fixed config values.\r
69 //\r
70 QncIClkAndThenOr (\r
71 QUARK_ICLK_MUXTOP,\r
72 (UINT32) ~(B_MUXTOP_FLEX2_MASK | B_MUXTOP_FLEX1_MASK),\r
73 (V_MUXTOP_FLEX2 << B_MUXTOP_FLEX2_BP) | (V_MUXTOP_FLEX1 << B_MUXTOP_FLEX1_BP)\r
74 );\r
75 QncIClkAndThenOr (\r
76 QUARK_ICLK_REF2_DBUFF0,\r
77 (UINT32) ~(BIT0), // bit[0] cleared\r
78 0\r
79 );\r
80 QncIClkOr (\r
81 QUARK_ICLK_SSC1,\r
82 BIT0 // bit[0] set\r
83 );\r
84 QncIClkOr (\r
85 QUARK_ICLK_SSC2,\r
86 BIT0 // bit[0] set\r
87 );\r
88 QncIClkOr (\r
89 QUARK_ICLK_SSC3,\r
90 BIT0 // bit[0] set\r
91 );\r
92\r
93 //\r
94 // Set RMU DMA disable bit post boot.\r
95 //\r
96 RegValue = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_OPTIONS_1);\r
97 RegValue |= OPTIONS_1_DMA_DISABLE;\r
98 QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_OPTIONS_1, RegValue);\r
99}\r
100\r
101/**\r
102 Do north cluster init which needs to be done AFTER MRC init.\r
103\r
104 @param VOID\r
105\r
106 @retval VOID\r
107**/\r
108\r
109VOID\r
110EFIAPI\r
111PeiQNCPostMemInit (\r
112 VOID\r
113 )\r
114{\r
115 //\r
116 // Program SVID/SID the same as VID/DID for all devices except root ports.\r
117 //\r
118 QNCMmPci32(0, MC_BUS, MC_DEV, MC_FUN, R_EFI_PCI_SVID) = QNCMmPci32(0, MC_BUS, MC_DEV, MC_FUN, PCI_VENDOR_ID_OFFSET);\r
119 QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, R_EFI_PCI_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, PCI_VENDOR_ID_OFFSET);\r
120 QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_0, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, R_EFI_PCI_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_0, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, PCI_VENDOR_ID_OFFSET);\r
121 QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_1, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, R_EFI_PCI_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_1, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, PCI_VENDOR_ID_OFFSET);\r
122 return;\r
123}\r
124\r
125/**\r
126 Used to check QNC if it's S3 state. Clear the register state after query.\r
127\r
128 @retval TRUE if it's S3 state.\r
129 @retval FALSE if it's not S3 state.\r
130\r
131**/\r
132BOOLEAN\r
133EFIAPI\r
134QNCCheckS3AndClearState (\r
135 VOID\r
136 )\r
137{\r
138 BOOLEAN S3WakeEventFound;\r
139 UINT16 Pm1Sts;\r
140 UINT16 Pm1En;\r
141 UINT16 Pm1Cnt;\r
142 UINT32 Gpe0Sts;\r
143 UINT32 Gpe0En;\r
144 UINT32 NewValue;\r
145 CHAR8 *EventDescStr;\r
146\r
147 S3WakeEventFound = FALSE;\r
148 EventDescStr = NULL;\r
149\r
150 //\r
151 // Read the ACPI registers,\r
152 //\r
153 Pm1Sts = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S);\r
154 Pm1En = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E);\r
155 Pm1Cnt = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);\r
156 Gpe0Sts = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S);\r
157 Gpe0En = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0E);\r
158\r
159 //\r
160 // Clear Power Management 1 Enable Register and\r
161 // General Purpost Event 0 Enables Register\r
162 //\r
163 IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, 0);\r
164 IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0E, 0);\r
165\r
166 if ((Pm1Sts & B_QNC_PM1BLK_PM1S_WAKE) != 0 && (Pm1Cnt & B_QNC_PM1BLK_PM1C_SLPTP) == V_S3) {\r
167\r
168 //\r
169 // Detect the actual WAKE event\r
170 //\r
171 if ((Pm1Sts & B_QNC_PM1BLK_PM1S_RTC) && (Pm1En & B_QNC_PM1BLK_PM1E_RTC)) {\r
172 EventDescStr = "RTC Alarm";\r
173 S3WakeEventFound = TRUE;\r
174 }\r
175 if ((Pm1Sts & B_QNC_PM1BLK_PM1S_PCIEWSTS) && !(Pm1En & B_QNC_PM1BLK_PM1E_PWAKED)) {\r
176 EventDescStr = "PCIe WAKE";\r
177 S3WakeEventFound = TRUE;\r
178 }\r
179 if ((Gpe0Sts & B_QNC_GPE0BLK_GPE0S_PCIE) && (Gpe0En & B_QNC_GPE0BLK_GPE0E_PCIE)) {\r
180 EventDescStr = "PCIe";\r
181 S3WakeEventFound = TRUE;\r
182 }\r
183 if ((Gpe0Sts & B_QNC_GPE0BLK_GPE0S_GPIO) && (Gpe0En & B_QNC_GPE0BLK_GPE0E_GPIO)) {\r
184 EventDescStr = "GPIO";\r
185 S3WakeEventFound = TRUE;\r
186 }\r
187 if ((Gpe0Sts & B_QNC_GPE0BLK_GPE0S_EGPE) && (Gpe0En & B_QNC_GPE0BLK_GPE0E_EGPE)) {\r
188 EventDescStr = "Ext. GPE";\r
189 S3WakeEventFound = TRUE;\r
190 }\r
191 if (S3WakeEventFound == FALSE) {\r
192 EventDescStr = "Unknown";\r
193 }\r
194 DEBUG ((EFI_D_INFO, "S3 Wake Event - %a\n", EventDescStr));\r
195\r
196 //\r
197 // If no Power Button Override event occurs and one enabled wake event occurs,\r
198 // just do S3 resume and clear the state.\r
199 //\r
200 IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, (Pm1Cnt & (~B_QNC_PM1BLK_PM1C_SLPTP)));\r
201\r
202 //\r
203 // Set EOS to de Assert SMI\r
204 //\r
205 IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_EOS);\r
206\r
207 //\r
208 // Enable SMI globally\r
209 //\r
210 NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
211 NewValue |= SMI_EN;\r
212 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);\r
213\r
214 return TRUE;\r
215 }\r
216\r
217 return FALSE;\r
218}\r
219\r
220/**\r
221 Used to check QNC if system wakes up from power on reset. Clear the register state after query.\r
222\r
223 @retval TRUE if system wakes up from power on reset\r
224 @retval FALSE if system does not wake up from power on reset\r
225\r
226**/\r
227BOOLEAN\r
228EFIAPI\r
229QNCCheckPowerOnResetAndClearState (\r
230 VOID\r
231 )\r
232{\r
233 UINT16 Pm1Sts;\r
234 UINT16 Pm1Cnt;\r
235\r
236 //\r
237 // Read the ACPI registers,\r
238 // PM1_STS information cannot be lost after power down, unless CMOS is cleared.\r
239 //\r
240 Pm1Sts = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S);\r
241 Pm1Cnt = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);\r
242\r
243 //\r
244 // If B_SLP_TYP is S5\r
245 //\r
246 if ((Pm1Sts & B_QNC_PM1BLK_PM1S_WAKE) != 0 && (Pm1Cnt & B_QNC_PM1BLK_PM1C_SLPTP) == V_S5) {\r
247 IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, (Pm1Cnt & (~B_QNC_PM1BLK_PM1C_SLPTP)));\r
248 return TRUE;\r
249 }\r
250\r
251 return FALSE;\r
252}\r
253\r
254/**\r
255 This function is used to clear SMI and wake status.\r
256\r
257**/\r
258VOID\r
259EFIAPI\r
260QNCClearSmiAndWake (\r
261 VOID\r
262 )\r
263{\r
264 UINT32 Gpe0Sts;\r
265 UINT32 SmiSts;\r
266\r
267 //\r
268 // Read the ACPI registers\r
269 //\r
270 Gpe0Sts = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S);\r
271 SmiSts = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);\r
272\r
273 //\r
274 // Clear any SMI or wake state from the boot\r
275 //\r
276 Gpe0Sts |= B_QNC_GPE0BLK_GPE0S_ALL;\r
277 SmiSts |= B_QNC_GPE0BLK_SMIS_ALL;\r
278\r
279 //\r
280 // Write them back\r
281 //\r
282 IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S, Gpe0Sts);\r
283 IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS, SmiSts);\r
284}\r
285\r
286/** Send DRAM Ready opcode.\r
287\r
288 @param[in] OpcodeParam Parameter to DRAM ready opcode.\r
289\r
290 @retval VOID\r
291**/\r
292VOID\r
293EFIAPI\r
294QNCSendOpcodeDramReady (\r
295 IN UINT32 OpcodeParam\r
296 )\r
297{\r
298\r
299 //\r
300 // Before sending DRAM ready place invalid value in Scrub Config.\r
301 //\r
302 QNCPortWrite (\r
303 QUARK_NC_RMU_SB_PORT_ID,\r
304 QUARK_NC_ECC_SCRUB_CONFIG_REG,\r
305 SCRUB_CFG_INVALID\r
306 );\r
307\r
308 //\r
309 // Send opcode and use param to notify HW of new RMU firmware location.\r
310 //\r
311 McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = OpcodeParam;\r
312 McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_SHADOW_DW (QUARK_NC_RMU_SB_PORT_ID, 0);\r
313\r
314 //\r
315 // HW completed tasks on DRAM ready when scrub config read back as zero.\r
316 //\r
317 while (QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG) != 0) {\r
318 MicroSecondDelay (10);\r
319 }\r
320}\r
321\r
322/**\r
323\r
324 Relocate RMU Main binary to memory after MRC to improve performance.\r
325\r
326 @param[in] DestBaseAddress - Specify the new memory address for the RMU Main binary.\r
327 @param[in] SrcBaseAddress - Specify the current memory address for the RMU Main binary.\r
328 @param[in] Size - Specify size of the RMU Main binary.\r
329\r
330 @retval VOID\r
331\r
332**/\r
333VOID\r
334EFIAPI\r
335RmuMainRelocation (\r
336 IN CONST UINT32 DestBaseAddress,\r
337 IN CONST UINT32 SrcBaseAddress,\r
338 IN CONST UINTN Size\r
339 )\r
340{\r
341 //\r
342 // Shadow RMU Main binary into main memory.\r
343 //\r
344 CopyMem ((VOID *)(UINTN)DestBaseAddress,(VOID *)(UINTN) SrcBaseAddress, Size);\r
345}\r
346\r
347\r
348/**\r
349 Get the total memory size\r
350\r
351**/\r
352UINT32\r
353EFIAPI\r
354QNCGetTotalMemorysize (\r
355 VOID\r
356 )\r
357{\r
358 return QNCPortRead(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HMBOUND_REG) & HMBOUND_MASK;\r
359}\r
360\r
361\r
362/**\r
363 Get the memory range of TSEG.\r
364 The TSEG's memory is below TOLM.\r
365\r
366 @param[out] BaseAddress The base address of TSEG's memory range\r
367 @param[out] MemorySize The size of TSEG's memory range\r
368\r
369**/\r
370VOID\r
371EFIAPI\r
372QNCGetTSEGMemoryRange (\r
373 OUT UINT64 *BaseAddress,\r
374 OUT UINT64 *MemorySize\r
375 )\r
376{\r
377 UINT64 Register = 0;\r
378 UINT64 SMMAddress = 0;\r
379\r
380 Register = QncHsmmcRead ();\r
381\r
382 //\r
383 // Get the SMRAM Base address\r
384 //\r
385 SMMAddress = Register & SMM_START_MASK;\r
386 *BaseAddress = LShift16 (SMMAddress);\r
387\r
388 //\r
389 // Get the SMRAM size\r
390 //\r
391 SMMAddress = ((Register & SMM_END_MASK) | (~SMM_END_MASK)) + 1;\r
392 *MemorySize = SMMAddress - (*BaseAddress);\r
393\r
394 DEBUG ((\r
395 EFI_D_INFO,\r
396 "TSEG's memory range: BaseAddress = 0x%x, Size = 0x%x\n",\r
397 (UINT32)*BaseAddress,\r
398 (UINT32)*MemorySize\r
399 ));\r
400}\r
401\r
402/**\r
403 Updates the PAM registers in the MCH for the requested range and mode.\r
404\r
405 @param Start The start address of the memory region\r
406 @param Length The length, in bytes, of the memory region\r
407 @param ReadEnable Pointer to the boolean variable on whether to enable read for legacy memory section.\r
408 If NULL, then read attribute will not be touched by this call.\r
409 @param ReadEnable Pointer to the boolean variable on whether to enable write for legacy memory section.\r
410 If NULL, then write attribute will not be touched by this call.\r
411 @param Granularity A pointer to granularity, in bytes, that the PAM registers support\r
412\r
413 @retval RETURN_SUCCESS The PAM registers in the MCH were updated\r
414 @retval RETURN_INVALID_PARAMETER The memory range is not valid in legacy region.\r
415\r
416**/\r
417EFI_STATUS\r
418EFIAPI\r
419QNCLegacyRegionManipulation (\r
420 IN UINT32 Start,\r
421 IN UINT32 Length,\r
422 IN BOOLEAN *ReadEnable,\r
423 IN BOOLEAN *WriteEnable,\r
424 OUT UINT32 *Granularity\r
425 )\r
426{\r
427 //\r
428 // Do nothing cos no such support on QNC\r
429 //\r
430 return RETURN_SUCCESS;\r
431}\r
432\r
433/**\r
434 Determine if QNC is supported.\r
435\r
436 @retval FALSE QNC is not supported.\r
437 @retval TRUE QNC is supported.\r
438**/\r
439BOOLEAN\r
440EFIAPI\r
441IsQncSupported (\r
442 VOID\r
443 )\r
444{\r
445 UINT16 SocVendorId;\r
446 UINT16 SocDeviceId;\r
447\r
448 SocVendorId = MmioRead16 (\r
449 PciDeviceMmBase (MC_BUS,\r
450 MC_DEV,\r
451 MC_FUN) + PCI_VENDOR_ID_OFFSET\r
452 );\r
453\r
454 SocDeviceId = QncGetSocDeviceId();\r
455\r
456 //\r
457 // Verify that this is a supported chipset\r
458 //\r
459 if ((SocVendorId != QUARK_MC_VENDOR_ID) || ((SocDeviceId != QUARK_MC_DEVICE_ID) && (SocDeviceId != QUARK2_MC_DEVICE_ID))) {\r
460 DEBUG ((DEBUG_ERROR, "QNC code doesn't support the Soc VendorId:0x%04x Soc DeviceId:0x%04x!\n", SocVendorId, SocDeviceId));\r
461 return FALSE;\r
462 }\r
463 return TRUE;\r
464}\r
465\r
466/**\r
467 Get the DeviceId of the SoC\r
468\r
469 @retval PCI DeviceId of the SoC\r
470**/\r
471UINT16\r
472EFIAPI\r
473QncGetSocDeviceId (\r
474 VOID\r
475 )\r
476{\r
477 UINT16 SocDeviceId;\r
478\r
479 SocDeviceId = MmioRead16 (\r
480 PciDeviceMmBase (\r
481 MC_BUS,\r
482 MC_DEV,\r
483 MC_FUN\r
484 ) + PCI_DEVICE_ID_OFFSET\r
485 );\r
486\r
487 return SocDeviceId;\r
488}\r
489\r
490/**\r
491 Enable SMI detection of legacy flash access violations.\r
492**/\r
493VOID\r
494EFIAPI\r
495QncEnableLegacyFlashAccessViolationSmi (\r
496 VOID\r
497 )\r
498{\r
499 UINT32 BcValue;\r
500\r
501 BcValue = LpcPciCfg32 (R_QNC_LPC_BIOS_CNTL);\r
502\r
503 //\r
504 // Clear BIOSWE & set BLE.\r
505 //\r
506 BcValue &= (~B_QNC_LPC_BIOS_CNTL_BIOSWE);\r
507 BcValue |= (B_QNC_LPC_BIOS_CNTL_BLE);\r
508\r
509 LpcPciCfg32 (R_QNC_LPC_BIOS_CNTL) = BcValue;\r
510\r
511 DEBUG ((EFI_D_INFO, "BIOS Control Lock Enabled!\n"));\r
512}\r
513\r
514/**\r
515 Setup RMU Thermal sensor registers for Vref mode.\r
516**/\r
517VOID\r
518EFIAPI\r
519QNCThermalSensorSetVRefMode (\r
520 VOID\r
521 )\r
522{\r
523 UINT32 Tscgf1Config;\r
524 UINT32 Tscgf2Config;\r
525 UINT32 Tscgf2Config2;\r
526\r
527 Tscgf1Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG);\r
528 Tscgf2Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG);\r
529 Tscgf2Config2 = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2);\r
530\r
531 Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSCURRENTSEL_MASK);\r
532 Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSCURRENTSEL_VREF_MODE << B_TSCGF1_CONFIG_ISNSCURRENTSEL_BP);\r
533\r
534 Tscgf1Config &= ~(B_TSCGF1_CONFIG_IBGEN);\r
535 Tscgf1Config |= (V_TSCGF1_CONFIG_IBGEN_VREF_MODE << B_TSCGF1_CONFIG_IBGEN_BP);\r
536\r
537 Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ISPARECTRL_MASK);\r
538 Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ISPARECTRL_VREF_MODE << B_TSCGF2_CONFIG2_ISPARECTRL_BP);\r
539\r
540 Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ICALCOARSETUNE_MASK);\r
541 Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ICALCOARSETUNE_VREF_MODE << B_TSCGF2_CONFIG2_ICALCOARSETUNE_BP);\r
542\r
543 Tscgf2Config &= ~(B_TSCGF2_CONFIG_IDSCONTROL_MASK);\r
544 Tscgf2Config |= (V_TSCGF2_CONFIG_IDSCONTROL_VREF_MODE << B_TSCGF2_CONFIG_IDSCONTROL_BP);\r
545\r
546 QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG, Tscgf1Config);\r
547 QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG, Tscgf2Config);\r
548 QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2, Tscgf2Config2);\r
549}\r
550\r
551/**\r
552 Setup RMU Thermal sensor registers for Ratiometric mode.\r
553**/\r
554VOID\r
555EFIAPI\r
556QNCThermalSensorSetRatiometricMode (\r
557 VOID\r
558 )\r
559{\r
560 UINT32 Tscgf1Config;\r
561 UINT32 Tscgf2Config;\r
562 UINT32 Tscgf2Config2;\r
563 UINT32 Tscgf3Config;\r
564\r
565 Tscgf1Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG);\r
566 Tscgf2Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG);\r
567 Tscgf2Config2 = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2);\r
568 Tscgf3Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG);\r
569\r
570 Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSCURRENTSEL_MASK);\r
571 Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSCURRENTSEL_RATIO_MODE << B_TSCGF1_CONFIG_ISNSCURRENTSEL_BP);\r
572\r
573 Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSCHOPSEL_MASK);\r
574 Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSCHOPSEL_RATIO_MODE << B_TSCGF1_CONFIG_ISNSCHOPSEL_BP);\r
575\r
576 Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSINTERNALVREFEN);\r
577 Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSINTERNALVREFEN_RATIO_MODE << B_TSCGF1_CONFIG_ISNSINTERNALVREFEN_BP);\r
578\r
579 Tscgf1Config &= ~(B_TSCGF1_CONFIG_IBGEN);\r
580 Tscgf1Config |= (V_TSCGF1_CONFIG_IBGEN_RATIO_MODE << B_TSCGF1_CONFIG_IBGEN_BP);\r
581\r
582 Tscgf1Config &= ~(B_TSCGF1_CONFIG_IBGCHOPEN);\r
583 Tscgf1Config |= (V_TSCGF1_CONFIG_IBGCHOPEN_RATIO_MODE << B_TSCGF1_CONFIG_IBGCHOPEN_BP);\r
584\r
585 Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ICALCONFIGSEL_MASK);\r
586 Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ICALCONFIGSEL_RATIO_MODE << B_TSCGF2_CONFIG2_ICALCONFIGSEL_BP);\r
587\r
588 Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ISPARECTRL_MASK);\r
589 Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ISPARECTRL_RATIO_MODE << B_TSCGF2_CONFIG2_ISPARECTRL_BP);\r
590\r
591 Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ICALCOARSETUNE_MASK);\r
592 Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ICALCOARSETUNE_RATIO_MODE << B_TSCGF2_CONFIG2_ICALCOARSETUNE_BP);\r
593\r
594 Tscgf2Config &= ~(B_TSCGF2_CONFIG_IDSCONTROL_MASK);\r
595 Tscgf2Config |= (V_TSCGF2_CONFIG_IDSCONTROL_RATIO_MODE << B_TSCGF2_CONFIG_IDSCONTROL_BP);\r
596\r
597 Tscgf2Config &= ~(B_TSCGF2_CONFIG_IDSTIMING_MASK);\r
598 Tscgf2Config |= (V_TSCGF2_CONFIG_IDSTIMING_RATIO_MODE << B_TSCGF2_CONFIG_IDSTIMING_BP);\r
599\r
600 Tscgf3Config &= ~(B_TSCGF3_CONFIG_ITSGAMMACOEFF_MASK);\r
601 Tscgf3Config |= (V_TSCGF3_CONFIG_ITSGAMMACOEFF_RATIO_MODE << B_TSCGF3_CONFIG_ITSGAMMACOEFF_BP);\r
602\r
603 QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG, Tscgf1Config);\r
604 QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG, Tscgf2Config);\r
605 QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2, Tscgf2Config2);\r
606 QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG, Tscgf3Config);\r
607}\r
608\r
609/**\r
610 Setup RMU Thermal sensor trip point values.\r
611\r
612 @param[in] CatastrophicTripOnDegreesCelsius - Catastrophic set trip point threshold.\r
613 @param[in] HotTripOnDegreesCelsius - Hot set trip point threshold.\r
614 @param[in] HotTripOffDegreesCelsius - Hot clear trip point threshold.\r
615\r
616 @retval EFI_SUCCESS Trip points setup.\r
617 @retval EFI_INVALID_PARAMETER Invalid trip point value.\r
618\r
619**/\r
620EFI_STATUS\r
621EFIAPI\r
622QNCThermalSensorSetTripValues (\r
623 IN CONST UINTN CatastrophicTripOnDegreesCelsius,\r
624 IN CONST UINTN HotTripOnDegreesCelsius,\r
625 IN CONST UINTN HotTripOffDegreesCelsius\r
626 )\r
627{\r
628 UINT32 RegisterValue;\r
629\r
630 //\r
631 // Register fields are 8-bit temperature values of granularity 1 degree C\r
632 // where 0x00 corresponds to -50 degrees C\r
633 // and 0xFF corresponds to 205 degrees C.\r
634 //\r
635 // User passes unsigned values in degrees Celsius so trips < 0 not supported.\r
636 //\r
637 // Add 50 to user values to get values for register fields.\r
638 //\r
639\r
640 if ((CatastrophicTripOnDegreesCelsius > 205) || (HotTripOnDegreesCelsius > 205) || (HotTripOffDegreesCelsius > 205)) {\r
641 return EFI_INVALID_PARAMETER;\r
642 }\r
643\r
644 //\r
645 // Set new values.\r
646 //\r
647 RegisterValue =\r
648 ((0 + 50) << TS_CAT_TRIP_CLEAR_THOLD_BP) | // Cat Trip Clear value must be less than Cat Trip Set Value.\r
649 ((CatastrophicTripOnDegreesCelsius + 50) << TS_CAT_TRIP_SET_THOLD_BP) |\r
650 ((HotTripOnDegreesCelsius + 50) << TS_HOT_TRIP_SET_THOLD_BP) |\r
651 ((HotTripOffDegreesCelsius + 50) << TS_HOT_TRIP_CLEAR_THOLD_BP)\r
652 ;\r
653\r
654 QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_TRIP, RegisterValue);\r
655\r
656 return EFI_SUCCESS;\r
657}\r
658\r
659/**\r
660 Enable RMU Thermal sensor with a Catastrophic Trip point.\r
661\r
662 @retval EFI_SUCCESS Trip points setup.\r
663 @retval EFI_INVALID_PARAMETER Invalid trip point value.\r
664\r
665**/\r
666EFI_STATUS\r
667EFIAPI\r
668QNCThermalSensorEnableWithCatastrophicTrip (\r
669 IN CONST UINTN CatastrophicTripOnDegreesCelsius\r
670 )\r
671{\r
672 UINT32 Tscgf3Config;\r
673 UINT32 TsModeReg;\r
674 UINT32 TsTripReg;\r
675\r
676 //\r
677 // Trip Register fields are 8-bit temperature values of granularity 1 degree C\r
678 // where 0x00 corresponds to -50 degrees C\r
679 // and 0xFF corresponds to 205 degrees C.\r
680 //\r
681 // User passes unsigned values in degrees Celsius so trips < 0 not supported.\r
682 //\r
683 // Add 50 to user values to get values for register fields.\r
684 //\r
685\r
686 if (CatastrophicTripOnDegreesCelsius > 205) {\r
687 return EFI_INVALID_PARAMETER;\r
688 }\r
689\r
690 Tscgf3Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG);\r
691 TsModeReg = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_MODE);\r
692 TsTripReg = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_TRIP);\r
693\r
694 //\r
695 // Setup Catastrophic Trip point.\r
696 //\r
697 TsTripReg &= ~(TS_CAT_TRIP_SET_THOLD_MASK);\r
698 TsTripReg |= ((CatastrophicTripOnDegreesCelsius + 50) << TS_CAT_TRIP_SET_THOLD_BP);\r
699 TsTripReg &= ~(TS_CAT_TRIP_CLEAR_THOLD_MASK);\r
700 TsTripReg |= ((0 + 50) << TS_CAT_TRIP_CLEAR_THOLD_BP); // Cat Trip Clear value must be less than Cat Trip Set Value.\r
701 QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_TRIP, TsTripReg);\r
702\r
703 //\r
704 // To enable the TS do the following:\r
705 // 1) Take the TS out of reset by setting itsrst to 0x0.\r
706 // 2) Enable the TS using RMU Thermal sensor mode register.\r
707 //\r
708\r
709 Tscgf3Config &= ~(B_TSCGF3_CONFIG_ITSRST);\r
710 TsModeReg |= TS_ENABLE;\r
711\r
712 QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG, Tscgf3Config);\r
713 QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_MODE, TsModeReg);\r
714\r
715 return EFI_SUCCESS;\r
716}\r
717\r
718/**\r
719 Lock all RMU Thermal sensor control & trip point registers.\r
720\r
721**/\r
722VOID\r
723EFIAPI\r
724QNCThermalSensorLockAllRegisters (\r
725 VOID\r
726 )\r
727{\r
728 UINT32 RegValue;\r
729 UINT32 LockMask;\r
730\r
731 LockMask = TS_LOCK_THRM_CTRL_REGS_ENABLE | TS_LOCK_AUX_TRIP_PT_REGS_ENABLE;\r
732\r
733 RegValue = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_CONFIG);\r
734 RegValue |= LockMask;\r
735 QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_CONFIG, RegValue);\r
736\r
737 ASSERT ((LockMask == (QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_CONFIG) & LockMask)));\r
738}\r
739\r
740/**\r
741 Set chipset policy for double bit ECC error.\r
742\r
743 @param[in] PolicyValue Policy to config on double bit ECC error.\r
744\r
745**/\r
746VOID\r
747EFIAPI\r
748QNCPolicyDblEccBitErr (\r
749 IN CONST UINT32 PolicyValue\r
750 )\r
751{\r
752 UINT32 Register;\r
753 Register = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_WDT_CONTROL);\r
754 Register &= ~(B_WDT_CONTROL_DBL_ECC_BIT_ERR_MASK);\r
755 Register |= PolicyValue;\r
756 QNCPortWrite (\r
757 QUARK_NC_RMU_SB_PORT_ID,\r
758 QUARK_NC_RMU_REG_WDT_CONTROL,\r
759 Register\r
760 );\r
761}\r
762\r
763/**\r
764 Determine if running on secure Quark hardware Sku.\r
765\r
766 @retval FALSE Base Quark Sku or unprovisioned Secure Sku running.\r
767 @retval TRUE Provisioned SecureSku hardware running.\r
768**/\r
769BOOLEAN\r
770EFIAPI\r
771QncIsSecureProvisionedSku (\r
772 VOID\r
773 )\r
774{\r
775 // Read QUARK Secure SKU Fuse\r
776 return ((QNCAltPortRead (QUARK_SCSS_FUSE_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SPI_ROM_FUSE) & BIT6) == BIT6);\r
777}\r