diff options
author | oliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-03-31 11:20:15 +0000 |
---|---|---|
committer | oliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-03-31 11:20:15 +0000 |
commit | 2ed2ed29c27dc488dcfa602059847a168941e593 (patch) | |
tree | 535f357527b7c242dbe3c4bcf044a42bd2ddd435 /ArmPkg | |
parent | a1ab9143e26e94112cb7b4fe280b2c6db1cb81ac (diff) | |
download | edk2-platforms-2ed2ed29c27dc488dcfa602059847a168941e593.tar.xz |
ArmPkg/PL180MciDxe: Improve error handling
Get more error handling using PL180 status registers.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11466 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ArmPkg')
-rw-r--r-- | ArmPkg/Drivers/PL180MciDxe/PL180Mci.c | 720 | ||||
-rw-r--r-- | ArmPkg/Drivers/PL180MciDxe/PL180Mci.h | 4 |
2 files changed, 435 insertions, 289 deletions
diff --git a/ArmPkg/Drivers/PL180MciDxe/PL180Mci.c b/ArmPkg/Drivers/PL180MciDxe/PL180Mci.c index fe6c904ff3..250ea8b54d 100644 --- a/ArmPkg/Drivers/PL180MciDxe/PL180Mci.c +++ b/ArmPkg/Drivers/PL180MciDxe/PL180Mci.c @@ -27,341 +27,485 @@ EFI_MMC_HOST_PROTOCOL *gpMmcHost; #define MMCI0_POW2_BLOCKLEN 9
#define MMCI0_TIMEOUT 1000
-BOOLEAN MciIsPowerOn() {
- return ((MmioRead32(MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);
+BOOLEAN
+MciIsPowerOn (
+ VOID
+ )
+{
+ return ((MmioRead32(MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);
}
-EFI_STATUS MciInitialize() {
- MCI_TRACE("MciInitialize()");
- return EFI_SUCCESS;
+EFI_STATUS
+MciInitialize (
+ VOID
+ )
+{
+ MCI_TRACE("MciInitialize()");
+ return EFI_SUCCESS;
}
-BOOLEAN MciIsCardPresent() {
- return (MmioRead32(FixedPcdGet32(PcdPL180SysMciRegAddress)) & 1);
+BOOLEAN
+MciIsCardPresent (
+ VOID
+ )
+{
+ return (MmioRead32(FixedPcdGet32(PcdPL180SysMciRegAddress)) & 1);
}
-BOOLEAN MciIsReadOnly() {
- return (MmioRead32(FixedPcdGet32(PcdPL180SysMciRegAddress)) & 2);
+BOOLEAN
+MciIsReadOnly (
+ VOID
+ )
+{
+ return (MmioRead32(FixedPcdGet32(PcdPL180SysMciRegAddress)) & 2);
}
// Convert block size to 2^n
-UINT32 GetPow2BlockLen(UINT32 BlockLen) {
- UINTN Loop;
- UINTN Pow2BlockLen;
-
- Loop = 0x8000;
- Pow2BlockLen = 15;
- do {
- Loop = (Loop >> 1) & 0xFFFF;
- Pow2BlockLen--;
- } while (Pow2BlockLen && (!(Loop & BlockLen)));
-
- return Pow2BlockLen;
+STATIC
+UINT32
+GetPow2BlockLen (
+ IN UINT32 BlockLen
+ )
+{
+ UINTN Loop;
+ UINTN Pow2BlockLen;
+
+ Loop = 0x8000;
+ Pow2BlockLen = 15;
+ do {
+ Loop = (Loop >> 1) & 0xFFFF;
+ Pow2BlockLen--;
+ } while (Pow2BlockLen && (!(Loop & BlockLen)));
+
+ return Pow2BlockLen;
}
-VOID MciPrepareDataPath(UINTN TransferDirection) {
- // Set Data Length & Data Timer
- MmioWrite32(MCI_DATA_TIMER_REG,0xFFFFFFF);
- MmioWrite32(MCI_DATA_LENGTH_REG,MMCI0_BLOCKLEN);
+VOID
+MciPrepareDataPath (
+ IN UINTN TransferDirection
+ )
+{
+ // Set Data Length & Data Timer
+ MmioWrite32(MCI_DATA_TIMER_REG,0xFFFFFFF);
+ MmioWrite32(MCI_DATA_LENGTH_REG,MMCI0_BLOCKLEN);
#ifndef USE_STREAM
- //Note: we are using a hardcoded BlockLen (=512). If we decide to use a variable size, we could
- // compute the pow2 of BlockLen with the above function GetPow2BlockLen()
- MmioWrite32(MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | TransferDirection | (MMCI0_POW2_BLOCKLEN << 4));
+ //Note: we are using a hardcoded BlockLen (=512). If we decide to use a variable size, we could
+ // compute the pow2 of BlockLen with the above function GetPow2BlockLen()
+ MmioWrite32(MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_DMA_ENABLE | TransferDirection | (MMCI0_POW2_BLOCKLEN << 4));
#else
- MmioWrite32(MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | TransferDirection | MCI_DATACTL_STREAM_TRANS);
+ MmioWrite32(MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_DMA_ENABLE | TransferDirection | MCI_DATACTL_STREAM_TRANS);
#endif
}
-EFI_STATUS MciSendCommand(MMC_CMD MmcCmd, UINT32 Argument) {
- UINT32 Status;
- UINT32 Timer;
- UINT32 Cmd;
+EFI_STATUS
+MciSendCommand (
+ IN MMC_CMD MmcCmd,
+ IN UINT32 Argument
+ )
+{
+ UINT32 Status;
+ UINT32 Cmd;
+ UINTN RetVal;
+ UINTN CmdCtrlReg;
+
+ RetVal = EFI_SUCCESS;
+
+ if ((MmcCmd == MMC_CMD17) || (MmcCmd == MMC_CMD11)) {
+ MciPrepareDataPath(MCI_DATACTL_CARD_TO_CONT);
+ } else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {
+ MciPrepareDataPath(MCI_DATACTL_CONT_TO_CARD);
+ }
+
+ // Create Command for PL180
+ Cmd = INDX(MmcCmd);
+ if (MmcCmd & MMC_CMD_WAIT_RESPONSE) {
+ Cmd |= MCI_CPSM_WAIT_RESPONSE;
+ }
+
+ if (MmcCmd & MMC_CMD_LONG_RESPONSE) {
+ Cmd |= MCI_CPSM_LONG_RESPONSE;
+ }
- if ((MmcCmd == MMC_CMD17) || (MmcCmd == MMC_CMD11)) {
- MciPrepareDataPath(MCI_DATACTL_CARD_TO_CONT);
- } else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {
- MciPrepareDataPath(MCI_DATACTL_CONT_TO_CARD);
+ // Clear Status register static flags
+ MmioWrite32(MCI_CLEAR_STATUS_REG,0x7FF);
+
+ //Write to command argument register
+ MmioWrite32(MCI_ARGUMENT_REG,Argument);
+
+ //Write to command register
+ MmioWrite32(MCI_COMMAND_REG,Cmd);
+
+ if (Cmd & MCI_CPSM_WAIT_RESPONSE) {
+ Status = MmioRead32(MCI_STATUS_REG);
+ while (!(Status & (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_CMDCRCFAIL | MCI_STATUS_CMD_CMDTIMEOUT | MCI_STATUS_CMD_START_BIT_ERROR))) {
+ Status = MmioRead32(MCI_STATUS_REG);
}
- // Create Command for PL180
- Cmd = INDX(MmcCmd);
- if (MmcCmd & MMC_CMD_WAIT_RESPONSE)
- Cmd |= MCI_CPSM_WAIT_RESPONSE;
- if (MmcCmd & MMC_CMD_LONG_RESPONSE)
- Cmd |= MCI_CPSM_LONG_RESPONSE;
-
- MmioWrite32(MCI_CLEAR_STATUS_REG,0x5FFF);
- MmioWrite32(MCI_ARGUMENT_REG,Argument);
- MmioWrite32(MCI_COMMAND_REG,Cmd);
-
- Timer = 1000;
- if (Cmd & MCI_CPSM_WAIT_RESPONSE) {
- Status = MmioRead32(MCI_STATUS_REG);
- while (!(Status & (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_CMDCRCFAIL | MCI_STATUS_CMD_CMDTIMEOUT)) && Timer) {
- //NanoSecondDelay(10);
- Status = MmioRead32(MCI_STATUS_REG);
- Timer--;
- }
-
- if ((Timer == 0) || (Status == MCI_STATUS_CMD_CMDTIMEOUT)) {
- //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%X\n",Cmd & 0x3F,MmioRead32(MCI_RESPONSE0_REG),Status));
- return EFI_TIMEOUT;
- } else if (!((Cmd & 0x3F) == INDX(1)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {
- // The CMD1 does not contain CRC. We should ignore the CRC failed Status.
- return EFI_CRC_ERROR;
- } else {
- return EFI_SUCCESS;
- }
+ if ((Status & MCI_STATUS_CMD_START_BIT_ERROR)) {
+ DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) Start bit Error! Response:0x%X Status:0x%x\n",(Cmd & 0x3F),MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_NO_RESPONSE;
+ goto Exit;
+ } else if ((Status & MCI_STATUS_CMD_CMDTIMEOUT)) {
+ //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%x\n",(Cmd & 0x3F),MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_TIMEOUT;
+ goto Exit;
+ } else if (!((Cmd & 0x3F) == INDX(1)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {
+ // The CMD1 does not contain CRC. We should ignore the CRC failed Status.
+ RetVal = EFI_CRC_ERROR;
+ goto Exit;
} else {
- Status = MmioRead32(MCI_STATUS_REG);
- while (!(Status & MCI_STATUS_CMD_SENT) && Timer) {
- //NanoSecondDelay(10);
- Status = MmioRead32(MCI_STATUS_REG);
- Timer--;
- }
-
- if (Timer == 0) {
- //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT2! 0x%X\n",Cmd & 0x3F,MmioRead32(MCI_RESPONSE0_REG)));
- return EFI_TIMEOUT;
- } else {
- return EFI_SUCCESS;
- }
+ RetVal = EFI_SUCCESS;
+ goto Exit;
}
-}
-
-EFI_STATUS MciReceiveResponse(MMC_RESPONSE_TYPE Type, UINT32* Buffer) {
- if (Buffer == NULL) {
- return EFI_INVALID_PARAMETER;
+ } else {
+ Status = MmioRead32(MCI_STATUS_REG);
+ while (!(Status & (MCI_STATUS_CMD_SENT | MCI_STATUS_CMD_CMDCRCFAIL | MCI_STATUS_CMD_CMDTIMEOUT| MCI_STATUS_CMD_START_BIT_ERROR))) {
+ Status = MmioRead32(MCI_STATUS_REG);
}
- if ((Type == MMC_RESPONSE_TYPE_R1) || (Type == MMC_RESPONSE_TYPE_R1b) ||
- (Type == MMC_RESPONSE_TYPE_R3) || (Type == MMC_RESPONSE_TYPE_R6) ||
- (Type == MMC_RESPONSE_TYPE_R7)) {
- Buffer[0] = MmioRead32(MCI_RESPONSE0_REG);
- Buffer[1] = MmioRead32(MCI_RESPONSE1_REG);
- } else if (Type == MMC_RESPONSE_TYPE_R2) {
- Buffer[0] = MmioRead32(MCI_RESPONSE0_REG);
- Buffer[1] = MmioRead32(MCI_RESPONSE1_REG);
- Buffer[2] = MmioRead32(MCI_RESPONSE2_REG);
- Buffer[3] = MmioRead32(MCI_RESPONSE3_REG);
+ if ((Status & MCI_STATUS_CMD_START_BIT_ERROR)) {
+ DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) Start bit Error! Response:0x%X Status:0x%x\n",(Cmd & 0x3F),MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_NO_RESPONSE;
+ goto Exit;
+ } else if ((Status & MCI_STATUS_CMD_CMDTIMEOUT)) {
+ //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%x\n",(Cmd & 0x3F),MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_TIMEOUT;
+ goto Exit;
+ } else
+ if (!((Cmd & 0x3F) == INDX(1)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {
+ // The CMD1 does not contain CRC. We should ignore the CRC failed Status.
+ RetVal = EFI_CRC_ERROR;
+ goto Exit;
+ } else {
+ RetVal = EFI_SUCCESS;
+ goto Exit;
}
+ }
- return EFI_SUCCESS;
-}
-
-EFI_STATUS MciReadBlockData(EFI_LBA Lba, UINTN Length, UINT32* Buffer) {
- UINTN Loop;
- UINTN Finish;
- UINTN Timer;
- UINTN Status;
-
- // Read data from the RX FIFO
- Loop = 0;
- Finish = MMCI0_BLOCKLEN / 4;
- Timer = MMCI0_TIMEOUT * 10;
- do {
- // Read the Status flags
- Status = MmioRead32(MCI_STATUS_REG);
- // Do eight reads if possible else a single read
- if (Status & MCI_STATUS_CMD_RXFIFOHALFFULL) {
- Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
- Loop++;
- Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
- Loop++;
- Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
- Loop++;
- Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
- Loop++;
- Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
- Loop++;
- Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
- Loop++;
- Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
- Loop++;
- Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
- Loop++;
- }
- else if (!(Status & MCI_STATUS_CMD_RXFIFOEMPTY)) {
- Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
- Loop++;
- } else
- Timer--;
- } while ((Loop < Finish) && Timer);
-
- if (Timer == 0) {
- DEBUG ((EFI_D_ERROR, "MciReadBlockData: Timeout Status:0x%X Loop:%d // Finish:%d\n",MmioRead32(MCI_STATUS_REG),Loop,Finish));
- return EFI_TIMEOUT;
- } else
- return EFI_SUCCESS;
+Exit:
+ //Disable Command Path
+ CmdCtrlReg = MmioRead32(MCI_COMMAND_REG);
+ MmioWrite32(MCI_COMMAND_REG, (CmdCtrlReg & ~MCI_CPSM_ENABLED));
+ return RetVal;
}
-EFI_STATUS MciWriteBlockData(EFI_LBA Lba, UINTN Length, UINT32* Buffer) {
- UINTN Loop;
- UINTN Finish;
- UINTN Timer;
- UINTN Status;
-
- // Write the data to the TX FIFO
- Loop = 0;
- Finish = MMCI0_BLOCKLEN / 4;
- Timer = MMCI0_TIMEOUT * 100;
- do {
- // Read the Status flags
- Status = MmioRead32(MCI_STATUS_REG);
-
- // Do eight writes if possible else a single write
- if (Status & MCI_STATUS_CMD_TXFIFOHALFEMPTY) {
- MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
- Loop++;
- MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
- Loop++;
- MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
- Loop++;
- MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
- Loop++;
- MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
- Loop++;
- MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
- Loop++;
- MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
- Loop++;
- MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
- Loop++;
- }
- else if (!(Status & MCI_STATUS_CMD_TXFIFOFULL)) {
- MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
- Loop++;
- }
- else
- Timer--;
- } while ((Loop < Finish) && Timer);
+EFI_STATUS
+MciReceiveResponse (
+ IN MMC_RESPONSE_TYPE Type,
+ IN UINT32* Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Type == MMC_RESPONSE_TYPE_R1) || (Type == MMC_RESPONSE_TYPE_R1b) ||
+ (Type == MMC_RESPONSE_TYPE_R3) || (Type == MMC_RESPONSE_TYPE_R6) ||
+ (Type == MMC_RESPONSE_TYPE_R7))
+ {
+ Buffer[0] = MmioRead32(MCI_RESPONSE0_REG);
+ Buffer[1] = MmioRead32(MCI_RESPONSE1_REG);
+ } else if (Type == MMC_RESPONSE_TYPE_R2) {
+ Buffer[0] = MmioRead32(MCI_RESPONSE0_REG);
+ Buffer[1] = MmioRead32(MCI_RESPONSE1_REG);
+ Buffer[2] = MmioRead32(MCI_RESPONSE2_REG);
+ Buffer[3] = MmioRead32(MCI_RESPONSE3_REG);
+ }
- ASSERT(Timer > 0);
+ return EFI_SUCCESS;
+}
- // Wait for FIFO to drain
- Timer = MMCI0_TIMEOUT;
+EFI_STATUS
+MciReadBlockData (
+ IN EFI_LBA Lba,
+ IN UINTN Length,
+ IN UINT32* Buffer
+ )
+{
+ UINTN Loop;
+ UINTN Finish;
+ UINTN Status;
+ EFI_STATUS RetVal;
+ UINTN DataCtrlReg;
+
+ RetVal = EFI_SUCCESS;
+
+ // Read data from the RX FIFO
+ Loop = 0;
+ Finish = MMCI0_BLOCKLEN / 4;
+ do {
+ // Read the Status flags
Status = MmioRead32(MCI_STATUS_REG);
-/*#ifndef USE_STREAM
- // Single block
- while (((Status & MCI_STATUS_CMD_TXDONE) != MCI_STATUS_CMD_TXDONE) && Timer) {
-#else*/
- // Stream
- while (((Status & MCI_STATUS_CMD_DATAEND) != MCI_STATUS_CMD_DATAEND) && Timer) {
-//#endif
- NanoSecondDelay(10);
- Status = MmioRead32(MCI_STATUS_REG);
- Timer--;
+
+ // Do eight reads if possible else a single read
+ if (Status & MCI_STATUS_CMD_RXFIFOHALFFULL) {
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ } else if (Status & MCI_STATUS_CMD_RXDATAAVAILBL) {
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ } else {
+ //Check for error conditions and timeouts
+ if(Status & MCI_STATUS_CMD_DATATIMEOUT) {
+ DEBUG ((EFI_D_ERROR, "MciReadBlockData(): TIMEOUT! Response:0x%X Status:0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_TIMEOUT;
+ break;
+ } else if(Status & MCI_STATUS_CMD_DATACRCFAIL) {
+ DEBUG ((EFI_D_ERROR, "MciReadBlockData(): CRC Error! Response:0x%X Status:0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_CRC_ERROR;
+ break;
+ } else if(Status & MCI_STATUS_CMD_START_BIT_ERROR) {
+ DEBUG ((EFI_D_ERROR, "MciReadBlockData(): Start-bit Error! Response:0x%X Status:0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_NO_RESPONSE;
+ break;
+ }
}
+ //clear RX over run flag
+ if(Status & MCI_STATUS_CMD_RXOVERRUN) {
+ MmioWrite32(MCI_CLEAR_STATUS_REG, MCI_STATUS_CMD_RXOVERRUN);
+ }
+ } while ((Loop < Finish));
- ASSERT(Timer > 0);
+ //Clear Status flags
+ MmioWrite32(MCI_CLEAR_STATUS_REG, 0x7FF);
+
+ //Disable Data path
+ DataCtrlReg = MmioRead32(MCI_DATA_CTL_REG);
+ MmioWrite32(MCI_DATA_CTL_REG, (DataCtrlReg & 0xFE));
- if (Timer == 0)
- return EFI_TIMEOUT;
- else
- return EFI_SUCCESS;
+ return RetVal;
}
-EFI_STATUS MciNotifyState(MMC_STATE State) {
- UINT32 Data32;
+EFI_STATUS
+MciWriteBlockData (
+ IN EFI_LBA Lba,
+ IN UINTN Length,
+ IN UINT32* Buffer
+ )
+{
+ UINTN Loop;
+ UINTN Finish;
+ UINTN Timer;
+ UINTN Status;
+ EFI_STATUS RetVal;
+ UINTN DataCtrlReg;
+
+ RetVal = EFI_SUCCESS;
+
+ // Write the data to the TX FIFO
+ Loop = 0;
+ Finish = MMCI0_BLOCKLEN / 4;
+ Timer = MMCI0_TIMEOUT * 100;
+ do {
+ // Read the Status flags
+ Status = MmioRead32(MCI_STATUS_REG);
- switch(State) {
- case MmcInvalidState:
- ASSERT(0);
- break;
- case MmcHwInitializationState:
- // If device already turn on then restart it
- Data32 = MmioRead32(MCI_POWER_CONTROL_REG);
- if ((Data32 & 0x2) == MCI_POWER_UP) {
- MCI_TRACE("MciNotifyState(MmcHwInitializationState): TurnOff MCI");
-
- // Turn off
- MmioWrite32(MCI_CLOCK_CONTROL_REG, 0);
- MmioWrite32(MCI_POWER_CONTROL_REG, 0);
- MicroSecondDelay(100);
- }
-
- MCI_TRACE("MciNotifyState(MmcHwInitializationState): TurnOn MCI");
- // Setup clock
- // - 0x1D = 29 => should be the clock divider to be less than 400kHz at MCLK = 24Mhz
- MmioWrite32(MCI_CLOCK_CONTROL_REG,0x1D | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);
- //MmioWrite32(MCI_CLOCK_CONTROL_REG,0x1D | MCI_CLOCK_ENABLE);
-
- // Set the voltage
- MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_OPENDRAIN | (15<<2));
- MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_UP);
- MicroSecondDelay(10);
- MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_ON);
- MicroSecondDelay(100);
-
- // Set Data Length & Data Timer
- MmioWrite32(MCI_DATA_TIMER_REG,0xFFFFF);
- MmioWrite32(MCI_DATA_LENGTH_REG,8);
-
- ASSERT((MmioRead32(MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);
- break;
- case MmcIdleState:
- MCI_TRACE("MciNotifyState(MmcIdleState)");
- break;
- case MmcReadyState:
- MCI_TRACE("MciNotifyState(MmcReadyState)");
- break;
- case MmcIdentificationState:
- MCI_TRACE("MciNotifyState(MmcIdentificationState)");
- break;
- case MmcStandByState:
- MCI_TRACE("MciNotifyState(MmcStandByState)");
-
- // Enable MCICMD push-pull drive
- MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_ROD | (15<<2) | MCI_POWER_ON);
-
- /*// Set MMCI0 clock to 4MHz (24MHz may be possible with cache enabled)
- MmioWrite32(MCI_CLOCK_CONTROL_REG,0x02 | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);*/
- // Set MMCI0 clock to 24MHz (by bypassing the divider)
- MmioWrite32(MCI_CLOCK_CONTROL_REG,MCI_CLOCK_BYPASS | MCI_CLOCK_ENABLE);
- break;
- case MmcTransferState:
- //MCI_TRACE("MciNotifyState(MmcTransferState)");
- break;
- case MmcSendingDataState:
- MCI_TRACE("MciNotifyState(MmcSendingDataState)");
- break;
- case MmcReceiveDataState:
- MCI_TRACE("MciNotifyState(MmcReceiveDataState)");
- break;
- case MmcProgrammingState:
- MCI_TRACE("MciNotifyState(MmcProgrammingState)");
- break;
- case MmcDisconnectState:
- MCI_TRACE("MciNotifyState(MmcDisconnectState)");
- break;
- default:
+ // Do eight writes if possible else a single write
+ if (Status & MCI_STATUS_CMD_TXFIFOHALFEMPTY) {
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ } else if ((Status & MCI_STATUS_CMD_TXFIFOEMPTY)) {
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ } else {
+ //Check for error conditions and timeouts
+ if(Status & MCI_STATUS_CMD_DATATIMEOUT) {
+ DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): TIMEOUT! Response:0x%X Status:0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_TIMEOUT;
+ goto Exit;
+ } else if(Status & MCI_STATUS_CMD_DATACRCFAIL) {
+ DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): CRC Error! Response:0x%X Status:0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_CRC_ERROR;
+ goto Exit;
+ } else if(Status & MCI_STATUS_CMD_TX_UNDERRUN) {
+ DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): TX buffer Underrun! Response:0x%X Status:0x%x, Number of bytes written 0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status, Loop));
+ RetVal = EFI_BUFFER_TOO_SMALL;
ASSERT(0);
+ goto Exit;
+ }
}
- return EFI_SUCCESS;
+ } while (Loop < Finish);
+
+ // Wait for FIFO to drain
+ Timer = MMCI0_TIMEOUT * 60;
+ Status = MmioRead32(MCI_STATUS_REG);
+#ifndef USE_STREAM
+ // Single block
+ while (((Status & MCI_STATUS_CMD_TXDONE) != MCI_STATUS_CMD_TXDONE) && Timer) {
+#else
+ // Stream
+ while (((Status & MCI_STATUS_CMD_DATAEND) != MCI_STATUS_CMD_DATAEND) && Timer) {
+#endif
+ NanoSecondDelay(10);
+ Status = MmioRead32(MCI_STATUS_REG);
+ Timer--;
+ }
+
+ if(Timer == 0) {
+ DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): Data End timeout Number of bytes written 0x%x\n",Loop));
+ ASSERT(Timer > 0);
+ return EFI_TIMEOUT;
+ }
+
+ //Clear Status flags
+ MmioWrite32(MCI_CLEAR_STATUS_REG, 0x7FF);
+ if (Timer == 0) {
+ RetVal = EFI_TIMEOUT;
+ }
+
+Exit:
+ //Disable Data path
+ DataCtrlReg = MmioRead32(MCI_DATA_CTL_REG);
+ MmioWrite32(MCI_DATA_CTL_REG, (DataCtrlReg & 0xFE));
+ return RetVal;
+}
+
+EFI_STATUS
+MciNotifyState (
+ IN MMC_STATE State
+ )
+{
+ UINT32 Data32;
+
+ switch(State) {
+ case MmcInvalidState:
+ ASSERT(0);
+ break;
+ case MmcHwInitializationState:
+ // If device already turn on then restart it
+ Data32 = MmioRead32(MCI_POWER_CONTROL_REG);
+ if ((Data32 & 0x2) == MCI_POWER_UP) {
+ MCI_TRACE("MciNotifyState(MmcHwInitializationState): TurnOff MCI");
+
+ // Turn off
+ MmioWrite32(MCI_CLOCK_CONTROL_REG, 0);
+ MmioWrite32(MCI_POWER_CONTROL_REG, 0);
+ MicroSecondDelay(100);
+ }
+
+ MCI_TRACE("MciNotifyState(MmcHwInitializationState): TurnOn MCI");
+ // Setup clock
+ // - 0x1D = 29 => should be the clock divider to be less than 400kHz at MCLK = 24Mhz
+ MmioWrite32(MCI_CLOCK_CONTROL_REG,0x1D | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);
+ //MmioWrite32(MCI_CLOCK_CONTROL_REG,0x1D | MCI_CLOCK_ENABLE);
+
+ // Set the voltage
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_OPENDRAIN | (15<<2));
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_UP);
+ MicroSecondDelay(10);
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_ON);
+ MicroSecondDelay(100);
+
+ // Set Data Length & Data Timer
+ MmioWrite32(MCI_DATA_TIMER_REG,0xFFFFF);
+ MmioWrite32(MCI_DATA_LENGTH_REG,8);
+
+ ASSERT((MmioRead32(MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);
+ break;
+ case MmcIdleState:
+ MCI_TRACE("MciNotifyState(MmcIdleState)");
+ break;
+ case MmcReadyState:
+ MCI_TRACE("MciNotifyState(MmcReadyState)");
+ break;
+ case MmcIdentificationState:
+ MCI_TRACE("MciNotifyState(MmcIdentificationState)");
+ break;
+ case MmcStandByState:{
+ volatile UINT32 PwrCtrlReg;
+ MCI_TRACE("MciNotifyState(MmcStandByState)");
+
+ // Enable MCICMD push-pull drive
+ PwrCtrlReg = MmioRead32(MCI_POWER_CONTROL_REG);
+ //Disable Open Drain output
+ PwrCtrlReg &=~(MCI_POWER_OPENDRAIN);
+ MmioWrite32(MCI_POWER_CONTROL_REG,PwrCtrlReg);
+
+ // Set MMCI0 clock to 4MHz (24MHz may be possible with cache enabled)
+ //
+ // Note: Increasing clock speed causes TX FIFO under-run errors.
+ // So careful when optimising this driver for higher performance.
+ //
+ MmioWrite32(MCI_CLOCK_CONTROL_REG,0x02 | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);
+ // Set MMCI0 clock to 24MHz (by bypassing the divider)
+ //MmioWrite32(MCI_CLOCK_CONTROL_REG,MCI_CLOCK_BYPASS | MCI_CLOCK_ENABLE);
+ break;
+ }
+ case MmcTransferState:
+ //MCI_TRACE("MciNotifyState(MmcTransferState)");
+ break;
+ case MmcSendingDataState:
+ MCI_TRACE("MciNotifyState(MmcSendingDataState)");
+ break;
+ case MmcReceiveDataState:
+ MCI_TRACE("MciNotifyState(MmcReceiveDataState)");
+ break;
+ case MmcProgrammingState:
+ MCI_TRACE("MciNotifyState(MmcProgrammingState)");
+ break;
+ case MmcDisconnectState:
+ MCI_TRACE("MciNotifyState(MmcDisconnectState)");
+ break;
+ default:
+ ASSERT(0);
+ }
+ return EFI_SUCCESS;
}
EFI_GUID mPL180MciDevicePathGuid = { 0x621b6fa5, 0x4dc1, 0x476f, 0xb9, 0xd8, 0x52, 0xc5, 0x57, 0xd8, 0x10, 0x70 };
-EFI_STATUS MciBuildDevicePath(EFI_DEVICE_PATH_PROTOCOL **DevicePath) {
- EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
+EFI_STATUS
+MciBuildDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
- NewDevicePathNode = CreateDeviceNode(HARDWARE_DEVICE_PATH,HW_VENDOR_DP,sizeof(VENDOR_DEVICE_PATH));
- CopyGuid(&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid,&mPL180MciDevicePathGuid);
-
- *DevicePath = NewDevicePathNode;
- return EFI_SUCCESS;
+ NewDevicePathNode = CreateDeviceNode(HARDWARE_DEVICE_PATH,HW_VENDOR_DP,sizeof(VENDOR_DEVICE_PATH));
+ CopyGuid(&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid,&mPL180MciDevicePathGuid);
+
+ *DevicePath = NewDevicePathNode;
+ return EFI_SUCCESS;
}
EFI_MMC_HOST_PROTOCOL gMciHost = {
- MciIsCardPresent,
- MciIsReadOnly,
- MciBuildDevicePath,
- MciNotifyState,
- MciSendCommand,
- MciReceiveResponse,
- MciReadBlockData,
- MciWriteBlockData
+ MciIsCardPresent,
+ MciIsReadOnly,
+ MciBuildDevicePath,
+ MciNotifyState,
+ MciSendCommand,
+ MciReceiveResponse,
+ MciReadBlockData,
+ MciWriteBlockData
};
EFI_STATUS
diff --git a/ArmPkg/Drivers/PL180MciDxe/PL180Mci.h b/ArmPkg/Drivers/PL180MciDxe/PL180Mci.h index 2120716554..46c6700974 100644 --- a/ArmPkg/Drivers/PL180MciDxe/PL180Mci.h +++ b/ArmPkg/Drivers/PL180MciDxe/PL180Mci.h @@ -64,11 +64,13 @@ #define MCI_STATUS_CMD_DATACRCFAIL 0x2
#define MCI_STATUS_CMD_CMDTIMEOUT 0x4
#define MCI_STATUS_CMD_DATATIMEOUT 0x8
+#define MCI_STATUS_CMD_TX_UNDERRUN 0x10
#define MCI_STATUS_CMD_RXOVERRUN 0x20
#define MCI_STATUS_CMD_RESPEND 0x40
#define MCI_STATUS_CMD_SENT 0x80
#define MCI_STATUS_CMD_TXDONE (MCI_STATUS_CMD_DATAEND | MCI_STATUS_CMD_DATABLOCKEND)
#define MCI_STATUS_CMD_DATAEND 0x000100 // Command Status - Data end
+#define MCI_STATUS_CMD_START_BIT_ERROR 0x000200
#define MCI_STATUS_CMD_DATABLOCKEND 0x000400 // Command Status - Data end
#define MCI_STATUS_CMD_ACTIVE 0x800
#define MCI_STATUS_CMD_RXACTIVE (1 << 13)
@@ -86,7 +88,7 @@ #define MCI_DATACTL_CARD_TO_CONT 2
#define MCI_DATACTL_BLOCK_TRANS 0
#define MCI_DATACTL_STREAM_TRANS 4
-#define MCI_DATACTL_DMA_ENABLE 8
+#define MCI_DATACTL_DMA_ENABLE (1 << 3)
#define INDX(CMD_INDX) ((CMD_INDX & 0x3F) | MCI_CPSM_ENABLED)
|