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