• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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