Exemplo n.º 1
0
VOID
PlatformSsaInit (
  IN SYSTEM_CONFIGURATION        *SystemConfiguration,
  IN CONST EFI_PEI_SERVICES          **PeiServices
  )
{

  DEBUG ((EFI_D_ERROR, "PlatformSsaInit() - Start\n"));
  DEBUG ((EFI_D_ERROR, "PlatformSsaInit() - SystemConfiguration->ISPDevSel 0x%x\n",SystemConfiguration->ISPDevSel));
  if(SystemConfiguration->ISPDevSel == 0x02)
  {
    //
    // Device 3 Interrupt Route
    //
    MmioWrite16 (
      (ILB_BASE_ADDRESS + R_PCH_ILB_D3IR),
      V_PCH_ILB_DXXIR_IAR_PIRQH   // For IUNIT
    );
    MmioRead16(ILB_BASE_ADDRESS + R_PCH_ILB_D3IR); // Read Posted Writes Register
    DEBUG ((EFI_D_ERROR, "PlatformSsaInit() - Device 3 Interrupt Route Done\n"));
  }

  //
  // Device 2 Interrupt Route
  //
  MmioWrite16 (
    (ILB_BASE_ADDRESS + R_PCH_ILB_D2IR),
    V_PCH_ILB_DXXIR_IAR_PIRQA   // For IGD
  );
  MmioRead16(ILB_BASE_ADDRESS + R_PCH_ILB_D2IR); // Read Posted Writes Register
  DEBUG ((EFI_D_ERROR, "PlatformSsaInit() - Device 2 Interrupt Route Done\n"));

  return;
}
Exemplo n.º 2
0
/**
  Reads memory-mapped registers.

  @param[in]  PeiServices  An indirect pointer to the PEI Services Table
                           published by the PEI Foundation.
  @param[in]  This         Pointer to local data for the interface.
  @param[in]  Width        The width of the access. Enumerated in bytes.
  @param[in]  Address      The physical address of the access.
  @param[in]  Count        The number of accesses to perform.
  @param[out] Buffer       A pointer to the buffer of data.

  @retval EFI_SUCCESS            The function completed successfully.
  @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
                                 and Count is not valid for this EFI system.

**/
EFI_STATUS
EFIAPI
CpuMemoryServiceRead (
  IN  CONST EFI_PEI_SERVICES    **PeiServices,
  IN  CONST EFI_PEI_CPU_IO_PPI  *This,
  IN  EFI_PEI_CPU_IO_PPI_WIDTH  Width,
  IN  UINT64                    Address,
  IN  UINTN                     Count,
  OUT VOID                      *Buffer
  )
{
  EFI_STATUS                Status;
  UINT8                     InStride;
  UINT8                     OutStride;
  EFI_PEI_CPU_IO_PPI_WIDTH  OperationWidth;
  BOOLEAN                   Aligned;
  UINT8                     *Uint8Buffer;

  Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Select loop based on the width of the transfer
  //
  InStride = mInStride[Width];
  OutStride = mOutStride[Width];
  OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
  Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
    if (OperationWidth == EfiPeiCpuIoWidthUint8) {
      *Uint8Buffer = MmioRead8 ((UINTN)Address);
    } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
      if (Aligned) {
        *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
      } else {
        WriteUnaligned16 ((UINT16 *)Uint8Buffer, MmioRead16 ((UINTN)Address));
      }
    } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
      if (Aligned) {
        *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
      } else {
        WriteUnaligned32 ((UINT32 *)Uint8Buffer, MmioRead32 ((UINTN)Address));
      }
    } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
      if (Aligned) {
        *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
      } else {
        WriteUnaligned64 ((UINT64 *)Uint8Buffer, MmioRead64 ((UINTN)Address));
      }
    }
  }
  return EFI_SUCCESS;
}
Exemplo n.º 3
0
Arquivo: Smbus.c Projeto: B-Rich/edk2
STATIC
EFI_STATUS
I2CWriteOneByte (
  UINT8 Data    
  )
{
  EFI_STATUS Status;

  //I2C bus status checking
  Status = WaitForBusBusy();
  if (EFI_ERROR(Status)) {
    return Status;
  }

  //Data transfer
  //Poll till Transmit ready bit is set
  Status = PollForStatus(XRDY);
  if (EFI_ERROR(Status)) {
    return Status;
  }

  MmioWrite8(I2C_DATA, Data);

  //Wait and check if the NACK is not set.
  gBS->Stall(1000);
  if (MmioRead16(I2C_STAT) & NACK) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}
Exemplo n.º 4
0
EFIAPI
MmioReadBuffer16 (
  IN  UINTN       StartAddress,
  IN  UINTN       Length,
  OUT UINT16      *Buffer
  )
{
  UINT16    *ReturnBuffer;

  ASSERT ((StartAddress & (sizeof (UINT16) - 1)) == 0);

  ASSERT ((Length - 1) <=  (MAX_ADDRESS - StartAddress));
  ASSERT ((Length - 1) <=  (MAX_ADDRESS - (UINTN) Buffer));

  ASSERT ((Length & (sizeof (UINT16) - 1)) == 0);
  ASSERT (((UINTN) Buffer & (sizeof (UINT16) - 1)) == 0);

  ReturnBuffer = Buffer;

  while (Length > 0) {
    *(Buffer++) = MmioRead16 (StartAddress);
    StartAddress += sizeof (UINT16);
    Length -= sizeof (UINT16);
  }

  return ReturnBuffer;
}
Exemplo n.º 5
0
BOOLEAN
WaitForSpiCycleComplete (
  IN     EFI_SPI_PROTOCOL   *This,
  IN     BOOLEAN            ErrorCheck
  )
