Exemplo n.º 1
0
/**
  Triggers a run time or boot time SMI.

  This function triggers a software SMM interrupt and set the APMC status with an 8-bit Data.

  @param  Data                 The value to set the APMC status.

**/
VOID
InternalTriggerSmi (
  IN UINT8                     Data
  )
{
  UINT16        PM1BLK_Base;
  UINT16        GPE0BLK_Base;
  UINT32        NewValue;

  //
  // Get PM1BLK_Base & GPE0BLK_Base
  //
  PM1BLK_Base = PcdGet16 (PcdPm1blkIoBaseAddress);
  GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);


  //
  // Enable APM SMI
  //
  IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIE), B_QNC_GPE0BLK_SMIE_APM);

  //
  // Enable SMI globally
  //
  NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
  NewValue |= SMI_EN;
  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);

  //
  // Set APM_STS
  //
  IoWrite8 (PcdGet16 (PcdSmmDataPort), Data);

  //
  // Generate the APM SMI
  //
  IoWrite8 (PcdGet16 (PcdSmmActivationPort), PcdGet8 (PcdSmmActivationData));

  //
  // Clear the APM SMI Status Bit
  //
  IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);

  //
  // Set the EOS Bit
  //
  IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);
}
Exemplo n.º 2
0
/**
  Clear SMI related chipset status and re-enable SMI by setting the EOS bit.

  @retval EFI_SUCCESS The requested operation has been carried out successfully
  @retval EFI_DEVICE_ERROR  The EOS bit could not be set.

**/
EFI_STATUS
SmmClear (
  VOID
  )
{
  UINT16                       PM1BLK_Base;
  UINT16                       GPE0BLK_Base;

  //
  // Get PM1BLK_Base & GPE0BLK_Base
  //
  PM1BLK_Base  = PcdGet16 (PcdPm1blkIoBaseAddress);
  GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);

  //
  // Clear the Power Button Override Status Bit, it gates EOS from being set.
  // In QuarkNcSocId - Bit is read only. Handled by external SMC, do nothing.
  //

  //
  // Clear the APM SMI Status Bit
  //
  IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);

  //
  // Set the EOS Bit
  //
  IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);

  return EFI_SUCCESS;
}
Exemplo n.º 3
0
/**

  Clear APM SMI Status Bit; Set the EOS bit.

**/
VOID
EFIAPI
ClearSmi (
  VOID
  )
{

  UINT16                       GPE0BLK_Base;

  //
  // Get GpeBase
  //
  GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);

  //
  // Clear the APM SMI Status Bit
  //
  IoOr16 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_APM);

  //
  // Set the EOS Bit
  //
  IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_EOS);
}
Exemplo n.º 4
0
VOID
QNCSmmPeriodicTimerProgramTimers (
  VOID
  )
{
  UINT32            GpePmcwValue;
  SUPPORTED_TIMER   Timer;
  DATABASE_RECORD   *RecordInDb;
  LIST_ENTRY        *LinkInDb;
  TIMER_INTERVAL    *TimerInterval;

  //
  // Find the minimum required interval for each timer
  //
  for (Timer = (SUPPORTED_TIMER)0; Timer < NUM_TIMERS; Timer++) {
    mTimers[Timer].MinReqInterval = ~(UINT64)0x0;
    mTimers[Timer].NumChildren = 0;
  }
  LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);
  while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {
    RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);
    if (RecordInDb->ProtocolType == PeriodicTimerType) {
      //
      // This child is registerd with the PeriodicTimer protocol
      //
      TimerInterval = ContextToTimerInterval (&RecordInDb->ChildContext);

      if(TimerInterval != NULL) {
        Timer = (SUPPORTED_TIMER)((TIMER_INTERVAL *) (TimerInterval))->AssociatedTimer;

        ASSERT (Timer >= 0 && Timer < NUM_TIMERS);

        if (mTimers[Timer].MinReqInterval > RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval) {
          mTimers[Timer].MinReqInterval = RecordInDb->ChildContext.PeriodicTimer.SmiTickInterval;
        }
        mTimers[Timer].NumChildren++;
      }
    }
    LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, &RecordInDb->Link);
  }

  //
  // Program the hardware
  //
  GpePmcwValue = 0;
  if (mTimers[PERIODIC_TIMER].NumChildren > 0) {
    switch (mTimers[PERIODIC_TIMER].MinReqInterval) {

    case TIME_64s:
      GpePmcwValue = INDEX_TIME_64s;
      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64s;
      break;

    case TIME_32s:
      GpePmcwValue = INDEX_TIME_32s;
      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32s;
      break;

    case TIME_16s:
      GpePmcwValue = INDEX_TIME_16s;
      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16s;
      break;

    case TIME_8s:
      GpePmcwValue = INDEX_TIME_8s;
      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_8s;
      break;

    case TIME_64ms:
      GpePmcwValue = INDEX_TIME_64ms;
      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_64ms;
      break;

    case TIME_32ms:
      GpePmcwValue = INDEX_TIME_32ms;
      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_32ms;
      break;

    case TIME_16ms:
      GpePmcwValue = INDEX_TIME_16ms;
      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_16ms;
      break;

    case TIME_1_5ms:
      GpePmcwValue = INDEX_TIME_1_5ms;
      mTimers[PERIODIC_TIMER].CurrentSetting = INDEX_TIME_1_5ms;
      break;

    default:
      ASSERT (FALSE);
      break;
    };

    GpePmcwValue |= B_QNC_GPE0BLK_PMCW_PSE;

    IoOr32(((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_PMCW), GpePmcwValue);

    //
    // Restart the timer here, just need to clear the SMI
    //
    QNCSmmClearSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);
  } else {
    QNCSmmDisableSource (&mTIMER_SOURCE_DESCS[PERIODIC_TIMER]);
  }
}
Exemplo n.º 5
0
/**

  Do memory initialisation for QNC DDR3 SDRAM Controller

  @return EFI_SUCCESS  Memory initialisation completed successfully.
          All other error conditions encountered result in an ASSERT.

**/
EFI_STATUS
MemoryInit (
  VOID
  )
{
  MRC_PARAMS                                 MrcData;
  EFI_BOOT_MODE                               BootMode;
  EFI_STATUS                                  Status;
  EFI_STATUS_CODE_VALUE                       ErrorCodeValue;
  UINT16                                      PmswAdr;
  PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE MemoryMap[MAX_RANGES];
  UINT8                                 NumRanges;
  EFI_PHYSICAL_ADDRESS                  BadMemoryAddress;
  EFI_PHYSICAL_ADDRESS                  FspReservedArea;
  UINT64                                ReservedBytes;
  UINT32                                RmuMainMemoryAddress;

  ErrorCodeValue  = 0;

  //
  // It is critical that both of these data structures are initialized to 0.
  // This PEIM knows the number of DIMMs in the system and works with that
  // information.  The MCH PEIM that consumes these data structures does not
  // know the number of DIMMs so it expects the entire structure to be
  // properly initialized.  By initializing these to zero, all flags indicating
  // that the SPD is present or the row should be configured are set to false.
  //
  ZeroMem (&MrcData, sizeof(MrcData));

  //
  // Determine boot mode
  //
  BootMode = GetBootMode();

  //
  // Initialize Error type for reporting status code
  //
  switch (BootMode) {
  case BOOT_ON_FLASH_UPDATE:
    ErrorCodeValue = EFI_COMPUTING_UNIT_MEMORY + EFI_CU_MEMORY_EC_UPDATE_FAIL;
    break;
  case BOOT_ON_S3_RESUME:
    ErrorCodeValue = EFI_COMPUTING_UNIT_MEMORY + EFI_CU_MEMORY_EC_S3_RESUME_FAIL;
    break;
  default:
    ErrorCodeValue = EFI_COMPUTING_UNIT_MEMORY;
    break;
  }

  //
  // Specify MRC boot mode
  //
  switch (BootMode) {
  case BOOT_ON_S3_RESUME:
  case BOOT_ON_FLASH_UPDATE:
    MrcData.boot_mode = bmS3;
    break;
  case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
    MrcData.boot_mode = bmFast;
    break;
  default:
    MrcData.boot_mode = bmCold;
    break;
  }

  //
  // Configure MRC input parameters.
  //
  MrcConfigureFromMcFuses (&MrcData);
  MrcConfigureFromInfoHob (&MrcData);

  if (BootMode == BOOT_IN_RECOVERY_MODE) {
    //
    // Always do bmCold on recovery.
    //
    DEBUG ((DEBUG_INFO, "MemoryInit:Force bmCold on Recovery\n"));
    MrcData.boot_mode = bmCold;
  } else {

    //
    // Get the saved memory data if possible
    //
    if ((GetMrcDataPtr() != 0) && (GetMrcDataLength() != 0)) {
      ASSERT(GetMrcDataLength() == sizeof(MrcData.timings));
      CopyMem (&MrcData.timings, (void *)GetMrcDataPtr(), GetMrcDataLength());
    } else {
      switch (BootMode) {
      case BOOT_ON_S3_RESUME:
      case BOOT_ON_FLASH_UPDATE:
        DEBUG ((DEBUG_ERROR, "ERROR: MRC data missing - reboot\n"));
        REPORT_STATUS_CODE (
          EFI_ERROR_CODE + EFI_ERROR_UNRECOVERED,
          ErrorCodeValue
        );
        return FSP_STATUS_RESET_REQUIRED_COLD;
        break;

      default:
        MrcData.boot_mode = bmCold;
        break;
      }
    }
  }

  PmswAdr = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_PMSW;
  if( IoRead32 (PmswAdr) & B_QNC_GPE0BLK_PMSW_DRAM_INIT) {
    // MRC did not complete last execution, force cold boot path
    MrcData.boot_mode = bmCold;
  }

  // Mark MRC pending
  IoOr32 (PmswAdr, (UINT32)B_QNC_GPE0BLK_PMSW_DRAM_INIT);

  //
  // Call Memory Reference Code's Routines
  //
  Mrc (&MrcData);

  // Mark MRC completed
  IoAnd32 (PmswAdr, ~(UINT32)B_QNC_GPE0BLK_PMSW_DRAM_INIT);

  //
  // Get the Memory Map
  //
  NumRanges = MAX_RANGES;
  ZeroMem (MemoryMap, sizeof (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE) * NumRanges);
  Status = GetMemoryMap (
             MrcData.mem_size,
             (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *) MemoryMap,
             &NumRanges,
             &RmuMainMemoryAddress
             );
  ASSERT_EFI_ERROR (Status);
  ASSERT(NumRanges <= MAX_RANGES);

  //
  // Locate the FSP reserved memory (last entry).
  //
  FspReservedArea = MemoryMap[NumRanges - 1].PhysicalAddress;
  ReservedBytes = MemoryMap[NumRanges - 1].RangeLength;

  //
  // Test the memory from 1M->TOM
  //
  if (BootMode != BOOT_ON_S3_RESUME) {
    if (BootMode != BOOT_ON_FLASH_UPDATE) {
      Status = BaseMemoryTest (
                0x100000,
                (MrcData.mem_size - 0x100000),
                Quick,
                &BadMemoryAddress
                );
      ASSERT_EFI_ERROR (Status);
    }

    //
    // Assign physical memory to PEI
    //
    FspInstallPeiMemory (FspReservedArea, ReservedBytes);
  }

  //
  // Enable memory for use
  //
  PostInstallMemory (&MrcData, FALSE, RmuMainMemoryAddress);

  //
  // Save the memory configuration data into a HOB
  // HOB data size (stored in variable) is required to be multiple of 8 bytes
  //
  if (BootMode != BOOT_ON_S3_RESUME) {
    InitializeHeap((UINTN)FspReservedArea, (UINTN)ReservedBytes);
    BuildHobs (MemoryMap,
               NumRanges,
               FspReservedArea,
               ReservedBytes,
               &MrcData);
  }

  DEBUG ((EFI_D_INFO, "MemoryInit Complete.\n"));
  return EFI_SUCCESS;
}