This file implement the MMC Host Protocol for the ARM PrimeCell PL180.\r
\r
Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
- \r
- This program and the accompanying materials \r
- are licensed and made available under the terms and conditions of the BSD License \r
- which accompanies this distribution. The full text of the license may be found at \r
- http://opensource.org/licenses/bsd-license.php \r
\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
**/\r
\r
UINT32 Cmd;\r
UINTN RetVal;\r
UINTN CmdCtrlReg;\r
+ UINT32 DoneMask;\r
\r
RetVal = EFI_SUCCESS;\r
\r
// Write to command register\r
MmioWrite32 (MCI_COMMAND_REG, Cmd);\r
\r
- if (Cmd & MCI_CPSM_WAIT_RESPONSE) {\r
+ DoneMask = (Cmd & MCI_CPSM_WAIT_RESPONSE)\r
+ ? (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_ERROR)\r
+ : (MCI_STATUS_CMD_SENT | MCI_STATUS_CMD_ERROR);\r
+ do {\r
Status = MmioRead32 (MCI_STATUS_REG);\r
- while (!(Status & (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_CMDCRCFAIL | MCI_STATUS_CMD_CMDTIMEOUT | MCI_STATUS_CMD_START_BIT_ERROR))) {\r
- Status = MmioRead32(MCI_STATUS_REG);\r
- }\r
+ } while (! (Status & DoneMask));\r
+\r
+ if ((Status & MCI_STATUS_CMD_ERROR)) {\r
+ // Clear Status register error flags\r
+ MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_STATUS_CMD_ERROR);\r
\r
if ((Status & MCI_STATUS_CMD_START_BIT_ERROR)) {\r
DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) Start bit Error! Response:0x%X Status:0x%x\n", (Cmd & 0x3F), MmioRead32 (MCI_RESPONSE0_REG), Status));\r
RetVal = EFI_NO_RESPONSE;\r
- goto Exit;\r
} else if ((Status & MCI_STATUS_CMD_CMDTIMEOUT)) {\r
//DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%x\n", (Cmd & 0x3F), MmioRead32 (MCI_RESPONSE0_REG), Status));\r
RetVal = EFI_TIMEOUT;\r
- goto Exit;\r
- } else if ((! (MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {\r
+ } else if ((!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {\r
// The CMD1 and response type R3 do not contain CRC. We should ignore the CRC failed Status.\r
RetVal = EFI_CRC_ERROR;\r
- goto Exit;\r
- } else {\r
- RetVal = EFI_SUCCESS;\r
- goto Exit;\r
- }\r
- } else {\r
- Status = MmioRead32(MCI_STATUS_REG);\r
- while (!(Status & (MCI_STATUS_CMD_SENT | MCI_STATUS_CMD_CMDCRCFAIL | MCI_STATUS_CMD_CMDTIMEOUT| MCI_STATUS_CMD_START_BIT_ERROR))) {\r
- Status = MmioRead32(MCI_STATUS_REG);\r
- }\r
-\r
- if ((Status & MCI_STATUS_CMD_START_BIT_ERROR)) {\r
- DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) Start bit Error! Response:0x%X Status:0x%x\n",(Cmd & 0x3F),MmioRead32(MCI_RESPONSE0_REG),Status));\r
- RetVal = EFI_NO_RESPONSE;\r
- goto Exit;\r
- } else if ((Status & MCI_STATUS_CMD_CMDTIMEOUT)) {\r
- //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%x\n",(Cmd & 0x3F),MmioRead32(MCI_RESPONSE0_REG),Status));\r
- RetVal = EFI_TIMEOUT;\r
- goto Exit;\r
- } else\r
- if ((!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {\r
- // The CMD1 does not contain CRC. We should ignore the CRC failed Status.\r
- RetVal = EFI_CRC_ERROR;\r
- goto Exit;\r
- } else {\r
- RetVal = EFI_SUCCESS;\r
- goto Exit;\r
}\r
}\r
\r
-Exit:\r
// Disable Command Path\r
CmdCtrlReg = MmioRead32 (MCI_COMMAND_REG);\r
MmioWrite32 (MCI_COMMAND_REG, (CmdCtrlReg & ~MCI_CPSM_ENABLE));\r
UINTN Status;\r
EFI_STATUS RetVal;\r
UINTN DataCtrlReg;\r
+ EFI_TPL Tpl;\r
\r
RetVal = EFI_SUCCESS;\r
\r
// Read data from the RX FIFO\r
Loop = 0;\r
Finish = MMCI0_BLOCKLEN / 4;\r
+\r
+ // Raise the TPL at the highest level to disable Interrupts.\r
+ Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
do {\r
// Read the Status flags\r
Status = MmioRead32 (MCI_STATUS_REG);\r
}\r
} while ((Loop < Finish));\r
\r
+ // Restore Tpl\r
+ gBS->RestoreTPL (Tpl);\r
+\r
// Clear Status flags\r
MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);\r
\r
UINTN Status;\r
EFI_STATUS RetVal;\r
UINTN DataCtrlReg;\r
+ EFI_TPL Tpl;\r
\r
RetVal = EFI_SUCCESS;\r
\r
Loop = 0;\r
Finish = MMCI0_BLOCKLEN / 4;\r
Timer = MMCI0_TIMEOUT * 100;\r
+\r
+ // Raise the TPL at the highest level to disable Interrupts.\r
+ Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
do {\r
// Read the Status flags\r
Status = MmioRead32 (MCI_STATUS_REG);\r
Loop++;\r
MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
Loop++;\r
- } else if ((Status & MCI_STATUS_CMD_TXFIFOEMPTY)) {\r
+ } else if (!(Status & MCI_STATUS_CMD_TXFIFOFULL)) {\r
MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
Loop++;\r
} else {\r
}\r
} while (Loop < Finish);\r
\r
+ // Restore Tpl\r
+ gBS->RestoreTPL (Tpl);\r
+\r
// Wait for FIFO to drain\r
Timer = MMCI0_TIMEOUT * 60;\r
Status = MmioRead32 (MCI_STATUS_REG);\r
Timer--;\r
}\r
\r
- if (Timer == 0) {\r
- DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): Data End timeout Number of bytes written 0x%x\n",Loop));\r
- ASSERT (Timer > 0);\r
- return EFI_TIMEOUT;\r
- }\r
-\r
// Clear Status flags\r
MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);\r
+\r
if (Timer == 0) {\r
+ DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): Data End timeout Number of words written 0x%x\n", Loop));\r
RetVal = EFI_TIMEOUT;\r
}\r
\r
// Setup clock\r
// - 0x1D = 29 => should be the clock divider to be less than 400kHz at MCLK = 24Mhz\r
MmioWrite32 (MCI_CLOCK_CONTROL_REG, 0x1D | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);\r
- //MmioWrite32(MCI_CLOCK_CONTROL_REG,0x1D | MCI_CLOCK_ENABLE);\r
\r
// Set the voltage\r
MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_OPENDRAIN | (15<<2));\r
EFI_STATUS Status;\r
EFI_HANDLE Handle;\r
\r
+ DEBUG ((EFI_D_WARN, "Probing ID registers at 0x%lx for a PL180\n",\r
+ MCI_PERIPH_ID_REG0));\r
+\r
+ // Check if this is a PL180\r
+ if (MmioRead8 (MCI_PERIPH_ID_REG0) != MCI_PERIPH_ID0 ||\r
+ MmioRead8 (MCI_PERIPH_ID_REG1) != MCI_PERIPH_ID1 ||\r
+ MmioRead8 (MCI_PERIPH_ID_REG2) != MCI_PERIPH_ID2 ||\r
+ MmioRead8 (MCI_PERIPH_ID_REG3) != MCI_PERIPH_ID3 ||\r
+ MmioRead8 (MCI_PCELL_ID_REG0) != MCI_PCELL_ID0 ||\r
+ MmioRead8 (MCI_PCELL_ID_REG1) != MCI_PCELL_ID1 ||\r
+ MmioRead8 (MCI_PCELL_ID_REG2) != MCI_PCELL_ID2 ||\r
+ MmioRead8 (MCI_PCELL_ID_REG3) != MCI_PCELL_ID3) {\r
+\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
Handle = NULL;\r
\r
MCI_TRACE ("PL180MciDxeInitialize()");\r
\r
//Publish Component Name, BlockIO protocol interfaces\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Handle, \r
+ &Handle,\r
&gEfiMmcHostProtocolGuid, &gMciHost,\r
NULL\r
);\r