/*++

Routine Description:

  Wait execution cycle to complete on the SPI interface. Check both Hardware
  and Software Sequencing status registers

Arguments:

  This                - The SPI protocol instance
  UseSoftwareSequence - TRUE if this is a Hardware Sequencing operation
  ErrorCheck          - TRUE if the SpiCycle needs to do the error check

Returns:

  TRUE       SPI cycle completed on the interface.
  FALSE      Time out while waiting the SPI cycle to complete.
             It's not safe to program the next command on the SPI interface.

--*/
{
  UINT64        WaitTicks;
  UINT64        WaitCount;
  UINT16        Data16;
  SPI_INSTANCE  *SpiInstance;
  UINTN         PchRootComplexBar;

  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
  PchRootComplexBar = SpiInstance->PchRootComplexBar;

  //
  // Convert the wait period allowed into to tick count
  //
  WaitCount = WAIT_TIME / WAIT_PERIOD;

  //
  // Wait for the SPI cycle to complete.
  //
  for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
    Data16 = MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS);
    if ((Data16 & B_QNC_RCRB_SPIS_SCIP) == 0) {
      MmioWrite16 (PchRootComplexBar + R_QNC_RCRB_SPIS, (B_QNC_RCRB_SPIS_BAS | B_QNC_RCRB_SPIS_CDS));
      if ((Data16 & B_QNC_RCRB_SPIS_BAS) && (ErrorCheck == TRUE)) {
        return FALSE;
      } else {
        return TRUE;
      }
    }

    MicroSecondDelay (WAIT_PERIOD);
  }

  return FALSE;
}
Exemplo n.º 6
0
/**
  Reads a 16-bit PCI configuration register.

  Reads and returns the 16-bit PCI configuration register specified by Address.
  This function must guarantee that all PCI read and write operations are
  serialized.

  If Address > 0x0FFFFFFF, then ASSERT().
  If Address is not aligned on a 16-bit boundary, then ASSERT().

  @param  Address Address that encodes the PCI Bus, Device, Function and
                  Register.

  @return The read value from the PCI configuration register.

**/
UINT16
EFIAPI
PciExpressRead16 (
  IN      UINTN                     Address
  )
{
  ASSERT_INVALID_PCI_ADDRESS (Address);
  return MmioRead16 ((UINTN) GetPciExpressBaseAddress () + Address);
}
Exemplo n.º 7
0
/**
  16-bit memory read operations.

  @param[in] PeiServices  An indirect pointer to the PEI Services Table published
                          by the PEI Foundation.
  @param[in] This         Pointer to local data for the interface.
  @param[in] Address      The physical address of the access.

  @return  A 16-bit value returned from the memory space.

**/
UINT16
EFIAPI
CpuMemRead16 (
  IN CONST EFI_PEI_SERVICES    **PeiServices,
  IN CONST EFI_PEI_CPU_IO_PPI  *This,
  IN UINT64                    Address
  )
{
  return MmioRead16 ((UINTN)Address);
}
Exemplo n.º 8
0
BOOLEAN
GetSleepTypeAfterWakeup (
  IN  CONST EFI_PEI_SERVICES          **PeiServices,
  OUT UINT16                    *SleepType
  )
{
  UINT16  Pm1Sts;
  UINT16  Pm1Cnt;
  UINT16  GenPmCon1;
  //
  // VLV BIOS Specification 0.6.2 - Section 18.4, "Power Failure Consideration"
  //
  // When the SUS_PWR_FLR bit is set, it indicates the SUS well power is lost.
  // This bit is in the SUS Well and defaults to 1’b1 based on RSMRST# assertion (not cleared by any type of reset).
  // System BIOS should follow cold boot path if SUS_PWR_FLR (PBASE + 0x20[14]),
  // GEN_RST_STS (PBASE + 0x20[9]) or PWRBTNOR_STS (ABASE + 0x00[11]) is set to 1’b1
  // regardless of the value in the SLP_TYP (ABASE + 0x04[12:10]) field.
  //
  GenPmCon1 = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1);

  //
  // Read the ACPI registers
  //
  Pm1Sts  = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS);
  Pm1Cnt  = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT);

  if ((GenPmCon1 & (B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR | B_PCH_PMC_GEN_PMCON_GEN_RST_STS)) ||
     (Pm1Sts & B_PCH_ACPI_PM1_STS_PRBTNOR)) {
	  //
    // If power failure indicator, then don't attempt s3 resume.
    // Clear PM1_CNT of S3 and set it to S5 as we just had a power failure, and memory has
    // lost already.  This is to make sure no one will use PM1_CNT to check for S3 after
    // power failure.
	  //
    if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {
      Pm1Cnt = ((Pm1Cnt & ~B_PCH_ACPI_PM1_CNT_SLP_TYP) | V_PCH_ACPI_PM1_CNT_S5);
      IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, Pm1Cnt);
    }
	  //
    // Clear Wake Status (WAK_STS)
    //
  }
  //
  // Get sleep type if a wake event occurred and there is no power failure
  //
  if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {
    *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP;
    return TRUE;
  } else if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S4) {
    *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP;
    return TRUE;
  }
  return FALSE;
}
Exemplo n.º 9
0
Arquivo: Smbus.c Projeto: B-Rich/edk2
//
// Internal Functions
//
STATIC
EFI_STATUS
WaitForBusBusy (
  VOID
  )
{
  UINTN Retry = 0;

  while (++Retry < MAX_RETRY && (MmioRead16(I2C_STAT) & BB) == 0x1);

  if (Retry == MAX_RETRY) {
    return EFI_TIMEOUT;
  }

  return EFI_SUCCESS;
}
Exemplo n.º 10
0
/**
  Reads a 16-bit I/O port.

  Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned.
  This function must guarantee that all I/O read and write operations are
  serialized.

  @param  Port  The I/O port to read.

  @return The value read.

**/
UINT16
EFIAPI
IoRead16 (
  IN  UINT64                 Port
  )
{
  UINT64           Address;

  //
  // Add the 64MB aligned IO Port space to the IO address
  //
  Address = MAP_PORT_BASE_TO_MEM (Port);
  Address += PcdGet64(PcdIoBlockBaseAddressForIpf);

  return MmioRead16 (Address);
}
Exemplo n.º 11
0
BOOLEAN
GetSleepTypeAfterWakeup (
  IN  CONST EFI_PEI_SERVICES          **PeiServices,
  OUT UINT16                    *SleepType
  )
{
  UINT16  Pm1Sts;
  UINT16  Pm1Cnt;
  UINT16  GenPmCon1;
  GenPmCon1 = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1);

  //
  // Read the ACPI registers
  //
  Pm1Sts  = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS);
  Pm1Cnt  = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT);

  if ((GenPmCon1 & (B_PCH_PMC_GEN_PMCON_SUS_PWR_FLR | B_PCH_PMC_GEN_PMCON_GEN_RST_STS)) ||
     (Pm1Sts & B_PCH_ACPI_PM1_STS_PRBTNOR)) {
    //
    // If power failure indicator, then don't attempt s3 resume.
    // Clear PM1_CNT of S3 and set it to S5 as we just had a power failure, and memory has
    // lost already.  This is to make sure no one will use PM1_CNT to check for S3 after
    // power failure.
    //
    if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {
      Pm1Cnt = ((Pm1Cnt & ~B_PCH_ACPI_PM1_CNT_SLP_TYP) | V_PCH_ACPI_PM1_CNT_S5);
      IoWrite16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_CNT, Pm1Cnt);
    }
    //
    // Clear Wake Status (WAK_STS)
    //
    IoWrite16 ((ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS), B_PCH_ACPI_PM1_STS_WAK);
   }
  //
  // Get sleep type if a wake event occurred and there is no power failure
  //
  if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S3) {
    *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP;
    return TRUE;
  } else if ((Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP) == V_PCH_ACPI_PM1_CNT_S4){
    *SleepType = Pm1Cnt & B_PCH_ACPI_PM1_CNT_SLP_TYP;
    return TRUE;
  }
  return FALSE;
}
Exemplo n.º 12
0
/**
  Reads I/O registers.

  The I/O operations are carried out exactly as requested. The caller is responsible
  for satisfying any alignment and I/O width restrictions that a PI System on a
  platform might require. For example on some platforms, width requests of
  EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
  be handled by the driver.

  If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
  or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
  each of the Count operations that is performed.

  If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
  EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
  incremented for each of the Count operations that is performed. The read or
  write operation is performed Count times on the same Address.

  If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
  EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
  incremented for each of the Count operations that is performed. The read or
  write operation is performed Count times from the first element of Buffer.

  @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
  @param[in]  Width    Signifies the width of the I/O or Memory operation.
  @param[in]  Address  The base address of the I/O operation.
  @param[in]  Count    The number of I/O operations to perform. The number of
                       bytes moved is Width size * Count, starting at Address.
  @param[out] Buffer   For read operations, the destination buffer to store the results.
                       For write operations, the source buffer from which to write data.

  @retval EFI_SUCCESS            The data was read from or written to the PI system.
  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
                                 and Count is not valid for this PI system.

**/
STATIC
EFI_STATUS
EFIAPI
CpuIoServiceRead (
  IN  EFI_CPU_IO2_PROTOCOL       *This,
  IN  EFI_CPU_IO_PROTOCOL_WIDTH  Width,
  IN  UINT64                     Address,
  IN  UINTN                      Count,
  OUT VOID                       *Buffer
  )
{
  EFI_STATUS                 Status;
  UINT8                      InStride;
  UINT8                      OutStride;
  EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
  UINT8                      *Uint8Buffer;

  Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Address += PcdGet64 (PcdPciIoTranslation);

  //
  // Select loop based on the width of the transfer
  //
  InStride = mInStride[Width];
  OutStride = mOutStride[Width];
  OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);

  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
    if (OperationWidth == EfiCpuIoWidthUint8) {
      *Uint8Buffer = MmioRead8 ((UINTN)Address);
    } else if (OperationWidth == EfiCpuIoWidthUint16) {
      *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
    } else if (OperationWidth == EfiCpuIoWidthUint32) {
      *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
    }
  }

  return EFI_SUCCESS;
}
Exemplo n.º 13
0
Arquivo: Smbus.c Projeto: B-Rich/edk2
STATIC
EFI_STATUS
PollForStatus(
  UINT16 StatusBit
  )
{
  UINTN Retry = 0;

  while(Retry < MAX_RETRY) {
    if (MmioRead16(I2C_STAT) & StatusBit) {
      //Clear particular status bit from Status register.
      MmioOr16(I2C_STAT, StatusBit);
      break;
    }
    Retry++;
  }

  if (Retry == MAX_RETRY) {
    return EFI_TIMEOUT;
  }

  return EFI_SUCCESS;
}
Exemplo n.º 14
0
/**
  Reads memory-mapped registers.

  The I/O operations are carried out exactly as requested.  The caller is 
  responsible for any alignment and I/O width issues that the bus, device, 
  platform, or type of I/O might require.

  @param[in]  This     The EFI_SMM_CPU_IO2_PROTOCOL instance.
  @param[in]  Width    Signifies the width of the I/O operations.
  @param[in]  Address  The base address of the I/O operations.  The caller is 
                       responsible for aligning the Address if required. 
  @param[in]  Count    The number of I/O operations to perform.
  @param[out] Buffer   For read operations, the destination buffer to store 
                       the results.  For write operations, the source buffer 
                       from which to write data.

  @retval EFI_SUCCESS            The data was read from or written to the device.
  @retval EFI_UNSUPPORTED        The Address is not valid for this system.
  @retval EFI_INVALID_PARAMETER  Width or Count, or both, were invalid.
  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a 
                                 lack of resources

**/
EFI_STATUS
EFIAPI
CpuMemoryServiceRead (
  IN  CONST EFI_SMM_CPU_IO2_PROTOCOL  *This,
  IN  EFI_SMM_IO_WIDTH                Width,
  IN  UINT64                          Address,
  IN  UINTN                           Count,
  OUT VOID                            *Buffer
  )
{
  EFI_STATUS  Status;
  UINT8       Stride;
  UINT8       *Uint8Buffer;

  Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Select loop based on the width of the transfer
  //
  Stride = mStride[Width];
  for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
    if (Width == SMM_IO_UINT8) {
      *Uint8Buffer = MmioRead8 ((UINTN)Address);
    } else if (Width == SMM_IO_UINT16) {
      *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
    } else if (Width == SMM_IO_UINT32) {
      *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
    } else if (Width == SMM_IO_UINT64) {
      *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
    }
  }
  return EFI_SUCCESS;
}
Exemplo n.º 15
0
/**
  Writes a Byte to I2C Device.
 
  @param  I2cControllerIndex   I2C Bus no to which the I2C device has been connected
  @param  SlaveAddress         Device Address from which the byte value has to be written
  @param  Offset               Offset from which the data has to be read
  @param  *Byte                Address to which the value written is stored
  @param  Start               Whether a RESTART is issued before the byte is sent or received
  @param  End                 Whether STOP is generated after a data byte is sent or received  
                                    
  @return  EFI_SUCCESS         IF the byte value has been successfully written
  @return  EFI_DEVICE_ERROR    Operation Failed, Device Error
**/
EFI_STATUS ByteWriteI2CBasic(
  IN  UINT8 I2cControllerIndex,
  IN  UINT8 SlaveAddress,
  IN  UINTN WriteBytes,
  IN  UINT8 *WriteBuffer,
  IN  UINT8 Start,
  IN  UINT8 End
  )
{

  EFI_STATUS Status;
  UINT32 I2cStatus;
  UINT8 *TransmitEnd;
  UINT16 RawIntrStat;
  UINT32 Count=0;

  Status = EFI_SUCCESS;

  Status=I2CInit(I2cControllerIndex, SlaveAddress);
  if(Status!=EFI_SUCCESS)
    return Status;

  TransmitEnd = &WriteBuffer[WriteBytes];
  if( WriteBytes ) {
    DEBUG((EFI_D_INFO,"Write: --------------%d bytes to TX\r\n",TransmitEnd - WriteBuffer));
    while (TransmitEnd > WriteBuffer) {
      I2cStatus = MmioRead32 (mI2CBaseAddress + R_IC_STATUS);
      RawIntrStat = (UINT16)MmioRead32 (mI2CBaseAddress + R_IC_RawIntrStat);
      if (0 != ( RawIntrStat & I2C_INTR_TX_ABRT)) {
        MmioRead32 ( mI2CBaseAddress + R_IC_CLR_TX_ABRT);
        Status = RETURN_DEVICE_ERROR;
        DEBUG((EFI_D_ERROR,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd, WriteBuffer));
        break;
      }
      if (0 == (I2cStatus & STAT_TFNF)) {
        //
        // If TX not full , will  send cmd  or continue to wait
        //
        MicroSecondDelay (FIFO_WRITE_DELAY);
        continue;
      }

      if(End && Start) {
        MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_RESTART|B_CMD_STOP);
      } else if (!End && Start) {
        MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_RESTART);
      } else if (End && !Start) {
        MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++)|B_CMD_STOP);
      } else if (!End && !Start ) {
        MmioWrite32 (mI2CBaseAddress + R_IC_DATA_CMD, (*WriteBuffer++));
      }
      
      //
      // Add a small delay to work around some odd behavior being seen.  Without this delay bytes get dropped.
      //
      MicroSecondDelay ( FIFO_WRITE_DELAY );//wait after send cmd
      
      //
      // Time out
      //
      while(1) {
        RawIntrStat = MmioRead16 ( mI2CBaseAddress + R_IC_RawIntrStat );
        if (0 != ( RawIntrStat & I2C_INTR_TX_ABRT)) {
          MmioRead16 (mI2CBaseAddress + R_IC_CLR_TX_ABRT);
          Status = RETURN_DEVICE_ERROR;
          DEBUG((EFI_D_ERROR,"TX ABRT TransmitEnd:0x%x WriteBuffer:0x%x\r\n", TransmitEnd, WriteBuffer));
        }
        if(0 == MmioRead16(mI2CBaseAddress + R_IC_TXFLR)) break;

        MicroSecondDelay (FIFO_WRITE_DELAY);
        Count++;
        if(Count<1024) {
          //
          // to avoid sys hung without ul-pmc device on RVP.
          // Waiting the last request to get data and make (ReceiveDataEnd > ReadBuffer) =TRUE.
          //
          continue;
        } else {
          break;
        }
      }//while( 1 )
    }

  }

  return Status;
}
Exemplo n.º 16
0
EFI_STATUS
EFIAPI
SpiProtocolLock (
  IN EFI_SPI_PROTOCOL     *This
  )
