MdeModulePkg/SdMmcPciHcDxe: Using PIO rather than DMA for clock tuning

The original code is using ADMA mode to do clock tuning procedure. It
may have problem on some SD/MMC host controllers as there is no way to
know when to send next tuning cmd.

Update it to PIO mode to strictly follow SD Host Controller Simplified
Specification 3.0 Figure 2-29. By this way, if the Buffer Read Ready
interrupt is set, we could know it's ok to send the next clock tuning
cmd.

Cc: Wu, Hao A <hao.a.wu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Feng Tian <feng.tian@intel.com>
This commit is contained in:
Feng Tian 2016-04-29 16:02:50 +08:00
parent cb9cb9e2aa
commit e7e89b0861
3 changed files with 167 additions and 101 deletions

View File

@ -1265,6 +1265,16 @@ SdMmcCreateTrb (
goto Error; goto Error;
} }
if (Trb->DataLen < Trb->BlockSize) {
Trb->BlockSize = (UINT16)Trb->DataLen;
}
if (((Private->Slot[Trb->Slot].CardType == EmmcCardType) &&
(Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||
((Private->Slot[Trb->Slot].CardType == SdCardType) &&
(Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {
Trb->Mode = SdMmcPioMode;
} else {
if (Trb->Read) { if (Trb->Read) {
Flag = EfiPciIoOperationBusMasterWrite; Flag = EfiPciIoOperationBusMasterWrite;
} else { } else {
@ -1288,12 +1298,6 @@ SdMmcCreateTrb (
} }
} }
if ((Trb->DataLen % Trb->BlockSize) != 0) {
if (Trb->DataLen < Trb->BlockSize) {
Trb->BlockSize = (UINT16)Trb->DataLen;
}
}
if (Trb->DataLen == 0) { if (Trb->DataLen == 0) {
Trb->Mode = SdMmcNoData; Trb->Mode = SdMmcNoData;
} else if (Private->Capability[Slot].Adma2 != 0) { } else if (Private->Capability[Slot].Adma2 != 0) {
@ -1308,6 +1312,7 @@ SdMmcCreateTrb (
} else { } else {
Trb->Mode = SdMmcPioMode; Trb->Mode = SdMmcPioMode;
} }
}
if (Event != NULL) { if (Event != NULL) {
OldTpl = gBS->RaiseTPL (TPL_CALLBACK); OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
@ -1392,15 +1397,6 @@ SdMmcCheckTrbEnv (
// the Present State register to be 0 // the Present State register to be 0
// //
PresentState = BIT0 | BIT1; PresentState = BIT0 | BIT1;
//
// For Send Tuning Block cmd, just wait for Command Inhibit (CMD) to be 0
//
if (((Private->Slot[Trb->Slot].CardType == EmmcCardType) &&
(Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||
((Private->Slot[Trb->Slot].CardType == SdCardType) &&
(Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {
PresentState = BIT0;
}
} else { } else {
// //
// Wait Command Inhibit (CMD) in the Present State register // Wait Command Inhibit (CMD) in the Present State register
@ -1565,7 +1561,13 @@ SdMmcExecTrb (
return Status; return Status;
} }
BlkCount = 0;
if (Trb->Mode != SdMmcNoData) {
//
// Calcuate Block Count.
//
BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize); BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
}
Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount); Status = SdMmcHcRwMmio (PciIo, Trb->Slot, SD_MMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
@ -1585,7 +1587,7 @@ SdMmcExecTrb (
if (Trb->Read) { if (Trb->Read) {
TransMode |= BIT4; TransMode |= BIT4;
} }
if (BlkCount != 0) { if (BlkCount > 1) {
TransMode |= BIT5 | BIT1; TransMode |= BIT5 | BIT1;
} }
// //
@ -1665,6 +1667,7 @@ SdMmcCheckTrbResult (
UINT32 SdmaAddr; UINT32 SdmaAddr;
UINT8 Index; UINT8 Index;
UINT8 SwReset; UINT8 SwReset;
UINT32 PioLength;
SwReset = 0; SwReset = 0;
Packet = Trb->Packet; Packet = Trb->Packet;
@ -1814,13 +1817,26 @@ SdMmcCheckTrbResult (
((Private->Slot[Trb->Slot].CardType == SdCardType) && ((Private->Slot[Trb->Slot].CardType == SdCardType) &&
(Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) { (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {
// //
// While performing tuning procedure (Execute Tuning is set to 1), // When performing tuning procedure (Execute Tuning is set to 1) through PIO mode,
// Transfer Completeis not set to 1 // wait Buffer Read Ready bit of Normal Interrupt Status Register to be 1.
// Refer to SD Host Controller Simplified Specification 3.0 table 2-23 for details. // 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; Status = EFI_SUCCESS;
goto Done; goto Done;
} }
}
Status = EFI_NOT_READY; Status = EFI_NOT_READY;
Done: Done:

View File

@ -1032,12 +1032,13 @@ EmmcPeimCreateTrb (
goto Error; goto Error;
} }
if ((Trb->DataLen % Trb->BlockSize) != 0) {
if (Trb->DataLen < Trb->BlockSize) { if (Trb->DataLen < Trb->BlockSize) {
Trb->BlockSize = (UINT16)Trb->DataLen; Trb->BlockSize = (UINT16)Trb->DataLen;
} }
}
if (Packet->EmmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK) {
Trb->Mode = EmmcPioMode;
} else {
if (Trb->DataLen == 0) { if (Trb->DataLen == 0) {
Trb->Mode = EmmcNoData; Trb->Mode = EmmcNoData;
} else if (Capability.Adma2 != 0) { } else if (Capability.Adma2 != 0) {
@ -1051,7 +1052,7 @@ EmmcPeimCreateTrb (
} else { } else {
Trb->Mode = EmmcPioMode; Trb->Mode = EmmcPioMode;
} }
}
return Trb; return Trb;
Error: Error:
@ -1111,9 +1112,6 @@ EmmcPeimCheckTrbEnv (
// the Present State register to be 0 // the Present State register to be 0
// //
PresentState = BIT0 | BIT1; PresentState = BIT0 | BIT1;
if (Packet->EmmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK) {
PresentState = BIT0;
}
} else { } else {
// //
// Wait Command Inhibit (CMD) in the Present State register // Wait Command Inhibit (CMD) in the Present State register
@ -1273,7 +1271,14 @@ EmmcPeimExecTrb (
return Status; return Status;
} }
BlkCount = 0;
if (Trb->Mode != EmmcNoData) {
//
// Calcuate Block Count.
//
BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize); BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
}
Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount); Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
@ -1293,7 +1298,7 @@ EmmcPeimExecTrb (
if (Trb->Read) { if (Trb->Read) {
TransMode |= BIT4; TransMode |= BIT4;
} }
if (BlkCount != 0) { if (BlkCount > 1) {
TransMode |= BIT5 | BIT1; TransMode |= BIT5 | BIT1;
} }
} }
@ -1365,6 +1370,7 @@ EmmcPeimCheckTrbResult (
UINT32 SdmaAddr; UINT32 SdmaAddr;
UINT8 Index; UINT8 Index;
UINT8 SwReset; UINT8 SwReset;
UINT32 PioLength;
SwReset = 0; SwReset = 0;
Packet = Trb->Packet; Packet = Trb->Packet;
@ -1497,9 +1503,27 @@ EmmcPeimCheckTrbResult (
} }
if (Packet->EmmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK) { if (Packet->EmmcCmdBlk->CommandIndex == EMMC_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;
EmmcPeimHcRwMmio (Bar + EMMC_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);
//
// Read data out from Buffer Port register
//
for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) {
EmmcPeimHcRwMmio (Bar + EMMC_HC_BUF_DAT_PORT, TRUE, 4, (UINT8*)Trb->Data + PioLength);
}
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
goto Done; goto Done;
} }
}
Status = EFI_NOT_READY; Status = EFI_NOT_READY;
Done: Done:

View File

@ -1032,12 +1032,13 @@ SdPeimCreateTrb (
goto Error; goto Error;
} }
if ((Trb->DataLen % Trb->BlockSize) != 0) {
if (Trb->DataLen < Trb->BlockSize) { if (Trb->DataLen < Trb->BlockSize) {
Trb->BlockSize = (UINT16)Trb->DataLen; Trb->BlockSize = (UINT16)Trb->DataLen;
} }
}
if (Packet->SdCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK) {
Trb->Mode = SdPioMode;
} else {
if (Trb->DataLen == 0) { if (Trb->DataLen == 0) {
Trb->Mode = SdNoData; Trb->Mode = SdNoData;
} else if (Capability.Adma2 != 0) { } else if (Capability.Adma2 != 0) {
@ -1051,7 +1052,7 @@ SdPeimCreateTrb (
} else { } else {
Trb->Mode = SdPioMode; Trb->Mode = SdPioMode;
} }
}
return Trb; return Trb;
Error: Error:
@ -1111,9 +1112,6 @@ SdPeimCheckTrbEnv (
// the Present State register to be 0 // the Present State register to be 0
// //
PresentState = BIT0 | BIT1; PresentState = BIT0 | BIT1;
if (Packet->SdCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK) {
PresentState = BIT0;
}
} else { } else {
// //
// Wait Command Inhibit (CMD) in the Present State register // Wait Command Inhibit (CMD) in the Present State register
@ -1273,7 +1271,13 @@ SdPeimExecTrb (
return Status; return Status;
} }
BlkCount = 0;
if (Trb->Mode != SdNoData) {
//
// Calcuate Block Count.
//
BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize); BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);
}
Status = SdPeimHcRwMmio (Bar + SD_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount); Status = SdPeimHcRwMmio (Bar + SD_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
@ -1293,9 +1297,12 @@ SdPeimExecTrb (
if (Trb->Read) { if (Trb->Read) {
TransMode |= BIT4; TransMode |= BIT4;
} }
if (BlkCount != 0) { if (BlkCount > 1) {
TransMode |= BIT5 | BIT1; TransMode |= BIT5 | BIT1;
} }
//
// SD memory card needs to use AUTO CMD12 feature.
//
if (BlkCount > 1) { if (BlkCount > 1) {
TransMode |= BIT2; TransMode |= BIT2;
} }
@ -1368,6 +1375,7 @@ SdPeimCheckTrbResult (
UINT32 SdmaAddr; UINT32 SdmaAddr;
UINT8 Index; UINT8 Index;
UINT8 SwReset; UINT8 SwReset;
UINT32 PioLength;
SwReset = 0; SwReset = 0;
Packet = Trb->Packet; Packet = Trb->Packet;
@ -1500,9 +1508,27 @@ SdPeimCheckTrbResult (
} }
if (Packet->SdCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK) { if (Packet->SdCmdBlk->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;
SdPeimHcRwMmio (Bar + SD_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);
//
// Read data out from Buffer Port register
//
for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) {
SdPeimHcRwMmio (Bar + SD_HC_BUF_DAT_PORT, TRUE, 4, (UINT8*)Trb->Data + PioLength);
}
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
goto Done; goto Done;
} }
}
Status = EFI_NOT_READY; Status = EFI_NOT_READY;
Done: Done: