From: Albecki, Mateusz Date: Thu, 27 Feb 2020 17:25:26 +0000 (+0800) Subject: MdeModulePkg/SdMmcPciHcDxe: Fix PIO transfer mode X-Git-Tag: edk2-stable202005~355 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=9bfaa3da1ee553ee40f584e47aa6418d7d83460d MdeModulePkg/SdMmcPciHcDxe: Fix PIO transfer mode Current driver does not support PIO transfer mode for commands other then tuning. This change adds the code to transfer PIO data. Cc: Hao A Wu Cc: Marcin Wojtas Cc: Zhichao Gao Cc: Liming Gao Signed-off-by: Mateusz Albecki Tested-by: Hao A Wu Reviewed-by: Hao A Wu --- diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h index c092d50422..40e4373e57 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h @@ -158,6 +158,9 @@ typedef struct { UINT64 Timeout; UINT32 Retries; + BOOLEAN PioModeTransferCompleted; + UINT32 PioBlockIndex; + SD_MMC_HC_ADMA_32_DESC_LINE *Adma32Desc; SD_MMC_HC_ADMA_64_V3_DESC_LINE *Adma64V3Desc; SD_MMC_HC_ADMA_64_V4_DESC_LINE *Adma64V4Desc; diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c index 6e419e0d98..6548ef71de 100644 --- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c +++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c @@ -1715,6 +1715,8 @@ SdMmcPrintTrb ( DEBUG ((DebugLevel, "CommandComplete: %d\n", Trb->CommandComplete)); DEBUG ((DebugLevel, "Timeout: %ld\n", Trb->Timeout)); DEBUG ((DebugLevel, "Retries: %d\n", Trb->Retries)); + DEBUG ((DebugLevel, "PioModeTransferCompleted: %d\n", Trb->PioModeTransferCompleted)); + DEBUG ((DebugLevel, "PioBlockIndex: %d\n", Trb->PioBlockIndex)); DEBUG ((DebugLevel, "Adma32Desc: %p\n", Trb->Adma32Desc)); DEBUG ((DebugLevel, "Adma64V3Desc: %p\n", Trb->Adma64V3Desc)); DEBUG ((DebugLevel, "Adma64V4Desc: %p\n", Trb->Adma64V4Desc)); @@ -1819,6 +1821,8 @@ SdMmcCreateTrb ( Trb->CommandComplete = FALSE; Trb->Timeout = Packet->Timeout; Trb->Retries = SD_MMC_TRB_RETRIES; + Trb->PioModeTransferCompleted = FALSE; + Trb->PioBlockIndex = 0; Trb->Private = Private; if ((Packet->InTransferLength != 0) && (Packet->InDataBuffer != NULL)) { @@ -2481,6 +2485,104 @@ SdMmcCheckCommandComplete ( return EFI_NOT_READY; } +/** + Transfers data from card using PIO method. + + @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance. + @param[in] Trb The pointer to the SD_MMC_HC_TRB instance. + @param[in] IntStatus Snapshot of the normal interrupt status register. + + @retval EFI_SUCCESS PIO transfer completed successfully. + @retval EFI_NOT_READY PIO transfer completion still pending. + @retval Others PIO transfer failed to complete. +**/ +EFI_STATUS +SdMmcTransferDataWithPio ( + IN SD_MMC_HC_PRIVATE_DATA *Private, + IN SD_MMC_HC_TRB *Trb, + IN UINT16 IntStatus + ) +{ + EFI_STATUS Status; + UINT16 Data16; + UINT32 BlockCount; + EFI_PCI_IO_PROTOCOL_WIDTH Width; + UINTN Count; + + BlockCount = (Trb->DataLen / Trb->BlockSize); + if (Trb->DataLen % Trb->BlockSize != 0) { + BlockCount += 1; + } + + if (Trb->PioBlockIndex >= BlockCount) { + return EFI_SUCCESS; + } + + switch (Trb->BlockSize % sizeof (UINT32)) { + case 0: + Width = EfiPciIoWidthFifoUint32; + Count = Trb->BlockSize / sizeof (UINT32); + break; + case 2: + Width = EfiPciIoWidthFifoUint16; + Count = Trb->BlockSize / sizeof (UINT16); + break; + case 1: + case 3: + default: + Width = EfiPciIoWidthFifoUint8; + Count = Trb->BlockSize; + break; + } + + if (Trb->Read) { + if ((IntStatus & BIT5) == 0) { + return EFI_NOT_READY; + } + Data16 = BIT5; + SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (Data16), &Data16); + + Status = Private->PciIo->Mem.Read ( + Private->PciIo, + Width, + Trb->Slot, + SD_MMC_HC_BUF_DAT_PORT, + Count, + (VOID*)((UINT8*)Trb->Data + (Trb->BlockSize * Trb->PioBlockIndex)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + Trb->PioBlockIndex++; + } else { + if ((IntStatus & BIT4) == 0) { + return EFI_NOT_READY; + } + Data16 = BIT4; + SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (Data16), &Data16); + + Status = Private->PciIo->Mem.Write ( + Private->PciIo, + Width, + Trb->Slot, + SD_MMC_HC_BUF_DAT_PORT, + Count, + (VOID*)((UINT8*)Trb->Data + (Trb->BlockSize * Trb->PioBlockIndex)) + ); + if (EFI_ERROR (Status)) { + return Status; + } + Trb->PioBlockIndex++; + } + + if (Trb->PioBlockIndex >= BlockCount) { + Trb->PioModeTransferCompleted = TRUE; + return EFI_SUCCESS; + } else { + return EFI_NOT_READY; + } +} + /** Update the SDMA address on the SDMA buffer boundary interrupt. @@ -2565,6 +2667,13 @@ SdMmcCheckDataTransfer ( return Status; } + if (Trb->Mode == SdMmcPioMode && !Trb->PioModeTransferCompleted) { + Status = SdMmcTransferDataWithPio (Private, Trb, IntStatus); + if (EFI_ERROR (Status)) { + return Status; + } + } + if ((Trb->Mode == SdMmcSdmaMode) && ((IntStatus & BIT3) != 0)) { Data16 = BIT3; Status = SdMmcHcRwMmio ( @@ -2607,7 +2716,6 @@ SdMmcCheckTrbResult ( EFI_STATUS Status; EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet; UINT16 IntStatus; - UINT32 PioLength; Packet = Trb->Packet; // @@ -2643,26 +2751,8 @@ SdMmcCheckTrbResult ( (Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) || ((Private->Slot[Trb->Slot].CardType == SdCardType) && (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) { - // - // When performing tuning procedure (Execute Tuning is set to 1) through PIO mode, - // wait Buffer Read Ready bit of Normal Interrupt Status Register to be 1. - // Refer to SD Host Controller Simplified Specification 3.0 figure 2-29 for details. - // - if ((IntStatus & BIT5) == BIT5) { - // - // Clear Buffer Read Ready interrupt at first. - // - IntStatus = BIT5; - SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus); - // - // Read data out from Buffer Port register - // - for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) { - SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_BUF_DAT_PORT, TRUE, 4, (UINT8*)Trb->Data + PioLength); - } - Status = EFI_SUCCESS; - goto Done; - } + Status = SdMmcTransferDataWithPio (Private, Trb, IntStatus); + goto Done; } if (!Trb->CommandComplete) {