Home | History | Annotate | Download | only in IntelQNCLib
      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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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