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