123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820 |
- /** @file
- This file implement the MMC Host Protocol for the DesignWare eMMC.
- WARNING:
- This driver fails to follow the UEFI driver model without a good
- reason, and only remains in the tree because it is still used by
- a small number of platforms. It will be removed when no longer used.
- Copyright (c) 2014-2017, Linaro Limited. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <Library/BaseMemoryLib.h>
- #include <Library/CacheMaintenanceLib.h>
- #include <Library/DebugLib.h>
- #include <Library/DevicePathLib.h>
- #include <Library/IoLib.h>
- #include <Library/MemoryAllocationLib.h>
- #include <Library/PcdLib.h>
- #include <Library/TimerLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <Library/UefiLib.h>
- #include <Protocol/MmcHost.h>
- #ifdef CONFIG_DWEMMC
- #define PcdDwDxeBaseAddress ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress))
- #elif CONFIG_DWSDMMC
- #define PcdDwDxeBaseAddress ((UINT32)PcdGet32 (PcdDwSdDxeBaseAddress))
- #endif
- #include "DwEmmc.h"
- #define DWEMMC_DESC_PAGE 1
- #define DWEMMC_BLOCK_SIZE 512
- #define DWEMMC_DMA_BUF_SIZE (512 * 8)
- #define DWEMMC_MAX_DESC_PAGES 512
- /* Internal IDMAC interrupt defines */
- #define DWMCI_IDINTEN_RI (1 << 1)
- #define DWMCI_IDINTEN_TI (1 << 0)
- #define DWMCI_IDINTEN_MASK (DWMCI_IDINTEN_TI | \
- DWMCI_IDINTEN_RI)
- #define DWMCI_DMA_EN (1 << 5)
- typedef struct {
- UINT32 Des0;
- UINT32 Des1;
- UINT32 Des2;
- UINT32 Des3;
- } DWEMMC_IDMAC_DESCRIPTOR;
- EFI_MMC_HOST_PROTOCOL *gpMmcHost;
- DWEMMC_IDMAC_DESCRIPTOR *gpIdmacDesc;
- EFI_GUID mDwEmmcDevicePathGuid = EFI_CALLER_ID_GUID;
- STATIC UINT32 mDwEmmcCommand;
- STATIC UINT32 mDwEmmcArgument;
- STATIC UINT32 app_cmd = 0;
- EFI_STATUS
- DwEmmcReadBlockData (
- IN EFI_MMC_HOST_PROTOCOL *This,
- IN EFI_LBA Lba,
- IN UINTN Length,
- IN UINT32* Buffer
- );
- BOOLEAN
- DwEmmcIsPowerOn (
- VOID
- )
- {
- return TRUE;
- }
- EFI_STATUS
- DwEmmcInitialize (
- VOID
- )
- {
- DEBUG ((DEBUG_BLKIO, "DwEmmcInitialize()"));
- return EFI_SUCCESS;
- }
- BOOLEAN
- DwEmmcIsCardPresent (
- IN EFI_MMC_HOST_PROTOCOL *This
- )
- {
- return TRUE;
- }
- BOOLEAN
- DwEmmcIsReadOnly (
- IN EFI_MMC_HOST_PROTOCOL *This
- )
- {
- return FALSE;
- }
- BOOLEAN
- DwEmmcIsDmaSupported (
- IN EFI_MMC_HOST_PROTOCOL *This
- )
- {
- return TRUE;
- }
- void mmc_debug_printf()
- {
- //UINT32 data, data1,
- UINT32 addr = 0x16020000;
- //data = MmioRead32(0x13020170);
- //data1 = MmioRead32(0x13020178);
- //DEBUG ((DEBUG_INFO, "\nCLK 0 0x%x clk 1 0x%x\n", data, data1));
- for (; addr <= 0x16020098; addr+=4) {
- if ((addr & 0xf) == 0x0) {
- DEBUG ((DEBUG_INFO,"\naddr 0x%08x:", addr));
- }
- DEBUG ((DEBUG_INFO, " %08x", MmioRead32(addr)));
- }
- DEBUG ((DEBUG_INFO, "\n"));
- }
- EFI_STATUS
- DwEmmcBuildDevicePath (
- 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, &mDwEmmcDevicePathGuid);
- *DevicePath = NewDevicePathNode;
- return EFI_SUCCESS;
- }
- EFI_STATUS
- DwEmmcUpdateClock (
- VOID
- )
- {
- UINT32 Data;
- /* CMD_UPDATE_CLK */
- Data = BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_UPDATE_CLOCK_ONLY |
- BIT_CMD_START;
- MmioWrite32 (DWEMMC_CMD, Data);
- while (1) {
- Data = MmioRead32 (DWEMMC_CMD);
- if (!(Data & CMD_START_BIT)) {
- break;
- }
- Data = MmioRead32 (DWEMMC_RINTSTS);
- if (Data & DWEMMC_INT_HLE) {
- Print (L"failed to update mmc clock frequency\n");
- return EFI_DEVICE_ERROR;
- }
- }
- return EFI_SUCCESS;
- }
- EFI_STATUS
- DwEmmcSetClock (
- IN UINTN ClockFreq
- )
- {
- UINT32 Divider, Rate, Data;
- EFI_STATUS Status;
- BOOLEAN Found = FALSE;
- for (Divider = 1; Divider < 256; Divider++) {
- Rate = PcdGet32 (PcdDwEmmcDxeClockFrequencyInHz);
- if ((Rate / (2 * Divider)) <= ClockFreq) {
- Found = TRUE;
- break;
- }
- }
- if (Found == FALSE) {
- return EFI_NOT_FOUND;
- }
- // Wait until MMC is idle
- do {
- Data = MmioRead32 (DWEMMC_STATUS);
- } while (Data & DWEMMC_STS_DATA_BUSY);
- // Disable MMC clock first
- MmioWrite32 (DWEMMC_CLKENA, 0);
- Status = DwEmmcUpdateClock ();
- ASSERT (!EFI_ERROR (Status));
- MmioWrite32 (DWEMMC_CLKDIV, Divider);
- Status = DwEmmcUpdateClock ();
- ASSERT (!EFI_ERROR (Status));
- // Enable MMC clock
- MmioWrite32 (DWEMMC_CLKENA, 1);
- MmioWrite32 (DWEMMC_CLKSRC, 0);
- Status = DwEmmcUpdateClock ();
- ASSERT (!EFI_ERROR (Status));
- return EFI_SUCCESS;
- }
- EFI_STATUS
- DwEmmcNotifyState (
- IN EFI_MMC_HOST_PROTOCOL *This,
- IN MMC_STATE State
- )
- {
- UINT32 Data;
- EFI_STATUS Status;
- switch (State) {
- case MmcInvalidState:
- return EFI_INVALID_PARAMETER;
- case MmcHwInitializationState:
- MmioWrite32 (DWEMMC_PWREN, 1);
- // If device already turn on then restart it
- Data = DWEMMC_CTRL_RESET_ALL;
- MmioWrite32 (DWEMMC_CTRL, Data);
- do {
- // Wait until reset operation finished
- Data = MmioRead32 (DWEMMC_CTRL);
- } while (Data & DWEMMC_CTRL_RESET_ALL);
- // Setup clock that could not be higher than 400KHz.
- Status = DwEmmcSetClock (400000);
- ASSERT (!EFI_ERROR (Status));
- // Wait clock stable
- MicroSecondDelay (100);
- MmioWrite32 (DWEMMC_CTYPE, 0);
- MmioWrite32 (DWEMMC_RINTSTS, ~0);
- MmioWrite32 (DWEMMC_INTMASK, 0);
- MmioWrite32 (DWEMMC_TMOUT, ~0);
- MmioWrite32 (DWEMMC_IDINTEN, 0);
- MmioWrite32 (DWEMMC_BMOD, DWEMMC_IDMAC_SWRESET);
- MmioWrite32 (DWEMMC_BLKSIZ, DWEMMC_BLOCK_SIZE);
- do {
- Data = MmioRead32 (DWEMMC_BMOD);
- } while (Data & DWEMMC_IDMAC_SWRESET);
- MmioWrite32 (DWEMMC_IDINTEN, 0x3);
- break;
- case MmcIdleState:
- break;
- case MmcReadyState:
- break;
- case MmcIdentificationState:
- break;
- case MmcStandByState:
- break;
- case MmcTransferState:
- break;
- case MmcSendingDataState:
- break;
- case MmcReceiveDataState:
- break;
- case MmcProgrammingState:
- break;
- case MmcDisconnectState:
- break;
- default:
- return EFI_INVALID_PARAMETER;
- }
- return EFI_SUCCESS;
- }
- // Need to prepare DMA buffer first before sending commands to MMC card
- BOOLEAN
- IsPendingReadCommand (
- IN MMC_CMD MmcCmd
- )
- {
- UINTN Mask;
- Mask = BIT_CMD_DATA_EXPECTED | BIT_CMD_READ;
- if ((MmcCmd & Mask) == Mask) {
- return TRUE;
- }
- return FALSE;
- }
- BOOLEAN
- IsPendingWriteCommand (
- IN MMC_CMD MmcCmd
- )
- {
- UINTN Mask;
- Mask = BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE;
- if ((MmcCmd & Mask) == Mask) {
- return TRUE;
- }
- return FALSE;
- }
- EFI_STATUS
- SendCommand (
- IN MMC_CMD MmcCmd,
- IN UINT32 Argument
- )
- {
- UINT32 Data, ErrMask;
- // Wait until MMC is idle
- do {
- Data = MmioRead32 (DWEMMC_STATUS);
- } while (Data & DWEMMC_STS_DATA_BUSY);
- MmioWrite32 (DWEMMC_RINTSTS, ~0);
- MmioWrite32 (DWEMMC_CMDARG, Argument);
- MmioWrite32 (DWEMMC_CMD, MmcCmd);
- //DEBUG ((DEBUG_INFO, "send cmd %d arg %x\n", MmcCmd & 0x3f, Argument));
- ErrMask = DWEMMC_INT_EBE | DWEMMC_INT_HLE | DWEMMC_INT_RTO |
- DWEMMC_INT_RCRC | DWEMMC_INT_RE;
- ErrMask |= DWEMMC_INT_DCRC | DWEMMC_INT_DRT | DWEMMC_INT_SBE;
- do {
- MicroSecondDelay(500);
- Data = MmioRead32 (DWEMMC_RINTSTS);
- if (Data & ErrMask) {
- return EFI_DEVICE_ERROR;
- }
- if (Data & DWEMMC_INT_DTO) { // Transfer Done
- break;
- }
- } while (!(Data & DWEMMC_INT_CMD_DONE));
- return EFI_SUCCESS;
- }
- EFI_STATUS
- DwEmmcSendCommand (
- IN EFI_MMC_HOST_PROTOCOL *This,
- IN MMC_CMD MmcCmd,
- IN UINT32 Argument
- )
- {
- UINT32 Cmd = 0;
- EFI_STATUS Status = EFI_SUCCESS;
- switch (MMC_GET_INDX(MmcCmd)) {
- case MMC_INDX(0):
- Cmd = BIT_CMD_SEND_INIT;
- break;
- case MMC_INDX(1):
- Cmd = BIT_CMD_RESPONSE_EXPECT;
- break;
- case MMC_INDX(2):
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE |
- BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_SEND_INIT;
- break;
- case MMC_INDX(3):
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
- BIT_CMD_SEND_INIT;
- break;
- case MMC_INDX(7):
- if (Argument)
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
- else
- Cmd = 0;
- break;
- case MMC_INDX(8):
- if (Argument) /* sd */
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
- BIT_CMD_WAIT_PRVDATA_COMPLETE;
- else /* emmc */
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
- BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
- BIT_CMD_WAIT_PRVDATA_COMPLETE;
- break;
- case MMC_INDX(9):
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
- BIT_CMD_LONG_RESPONSE;
- break;
- case MMC_INDX(12):
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
- BIT_CMD_STOP_ABORT_CMD;
- break;
- case MMC_INDX(13):
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
- BIT_CMD_WAIT_PRVDATA_COMPLETE;
- break;
- case MMC_INDX(16):
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
- /* BIT_CMD_DATA_EXPECTED | BIT_CMD_READ | */
- BIT_CMD_WAIT_PRVDATA_COMPLETE;
- break;
- case MMC_INDX(6): /* sd */
- if (MmcCmd & (1 << 31))
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
- BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
- BIT_CMD_WAIT_PRVDATA_COMPLETE;
- else
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
- break;
- case MMC_INDX(17):
- case MMC_INDX(18):
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
- BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
- BIT_CMD_WAIT_PRVDATA_COMPLETE;
- break;
- case MMC_INDX(24):
- case MMC_INDX(25):
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
- BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE |
- BIT_CMD_WAIT_PRVDATA_COMPLETE;
- break;
- case MMC_INDX(30):
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
- BIT_CMD_DATA_EXPECTED;
- break;
- default:
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
- break;
- }
- if (app_cmd) {
- switch (MMC_GET_INDX(MmcCmd)) {
- case MMC_INDX(41):
- Cmd = BIT_CMD_RESPONSE_EXPECT;
- break;
- case MMC_INDX(51):
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
- BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
- BIT_CMD_WAIT_PRVDATA_COMPLETE;
- break;
- case MMC_INDX(6):
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
- break;
- default:
- break;
- }
- }
- Cmd |= MMC_GET_INDX(MmcCmd) | BIT_CMD_USE_HOLD_REG | BIT_CMD_START;
- if (IsPendingReadCommand (Cmd) || IsPendingWriteCommand (Cmd)) {
- mDwEmmcCommand = Cmd;
- mDwEmmcArgument = Argument;
- } else {
- Status = SendCommand (Cmd, Argument);
- }
- if ((Status == EFI_SUCCESS) && ((MmcCmd & 0x3f) == 55))
- app_cmd = 1;
- else
- app_cmd = 0;
- return Status;
- }
- EFI_STATUS
- DwEmmcReceiveResponse (
- 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 (DWEMMC_RESP0);
- } else if (Type == MMC_RESPONSE_TYPE_R2) {
- Buffer[0] = MmioRead32 (DWEMMC_RESP0);
- Buffer[1] = MmioRead32 (DWEMMC_RESP1);
- Buffer[2] = MmioRead32 (DWEMMC_RESP2);
- Buffer[3] = MmioRead32 (DWEMMC_RESP3);
- }
- return EFI_SUCCESS;
- }
- VOID
- DwEmmcAdjustFifoThreshold (
- VOID
- )
- {
- /* DMA multiple transaction size map to reg value as array index */
- CONST UINT32 BurstSize[] = {1, 4, 8, 16, 32, 64, 128, 256};
- UINT32 BlkDepthInFifo, FifoThreshold, FifoWidth, FifoDepth;
- UINT32 BlkSize = DWEMMC_BLOCK_SIZE, Idx = 0, RxWatermark = 1, TxWatermark, TxWatermarkInvers;
- /* Skip FIFO adjustment if we do not have platform FIFO depth info */
- FifoDepth = PcdGet32 (PcdDwEmmcDxeFifoDepth);
- if (!FifoDepth) {
- return;
- }
- TxWatermark = FifoDepth / 2;
- TxWatermarkInvers = FifoDepth - TxWatermark;
- FifoWidth = DWEMMC_GET_HDATA_WIDTH (MmioRead32 (DWEMMC_HCON));
- if (!FifoWidth) {
- FifoWidth = 2;
- } else if (FifoWidth == 2) {
- FifoWidth = 8;
- } else {
- FifoWidth = 4;
- }
- BlkDepthInFifo = BlkSize / FifoWidth;
- Idx = ARRAY_SIZE (BurstSize) - 1;
- while (Idx && ((BlkDepthInFifo % BurstSize[Idx]) || (TxWatermarkInvers % BurstSize[Idx]))) {
- Idx--;
- }
- RxWatermark = BurstSize[Idx] - 1;
- FifoThreshold = DWEMMC_DMA_BURST_SIZE (Idx) | DWEMMC_FIFO_TWMARK (TxWatermark)
- | DWEMMC_FIFO_RWMARK (RxWatermark);
- MmioWrite32 (DWEMMC_FIFOTH, FifoThreshold);
- }
- EFI_STATUS
- PrepareDmaData (
- IN DWEMMC_IDMAC_DESCRIPTOR* IdmacDesc,
- IN UINTN Length,
- IN UINT32* Buffer
- )
- {
- UINTN Cnt, Blks, Idx, LastIdx;
- UINT32 Data/* , flag, cnt */;
- MmioWrite32 (DWEMMC_CTRL, DWEMMC_CTRL_FIFO_RESET);
- do {
- // Wait until reset operation finished
- Data = MmioRead32 (DWEMMC_CTRL);
- } while (Data & DWEMMC_CTRL_RESET_ALL);
- MmioWrite32 (DWEMMC_IDSTS, 0xffffffff);
- Cnt = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
- Blks = (Length + DWEMMC_BLOCK_SIZE - 1) / DWEMMC_BLOCK_SIZE;
- //Length = DWEMMC_BLOCK_SIZE * Blks;
- for (Idx = 0; Idx < Cnt; Idx++) {
- (IdmacDesc + Idx)->Des0 = DWEMMC_IDMAC_DES0_OWN | DWEMMC_IDMAC_DES0_CH |
- DWEMMC_IDMAC_DES0_DIC;
- (IdmacDesc + Idx)->Des1 = DWEMMC_IDMAC_DES1_BS1(DWEMMC_DMA_BUF_SIZE);
- /* Buffer Address */
- (IdmacDesc + Idx)->Des2 = (UINT32)((UINTN)Buffer + DWEMMC_DMA_BUF_SIZE * Idx);
- /* Next Descriptor Address */
- (IdmacDesc + Idx)->Des3 = (UINT32)((UINTN)IdmacDesc +
- (sizeof(DWEMMC_IDMAC_DESCRIPTOR) * (Idx + 1)));
- }
- /* First Descriptor */
- IdmacDesc->Des0 |= DWEMMC_IDMAC_DES0_FS;
- /* Last Descriptor */
- LastIdx = Cnt - 1;
- (IdmacDesc + LastIdx)->Des0 |= DWEMMC_IDMAC_DES0_LD;
- (IdmacDesc + LastIdx)->Des0 &= ~(DWEMMC_IDMAC_DES0_DIC | DWEMMC_IDMAC_DES0_CH);
- (IdmacDesc + LastIdx)->Des1 = DWEMMC_IDMAC_DES1_BS1(Length -
- (LastIdx * DWEMMC_DMA_BUF_SIZE));
- /* Set the Next field of Last Descriptor */
- //(IdmacDesc + LastIdx)->Des3 = 0;
- MmioWrite32 (DWEMMC_DBADDR, (UINT32)((UINTN)IdmacDesc));
- return EFI_SUCCESS;
- }
- VOID
- StartDma (
- UINTN Length
- )
- {
- UINT32 Data;
- Data = MmioRead32 (DWEMMC_CTRL);
- Data |= DWEMMC_CTRL_DMA_EN | DWEMMC_CTRL_IDMAC_EN;
- MmioWrite32 (DWEMMC_CTRL, Data);
- Data = MmioRead32 (DWEMMC_BMOD);
- Data |= DWEMMC_IDMAC_ENABLE | DWEMMC_IDMAC_FB;
- MmioWrite32 (DWEMMC_BMOD, Data);
- MmioWrite32 (DWEMMC_BLKSIZ,
- (Length < DWEMMC_BLOCK_SIZE) ? Length : DWEMMC_BLOCK_SIZE);
- MmioWrite32 (DWEMMC_BYTCNT, Length);
- }
- EFI_STATUS
- DwEmmcWaitDmaComplete (
- IN EFI_MMC_HOST_PROTOCOL *This,
- IN UINT32 read
- )
- {
- UINT32 mask, Ctrl, timeout = 100000;
- EFI_STATUS ret = EFI_SUCCESS;
- if (read)
- mask = DWMCI_IDINTEN_RI;
- else
- mask = DWMCI_IDINTEN_TI;
- do {
- Ctrl = MmioRead32 (DWEMMC_IDSTS);
- if (Ctrl & mask)
- break;
- timeout--;
- gBS->Stall(1);
- } while (timeout);
- if (!timeout) {
- DEBUG ((DEBUG_INFO, "wait dma to\n"));
- ret = EFI_DEVICE_ERROR;
- }
- MmioWrite32 (DWEMMC_IDSTS, DWMCI_IDINTEN_MASK);
- Ctrl = MmioRead32(DWEMMC_CTRL);
- Ctrl &= ~(DWMCI_DMA_EN);
- Ctrl = MmioWrite32(DWEMMC_CTRL, Ctrl);
- gBS->Stall(100);
- return ret;
- }
- EFI_STATUS
- DwEmmcReadBlockData (
- IN EFI_MMC_HOST_PROTOCOL *This,
- IN EFI_LBA Lba,
- IN UINTN Length,
- IN UINT32* Buffer
- )
- {
- EFI_STATUS Status;
- UINT32 DescPages, CountPerPage, Count;
- EFI_TPL Tpl;
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
- CountPerPage = EFI_PAGE_SIZE / 16;
- Count = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
- DescPages = (Count + CountPerPage - 1) / CountPerPage;
- InvalidateDataCacheRange (Buffer, Length);
- // DEBUG ((DEBUG_INFO, "BUFFER %lx length %x\n", (UINT64)Buffer, Length));
- Status = PrepareDmaData (gpIdmacDesc, Length, Buffer);
- if (EFI_ERROR (Status)) {
- goto out;
- }
- WriteBackDataCacheRange (gpIdmacDesc, DescPages * EFI_PAGE_SIZE);
- StartDma (Length);
- Status = SendCommand (mDwEmmcCommand, mDwEmmcArgument);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Failed to read data, mDwEmmcCommand:%x, mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand, mDwEmmcArgument, Status));
- goto out;
- }
- Status = DwEmmcWaitDmaComplete(This, 1);
- out:
- // Restore Tpl
- gBS->RestoreTPL (Tpl);
- return Status;
- }
- EFI_STATUS
- DwEmmcWriteBlockData (
- IN EFI_MMC_HOST_PROTOCOL *This,
- IN EFI_LBA Lba,
- IN UINTN Length,
- IN UINT32* Buffer
- )
- {
- EFI_STATUS Status;
- UINT32 DescPages, CountPerPage, Count;
- EFI_TPL Tpl;
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);
- CountPerPage = EFI_PAGE_SIZE / 16;
- Count = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
- DescPages = (Count + CountPerPage - 1) / CountPerPage;
- WriteBackDataCacheRange (Buffer, Length);
- Status = PrepareDmaData (gpIdmacDesc, Length, Buffer);
- if (EFI_ERROR (Status)) {
- goto out;
- }
- WriteBackDataCacheRange (gpIdmacDesc, DescPages * EFI_PAGE_SIZE);
- StartDma (Length);
- Status = SendCommand (mDwEmmcCommand, mDwEmmcArgument);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Failed to write data, mDwEmmcCommand:%x, mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand, mDwEmmcArgument, Status));
- goto out;
- }
- Status = DwEmmcWaitDmaComplete(This, 0);
- out:
- // Restore Tpl
- gBS->RestoreTPL (Tpl);
- return Status;
- }
- EFI_STATUS
- DwEmmcSetIos (
- IN EFI_MMC_HOST_PROTOCOL *This,
- IN UINT32 BusClockFreq,
- IN UINT32 BusWidth,
- IN UINT32 TimingMode
- )
- {
- EFI_STATUS Status = EFI_SUCCESS;
- UINT32 Data;
- if ((PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz) != 0) &&
- (BusClockFreq > PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz))) {
- return EFI_UNSUPPORTED;
- }
- if (TimingMode != EMMCBACKWARD) {
- Data = MmioRead32 (DWEMMC_UHSREG);
- switch (TimingMode) {
- case EMMCHS52DDR1V2:
- case EMMCHS52DDR1V8:
- //Data |= 1 << 16;
- //break;
- return EFI_UNSUPPORTED;
- case EMMCHS52:
- case EMMCHS26:
- Data &= ~(1 << 16);
- break;
- default:
- break;
- }
- MmioWrite32 (DWEMMC_UHSREG, Data);
- }
- //DEBUG ((DEBUG_INFO, "Set bus width %d clock %d\n",BusWidth, BusClockFreq));
- switch (BusWidth) {
- case 1:
- MmioWrite32 (DWEMMC_CTYPE, 0);
- break;
- case 4:
- MmioWrite32 (DWEMMC_CTYPE, 1);
- break;
- case 8:
- MmioWrite32 (DWEMMC_CTYPE, 1 << 16);
- break;
- default:
- return EFI_UNSUPPORTED;
- }
- if (BusClockFreq) {
- Status = DwEmmcSetClock (BusClockFreq);
- }
- return Status;
- }
- BOOLEAN
- DwEmmcIsMultiBlock (
- IN EFI_MMC_HOST_PROTOCOL *This
- )
- {
- return TRUE;
- }
- EFI_MMC_HOST_PROTOCOL gMciHost = {
- MMC_HOST_PROTOCOL_REVISION,
- DwEmmcIsCardPresent,
- DwEmmcIsReadOnly,
- DwEmmcBuildDevicePath,
- DwEmmcNotifyState,
- DwEmmcSendCommand,
- DwEmmcReceiveResponse,
- DwEmmcReadBlockData,
- DwEmmcWriteBlockData,
- DwEmmcSetIos,
- DwEmmcIsMultiBlock
- };
- EFI_STATUS
- DwEmmcDxeInitialize (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- EFI_HANDLE Handle;
- if (!FixedPcdGetBool (PcdDwPermitObsoleteDrivers)) {
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
- }
- Handle = NULL;
- DwEmmcAdjustFifoThreshold ();
- gpIdmacDesc = (DWEMMC_IDMAC_DESCRIPTOR *)AllocatePages (DWEMMC_MAX_DESC_PAGES);
- if (gpIdmacDesc == NULL) {
- return EFI_BUFFER_TOO_SMALL;
- }
- DEBUG ((DEBUG_BLKIO, "DwEmmcDxeInitialize()\n"));
- //Publish Component Name, BlockIO protocol interfaces
- Status = gBS->InstallMultipleProtocolInterfaces (
- &Handle,
- &gEmbeddedMmcHostProtocolGuid, &gMciHost,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
- return EFI_SUCCESS;
- }
|