/*++

Routine Description:

  Lock the SPI Static Configuration Interface.
  Once locked, the interface can not be changed and can only be clear by system reset.

Arguments:

  This      Pointer to the EFI_SPI_PROTOCOL instance.

Returns:

  EFI_SUCCESS             Lock operation succeed.
  EFI_DEVICE_ERROR        Device error, operation failed.
  EFI_ACCESS_DENIED       The interface has already been locked.

--*/
{
  SPI_INSTANCE  *SpiInstance;
  UINTN         PchRootComplexBar;

  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
  PchRootComplexBar = SpiInstance->PchRootComplexBar;

  //
  // Check if the SPI interface has been locked-down.
  //
  if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {
    return EFI_ACCESS_DENIED;
  }

  //
  // Lock-down the configuration interface.
  //
  MmioOr16 ((UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS), (UINT16) (B_QNC_RCRB_SPIS_SCL));

  //
  // Verify if it's really locked.
  //
  if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) == 0) {
    return EFI_DEVICE_ERROR;
  } else {
    //
    // Save updated register in S3 Boot script.
    //
    S3BootScriptSaveMemWrite (
      S3BootScriptWidthUint16,
        (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS),
        1,
        (VOID *) (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS)
        );
  }

  return EFI_SUCCESS;
}
Exemplo n.º 17
0
EFI_STATUS
SendSpiCmd (
  IN     EFI_SPI_PROTOCOL   *This,
  IN     UINT8              OpcodeIndex,
  IN     UINT8              PrefixOpcodeIndex,
  IN     BOOLEAN            DataCycle,
  IN     BOOLEAN            Atomic,
  IN     BOOLEAN            ShiftOut,
  IN     UINTN              Address,
  IN     UINT32             DataByteCount,
  IN OUT UINT8              *Buffer,
  IN     SPI_REGION_TYPE    SpiRegionType
  )
