summaryrefslogtreecommitdiff
path: root/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
diff options
context:
space:
mode:
Diffstat (limited to 'ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c')
-rw-r--r--ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c553
1 files changed, 0 insertions, 553 deletions
diff --git a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
deleted file mode 100644
index 688cd8a98c..0000000000
--- a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/** @file
- This file implement the MMC Host Protocol for the ARM PrimeCell PL180.
-
- Copyright (c) 2011-2012, ARM Limited. All rights reserved.
-
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "PL180Mci.h"
-
-#include <Library/DevicePathLib.h>
-#include <Library/BaseMemoryLib.h>
-
-EFI_MMC_HOST_PROTOCOL *gpMmcHost;
-
-// Untested ...
-//#define USE_STREAM
-
-#define MMCI0_BLOCKLEN 512
-#define MMCI0_POW2_BLOCKLEN 9
-#define MMCI0_TIMEOUT 1000
-
-#define SYS_MCI_CARDIN BIT0
-#define SYS_MCI_WPROT BIT1
-
-BOOLEAN
-MciIsPowerOn (
- VOID
- )
-{
- return ((MmioRead32 (MCI_POWER_CONTROL_REG) & MCI_POWER_ON) == MCI_POWER_ON);
-}
-
-EFI_STATUS
-MciInitialize (
- VOID
- )
-{
- MCI_TRACE ("MciInitialize()");
- return EFI_SUCCESS;
-}
-
-BOOLEAN
-MciIsCardPresent (
- IN EFI_MMC_HOST_PROTOCOL *This
- )
-{
- return (MmioRead32 (FixedPcdGet32 (PcdPL180SysMciRegAddress)) & SYS_MCI_CARDIN);
-}
-
-BOOLEAN
-MciIsReadOnly (
- IN EFI_MMC_HOST_PROTOCOL *This
- )
-{
- return (MmioRead32 (FixedPcdGet32 (PcdPL180SysMciRegAddress)) & SYS_MCI_WPROT);
-}
-
-#if 0
-//Note: This function has been commented out because it is not used yet.
-// This function could be used to remove the hardcoded BlockLen used
-// in MciPrepareDataPath
-
-// Convert block size to 2^n
-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;
-}
-#endif
-
-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 | MCI_DATACTL_DMA_ENABLE | TransferDirection | (MMCI0_POW2_BLOCKLEN << 4));
-#else
- MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_DMA_ENABLE | TransferDirection | MCI_DATACTL_STREAM_TRANS);
-#endif
-}
-
-EFI_STATUS
-MciSendCommand (
- IN EFI_MMC_HOST_PROTOCOL *This,
- IN MMC_CMD MmcCmd,
- IN UINT32 Argument
- )
-{
- UINT32 Status;
- UINT32 Cmd;
- UINTN RetVal;
- UINTN CmdCtrlReg;
- UINT32 DoneMask;
-
- 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 = (MMC_GET_INDX (MmcCmd) & INDX_MASK) | MCI_CPSM_ENABLE;
- if (MmcCmd & MMC_CMD_WAIT_RESPONSE) {
- Cmd |= MCI_CPSM_WAIT_RESPONSE;
- }
-
- if (MmcCmd & MMC_CMD_LONG_RESPONSE) {
- Cmd |= MCI_CPSM_LONG_RESPONSE;
- }
-
- // Clear Status register static flags
- MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);
-
- // Write to command argument register
- MmioWrite32 (MCI_ARGUMENT_REG, Argument);
-
- // Write to command register
- MmioWrite32 (MCI_COMMAND_REG, Cmd);
-
- DoneMask = (Cmd & MCI_CPSM_WAIT_RESPONSE)
- ? (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_ERROR)
- : (MCI_STATUS_CMD_SENT | MCI_STATUS_CMD_ERROR);
- do {
- Status = MmioRead32 (MCI_STATUS_REG);
- } while (! (Status & DoneMask));
-
- if ((Status & MCI_STATUS_CMD_ERROR)) {
- // Clear Status register error flags
- MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_STATUS_CMD_ERROR);
-
- 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;
- } 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;
- } else if ((!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {
- // The CMD1 and response type R3 do not contain CRC. We should ignore the CRC failed Status.
- RetVal = EFI_CRC_ERROR;
- }
- }
-
- // Disable Command Path
- CmdCtrlReg = MmioRead32 (MCI_COMMAND_REG);
- MmioWrite32 (MCI_COMMAND_REG, (CmdCtrlReg & ~MCI_CPSM_ENABLE));
- return RetVal;
-}
-
-EFI_STATUS
-MciReceiveResponse (
- IN EFI_MMC_HOST_PROTOCOL *This,
- 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_RESPONSE3_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);
- }
-
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-MciReadBlockData (
- IN EFI_MMC_HOST_PROTOCOL *This,
- IN EFI_LBA Lba,
- IN UINTN Length,
- IN UINT32* Buffer
- )
-{
- UINTN Loop;
- UINTN Finish;
- UINTN Status;
- EFI_STATUS RetVal;
- UINTN DataCtrlReg;
- EFI_TPL Tpl;
-
- RetVal = EFI_SUCCESS;
-
- // Read data from the RX FIFO
- Loop = 0;
- Finish = MMCI0_BLOCKLEN / 4;
-
- // Raise the TPL at the highest level to disable Interrupts.
- Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
-
- 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_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));
-
- // Restore Tpl
- gBS->RestoreTPL (Tpl);
-
- // Clear Status flags
- MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);
-
- //Disable Data path
- DataCtrlReg = MmioRead32 (MCI_DATA_CTL_REG);
- MmioWrite32 (MCI_DATA_CTL_REG, (DataCtrlReg & MCI_DATACTL_DISABLE_MASK));
-
- return RetVal;
-}
-
-EFI_STATUS
-MciWriteBlockData (
- IN EFI_MMC_HOST_PROTOCOL *This,
- IN EFI_LBA Lba,
- IN UINTN Length,
- IN UINT32* Buffer
- )
-{
- UINTN Loop;
- UINTN Finish;
- UINTN Timer;
- UINTN Status;
- EFI_STATUS RetVal;
- UINTN DataCtrlReg;
- EFI_TPL Tpl;
-
- RetVal = EFI_SUCCESS;
-
- // Write the data to the TX FIFO
- Loop = 0;
- Finish = MMCI0_BLOCKLEN / 4;
- Timer = MMCI0_TIMEOUT * 100;
-
- // Raise the TPL at the highest level to disable Interrupts.
- Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
-
- 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 {
- // 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;
- }
- }
- } while (Loop < Finish);
-
- // Restore Tpl
- gBS->RestoreTPL (Tpl);
-
- // Wait for FIFO to drain
- Timer = MMCI0_TIMEOUT * 60;
- Status = MmioRead32 (MCI_STATUS_REG);
-#ifndef USE_STREAM
- // Single block
- while (((Status & MCI_STATUS_TXDONE) != MCI_STATUS_TXDONE) && Timer) {
-#else
- // Stream
- while (((Status & MCI_STATUS_CMD_DATAEND) != MCI_STATUS_CMD_DATAEND) && Timer) {
-#endif
- NanoSecondDelay(10);
- Status = MmioRead32 (MCI_STATUS_REG);
- Timer--;
- }
-
- // Clear Status flags
- MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);
-
- if (Timer == 0) {
- DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): Data End timeout Number of words written 0x%x\n", Loop));
- RetVal = EFI_TIMEOUT;
- }
-
-Exit:
- // Disable Data path
- DataCtrlReg = MmioRead32 (MCI_DATA_CTL_REG);
- MmioWrite32 (MCI_DATA_CTL_REG, (DataCtrlReg & MCI_DATACTL_DISABLE_MASK));
- return RetVal;
-}
-
-EFI_STATUS
-MciNotifyState (
- IN EFI_MMC_HOST_PROTOCOL *This,
- 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);
-
- // 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 = EFI_CALLER_ID_GUID;
-
-EFI_STATUS
-MciBuildDevicePath (
- IN EFI_MMC_HOST_PROTOCOL *This,
- 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;
-}
-
-EFI_MMC_HOST_PROTOCOL gMciHost = {
- MMC_HOST_PROTOCOL_REVISION,
- MciIsCardPresent,
- MciIsReadOnly,
- MciBuildDevicePath,
- MciNotifyState,
- MciSendCommand,
- MciReceiveResponse,
- MciReadBlockData,
- MciWriteBlockData
-};
-
-EFI_STATUS
-PL180MciDxeInitialize (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE Handle;
-
- DEBUG ((EFI_D_WARN, "Probing ID registers at 0x%lx for a PL180\n",
- MCI_PERIPH_ID_REG0));
-
- // Check if this is a PL180
- if (MmioRead8 (MCI_PERIPH_ID_REG0) != MCI_PERIPH_ID0 ||
- MmioRead8 (MCI_PERIPH_ID_REG1) != MCI_PERIPH_ID1 ||
- MmioRead8 (MCI_PERIPH_ID_REG2) != MCI_PERIPH_ID2 ||
- MmioRead8 (MCI_PERIPH_ID_REG3) != MCI_PERIPH_ID3 ||
- MmioRead8 (MCI_PCELL_ID_REG0) != MCI_PCELL_ID0 ||
- MmioRead8 (MCI_PCELL_ID_REG1) != MCI_PCELL_ID1 ||
- MmioRead8 (MCI_PCELL_ID_REG2) != MCI_PCELL_ID2 ||
- MmioRead8 (MCI_PCELL_ID_REG3) != MCI_PCELL_ID3) {
-
- return EFI_NOT_FOUND;
- }
-
- Handle = NULL;
-
- MCI_TRACE ("PL180MciDxeInitialize()");
-
- //Publish Component Name, BlockIO protocol interfaces
- Status = gBS->InstallMultipleProtocolInterfaces (
- &Handle,
- &gEfiMmcHostProtocolGuid, &gMciHost,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
-
- return EFI_SUCCESS;
-}