summaryrefslogtreecommitdiff
path: root/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c')
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c638
1 files changed, 638 insertions, 0 deletions
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c
new file mode 100644
index 0000000000..cb7a1bb457
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Sdio/Dxe/SD/SdMediaDeviceDxe/CEATA.c
@@ -0,0 +1,638 @@
+/** @file
+ CEATA specific functions implementation
+
+ Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SdMediaDevice.h"
+
+/**
+ Send RW_MULTIPLE_REGISTER command
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] Address Register address.
+ @param[in] ByteCount Buffer size.
+ @param[in] Write TRUE means write, FALSE means read.
+ @param[in] Buffer Buffer pointer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+ReadWriteMultipleRegister (
+ IN CARD_DATA *CardData,
+ IN UINT16 Address,
+ IN UINT8 ByteCount,
+ IN BOOLEAN Write,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Argument;
+
+ Status = EFI_SUCCESS;
+
+ if ((Address % 4 != 0) || (ByteCount % 4 != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ Argument = (Address << 16) | ByteCount;
+ if (Write) {
+ Argument |= BIT31;
+ }
+
+ if (Write) {
+ CopyMem (CardData->AlignedBuffer, Buffer, ByteCount);
+
+ Status = SendCommand (
+ CardData,
+ RW_MULTIPLE_REGISTER,
+ Argument,
+ OutData,
+ CardData->AlignedBuffer,
+ ByteCount,
+ ResponseR1b,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ } else {
+ Status = SendCommand (
+ CardData,
+ RW_MULTIPLE_REGISTER,
+ Argument,
+ InData,
+ CardData->AlignedBuffer,
+ ByteCount,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ CopyMem (Buffer, CardData->AlignedBuffer, ByteCount);
+ }
+ }
+Exit:
+ return Status;
+}
+
+
+/**
+ Send ReadWriteMultipleBlock command with RW_MULTIPLE_REGISTER command
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] DataUnitCount Buffer size in 512 bytes unit.
+ @param[in] Write TRUE means write, FALSE means read.
+ @param[in] Buffer Buffer pointer.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+ReadWriteMultipleBlock (
+ IN CARD_DATA *CardData,
+ IN UINT16 DataUnitCount,
+ IN BOOLEAN Write,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
+ UINT32 TransferLength;
+
+ Status = EFI_SUCCESS;
+ SdHostIo = CardData->SdHostIo;
+
+ TransferLength = DataUnitCount * DATA_UNIT_SIZE;
+ if (TransferLength > SdHostIo->HostCapability.BoundarySize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Write) {
+ CopyMem (CardData->AlignedBuffer, Buffer, TransferLength);
+
+ Status = SendCommand (
+ CardData,
+ RW_MULTIPLE_BLOCK,
+ (DataUnitCount | BIT31),
+ OutData,
+ CardData->AlignedBuffer,
+ TransferLength,
+ ResponseR1b,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ } else {
+ Status = SendCommand (
+ CardData,
+ RW_MULTIPLE_BLOCK,
+ DataUnitCount,
+ InData,
+ CardData->AlignedBuffer,
+ TransferLength,
+ ResponseR1,
+ TIMEOUT_DATA,
+ (UINT32 *) &(CardData->CardStatus)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ CopyMem (Buffer, CardData->AlignedBuffer, TransferLength);
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Send software reset
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+SoftwareReset (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data;
+ UINT32 TimeOut;
+
+ Data = BIT2;
+
+ Status = FastIO (CardData, Reg_Control, &Data, TRUE);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ TimeOut = 5 * 1000;
+
+ do {
+ gBS->Stall (1 * 1000);
+ Status = FastIO (CardData, Reg_Control, &Data, FALSE);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ if ((Data & BIT2) == BIT2) {
+ break;
+ }
+
+ TimeOut--;
+ } while (TimeOut > 0);
+
+ if (TimeOut == 0) {
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+
+ Data &= ~BIT2;
+ Status = FastIO (CardData, Reg_Control, &Data, TRUE);
+
+ TimeOut = 5 * 1000;
+
+ do {
+ gBS->Stall (1 * 1000);
+ Status = FastIO (CardData, Reg_Control, &Data, FALSE);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ if ((Data & BIT2) != BIT2) {
+ break;
+ }
+
+ TimeOut--;
+ } while (TimeOut > 0);
+
+ if (TimeOut == 0) {
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+
+Exit:
+ return Status;
+}
+
+
+/**
+ SendATACommand specificed in Taskfile
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] TaskFile Pointer to TASK_FILE.
+ @param[in] Write TRUE means write, FALSE means read.
+ @param[in] Buffer If NULL, means no data transfer, neither read nor write.
+ @param[in] SectorCount Buffer size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+SendATACommand (
+ IN CARD_DATA *CardData,
+ IN TASK_FILE *TaskFile,
+ IN BOOLEAN Write,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Data;
+ UINT32 TimeOut;
+
+ //
+ // Write register
+ //
+ Status = ReadWriteMultipleRegister (
+ CardData,
+ 0,
+ sizeof (TASK_FILE),
+ TRUE,
+ (UINT8 *) TaskFile
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "ReadWriteMultipleRegister 0x%x\n", Status));
+ goto Exit;
+ }
+
+ TimeOut = 5000;
+ do {
+ gBS->Stall (1 * 1000);
+ Data = 0;
+ Status = FastIO (
+ CardData,
+ Reg_Command_Status,
+ &Data,
+ FALSE
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (((Data & BIT7) == 0) && ((Data & BIT6) == BIT6)) {
+ break;
+ }
+
+ TimeOut --;
+ } while (TimeOut > 0);
+
+ if (TimeOut == 0) {
+ DEBUG ((EFI_D_ERROR, "ReadWriteMultipleRegister FastIO EFI_TIMEOUT 0x%x\n", Data));
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+
+ if (Buffer != NULL) {
+ Status = ReadWriteMultipleBlock (
+ CardData,
+ SectorCount,
+ Write,
+ (UINT8 *) Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "ReadWriteMultipleBlock EFI_TIMEOUT 0x%x\n", Status));
+ goto Exit;
+ }
+
+ TimeOut = 5 * 1000;
+ do {
+ gBS->Stall (1 * 1000);
+ Data = 0;
+ Status = FastIO (
+ CardData,
+ Reg_Command_Status,
+ &Data,
+ FALSE
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (((Data & BIT7) == 0) && ((Data & BIT3) == 0)) {
+ break;
+ }
+
+ TimeOut --;
+ } while (TimeOut > 0);
+ if (TimeOut == 0) {
+ DEBUG ((EFI_D_ERROR, "ReadWriteMultipleBlock FastIO EFI_TIMEOUT 0x%x\n", Data));
+ Status = EFI_TIMEOUT;
+ goto Exit;
+ }
+
+ if (((Data & BIT6) == BIT6) && (Data & BIT0) == 0) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+Exit:
+ if (EFI_ERROR (Status)) {
+ SoftwareReset (CardData);
+ }
+
+ return Status;
+}
+
+
+/**
+ IDENTIFY_DEVICE command
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+IndentifyDevice (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
+
+ //
+ // The host only supports nIEN = 0
+ //
+ CardData->TaskFile.Command_Status = IDENTIFY_DEVICE;
+ Status = SendATACommand (
+ CardData,
+ &CardData->TaskFile,
+ FALSE,
+ (UINT8 *) &(CardData->IndentifyDeviceData),
+ 1
+ );
+
+ return Status;
+}
+
+
+/**
+ FLUSH_CACHE_EXT command
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+FlushCache (
+ IN CARD_DATA *CardData
+ )
+{
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ STANDBY_IMMEDIATE command
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+StandByImmediate (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
+
+ //
+ // The host only supports nIEN = 0
+ //
+ CardData->TaskFile.Command_Status = STANDBY_IMMEDIATE;
+ Status = SendATACommand (
+ CardData,
+ &CardData->TaskFile,
+ FALSE,
+ NULL,
+ 0
+ );
+
+ return Status;
+}
+
+
+/**
+ READ_DMA_EXT command
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] LBA The starting logical block address to read from on the device.
+ @param[in] Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+ @param[in] SectorCount Size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+ReadDMAExt (
+ IN CARD_DATA *CardData,
+ IN EFI_LBA LBA,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
+
+ //
+ // The host only supports nIEN = 0
+ //
+ CardData->TaskFile.Command_Status = READ_DMA_EXT;
+
+ CardData->TaskFile.SectorCount = (UINT8) SectorCount;
+ CardData->TaskFile.SectorCount_Exp = (UINT8) (SectorCount >> 8);
+
+ CardData->TaskFile.LBALow = (UINT8) LBA;
+ CardData->TaskFile.LBAMid = (UINT8) RShiftU64 (LBA, 8);
+ CardData->TaskFile.LBAHigh = (UINT8) RShiftU64 (LBA, 16);
+
+ CardData->TaskFile.LBALow_Exp = (UINT8) RShiftU64 (LBA, 24);
+ CardData->TaskFile.LBAMid_Exp = (UINT8) RShiftU64 (LBA, 32);
+ CardData->TaskFile.LBAHigh_Exp = (UINT8) RShiftU64 (LBA, 40);
+
+ Status = SendATACommand (
+ CardData,
+ &CardData->TaskFile,
+ FALSE,
+ Buffer,
+ SectorCount
+ );
+
+ return Status;
+}
+
+
+/**
+ WRITE_DMA_EXT command
+
+ @param[in] CardData Pointer to CARD_DATA.
+ @param[in] LBA The starting logical block address to read from on the device.
+ @param[in] Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+ @param[in] SectorCount Size in 512 bytes unit.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_DEVICE_ERROR Hardware Error
+ @retval EFI_INVALID_PARAMETER Parameter is error
+ @retval EFI_NO_MEDIA No media
+ @retval EFI_MEDIA_CHANGED Media Change
+ @retval EFI_BAD_BUFFER_SIZE Buffer size is bad
+
+**/
+EFI_STATUS
+WriteDMAExt (
+ IN CARD_DATA *CardData,
+ IN EFI_LBA LBA,
+ IN UINT8 *Buffer,
+ IN UINT16 SectorCount
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));
+
+ //
+ // The host only supports nIEN = 0
+ //
+ CardData->TaskFile.Command_Status = WRITE_DMA_EXT;
+
+ CardData->TaskFile.SectorCount = (UINT8) SectorCount;
+ CardData->TaskFile.SectorCount_Exp = (UINT8) (SectorCount >> 8);
+
+ CardData->TaskFile.LBALow = (UINT8) LBA;
+ CardData->TaskFile.LBAMid = (UINT8) RShiftU64 (LBA, 8);
+ CardData->TaskFile.LBAHigh = (UINT8) RShiftU64 (LBA, 16);
+
+ CardData->TaskFile.LBALow_Exp = (UINT8) RShiftU64 (LBA, 24);
+ CardData->TaskFile.LBAMid_Exp = (UINT8) RShiftU64 (LBA, 32);
+ CardData->TaskFile.LBAHigh_Exp = (UINT8) RShiftU64 (LBA, 40);
+
+ Status = SendATACommand (
+ CardData,
+ &CardData->TaskFile,
+ TRUE,
+ Buffer,
+ SectorCount
+ );
+
+ return Status;
+
+}
+
+
+/**
+ Judge whether it is CE-ATA device or not.
+
+ @param[in] CardData Pointer to CARD_DATA.
+
+ @retval TRUE
+ @retval FALSE
+
+**/
+BOOLEAN
+IsCEATADevice (
+ IN CARD_DATA *CardData
+ )
+{
+ EFI_STATUS Status;
+
+ Status = ReadWriteMultipleRegister (
+ CardData,
+ 0,
+ sizeof (TASK_FILE),
+ FALSE,
+ (UINT8 *) &CardData->TaskFile
+ );
+
+ if (EFI_ERROR (Status)) {
+ //
+ // To bring back the normal MMC card to work
+ //
+ CardData->SdHostIo->ResetSdHost (CardData->SdHostIo, Reset_DAT_CMD);
+ return FALSE;
+ }
+
+ if (CardData->TaskFile.LBAMid == CE_ATA_SIG_CE &&
+ CardData->TaskFile.LBAHigh == CE_ATA_SIG_AA
+ ) {
+ //
+ // Disable Auto CMD for CE-ATA
+ //
+ CardData->SdHostIo->EnableAutoStopCmd (CardData->SdHostIo, FALSE);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+