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