/*++

Routine Description:

  This function sends the programmed SPI command to the slave device.

Arguments:

  OpcodeIndex       Index of the command in the OpCode Menu.
  PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
  DataCycle         TRUE if the SPI cycle contains data
  Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
  ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
  Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
                    Region, this value specifies the offset from the Region Base; for BIOS Region,
                    this value specifies the offset from the start of the BIOS Image. In Non
                    Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
                    Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
                    Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
                    supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
                    the flash (in Non Descriptor Mode)
  DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the
                    data transfer into multiple operations. This function ensures each operation does
                    not cross 256 byte flash address boundary.
                    *NOTE: if there is some SPI chip that has a stricter address boundary requirement
                    (e.g., its write page size is < 256 byte), then the caller cannot rely on this
                    function to cut the data transfer at proper address boundaries, and it's the
                    caller's reponsibility to pass in a properly cut DataByteCount parameter.
  Buffer            Data received or sent during the SPI cycle.
  SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
                    EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
                    Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
                    and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
                    to base of the 1st flash device (i.e., it is a Flash Linear Address).

Returns:

  EFI_SUCCESS             SPI command completes successfully.
  EFI_DEVICE_ERROR        Device error, the command aborts abnormally.
  EFI_ACCESS_DENIED       Some unrecognized command encountered in hardware sequencing mode
  EFI_INVALID_PARAMETER   The parameters specified are not valid.

--*/
{
  UINT32        Index;
  SPI_INSTANCE  *SpiInstance;
  UINTN         HardwareSpiAddr;
  UINTN         SpiBiosSize;
  UINTN         BaseAddress;
  UINTN         LimitAddress;
  UINT32        SpiDataCount;
  UINT8         OpCode;
  SPI_OPERATION Operation;
  UINTN         PchRootComplexBar;

  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
  PchRootComplexBar = SpiInstance->PchRootComplexBar;
  SpiBiosSize       = SpiInstance->SpiInitTable.BiosSize;
  Operation         = SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex].Operation;
  OpCode            = MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + OpcodeIndex);

  //
  // Check if the value of opcode register is 0 or the BIOS Size of SpiInitTable is 0
  //
  if (OpCode == 0 || SpiBiosSize == 0) {
    ASSERT (FALSE);
    return EFI_INVALID_PARAMETER;
  }

  SpiOffset2Physical (This, Address, SpiRegionType, &HardwareSpiAddr, &BaseAddress, &LimitAddress);
  //
  // Have direct access to BIOS region in Descriptor mode,
  //
  if (SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex].Type == EnumSpiOpcodeRead &&
      SpiRegionType == EnumSpiRegionBios) {
    CopyMem (
      Buffer,
      (UINT8 *) ((HardwareSpiAddr - BaseAddress) + (UINT32) (~(SpiBiosSize - 1))),
      DataByteCount
      );
    return EFI_SUCCESS;
  }
  //
  // DEBUG((EFI_D_ERROR, "SPIADDR %x, %x, %x, %x\n", Address, HardwareSpiAddr, BaseAddress,
  // LimitAddress));
  //
  if ((DataCycle == FALSE) && (DataByteCount > 0)) {
    DataByteCount = 0;
  }

  do {
    //
    // Trim at 256 byte boundary per operation,
    // - PCH SPI controller requires trimming at 4KB boundary
    // - Some SPI chips require trimming at 256 byte boundary for write operation
    // - Trimming has limited performance impact as we can read / write atmost 64 byte
    //   per operation
    //
    if (HardwareSpiAddr + DataByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {
      SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);
    } else {
      SpiDataCount = DataByteCount;
    }
    //
    // Calculate the number of bytes to shift in/out during the SPI data cycle.
    // Valid settings for the number of bytes duing each data portion of the
    // PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
    //
    if (SpiDataCount >= 64) {
      SpiDataCount = 64;
    } else if ((SpiDataCount &~0x07) != 0) {
      SpiDataCount = SpiDataCount &~0x07;
    }
    //
    // If shifts data out, load data into the SPI data buffer.
    //
    if (ShiftOut) {
      for (Index = 0; Index < SpiDataCount; Index++) {
        MmioWrite8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index, Buffer[Index]);
        MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index);
      }
    }

    MmioWrite32 (
      (PchRootComplexBar + R_QNC_RCRB_SPIA),
      (UINT32) (HardwareSpiAddr & B_QNC_RCRB_SPIA_MASK)
      );
    MmioRead32 (PchRootComplexBar + R_QNC_RCRB_SPIA);

    //
    // Execute the command on the SPI compatible mode
    //

    //
    // Clear error flags
    //
    MmioOr16 ((PchRootComplexBar + R_QNC_RCRB_SPIS), B_QNC_RCRB_SPIS_BAS);

    //
    // Initialte the SPI cycle
    //
    if (DataCycle) {
      MmioWrite16 (
        (PchRootComplexBar + R_QNC_RCRB_SPIC),
        ( (UINT16) (B_QNC_RCRB_SPIC_DC) | (UINT16) (((SpiDataCount - 1) << 8) & B_QNC_RCRB_SPIC_DBC) |
          (UINT16) ((OpcodeIndex << 4) & B_QNC_RCRB_SPIC_COP) |
          (UINT16) ((PrefixOpcodeIndex << 3) & B_QNC_RCRB_SPIC_SPOP) |
          (UINT16) (Atomic ? B_QNC_RCRB_SPIC_ACS : 0) |
          (UINT16) (B_QNC_RCRB_SPIC_SCGO)));
    } else {
      MmioWrite16 (
        (PchRootComplexBar + R_QNC_RCRB_SPIC),
        ( (UINT16) ((OpcodeIndex << 4) & B_QNC_RCRB_SPIC_COP) |
          (UINT16) ((PrefixOpcodeIndex << 3) & B_QNC_RCRB_SPIC_SPOP) |
          (UINT16) (Atomic ? B_QNC_RCRB_SPIC_ACS : 0) |
          (UINT16) (B_QNC_RCRB_SPIC_SCGO)));
    }

    MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIC);

    //
    // end of command execution
    //
    // Wait the SPI cycle to complete.
    //
    if (!WaitForSpiCycleComplete (This, TRUE)) {
      return EFI_DEVICE_ERROR;
    }
    //
    // If shifts data in, get data from the SPI data buffer.
    //
    if (!ShiftOut) {
      for (Index = 0; Index < SpiDataCount; Index++) {
        Buffer[Index] = MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPID0 + Index);
      }
    }

    HardwareSpiAddr += SpiDataCount;
    Buffer += SpiDataCount;
    DataByteCount -= SpiDataCount;
  } while (DataByteCount > 0);

  return EFI_SUCCESS;
}
Exemplo n.º 18
0
EFI_STATUS
RtcPowerFailureHandler (
  IN CONST EFI_PEI_SERVICES       **PeiServices
  )
{

  UINT16          DataUint16;
  UINT8           DataUint8;
  BOOLEAN         RtcUipIsAlwaysSet;
  DataUint16        = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1);
  RtcUipIsAlwaysSet = IsRtcUipAlwaysSet (PeiServices);
  if ((DataUint16 & B_PCH_PMC_GEN_PMCON_RTC_PWR_STS) || (RtcUipIsAlwaysSet)) {
    //
    // Execute the sequence below. This will ensure that the RTC state machine has been initialized.
    //
    // Step 1.
    // BIOS clears this bit by writing a '0' to it.
    //
    if (DataUint16 & B_PCH_PMC_GEN_PMCON_RTC_PWR_STS) {
      //
      // Set to invalid date in order to reset the time to
      // BIOS build time later in the boot (SBRUN.c file).
      //
      IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_YEAR);
      IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF);
      IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_MONTH);
      IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF);
      IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_DAYOFMONTH);
      IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF);
      IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_DAYOFWEEK);
      IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF);

      IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_SECONDSALARM);
      IoWrite8 (R_PCH_RTC_TARGET2, 0x00);
      IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_MINUTESALARM);
      IoWrite8 (R_PCH_RTC_TARGET2, 0x00);
      IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_HOURSALARM);
      IoWrite8 (R_PCH_RTC_TARGET2, 0x00);
    }

    //
    // Step 2.
    // Set RTC Register 0Ah[6:4] to '110' or '111'.
    //
    IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA);
    IoWrite8 (R_PCH_RTC_TARGET2, (V_PCH_RTC_REGISTERA_DV_DIV_RST1 | V_PCH_RTC_REGISTERA_RS_976P5US));

    //
    // Step 3.
    // Set RTC Register 0Bh[7].
    //
    IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB);
    DataUint8 = (IoRead8 (R_PCH_RTC_TARGET2) | B_PCH_RTC_REGISTERB_SET);
    IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB);
    IoWrite8 (R_PCH_RTC_TARGET2, DataUint8);

    //
    // Step 4.
    // Set RTC Register 0Ah[6:4] to '010'.
    //
    IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA);
    IoWrite8 (R_PCH_RTC_TARGET2, (V_PCH_RTC_REGISTERA_DV_NORM_OP | V_PCH_RTC_REGISTERA_RS_976P5US));

    //
    // Step 5.
    // Clear RTC Register 0Bh[7].
    //
    IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB);
    DataUint8 = (IoRead8 (R_PCH_RTC_TARGET2) & (UINT8)~B_PCH_RTC_REGISTERB_SET);
    IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB);
    IoWrite8 (R_PCH_RTC_TARGET2, DataUint8);
  }

  return EFI_SUCCESS;
}
Exemplo n.º 19
0
EFI_STATUS
EFIAPI
SpiProtocolInit (
  IN EFI_SPI_PROTOCOL       *This,
  IN SPI_INIT_TABLE         *InitTable
  )
