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