X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=QuarkSocPkg%2FQuarkSouthCluster%2FSdio%2FDxe%2FSDMediaDeviceDxe%2FMMCSDTransfer.c;fp=QuarkSocPkg%2FQuarkSouthCluster%2FSdio%2FDxe%2FSDMediaDeviceDxe%2FMMCSDTransfer.c;h=0000000000000000000000000000000000000000;hp=65b71a008c00676a0469d83e3bc8ab579f4e8adc;hb=5347c48016f27061475fdb053e867a06ce73492f;hpb=96ef5a8e30a8da33eaab09f13cc8d752342717a5 diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDTransfer.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDTransfer.c deleted file mode 100644 index 65b71a008c..0000000000 --- a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDTransfer.c +++ /dev/null @@ -1,1708 +0,0 @@ -/** @file - -MMC/SD transfer specific functions - -Copyright (c) 2013-2015 Intel Corporation. - -SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include "SDMediaDevice.h" - -/** - Check card status, print the debug info and check the error - - @param Status Status got from card status register. - - @retval EFI_SUCCESS - @retval EFI_DEVICE_ERROR - -**/ -EFI_STATUS -CheckCardStatus ( - IN UINT32 Status - ) -{ - CARD_STATUS *CardStatus; - CardStatus = (CARD_STATUS*)(&Status); - - if (CardStatus->ADDRESS_OUT_OF_RANGE) { - DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_OUT_OF_RANGE\n")); - } - - if (CardStatus->ADDRESS_MISALIGN) { - DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_MISALIGN\n")); - } - - if (CardStatus->BLOCK_LEN_ERROR) { - DEBUG ((EFI_D_ERROR, "CardStatus: BLOCK_LEN_ERROR\n")); - } - - if (CardStatus->ERASE_SEQ_ERROR) { - DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_SEQ_ERROR\n")); - } - - if (CardStatus->ERASE_PARAM) { - DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_PARAM\n")); - } - - if (CardStatus->WP_VIOLATION) { - DEBUG ((EFI_D_ERROR, "CardStatus: WP_VIOLATION\n")); - } - - if (CardStatus->CARD_IS_LOCKED) { - DEBUG ((EFI_D_ERROR, "CardStatus: CARD_IS_LOCKED\n")); - } - - if (CardStatus->LOCK_UNLOCK_FAILED) { - DEBUG ((EFI_D_ERROR, "CardStatus: LOCK_UNLOCK_FAILED\n")); - } - - if (CardStatus->COM_CRC_ERROR) { - DEBUG ((EFI_D_ERROR, "CardStatus: COM_CRC_ERROR\n")); - } - - if (CardStatus->ILLEGAL_COMMAND) { - DEBUG ((EFI_D_ERROR, "CardStatus: ILLEGAL_COMMAND\n")); - } - - if (CardStatus->CARD_ECC_FAILED) { - DEBUG ((EFI_D_ERROR, "CardStatus: CARD_ECC_FAILED\n")); - } - - if (CardStatus->CC_ERROR) { - DEBUG ((EFI_D_ERROR, "CardStatus: CC_ERROR\n")); - } - - if (CardStatus->ERROR) { - DEBUG ((EFI_D_ERROR, "CardStatus: ERROR\n")); - } - - if (CardStatus->UNDERRUN) { - DEBUG ((EFI_D_ERROR, "CardStatus: UNDERRUN\n")); - } - - if (CardStatus->OVERRUN) { - DEBUG ((EFI_D_ERROR, "CardStatus: OVERRUN\n")); - } - - if (CardStatus->CID_CSD_OVERWRITE) { - DEBUG ((EFI_D_ERROR, "CardStatus: CID_CSD_OVERWRITE\n")); - } - - if (CardStatus->WP_ERASE_SKIP) { - DEBUG ((EFI_D_ERROR, "CardStatus: WP_ERASE_SKIP\n")); - } - - if (CardStatus->ERASE_RESET) { - DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_RESET\n")); - } - - if (CardStatus->SWITCH_ERROR) { - DEBUG ((EFI_D_ERROR, "CardStatus: SWITCH_ERROR\n")); - } - - if ((Status & 0xFCFFA080) != 0) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - Send command by using Host IO protocol - - @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance. - @param CommandIndex The command index to set the command index field of command register. - @param Argument Command argument to set the argument field of command register. - @param DataType TRANSFER_TYPE, indicates no data, data in or data out. - @param Buffer Contains the data read from / write to the device. - @param BufferSize The size of the buffer. - @param ResponseType RESPONSE_TYPE. - @param TimeOut Time out value in 1 ms unit. - @param ResponseData Depending on the ResponseType, such as CSD or card status. - - @retval EFI_SUCCESS - @retval EFI_INVALID_PARAMETER - @retval EFI_UNSUPPORTED - @retval EFI_DEVICE_ERROR - -**/ -EFI_STATUS -SendCommand ( - IN CARD_DATA *CardData, - IN UINT16 CommandIndex, - IN UINT32 Argument, - IN TRANSFER_TYPE DataType, - IN UINT8 *Buffer, OPTIONAL - IN UINT32 BufferSize, - IN RESPONSE_TYPE ResponseType, - IN UINT32 TimeOut, - OUT UINT32 *ResponseData - ) -{ - - EFI_STATUS Status; - EFI_SD_HOST_IO_PROTOCOL *SDHostIo; - SDHostIo = CardData->SDHostIo; - if (CardData->CardType != MMCCard && CardData->CardType != MMCCardHighCap) { - CommandIndex |= AUTO_CMD12_ENABLE; - } - - Status = SDHostIo->SendCommand ( - SDHostIo, - CommandIndex, - Argument, - DataType, - Buffer, - BufferSize, - ResponseType, - TimeOut, - ResponseData - ); - if (!EFI_ERROR (Status)) { - if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) { - ASSERT(ResponseData != NULL); - Status = CheckCardStatus (*ResponseData); - } - } else { - SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD); - } - - return Status; -} - -/** - Send the card APP_CMD command with the following command indicated by CommandIndex - - @param CardData Pointer to CARD_DATA. - @param CommandIndex The command index to set the command index field of command register. - @param Argument Command argument to set the argument field of command register. - @param DataType TRANSFER_TYPE, indicates no data, data in or data out. - @param Buffer Contains the data read from / write to the device. - @param BufferSize The size of the buffer. - @param ResponseType RESPONSE_TYPE. - @param TimeOut Time out value in 1 ms unit. - @param ResponseData Depending on the ResponseType, such as CSD or card status. - - @retval EFI_SUCCESS - @retval EFI_INVALID_PARAMETER - @retval EFI_UNSUPPORTED - @retval EFI_DEVICE_ERROR - -**/ -EFI_STATUS -SendAppCommand ( - IN CARD_DATA *CardData, - IN UINT16 CommandIndex, - IN UINT32 Argument, - IN TRANSFER_TYPE DataType, - IN UINT8 *Buffer, OPTIONAL - IN UINT32 BufferSize, - IN RESPONSE_TYPE ResponseType, - IN UINT32 TimeOut, - OUT UINT32 *ResponseData - ) -{ - - EFI_STATUS Status; - EFI_SD_HOST_IO_PROTOCOL *SDHostIo; - UINT8 Index; - - SDHostIo = CardData->SDHostIo; - Status = EFI_SUCCESS; - - for (Index = 0; Index < 2; Index++) { - Status = SDHostIo->SendCommand ( - SDHostIo, - APP_CMD, - (CardData->Address << 16), - NoData, - NULL, - 0, - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (!EFI_ERROR (Status)) { - Status = CheckCardStatus (*(UINT32*)&(CardData->CardStatus)); - if (CardData->CardStatus.SAPP_CMD != 1) { - Status = EFI_DEVICE_ERROR; - } - if (!EFI_ERROR (Status)) { - break; - } - } else { - SDHostIo->ResetSDHost (SDHostIo, Reset_Auto); - } - } - - if (EFI_ERROR (Status)) { - return Status; - } - if (CardData->CardType != MMCCard && CardData->CardType != MMCCardHighCap) { - CommandIndex |= AUTO_CMD12_ENABLE; - } - - Status = SDHostIo->SendCommand ( - SDHostIo, - CommandIndex, - Argument, - DataType, - Buffer, - BufferSize, - ResponseType, - TimeOut, - ResponseData - ); - if (!EFI_ERROR (Status)) { - if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) { - ASSERT(ResponseData != NULL); - Status = CheckCardStatus (*ResponseData); - } - } else { - SDHostIo->ResetSDHost (SDHostIo, Reset_Auto); - } - - return Status; -} - - -/** - Send the card FAST_IO command - - @param CardData Pointer to CARD_DATA. - @param RegisterAddress Register Address. - @param RegisterData Pointer to register Data. - @param Write TRUE for write, FALSE for read. - - @retval EFI_SUCCESS - @retval EFI_UNSUPPORTED - @retval EFI_INVALID_PARAMETER - @retval EFI_DEVICE_ERROR - -**/ -EFI_STATUS -FastIO ( - IN CARD_DATA *CardData, - IN UINT8 RegisterAddress, - IN OUT UINT8 *RegisterData, - IN BOOLEAN Write - ) -{ - EFI_STATUS Status; - UINT32 Argument; - UINT32 Data; - - Status = EFI_SUCCESS; - - if (RegisterData == NULL) { - Status = EFI_INVALID_PARAMETER; - goto Exit; - } - - Argument = (CardData->Address << 16) | (RegisterAddress << 8); - if (Write) { - Argument |= BIT15 | (*RegisterData); - } - - Status = SendCommand ( - CardData, - FAST_IO, - Argument, - NoData, - NULL, - 0, - ResponseR4, - TIMEOUT_COMMAND, - &Data - ); - if (EFI_ERROR (Status)) { - goto Exit; - } - - if ((Data & BIT15) == 0) { - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - if (!Write) { - *RegisterData = (UINT8)Data; - } - -Exit: - return Status; -} - -/** - Send the card GO_INACTIVE_STATE command. - - @param CardData Pointer to CARD_DATA. - - @return EFI_SUCCESS - @return others - -**/ -EFI_STATUS -PutCardInactive ( - IN CARD_DATA *CardData - ) -{ - EFI_STATUS Status; - - - Status = SendCommand ( - CardData, - GO_INACTIVE_STATE, - (CardData->Address << 16), - NoData, - NULL, - 0, - ResponseNo, - TIMEOUT_COMMAND, - NULL - ); - - return Status; - -} - -/** - Get card interested information for CSD rergister - - @param CardData Pointer to CARD_DATA. - - @retval EFI_SUCCESS - @retval EFI_UNSUPPORTED - @retval EFI_INVALID_PARAMETER - -**/ -EFI_STATUS -CaculateCardParameter ( - IN CARD_DATA *CardData - ) -{ - EFI_STATUS Status; - UINT32 Frequency; - UINT32 Multiple; - UINT32 CSize; - CSD_SDV2 *CsdSDV2; - - Status = EFI_SUCCESS; - - switch (CardData->CSDRegister.TRAN_SPEED & 0x7) { - case 0: - Frequency = 100 * 1000; - break; - - case 1: - Frequency = 1 * 1000 * 1000; - break; - - case 2: - Frequency = 10 * 1000 * 1000; - break; - - case 3: - Frequency = 100 * 1000 * 1000; - break; - - default: - Status = EFI_INVALID_PARAMETER; - goto Exit; - } - - switch ((CardData->CSDRegister.TRAN_SPEED >> 3) & 0xF) { - case 1: - Multiple = 10; - break; - - case 2: - Multiple = 12; - break; - - case 3: - Multiple = 13; - break; - - case 4: - Multiple = 15; - break; - - case 5: - Multiple = 20; - break; - - case 6: - if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) { - Multiple = 26; - } else { - Multiple = 25; - } - break; - - case 7: - Multiple = 30; - break; - - case 8: - Multiple = 35; - break; - - case 9: - Multiple = 40; - break; - - case 10: - Multiple = 45; - break; - - case 11: - if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) { - Multiple = 52; - } else { - Multiple = 50; - } - break; - - case 12: - Multiple = 55; - break; - - case 13: - Multiple = 60; - break; - - case 14: - Multiple = 70; - break; - - case 15: - Multiple = 80; - break; - - default: - Status = EFI_INVALID_PARAMETER; - goto Exit; - } - - Frequency = Frequency * Multiple / 10; - CardData->MaxFrequency = Frequency; - - CardData->BlockLen = 1 << CardData->CSDRegister.READ_BL_LEN; - - if (CardData->CardType == SDMemoryCard2High) { - ASSERT(CardData->CSDRegister.CSD_STRUCTURE == 1); - CsdSDV2 = (CSD_SDV2*)&CardData->CSDRegister; - // - // The SD Spec 2.0 says (CSize + 1) * 512K is the total size, so block numbber is (CSize + 1) * 1K - // the K here means 1024 not 1000 - // - CardData->BlockNumber = DivU64x32 (MultU64x32 (CsdSDV2->C_SIZE + 1, 512 * 1024) , CardData->BlockLen); - } else { - // - // For MMC card > 2G, the block number will be recaculate later - // - CSize = CardData->CSDRegister.C_SIZELow2 | (CardData->CSDRegister.C_SIZEHigh10 << 2); - CardData->BlockNumber = MultU64x32 (LShiftU64 (1, CardData->CSDRegister.C_SIZE_MULT + 2), CSize + 1); - } - - // - //For >= 2G card, BlockLen may be 1024, but the transfer size is still 512 bytes - // - if (CardData->BlockLen > 512) { - CardData->BlockNumber = DivU64x32 (MultU64x32 (CardData->BlockNumber, CardData->BlockLen), 512); - CardData->BlockLen = 512; - } - - DEBUG(( - EFI_D_INFO, - "CalculateCardParameter: Card Size: 0x%lx\n", MultU64x32 (CardData->BlockNumber, CardData->BlockLen) - )); - -Exit: - return Status; -} - -/** - Test the bus width setting for MMC card.It is used only for verification purpose. - - @param CardData Pointer to CARD_DATA. - @param Width 1, 4, 8 bits. - - @retval EFI_SUCCESS - @retval EFI_UNSUPPORTED - @retval EFI_INVALID_PARAMETER - -**/ -EFI_STATUS -MMCCardBusWidthTest ( - IN CARD_DATA *CardData, - IN UINT32 Width - ) -{ - EFI_STATUS Status; - UINT64 Data; - UINT64 Value; - - ASSERT(CardData != NULL); - - - Value = 0; - - switch (Width) { - case 1: - Data = 0x80; - break; - - case 4: - Data = 0x5A; - break; - - case 8: - Data = 0xAA55; - break; - - default: - Status = EFI_INVALID_PARAMETER; - goto Exit; - } - - CopyMem (CardData->AlignedBuffer, &Data, Width); - Status = SendCommand ( - CardData, - BUSTEST_W, - 0, - OutData, - CardData->AlignedBuffer, - Width, - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest:SendCommand BUSTEST_W 0x%x\n", *(UINT32*)&(CardData->CardStatus))); - goto Exit; - } - - gBS->Stall (10 * 1000); - - Data = 0; - - Status = SendCommand ( - CardData, - BUSTEST_R, - 0, - InData, - CardData->AlignedBuffer, - Width, - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest:SendCommand BUSTEST_R 0x%x\n", *(UINT32*)&(CardData->CardStatus))); - goto Exit; - } - CopyMem (&Data, CardData->AlignedBuffer, Width); - - switch (Width) { - case 1: - Value = (~(Data ^ 0x80)) & 0xC0; - break; - case 4: - Value = (~(Data ^ 0x5A)) & 0xFF; - break; - case 8: - Value = (~(Data ^ 0xAA55)) & 0xFFFF; - break; - } - - if (Value == 0) { - Status = EFI_SUCCESS; - } else { - Status = EFI_UNSUPPORTED; - } - - -Exit: - return Status; -} - -/** - This function can detect these card types: - 1. MMC card - 2. SD 1.1 card - 3. SD 2.0 standard card - 3. SD 2.0 high capacity card - - @param CardData Pointer to CARD_DATA. - - @return EFI_SUCCESS - @return others - -**/ -EFI_STATUS -GetCardType ( - IN CARD_DATA *CardData - ) -{ - EFI_STATUS Status; - EFI_SD_HOST_IO_PROTOCOL *SDHostIo; - UINT32 Argument; - UINT32 ResponseData; - UINT32 Count; - BOOLEAN SDCommand8Support; - - - SDHostIo = CardData->SDHostIo; - - // - // Reset the card - // - Status = SendCommand ( - CardData, - GO_IDLE_STATE, - 0, - NoData, - NULL, - 0, - ResponseNo, - TIMEOUT_COMMAND, - NULL - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status)); - goto Exit; - } - - // - //No spec requirment, can be adjusted - // - gBS->Stall (10 * 1000); - - - // - // Only 2.7V - 3.6V is supported for SD2.0, only SD 2.0 card can pass - // MMC and SD1.1 card will fail this command - // - Argument = (VOLTAGE_27_36 << 8) | CHECK_PATTERN; - ResponseData = 0; - SDCommand8Support = FALSE; - - Status = SendCommand ( - CardData, - SEND_IF_COND, - Argument, - NoData, - NULL, - 0, - ResponseR7, - TIMEOUT_COMMAND, - &ResponseData - ); - - if (EFI_ERROR (Status)) { - if (Status != EFI_TIMEOUT) { - DEBUG((EFI_D_ERROR, "SEND_IF_COND Fail, none time out error\n")); - goto Exit; - } - } else { - if (ResponseData != Argument) { - DEBUG((EFI_D_ERROR, "SEND_IF_COND Fail, respond data does not match send data\n")); - Status = EFI_DEVICE_ERROR; - goto Exit; - } - SDCommand8Support = TRUE; - } - - - Argument = 0; - if (SDHostIo->HostCapability.V30Support == TRUE) { - Argument |= BIT17 | BIT18; - } else if (SDHostIo->HostCapability.V33Support == TRUE) { - Argument |= BIT20 | BIT21; - } - - if (SDCommand8Support) { - // - //If command SD_SEND_OP_COND sucessed, it should be set. - // SD 1.1 card will ignore it - // SD 2.0 standard card will repsond with CCS 0, SD high capacity card will respond with CCS 1 - // CCS is BIT30 of OCR - Argument |= BIT30; - } - - - Count = 20; - // - //Only SD card will respond to this command, and spec says the card only checks condition at first ACMD41 command - // - do { - Status = SendAppCommand ( - CardData, - SD_SEND_OP_COND, - Argument, - NoData, - NULL, - 0, - ResponseR3, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->OCRRegister) - ); - if (EFI_ERROR (Status)) { - if ((Status == EFI_TIMEOUT) && (!SDCommand8Support)) { - CardData->CardType = MMCCard; - Status = EFI_SUCCESS; - DEBUG((EFI_D_INFO, "SD_SEND_OP_COND, MMC card was identified\n")); - } else { - // - // Not as expected, MMC card should has no response, which means timeout. - // SD card should pass this command - // - DEBUG((EFI_D_ERROR, "SD_SEND_OP_COND Fail, check whether it is neither a MMC card nor a SD card\n")); - } - goto Exit; - } - // - //Avoid waiting if sucess. Busy bit 0 means not ready - // - if (CardData->OCRRegister.Busy == 1) { - break; - } - - gBS->Stall (50 * 1000); - Count--; - if (Count == 0) { - DEBUG((EFI_D_ERROR, "Card is always in busy state\n")); - Status = EFI_TIMEOUT; - goto Exit; - } - } while (1); - - // - //Check supported voltage - // - Argument = 0; - if (SDHostIo->HostCapability.V30Support == TRUE) { - if ((CardData->OCRRegister.V270_V360 & BIT2) == BIT2) { - Argument |= BIT17; - } else if ((CardData->OCRRegister.V270_V360 & BIT3) == BIT3) { - Argument |= BIT18; - } - } else if (SDHostIo->HostCapability.V33Support == TRUE) { - if ((CardData->OCRRegister.V270_V360 & BIT5) == BIT5) { - Argument |= BIT20; - } else if ((CardData->OCRRegister.V270_V360 & BIT6) == BIT6) { - Argument |= BIT21; - } - } - - if (Argument == 0) { - // - //No matched support voltage - // - PutCardInactive (CardData); - DEBUG((EFI_D_ERROR, "No matched voltage for this card\n")); - Status = EFI_UNSUPPORTED; - goto Exit; - } - - CardData->CardType = SDMemoryCard; - if (SDCommand8Support == TRUE) { - CardData->CardType = SDMemoryCard2; - DEBUG((EFI_D_INFO, "SD_SEND_OP_COND, SD 2.0 or above standard card was identified\n")); - } - - if ((CardData->OCRRegister.AccessMode & BIT1) == BIT1) { - CardData->CardType = SDMemoryCard2High; - DEBUG((EFI_D_INFO, "SD_SEND_OP_COND, SD 2.0 or above high capacity card was identified\n")); - } - - - -Exit: - return Status; -} - -/** - MMC card high/low voltage selection function - - @param CardData Pointer to CARD_DATA. - - @retval EFI_SUCCESS - @retval EFI_INVALID_PARAMETER - @retval EFI_UNSUPPORTED - @retval EFI_BAD_BUFFER_SIZE - -**/ -EFI_STATUS -MMCCardVoltageSelection ( - IN CARD_DATA *CardData - ) -{ - EFI_STATUS Status; - UINT8 Retry; - UINT32 TimeOut; - - Status = EFI_SUCCESS; - // - //First try the high voltage, then if supported choose the low voltage - // - - for (Retry = 0; Retry < 3; Retry++) { - // - // To bring back the normal MMC card to work - // after sending the SD command. Otherwise some - // card could not work - - Status = SendCommand ( - CardData, - GO_IDLE_STATE, - 0, - NoData, - NULL, - 0, - ResponseNo, - TIMEOUT_COMMAND, - NULL - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status)); - continue; - } - // - //CE-ATA device needs long delay - // - gBS->Stall ((Retry + 1) * 50 * 1000); - - // - //Get OCR register to check voltage support, first time the OCR is 0 - // - Status = SendCommand ( - CardData, - SEND_OP_COND, - 0, - NoData, - NULL, - 0, - ResponseR3, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->OCRRegister) - ); - if (!EFI_ERROR (Status)) { - break; - } - } - - if (Retry == 3) { - DEBUG((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status)); - Status = EFI_DEVICE_ERROR; - goto Exit; - } - - // - //TimeOut Value, 5000 * 100 * 1000 = 5 s - // - TimeOut = 5000; - - do { - Status = SendCommand ( - CardData, - SEND_OP_COND, - 0x40300000, - NoData, - NULL, - 0, - ResponseR3, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->OCRRegister) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status)); - goto Exit; - } - - gBS->Stall (1 * 1000); - TimeOut--; - if (TimeOut == 0) { - Status = EFI_TIMEOUT; - DEBUG((EFI_D_ERROR, "Card is always in busy state\n")); - goto Exit; - } - } while (CardData->OCRRegister.Busy != 1); - - if (CardData->OCRRegister.AccessMode == 2) // eMMC Card uses Sector Addressing - High Capacity - { - DEBUG((EFI_D_INFO, "eMMC Card is High Capacity\n")); - CardData->CardType = MMCCardHighCap; - } - -Exit: - return Status; - -} - -/** - This function set the bus and device width for MMC card - - @param CardData Pointer to CARD_DATA. - @param Width 1, 4, 8 bits. - - @retval EFI_SUCCESS - @retval EFI_UNSUPPORTED - @retval EFI_INVALID_PARAMETER - -**/ -EFI_STATUS -MMCCardSetBusWidth ( - IN CARD_DATA *CardData, - IN UINT8 BusWidth, - IN BOOLEAN EnableDDRMode - ) -{ - EFI_STATUS Status; - EFI_SD_HOST_IO_PROTOCOL *SDHostIo; - SWITCH_ARGUMENT SwitchArgument; - UINT8 Value; - - SDHostIo = CardData->SDHostIo; - Value = 0; - switch (BusWidth) { - case 8: - if (EnableDDRMode) - Value = 6; - else - Value = 2; - break; - - case 4: - if (EnableDDRMode) - Value = 5; - else - Value = 1; - break; - - case 1: - if (EnableDDRMode) // Bus width 1 is not supported in ddr mode - return EFI_UNSUPPORTED; - Value = 0; - break; - - default: - ASSERT(0); - } - - - ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT)); - SwitchArgument.CmdSet = 0; - SwitchArgument.Value = Value; - SwitchArgument.Index = (UINT32)((UINTN) - (&(CardData->ExtCSDRegister.BUS_WIDTH)) - (UINTN)(&(CardData->ExtCSDRegister))); - SwitchArgument.Access = WriteByte_Mode; - Status = SendCommand ( - CardData, - SWITCH, - *(UINT32*)&SwitchArgument, - NoData, - NULL, - 0, - ResponseR1b, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (!EFI_ERROR (Status)) { - Status = SendCommand ( - CardData, - SEND_STATUS, - (CardData->Address << 16), - NoData, - NULL, - 0, - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SWITCH %d bits Fail\n", BusWidth)); - goto Exit; - } else { - DEBUG((EFI_D_ERROR, "MMCCardSetBusWidth:SWITCH Card Status:0x%x\n", *(UINT32*)&(CardData->CardStatus))); - Status = SDHostIo->SetBusWidth (SDHostIo, BusWidth); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SWITCH set %d bits Fail\n", BusWidth)); - goto Exit; - } - gBS->Stall (5 * 1000); - } - } - - if (!EnableDDRMode) { // CMD19 and CMD14 are illegal commands in ddr mode - //if (EFI_ERROR (Status)) { - // DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest: Fail to enable high speed mode\n")); - // goto Exit; - //} - - Status = MMCCardBusWidthTest (CardData, BusWidth); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest %d bit Fail\n", BusWidth)); - goto Exit; - } - } - - CardData->CurrentBusWidth = BusWidth; - -Exit: - return Status; -} - - -/** - MMC/SD card init function - - @param CardData Pointer to CARD_DATA. - - @return EFI_SUCCESS - @return others - -**/ -EFI_STATUS -MMCSDCardInit ( - IN CARD_DATA *CardData - ) -{ - EFI_STATUS Status; - EFI_SD_HOST_IO_PROTOCOL *SDHostIo; - SWITCH_ARGUMENT SwitchArgument; - UINT32 Data; - UINT32 Argument; - UINT32 nIndex; - UINT8 PowerValue; - BOOLEAN EnableDDRMode; - - ASSERT(CardData != NULL); - SDHostIo = CardData->SDHostIo; - EnableDDRMode = FALSE; - - CardData->CardType = UnknownCard; - Status = GetCardType (CardData); - if (EFI_ERROR (Status)) { - goto Exit; - } - DEBUG((DEBUG_INFO, "CardData->CardType 0x%x\n", CardData->CardType)); - - ASSERT (CardData->CardType != UnknownCard); - // - //MMC, SD card need host auto stop command support - // - SDHostIo->EnableAutoStopCmd (SDHostIo, TRUE); - - if (CardData->CardType == MMCCard) { - Status = MMCCardVoltageSelection (CardData); - if (EFI_ERROR(Status)) { - goto Exit; - } - } - - // - // Get CID Register - // - Status = SendCommand ( - CardData, - ALL_SEND_CID, - 0, - NoData, - NULL, - 0, - ResponseR2, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CIDRegister) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "ALL_SEND_CID Fail Status = 0x%x\n", Status)); - goto Exit; - } else { - // Dump out the Card ID data - DEBUG((EFI_D_INFO, "Product Name: ")); - for ( nIndex=0; nIndex<6; nIndex++ ) { - DEBUG((EFI_D_INFO, "%c", CardData->CIDRegister.PNM[nIndex])); - } - DEBUG((EFI_D_INFO, "\nApplication ID : %d\n", CardData->CIDRegister.OID)); - DEBUG((EFI_D_INFO, "Manufacturer ID: %d\n", CardData->CIDRegister.MID)); - DEBUG((EFI_D_INFO, "Revision ID : %d\n", CardData->CIDRegister.PRV)); - DEBUG((EFI_D_INFO, "Serial Number : %d\n", CardData->CIDRegister.PSN)); - } - - // - //SET_RELATIVE_ADDR - // - if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) { - // - //Hard code the RCA address - // - CardData->Address = 1; - - // - // Set RCA Register - // - Status = SendCommand ( - CardData, - SET_RELATIVE_ADDR, - (CardData->Address << 16), - NoData, - NULL, - 0, - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status)); - goto Exit; - } - } else { - Data = 0; - Status = SendCommand ( - CardData, - SET_RELATIVE_ADDR, - 0, - NoData, - NULL, - 0, - ResponseR6, - TIMEOUT_COMMAND, - &Data - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status)); - goto Exit; - } - - CardData->Address = (UINT16)(Data >> 16); - *(UINT32*)&CardData->CardStatus = Data & 0x1FFF; - CardData->CardStatus.ERROR = (Data >> 13) & 0x1; - CardData->CardStatus.ILLEGAL_COMMAND = (Data >> 14) & 0x1; - CardData->CardStatus.COM_CRC_ERROR = (Data >> 15) & 0x1; - Status = CheckCardStatus (*(UINT32*)&CardData->CardStatus); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status)); - goto Exit; - } - } - - // - // Get CSD Register - // - Status = SendCommand ( - CardData, - SEND_CSD, - (CardData->Address << 16), - NoData, - NULL, - 0, - ResponseR2, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CSDRegister) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SEND_CSD Fail Status = 0x%x\n", Status)); - goto Exit; - } - - DEBUG((EFI_D_INFO, "CardData->CSDRegister.SPEC_VERS = 0x%x\n", CardData->CSDRegister.SPEC_VERS)); - DEBUG((EFI_D_INFO, "CardData->CSDRegister.CSD_STRUCTURE = 0x%x\n", CardData->CSDRegister.CSD_STRUCTURE)); - - Status = CaculateCardParameter (CardData); - if (EFI_ERROR (Status)) { - goto Exit; - } - - - // - // It is platform and hardware specific, need hadrware engineer input - // - if (CardData->CSDRegister.DSR_IMP == 1) { - // - // Default is 0x404 - // - Status = SendCommand ( - CardData, - SET_DSR, - (DEFAULT_DSR_VALUE << 16), - NoData, - NULL, - 0, - ResponseNo, - TIMEOUT_COMMAND, - NULL - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SET_DSR Fail Status = 0x%x\n", Status)); - // - // Assume can operate even fail - // - } - } - // - //Change clock frequency from 400KHz to max supported when not in high speed mode - // - Status = SDHostIo->SetClockFrequency (SDHostIo, CardData->MaxFrequency); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "MMCSDCardInit:Fail to SetClockFrequency \n")); - goto Exit; - } - - // - //Put the card into tran state - // - Status = SendCommand ( - CardData, - SELECT_DESELECT_CARD, - (CardData->Address << 16), - NoData, - NULL, - 0, - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SELECT_DESELECT_CARD Fail Status = 0x%x\n", Status)); - goto Exit; - } - - // - // No spec requirment, can be adjusted - // - gBS->Stall (5 * 1000); - // - // No need to do so - // - // - Status = SendCommand ( - CardData, - SEND_STATUS, - (CardData->Address << 16), - NoData, - NULL, - 0, - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SELECT_DESELECT_CARD SEND_STATUS Fail Status = 0x%x\n", Status)); - goto Exit; - } - // - //if the SPEC_VERS indicates a version 4.0 or higher - //The card is a high speed card and support Switch - //and Send_ext_csd command - //otherwise it is an old card - // - - if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) { - // - //Only V4.0 and above supports more than 1 bits and high speed - // - if (CardData->CSDRegister.SPEC_VERS >= 4) { - // - //Get ExtCSDRegister - // - Status = SendCommand ( - CardData, - SEND_EXT_CSD, - 0x0, - InData, - CardData->AlignedBuffer, - sizeof (EXT_CSD), - ResponseR1, - TIMEOUT_DATA, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SEND_EXT_CSD Fail Status = 0x%x\n", Status)); - goto Exit; - } - - CopyMem (&(CardData->ExtCSDRegister), CardData->AlignedBuffer, sizeof (EXT_CSD)); - - // - // Recaculate the block number for >2G MMC card - // - Data = (CardData->ExtCSDRegister.SEC_COUNT[0]) | - (CardData->ExtCSDRegister.SEC_COUNT[1] << 8) | - (CardData->ExtCSDRegister.SEC_COUNT[2] << 16) | - (CardData->ExtCSDRegister.SEC_COUNT[3] << 24); - - if (Data != 0) { - CardData->BlockNumber = Data; - } - DEBUG((DEBUG_INFO, "CardData->BlockNumber %d\n", Data)); - DEBUG((EFI_D_ERROR, "CardData->ExtCSDRegister.CARD_TYPE -> %d\n", (UINTN)CardData->ExtCSDRegister.CARD_TYPE)); - if ((CardData->ExtCSDRegister.CARD_TYPE & BIT2)|| - (CardData->ExtCSDRegister.CARD_TYPE & BIT3)) { - //DEBUG((DEBUG_INFO, "To enable DDR mode\n")); - //EnableDDRMode = TRUE; - } - // - // Check current chipset capability and the plugged-in card - // whether supports HighSpeed - // - if (SDHostIo->HostCapability.HighSpeedSupport) { - - // - //Change card timing to high speed interface timing - // - ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT)); - SwitchArgument.CmdSet = 0; - SwitchArgument.Value = 1; - SwitchArgument.Index = (UINT32)((UINTN) - (&(CardData->ExtCSDRegister.HS_TIMING)) - (UINTN)(&(CardData->ExtCSDRegister))); - SwitchArgument.Access = WriteByte_Mode; - Status = SendCommand ( - CardData, - SWITCH, - *(UINT32*)&SwitchArgument, - NoData, - NULL, - 0, - ResponseR1b, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "MMCSDCardInit:SWITCH frequency Fail Status = 0x%x\n", Status)); - } - - gBS->Stall (5 * 1000); - - - if (!EFI_ERROR (Status)) { - Status = SendCommand ( - CardData, - SEND_STATUS, - (CardData->Address << 16), - NoData, - NULL, - 0, - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (!EFI_ERROR (Status)) { - if (EnableDDRMode) { - DEBUG((EFI_D_ERROR, "Enable ddr mode on host controller\n")); - SDHostIo->SetDDRMode (SDHostIo, TRUE); - } else { - DEBUG((EFI_D_ERROR, "Enable high speed mode on host controller\n")); - SDHostIo->SetHighSpeedMode (SDHostIo, TRUE); - } - // - // Change host clock to support high speed and enable chispet to - // support speed - // - if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) { - Status = SDHostIo->SetClockFrequency (SDHostIo, FREQUENCY_MMC_PP_HIGH); - } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) { - Status = SDHostIo->SetClockFrequency (SDHostIo, FREQUENCY_MMC_PP); - } else { - Status = EFI_UNSUPPORTED; - } - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "MMCSDCardInit:Fail to SetClockFrequency \n")); - goto Exit; - } - // - // It seems no need to stall after changing bus freqeuncy. - // It is said that the freqeuncy can be changed at any time. Just appends 8 clocks after command. - // But SetClock alreay has delay. - // - } - } - - } - - - - // - // Prefer wide bus width for performance - // - // - // Set to BusWidth bits mode, only version 4.0 or above support more than 1 bits - // - if (SDHostIo->HostCapability.BusWidth8 == TRUE) { - Status = MMCCardSetBusWidth (CardData, 8, EnableDDRMode); - if (EFI_ERROR (Status)) { - // - // CE-ATA may support 8 bits and 4 bits, but has no software method for detection - // - Status = MMCCardSetBusWidth (CardData, 4, EnableDDRMode); - if (EFI_ERROR (Status)) { - goto Exit; - } - } - } else if (SDHostIo->HostCapability.BusWidth4 == TRUE) { - Status = MMCCardSetBusWidth (CardData, 4, EnableDDRMode); - if (EFI_ERROR (Status)) { - goto Exit; - } - } - - PowerValue = 0; - - if (CardData->CurrentBusWidth == 8) { - if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) { - PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360; - PowerValue = PowerValue >> 4; - } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) { - PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360; - PowerValue = PowerValue >> 4; - } - } else if (CardData->CurrentBusWidth == 4) { - if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) { - PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360; - PowerValue = PowerValue & 0xF; - } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) { - PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360; - PowerValue = PowerValue & 0xF; - } - } - - if (PowerValue != 0) { - // - //Update Power Class - // - ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT)); - SwitchArgument.CmdSet = 0; - SwitchArgument.Value = PowerValue; - SwitchArgument.Index = (UINT32)((UINTN) - (&(CardData->ExtCSDRegister.POWER_CLASS)) - (UINTN)(&(CardData->ExtCSDRegister))); - SwitchArgument.Access = WriteByte_Mode; - Status = SendCommand ( - CardData, - SWITCH, - *(UINT32*)&SwitchArgument, - NoData, - NULL, - 0, - ResponseR1b, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (!EFI_ERROR (Status)) { - Status = SendCommand ( - CardData, - SEND_STATUS, - (CardData->Address << 16), - NoData, - NULL, - 0, - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SWITCH Power Class Fail Status = 0x%x\n", Status)); - } - //gBS->Stall (10 * 1000); - } - } - - - - } else { - - - DEBUG((EFI_D_ERROR, "MMC Card version %d only supportes 1 bits at lower transfer speed\n",CardData->CSDRegister.SPEC_VERS)); - } - } else { - // - // Pin 1, at power up this line has a 50KOhm pull up enabled in the card. - // This pull-up should be disconnected by the user, during regular data transfer, - // with SET_CLR_CARD_DETECT (ACMD42) command - // - Status = SendAppCommand ( - CardData, - SET_CLR_CARD_DETECT, - 0, - NoData, - NULL, - 0, - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SET_CLR_CARD_DETECT Fail Status = 0x%x\n", Status)); - goto Exit; - } - - /* - // - // Don't rely on SCR and SD status, some cards have unexpected SCR. - // It only sets private section, the other bits are 0 - // such as Sandisk Ultra II 4.0G, KinSton mini SD 128M, Toshiba 2.0GB - // Some card even fail this command, KinSton SD 4GB - // - Status = SendAppCommand ( - CardData, - SEND_SCR, - 0, - InData, - (UINT8*)&(CardData->SCRRegister), - sizeof(SCR), - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - goto Exit; - } - - // - // SD memory card at least supports 1 and 4 bits. - // - // ASSERT ((CardData->SCRRegister.SD_BUS_WIDTH & (BIT0 | BIT2)) == (BIT0 | BIT2)); - */ - - // - // Set Bus Width to 4 - // - Status = SendAppCommand ( - CardData, - SET_BUS_WIDTH, - SD_BUS_WIDTH_4, - NoData, - NULL, - 0, - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SET_BUS_WIDTH 4 bits Fail Status = 0x%x\n", Status)); - goto Exit; - } - - Status = SDHostIo->SetBusWidth (SDHostIo, 4); - if (EFI_ERROR (Status)) { - goto Exit; - } - CardData->CurrentBusWidth = 4; - - - if ((SDHostIo->HostCapability.HighSpeedSupport == FALSE) || - ((CardData->CSDRegister.CCC & BIT10) != BIT10)) { - // - // Host must support high speed - // Card must support Switch function - // - goto Exit; - } - - // - //Mode = 0, group 1, function 1, check operation - // - Argument = 0xFFFF01; - ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS)); - - Status = SendCommand ( - CardData, - SWITCH_FUNC, - Argument, - InData, - CardData->AlignedBuffer, - sizeof (SWITCH_STATUS), - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - goto Exit; - } - CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS)); - - if ((CardData->SwitchStatus.DataStructureVersion == 0x0) || - ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) { - // - // 1. SD 1.1 card does not suppport busy bit - // 2. Ready state - // - // - - // - //Mode = 1, group 1, function 1, BIT31 set means set mode - // - Argument = 0xFFFF01 | BIT31; - ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS)); - - Status = SendCommand ( - CardData, - SWITCH_FUNC, - Argument, - InData, - CardData->AlignedBuffer, - sizeof (SWITCH_STATUS), - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - goto Exit; - } - CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS)); - - if ((CardData->SwitchStatus.DataStructureVersion == 0x0) || - ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) { - // - // 1. SD 1.1 card does not suppport busy bit - // 2. Ready state - // - - // - // 8 clocks, (1/ 25M) * 8 ==> 320 us, so 1ms > 0.32 ms - // - gBS->Stall (1000); - - // - //Change host clock - // - Status = SDHostIo->SetClockFrequency (SDHostIo, FREQUENCY_SD_PP_HIGH); - if (EFI_ERROR (Status)) { - goto Exit; - } - - } - } - } - if (!((CardData->ExtCSDRegister.CARD_TYPE & BIT2) || - (CardData->ExtCSDRegister.CARD_TYPE & BIT3))) { - - // - // Set Block Length, to improve compatibility in case of some cards - // - Status = SendCommand ( - CardData, - SET_BLOCKLEN, - 512, - NoData, - NULL, - 0, - ResponseR1, - TIMEOUT_COMMAND, - (UINT32*)&(CardData->CardStatus) - ); - if (EFI_ERROR (Status)) { - DEBUG((EFI_D_ERROR, "SET_BLOCKLEN Fail Status = 0x%x\n", Status)); - goto Exit; - } - } - SDHostIo->SetBlockLength (SDHostIo, 512); - - -Exit: - return Status; -} -