/*++

Routine Description:

  Initialize the host controller to execute SPI command.

Arguments:

  This                    Pointer to the EFI_SPI_PROTOCOL instance.
  InitTable               Initialization data to be programmed into the SPI host controller.

Returns:

  EFI_SUCCESS             Initialization completed.
  EFI_ACCESS_DENIED       The SPI static configuration interface has been locked-down.
  EFI_INVALID_PARAMETER   Bad input parameters.
  EFI_UNSUPPORTED         Can't get Descriptor mode VSCC values
--*/
{
  EFI_STATUS    Status;
  UINT8         Index;
  UINT16        OpcodeType;
  SPI_INSTANCE  *SpiInstance;
  BOOLEAN       MultiPartitionIsSupported;
  UINTN         PchRootComplexBar;
  UINT8         SFDPCmdOpcodeIndex;
  UINT8         UnlockCmdOpcodeIndex;
  UINT8         ReadDataCmdOpcodeIndex;
  UINT8         FlashPartId[3];

  SpiInstance       = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
  PchRootComplexBar = SpiInstance->PchRootComplexBar;

  if (InitTable != NULL) {
    //
    // Copy table into SPI driver Private data structure
    //
    CopyMem (
      &SpiInstance->SpiInitTable,
      InitTable,
      sizeof (SPI_INIT_TABLE)
      );
  } else {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Check if the SPI interface has been locked-down.
  //
  if ((MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS) & B_QNC_RCRB_SPIS_SCL) != 0) {
    ASSERT_EFI_ERROR (EFI_ACCESS_DENIED);
    return EFI_ACCESS_DENIED;
  }
  //
  // Clear all the status bits for status regs.
  //
  MmioOr16 (
    (UINTN) (PchRootComplexBar + R_QNC_RCRB_SPIS),
    (UINT16) ((B_QNC_RCRB_SPIS_CDS | B_QNC_RCRB_SPIS_BAS))
    );
  MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIS);

  //
  // Set the Prefix Opcode registers.
  //
  MmioWrite16 (
    PchRootComplexBar + R_QNC_RCRB_SPIPREOP,
    (SpiInstance->SpiInitTable.PrefixOpcode[1] << 8) | InitTable->PrefixOpcode[0]
    );
  MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIPREOP);

  //
  // Set Opcode Type Configuration registers.
  //
  for (Index = 0, OpcodeType = 0; Index < SPI_NUM_OPCODE; Index++) {
    switch (SpiInstance->SpiInitTable.OpcodeMenu[Index].Type) {
    case EnumSpiOpcodeRead:
      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_READ << (Index * 2));
      break;
    case EnumSpiOpcodeWrite:
      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_ADD_WRITE << (Index * 2));
      break;
    case EnumSpiOpcodeWriteNoAddr:
      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_WRITE << (Index * 2));
      break;
    default:
      OpcodeType |= (UINT16) (B_QNC_RCRB_SPIOPTYPE_NOADD_READ << (Index * 2));
      break;
    }
  }
  MmioWrite16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE, OpcodeType);
  MmioRead16 (PchRootComplexBar + R_QNC_RCRB_SPIOPTYPE);

  //
  // Setup the Opcode Menu registers.
  //
  ReadDataCmdOpcodeIndex = SPI_NUM_OPCODE;
  SFDPCmdOpcodeIndex = SPI_NUM_OPCODE;
  UnlockCmdOpcodeIndex = SPI_NUM_OPCODE;
  for (Index = 0; Index < SPI_NUM_OPCODE; Index++) {
    MmioWrite8 (
      PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index,
      SpiInstance->SpiInitTable.OpcodeMenu[Index].Code
      );
    MmioRead8 (PchRootComplexBar + R_QNC_RCRB_SPIOPMENU + Index);
    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationJedecId) {
      Status = SpiProtocolExecute (
                This,
                Index,
                0,
                TRUE,
                TRUE,
                FALSE,
                (UINTN) 0,
                3,
                FlashPartId,
                EnumSpiRegionDescriptor
                );
      if (EFI_ERROR (Status)) {
        return Status;
      }
      if (FlashPartId[0] != SpiInstance->SpiInitTable.VendorId  ||
          FlashPartId[1] != SpiInstance->SpiInitTable.DeviceId0 ||
          FlashPartId[2] != SpiInstance->SpiInitTable.DeviceId1) {
        return EFI_INVALID_PARAMETER;
      }
    }

    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationReadData ||
        SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationFastRead ||
        SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDualOutputFastRead) {
      ReadDataCmdOpcodeIndex = Index;
    }

    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationDiscoveryParameters) {
      SFDPCmdOpcodeIndex = Index;
    }

    if (SpiInstance->SpiInitTable.OpcodeMenu[Index].Operation == EnumSpiOperationWriteStatus) {
      UnlockCmdOpcodeIndex = Index;
    }
  }

  MultiPartitionIsSupported = FALSE;

  Status = UnlockFlashComponents (
            This,
            UnlockCmdOpcodeIndex
            );
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "Unlock flash components fail!\n"));
  }

  SpiPhaseInit ();
  FillOutPublicInfoStruct (SpiInstance);
  SpiInstance->InitDone = TRUE;
  return EFI_SUCCESS;
}
Exemplo n.º 20
0
EFI_STATUS
SaveRuntimeScriptTable (
  VOID
  )
{
  SMM_PCI_IO_ADDRESS    PciAddress;
  UINT32                Data32;
  UINT16                Data16;
  UINT8                 Data8;
  UINT8                 Mask;
  UINTN                 Index;
  UINTN                 Offset;
  UINT8                 RegTable[] = {

	  //
    //Bus  ,   Dev,  Func,    DMI
	  //
      0x00 ,  0x00,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
	  //
      0x00 ,  0x08,  0x00,  0x00,  0x30,  0x00,  0x00,  0xa0,

	  //
    //Bus  ,   Dev,  Func,    LPC device
	  //
      0x00 ,  0x1F,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x00 ,  0x08,  0x00,  0x07,  0x00,  0x00,  0x90,  0x00,

	  //
    //Bus  ,   Dev,  Func,    PCIE device
	 //
      0x00 ,  0x1C,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0xC0 ,  0x83,  0x30,  0x00,  0x00,  0x00,  0x00,  0x00,

	  //
    //Bus  ,   Dev,  Func,    PCIE device
    //
	  0x00 ,  0x1C,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x03 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

	  //
    //Bus  ,   Dev,  Func,    SATA device
	  //
      0x00 ,  0x13,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0xf4 ,  0xab,  0x27,  0x10,  0xf1,  0x1d,  0x00,  0x40,

    //
    //Bus  ,   Dev,  Func,    EHCI device
    //
     0x00 ,  0x1D,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
     0x10 ,  0x88,  0x00,  0x00,  0x00,  0x00,  0x00,  0x80,

    //
    //Bus  ,   Dev,  Func,    SMBUS device
    //
     0x00 ,  0x1f,  0x03,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x10 ,  0x89,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    SMBUS device
    //
      0x00 ,  0x1f,  0x03,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x02 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    VGA bus1
    //
      0x01 ,  0x00,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x58 ,  0x81,  0x18,  0x01,  0xb0,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    VGA bus1
    //
      0x01 ,  0x00,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x02 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    VGA bus1 function 1
    //
      0x01 ,  0x00,  0x01,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x51 ,  0x80,  0x80,  0x01,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    VGA bus1 function 1
    //
      0x01 ,  0x00,  0x01,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x02 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    IGD bus0 function 0
    //
      0x00 ,  0x02,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x42 ,  0x81,  0x00,  0x00,  0x00,  0x00,  0x20,  0x00,

    //
    //Bus  ,   Dev,  Func,    USB bus0 function 0
    //
      0x00 ,  0x16,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x32 ,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    HD Audio bus0 function 0
    //
      0x00 ,  0x1B,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x00 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x02,  0x00,

    //
    //0xFF indicates the end of the table
    //
      0xFF
 };

  //
  // These registers have to set in byte order
  //
  UINT8                 ExtReg[] = { 0x9E, 0x9D };  // SMRAM settings



  //
  // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
  // and vital to S3 resume. That's why we put save code here
  //
  PciAddress.Bus      = 0;
  PciAddress.Device   = 0;
  PciAddress.Function = 0;
  PciAddress.ExtendedRegister = 0;

  for (Index = 0; Index < 2; Index++) {
    //
    // Read SRAM setting from Pci(0, 0, 0)
    //
    PciAddress.Register = ExtReg[Index];
    Data8 = MmioRead8 (
              MmPciAddress (0,
                PciAddress.Bus,
                PciAddress.Device,
                PciAddress.Function,
                PciAddress.Register
              )
            );

    //
    // Save latest settings to runtime script table
    //
    S3BootScriptSavePciCfgWrite(
      S3BootScriptWidthUint8,
      *(UINT64*)&PciAddress,
      1,
      &Data8
      );
  }


  //
  // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
  // and vital to S3 resume. That's why we put save code here
  //
  Index = 0;
  while (RegTable[Index] != 0xFF) {

    PciAddress.Bus      = RegTable[Index++];
    PciAddress.Device   = RegTable[Index++];
    PciAddress.Function = RegTable[Index++];
    PciAddress.Register = 0;
    PciAddress.ExtendedRegister = 0;

    Data16 = MmioRead16 (
              MmPciAddress (0,
                PciAddress.Bus,
                PciAddress.Device,
                PciAddress.Function,
                PciAddress.Register
              )
            );

    if (Data16 == 0xFFFF) {
      Index+=8;
      continue;
    }

    for (Offset = 0, Mask = 0x01; Offset < 256; Offset+=4, Mask<<=1) {

      if (Mask == 0x00) {
        Mask = 0x01;
      }

      if (RegTable[Index + Offset/32] & Mask ) {

        PciAddress.Register = (UINT8)Offset;
        Data32 = MmioRead32 (MmPciAddress (0, PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));

        //
        // Save latest settings to runtime script table
        //
        S3BootScriptSavePciCfgWrite (
          S3BootScriptWidthUint32,
          *(UINT64*)&PciAddress,
          1,
          &Data32
        );
      }
    }

    Index += 8;

  }


  //
  // Save I/O ports to S3 script table
  //

  //
  // Selftest KBC
  //
  Data8 = 0xAA;
  S3BootScriptSaveIoWrite (
    S3BootScriptWidthUint8,
    0x64,
    (UINTN)1,
    &Data8
    );

  Data32 = IoRead32(mAcpiBaseAddr + R_PCH_SMI_EN);

  S3BootScriptSaveIoWrite (
      S3BootScriptWidthUint32,
      (mAcpiBaseAddr + R_PCH_SMI_EN),
      1,
      &Data32
      );

  //
  // Save B_ICH_TCO_CNT_LOCK so it will be done on S3 resume path.
  //
  Data16 = IoRead16(mAcpiBaseAddr + R_PCH_TCO_CNT);

  S3BootScriptSaveIoWrite (
      S3BootScriptWidthUint16,
      mAcpiBaseAddr + R_PCH_TCO_CNT,
      1,
      &Data16
      );


  return EFI_SUCCESS;
}
Exemplo n.º 21
0
/**
  Do any final initialization on SATA controller

  @param[in] PchPlatformPolicy    The PCH Platform Policy protocol instance
  @param[in] IsSetS3BootScript    Is this function called for S3 boot script save

  @retval EFI_SUCCESS             The function completed successfully
**/
EFI_STATUS
ConfigureSataAtBoot (
  IN DXE_PCH_PLATFORM_POLICY_PROTOCOL *PchPlatformPolicy,
  IN BOOLEAN                          IsSetS3BootScript
  )
{
  UINT8                             Index;
  UINT32                            AhciBar;
  UINTN                             PciD19F0RegBase;
  UINT16                            SataModeSelect;
  UINT32                            PxSctlDet;
  UINT32                            PxCmdSud;
  UINT32                            OrgCmdWord;
  UINT32                            Data32And;
  UINT32                            Data32Or;

  DEBUG ((EFI_D_INFO, "ConfigureSataAtBoot() Start\n"));
  //
  // eSATA port support only up to Gen2
  //
  PciD19F0RegBase = MmPciAddress (0, PchPlatformPolicy->BusNumber, PCI_DEVICE_NUMBER_PCH_SATA, PCI_FUNCTION_NUMBER_PCH_SATA, 0);
  //
  // Make sure SATA device exists.
  //
  if (MmioRead16 (PciD19F0RegBase + R_PCH_SATA_ID) != 0xFFFF) {
    SataModeSelect  = MmioRead16 (PciD19F0RegBase + R_PCH_SATA_MAP) & B_PCH_SATA_MAP_SMS_MASK;
    if ((SataModeSelect == V_PCH_SATA_MAP_SMS_AHCI) ||
        (SataModeSelect == V_PCH_SATA_MAP_SMS_RAID)) {
      AhciBar = MmioRead32 (PciD19F0RegBase + R_PCH_SATA_ABAR) & B_PCH_SATA_ABAR_BA;
      //
      // Make sure the AhciBar is valid.
      //
      if ((AhciBar != 0x00000000) && (AhciBar != B_PCH_SATA_ABAR_BA)) {
        //
        // Keep original CMD word, and enable MSE
        //
        OrgCmdWord = MmioRead32 (PciD19F0RegBase + R_PCH_SATA_COMMAND);
        if ((OrgCmdWord & B_PCH_SATA_COMMAND_MSE) == 0) {
          Data32And = (UINT32) 0xFFFFFFFF;
          Data32Or  = (UINT32) B_PCH_SATA_COMMAND_MSE;
          if (!IsSetS3BootScript) {
            MmioOr32 ((PciD19F0RegBase + R_PCH_SATA_COMMAND), Data32Or);
          } else {
            //
            // Set S3 Boot Script
            //
            S3BootScriptSaveMemReadWrite (
              EfiBootScriptWidthUint32,
              (UINTN) (PciD19F0RegBase + R_PCH_SATA_COMMAND),
              &Data32Or,  /// Data to be ORed
              &Data32And  /// Data to be ANDed
              );
          }
        }
        for (Index = 0; Index < PCH_AHCI_MAX_PORTS; Index++) {
          if (PchPlatformPolicy->SataConfig->PortSettings[Index].External == PCH_DEVICE_ENABLE) {
            PxSctlDet = MmioRead32(AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))) & B_PCH_SATA_AHCI_PXSCTL_DET;
            PxCmdSud = MmioRead32(AhciBar + (R_PCH_SATA_AHCI_P0CMD  + (0x80 * Index))) & B_PCH_SATA_AHCI_PxCMD_SUD;
            //
            // Limit speed to Gen2
            //
            Data32And = (UINT32)~(B_PCH_SATA_AHCI_PXSCTL_SPD);
            Data32Or  = (UINT32) V_PCH_SATA_AHCI_PXSCTL_SPD_2;
            if (!IsSetS3BootScript) {
              MmioAndThenOr32 (
                (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))),
                Data32And,
                Data32Or
                );
            } else {
              //
              // Set S3 Boot Script
              //
              S3BootScriptSaveMemReadWrite (
                EfiBootScriptWidthUint32,
                (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))),
                &Data32Or,  /// Data to be ORed
                &Data32And  /// Data to be ANDed
                );
            }
            //
            // If port is not offline, and it's spin up, need to port reset.
            // After port reset, clear the SERR.
            // - Set DET=1, and then set DET=0.
            // - Finally, set FRE=1.
            //
            if ((PxSctlDet == V_PCH_SATA_AHCI_PXSCTL_DET_0) &&
                (PxCmdSud == B_PCH_SATA_AHCI_PxCMD_SUD))
            {
              if (!IsSetS3BootScript) {
                MmioOr32 (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index)), V_PCH_SATA_AHCI_PXSCTL_DET_1);
                PchPmTimerStall (1000);
                MmioAnd32(AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index)), (UINT32) ~(B_PCH_SATA_AHCI_PXSCTL_DET));
                MmioWrite32 (AhciBar + (R_PCH_SATA_AHCI_P0SERR + (0x80 * Index)), (UINT32)~0u);
                MmioOr32 (AhciBar + (R_PCH_SATA_AHCI_P0CMD + (0x80 * Index)), B_PCH_SATA_AHCI_PxCMD_FRE);
              } else {
                //
                // Set S3 Boot Script
                //
                Data32And = (UINT32) 0xFFFFFFFF;
                Data32Or  = (UINT32) V_PCH_SATA_AHCI_PXSCTL_DET_1;
                S3BootScriptSaveMemReadWrite (
                  EfiBootScriptWidthUint32,
                  (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))),
                  &Data32Or,  /// Data to be ORed
                  &Data32And  /// Data to be ANDed
                  );
                S3BootScriptSaveStall (1000);
                Data32And = (UINT32) ~(B_PCH_SATA_AHCI_PXSCTL_DET);
                Data32Or  = (UINT32) 0x00000000;
                S3BootScriptSaveMemReadWrite (
                  EfiBootScriptWidthUint32,
                  (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))),
                  &Data32Or,  /// Data to be ORed
                  &Data32And  /// Data to be ANDed
                  );
                Data32And = (UINT32) 0xFFFFFFFF;
                Data32Or  = (UINT32) 0xFFFFFFFF;
                S3BootScriptSaveMemReadWrite (
                  EfiBootScriptWidthUint32,
                  (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0SERR + (0x80 * Index))),
                  &Data32Or,  /// Data to be ORed
                  &Data32And  /// Data to be ANDed
                  );
                Data32And = (UINT32) 0xFFFFFFFF;
                Data32Or  = (UINT32) B_PCH_SATA_AHCI_PxCMD_FRE;
                S3BootScriptSaveMemReadWrite (
                  EfiBootScriptWidthUint32,
                  (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0CMD + (0x80 * Index))),
                  &Data32Or,  /// Data to be ORed
                  &Data32And  /// Data to be ANDed
                  );
              }
            }
            //
            // If port is offline, and it's not spin up, meets the power bug.
            // Need to do the W/A to spin up the port and then spin down.
            // Then entering back to offline and listen.
            // - Set DET=0, SUD=1, and then set SUD=0, DET=4.
            //
            if ((PxSctlDet == V_PCH_SATA_AHCI_PXSCTL_DET_4) &&
                (PxCmdSud == 0))
            {
              if (!IsSetS3BootScript) {
                MmioAnd32(AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index)), (UINT32) ~(B_PCH_SATA_AHCI_PXSCTL_DET));
                MmioOr32 (AhciBar + (R_PCH_SATA_AHCI_P0CMD  + (0x80 * Index)), B_PCH_SATA_AHCI_PxCMD_SUD);
                PchPmTimerStall (1000);
                MmioAnd32(AhciBar + (R_PCH_SATA_AHCI_P0CMD  + (0x80 * Index)), (UINT32) ~(B_PCH_SATA_AHCI_PxCMD_SUD));
                MmioOr32 (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index)), V_PCH_SATA_AHCI_PXSCTL_DET_4);
              } else {
                //
                // Set S3 Boot Script
                //
                Data32And = (UINT32) ~(B_PCH_SATA_AHCI_PXSCTL_DET);
                Data32Or  = (UINT32) 0x00000000;
                S3BootScriptSaveMemReadWrite (
                  EfiBootScriptWidthUint32,
                  (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))),
                  &Data32Or,  /// Data to be ORed
                  &Data32And  /// Data to be ANDed
                  );
                Data32And = (UINT32) 0xFFFFFFFF;
                Data32Or  = (UINT32) B_PCH_SATA_AHCI_PxCMD_SUD;
                S3BootScriptSaveMemReadWrite (
                  EfiBootScriptWidthUint32,
                  (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0CMD + (0x80 * Index))),
                  &Data32Or,  /// Data to be ORed
                  &Data32And  /// Data to be ANDed
                  );
                S3BootScriptSaveStall (1000);
                Data32And = (UINT32) ~(B_PCH_SATA_AHCI_PxCMD_SUD);
                Data32Or  = (UINT32) 0x00000000;
                S3BootScriptSaveMemReadWrite (
                  EfiBootScriptWidthUint32,
                  (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0CMD + (0x80 * Index))),
                  &Data32Or,  /// Data to be ORed
                  &Data32And  /// Data to be ANDed
                  );
                Data32And = (UINT32) 0xFFFFFFFF;
                Data32Or  = (UINT32) V_PCH_SATA_AHCI_PXSCTL_DET_4;
                S3BootScriptSaveMemReadWrite (
                  EfiBootScriptWidthUint32,
                  (UINTN) (AhciBar + (R_PCH_SATA_AHCI_P0SCTL + (0x80 * Index))),
                  &Data32Or,  /// Data to be ORed
                  &Data32And  /// Data to be ANDed
                  );
              }
            }
          }
        }
        //
        // Restore original CMD word.
        //
        if ((OrgCmdWord & B_PCH_SATA_COMMAND_MSE) == 0) {
          Data32And = (UINT32) 0xFFFFFFFF;
          Data32Or  = (UINT32) OrgCmdWord;
          if (!IsSetS3BootScript) {
            MmioWrite32 ((PciD19F0RegBase + R_PCH_SATA_COMMAND), Data32Or);
          } else {
            S3BootScriptSaveMemReadWrite (
              EfiBootScriptWidthUint32,
              (UINTN) (PciD19F0RegBase + R_PCH_SATA_COMMAND),
              &Data32Or,  /// Data to be ORed
              &Data32And  /// Data to be ANDed
              );
          }
        }
      } // AhciBar is vaild
    } // SATA mode is AHCI or RAID
  } // if D19F0 is existed

  DEBUG ((EFI_D_INFO, "ConfigureSataAtBoot() End\n"));
  return EFI_SUCCESS;
}