+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2014-2017, Linaro Limited. All rights reserved.\r
-*\r
-* SPDX-License-Identifier: BSD-2-Clause-Patent\r
-*\r
-**/\r
-\r
-\r
-#ifndef __DWEMMC_H__\r
-#define __DWEMMC_H__\r
-\r
-#include <Protocol/EmbeddedGpio.h>\r
-\r
-// DW MMC Registers\r
-#define DWEMMC_CTRL ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x000)\r
-#define DWEMMC_PWREN ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x004)\r
-#define DWEMMC_CLKDIV ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x008)\r
-#define DWEMMC_CLKSRC ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x00c)\r
-#define DWEMMC_CLKENA ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x010)\r
-#define DWEMMC_TMOUT ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x014)\r
-#define DWEMMC_CTYPE ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x018)\r
-#define DWEMMC_BLKSIZ ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x01c)\r
-#define DWEMMC_BYTCNT ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x020)\r
-#define DWEMMC_INTMASK ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x024)\r
-#define DWEMMC_CMDARG ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x028)\r
-#define DWEMMC_CMD ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x02c)\r
-#define DWEMMC_RESP0 ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x030)\r
-#define DWEMMC_RESP1 ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x034)\r
-#define DWEMMC_RESP2 ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x038)\r
-#define DWEMMC_RESP3 ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x03c)\r
-#define DWEMMC_RINTSTS ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x044)\r
-#define DWEMMC_STATUS ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x048)\r
-#define DWEMMC_FIFOTH ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x04c)\r
-#define DWEMMC_TCBCNT ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x05c)\r
-#define DWEMMC_TBBCNT ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x060)\r
-#define DWEMMC_DEBNCE ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x064)\r
-#define DWEMMC_HCON ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x070)\r
-#define DWEMMC_UHSREG ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x074)\r
-#define DWEMMC_BMOD ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x080)\r
-#define DWEMMC_DBADDR ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x088)\r
-#define DWEMMC_IDSTS ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x08c)\r
-#define DWEMMC_IDINTEN ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x090)\r
-#define DWEMMC_DSCADDR ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x094)\r
-#define DWEMMC_BUFADDR ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0x098)\r
-#define DWEMMC_CARDTHRCTL ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0X100)\r
-#define DWEMMC_DATA ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress) + 0X200)\r
-\r
-#define CMD_UPDATE_CLK 0x80202000\r
-#define CMD_START_BIT (1 << 31)\r
-\r
-#define MMC_8BIT_MODE (1 << 16)\r
-\r
-#define BIT_CMD_RESPONSE_EXPECT (1 << 6)\r
-#define BIT_CMD_LONG_RESPONSE (1 << 7)\r
-#define BIT_CMD_CHECK_RESPONSE_CRC (1 << 8)\r
-#define BIT_CMD_DATA_EXPECTED (1 << 9)\r
-#define BIT_CMD_READ (0 << 10)\r
-#define BIT_CMD_WRITE (1 << 10)\r
-#define BIT_CMD_BLOCK_TRANSFER (0 << 11)\r
-#define BIT_CMD_STREAM_TRANSFER (1 << 11)\r
-#define BIT_CMD_SEND_AUTO_STOP (1 << 12)\r
-#define BIT_CMD_WAIT_PRVDATA_COMPLETE (1 << 13)\r
-#define BIT_CMD_STOP_ABORT_CMD (1 << 14)\r
-#define BIT_CMD_SEND_INIT (1 << 15)\r
-#define BIT_CMD_UPDATE_CLOCK_ONLY (1 << 21)\r
-#define BIT_CMD_READ_CEATA_DEVICE (1 << 22)\r
-#define BIT_CMD_CCS_EXPECTED (1 << 23)\r
-#define BIT_CMD_ENABLE_BOOT (1 << 24)\r
-#define BIT_CMD_EXPECT_BOOT_ACK (1 << 25)\r
-#define BIT_CMD_DISABLE_BOOT (1 << 26)\r
-#define BIT_CMD_MANDATORY_BOOT (0 << 27)\r
-#define BIT_CMD_ALTERNATE_BOOT (1 << 27)\r
-#define BIT_CMD_VOLT_SWITCH (1 << 28)\r
-#define BIT_CMD_USE_HOLD_REG (1 << 29)\r
-#define BIT_CMD_START (1 << 31)\r
-\r
-#define DWEMMC_INT_EBE (1 << 15) /* End-bit Err */\r
-#define DWEMMC_INT_SBE (1 << 13) /* Start-bit Err */\r
-#define DWEMMC_INT_HLE (1 << 12) /* Hardware-lock Err */\r
-#define DWEMMC_INT_FRUN (1 << 11) /* FIFO UN/OV RUN */\r
-#define DWEMMC_INT_DRT (1 << 9) /* Data timeout */\r
-#define DWEMMC_INT_RTO (1 << 8) /* Response timeout */\r
-#define DWEMMC_INT_DCRC (1 << 7) /* Data CRC err */\r
-#define DWEMMC_INT_RCRC (1 << 6) /* Response CRC err */\r
-#define DWEMMC_INT_RXDR (1 << 5)\r
-#define DWEMMC_INT_TXDR (1 << 4)\r
-#define DWEMMC_INT_DTO (1 << 3) /* Data trans over */\r
-#define DWEMMC_INT_CMD_DONE (1 << 2)\r
-#define DWEMMC_INT_RE (1 << 1)\r
-\r
-#define DWEMMC_IDMAC_DES0_DIC (1 << 1)\r
-#define DWEMMC_IDMAC_DES0_LD (1 << 2)\r
-#define DWEMMC_IDMAC_DES0_FS (1 << 3)\r
-#define DWEMMC_IDMAC_DES0_CH (1 << 4)\r
-#define DWEMMC_IDMAC_DES0_ER (1 << 5)\r
-#define DWEMMC_IDMAC_DES0_CES (1 << 30)\r
-#define DWEMMC_IDMAC_DES0_OWN (1 << 31)\r
-#define DWEMMC_IDMAC_DES1_BS1(x) ((x) & 0x1fff)\r
-#define DWEMMC_IDMAC_DES2_BS2(x) (((x) & 0x1fff) << 13)\r
-#define DWEMMC_IDMAC_SWRESET (1 << 0)\r
-#define DWEMMC_IDMAC_FB (1 << 1)\r
-#define DWEMMC_IDMAC_ENABLE (1 << 7)\r
-\r
-#define EMMC_FIX_RCA 6\r
-\r
-/* bits in MMC0_CTRL */\r
-#define DWEMMC_CTRL_RESET (1 << 0)\r
-#define DWEMMC_CTRL_FIFO_RESET (1 << 1)\r
-#define DWEMMC_CTRL_DMA_RESET (1 << 2)\r
-#define DWEMMC_CTRL_INT_EN (1 << 4)\r
-#define DWEMMC_CTRL_DMA_EN (1 << 5)\r
-#define DWEMMC_CTRL_IDMAC_EN (1 << 25)\r
-#define DWEMMC_CTRL_RESET_ALL (DWEMMC_CTRL_RESET | DWEMMC_CTRL_FIFO_RESET | DWEMMC_CTRL_DMA_RESET)\r
-\r
-#define DWEMMC_STS_DATA_BUSY (1 << 9)\r
-\r
-#define DWEMMC_FIFO_TWMARK(x) (x & 0xfff)\r
-#define DWEMMC_FIFO_RWMARK(x) ((x & 0x1ff) << 16)\r
-#define DWEMMC_DMA_BURST_SIZE(x) ((x & 0x7) << 28)\r
-\r
-#define DWEMMC_CARD_RD_THR(x) ((x & 0xfff) << 16)\r
-#define DWEMMC_CARD_RD_THR_EN (1 << 0)\r
-\r
-#define DWEMMC_GET_HDATA_WIDTH(x) (((x) >> 7) & 0x7)\r
-\r
-#endif // __DWEMMC_H__\r
+++ /dev/null
-/** @file\r
- This file implement the MMC Host Protocol for the DesignWare eMMC.\r
-\r
- Copyright (c) 2014-2017, Linaro Limited. All rights reserved.\r
-\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/CacheMaintenanceLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/DevicePathLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/TimerLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiLib.h>\r
-\r
-#include <Protocol/MmcHost.h>\r
-\r
-#include "DwEmmc.h"\r
-\r
-#define DWEMMC_DESC_PAGE 1\r
-#define DWEMMC_BLOCK_SIZE 512\r
-#define DWEMMC_DMA_BUF_SIZE (512 * 8)\r
-#define DWEMMC_MAX_DESC_PAGES 512\r
-\r
-typedef struct {\r
- UINT32 Des0;\r
- UINT32 Des1;\r
- UINT32 Des2;\r
- UINT32 Des3;\r
-} DWEMMC_IDMAC_DESCRIPTOR;\r
-\r
-EFI_MMC_HOST_PROTOCOL *gpMmcHost;\r
-DWEMMC_IDMAC_DESCRIPTOR *gpIdmacDesc;\r
-EFI_GUID mDwEmmcDevicePathGuid = EFI_CALLER_ID_GUID;\r
-STATIC UINT32 mDwEmmcCommand;\r
-STATIC UINT32 mDwEmmcArgument;\r
-\r
-EFI_STATUS\r
-DwEmmcReadBlockData (\r
- IN EFI_MMC_HOST_PROTOCOL *This,\r
- IN EFI_LBA Lba,\r
- IN UINTN Length,\r
- IN UINT32* Buffer\r
- );\r
-\r
-BOOLEAN\r
-DwEmmcIsPowerOn (\r
- VOID\r
- )\r
-{\r
- return TRUE;\r
-}\r
-\r
-EFI_STATUS\r
-DwEmmcInitialize (\r
- VOID\r
- )\r
-{\r
- DEBUG ((DEBUG_BLKIO, "DwEmmcInitialize()"));\r
- return EFI_SUCCESS;\r
-}\r
-\r
-BOOLEAN\r
-DwEmmcIsCardPresent (\r
- IN EFI_MMC_HOST_PROTOCOL *This\r
- )\r
-{\r
- return TRUE;\r
-}\r
-\r
-BOOLEAN\r
-DwEmmcIsReadOnly (\r
- IN EFI_MMC_HOST_PROTOCOL *This\r
- )\r
-{\r
- return FALSE;\r
-}\r
-\r
-BOOLEAN\r
-DwEmmcIsDmaSupported (\r
- IN EFI_MMC_HOST_PROTOCOL *This\r
- )\r
-{\r
- return TRUE;\r
-}\r
-\r
-EFI_STATUS\r
-DwEmmcBuildDevicePath (\r
- IN EFI_MMC_HOST_PROTOCOL *This,\r
- IN EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
- )\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
-\r
- NewDevicePathNode = CreateDeviceNode (HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH));\r
- CopyGuid (& ((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &mDwEmmcDevicePathGuid);\r
-\r
- *DevicePath = NewDevicePathNode;\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-DwEmmcUpdateClock (\r
- VOID\r
- )\r
-{\r
- UINT32 Data;\r
-\r
- /* CMD_UPDATE_CLK */\r
- Data = BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_UPDATE_CLOCK_ONLY |\r
- BIT_CMD_START;\r
- MmioWrite32 (DWEMMC_CMD, Data);\r
- while (1) {\r
- Data = MmioRead32 (DWEMMC_CMD);\r
- if (!(Data & CMD_START_BIT)) {\r
- break;\r
- }\r
- Data = MmioRead32 (DWEMMC_RINTSTS);\r
- if (Data & DWEMMC_INT_HLE) {\r
- Print (L"failed to update mmc clock frequency\n");\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-DwEmmcSetClock (\r
- IN UINTN ClockFreq\r
- )\r
-{\r
- UINT32 Divider, Rate, Data;\r
- EFI_STATUS Status;\r
- BOOLEAN Found = FALSE;\r
-\r
- for (Divider = 1; Divider < 256; Divider++) {\r
- Rate = PcdGet32 (PcdDwEmmcDxeClockFrequencyInHz);\r
- if ((Rate / (2 * Divider)) <= ClockFreq) {\r
- Found = TRUE;\r
- break;\r
- }\r
- }\r
- if (Found == FALSE) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- // Wait until MMC is idle\r
- do {\r
- Data = MmioRead32 (DWEMMC_STATUS);\r
- } while (Data & DWEMMC_STS_DATA_BUSY);\r
-\r
- // Disable MMC clock first\r
- MmioWrite32 (DWEMMC_CLKENA, 0);\r
- Status = DwEmmcUpdateClock ();\r
- ASSERT (!EFI_ERROR (Status));\r
-\r
- MmioWrite32 (DWEMMC_CLKDIV, Divider);\r
- Status = DwEmmcUpdateClock ();\r
- ASSERT (!EFI_ERROR (Status));\r
-\r
- // Enable MMC clock\r
- MmioWrite32 (DWEMMC_CLKENA, 1);\r
- MmioWrite32 (DWEMMC_CLKSRC, 0);\r
- Status = DwEmmcUpdateClock ();\r
- ASSERT (!EFI_ERROR (Status));\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-DwEmmcNotifyState (\r
- IN EFI_MMC_HOST_PROTOCOL *This,\r
- IN MMC_STATE State\r
- )\r
-{\r
- UINT32 Data;\r
- EFI_STATUS Status;\r
-\r
- switch (State) {\r
- case MmcInvalidState:\r
- return EFI_INVALID_PARAMETER;\r
- case MmcHwInitializationState:\r
- MmioWrite32 (DWEMMC_PWREN, 1);\r
-\r
- // If device already turn on then restart it\r
- Data = DWEMMC_CTRL_RESET_ALL;\r
- MmioWrite32 (DWEMMC_CTRL, Data);\r
- do {\r
- // Wait until reset operation finished\r
- Data = MmioRead32 (DWEMMC_CTRL);\r
- } while (Data & DWEMMC_CTRL_RESET_ALL);\r
-\r
- // Setup clock that could not be higher than 400KHz.\r
- Status = DwEmmcSetClock (400000);\r
- ASSERT (!EFI_ERROR (Status));\r
- // Wait clock stable\r
- MicroSecondDelay (100);\r
-\r
- MmioWrite32 (DWEMMC_RINTSTS, ~0);\r
- MmioWrite32 (DWEMMC_INTMASK, 0);\r
- MmioWrite32 (DWEMMC_TMOUT, ~0);\r
- MmioWrite32 (DWEMMC_IDINTEN, 0);\r
- MmioWrite32 (DWEMMC_BMOD, DWEMMC_IDMAC_SWRESET);\r
-\r
- MmioWrite32 (DWEMMC_BLKSIZ, DWEMMC_BLOCK_SIZE);\r
- do {\r
- Data = MmioRead32 (DWEMMC_BMOD);\r
- } while (Data & DWEMMC_IDMAC_SWRESET);\r
- break;\r
- case MmcIdleState:\r
- break;\r
- case MmcReadyState:\r
- break;\r
- case MmcIdentificationState:\r
- break;\r
- case MmcStandByState:\r
- break;\r
- case MmcTransferState:\r
- break;\r
- case MmcSendingDataState:\r
- break;\r
- case MmcReceiveDataState:\r
- break;\r
- case MmcProgrammingState:\r
- break;\r
- case MmcDisconnectState:\r
- break;\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- return EFI_SUCCESS;\r
-}\r
-\r
-// Need to prepare DMA buffer first before sending commands to MMC card\r
-BOOLEAN\r
-IsPendingReadCommand (\r
- IN MMC_CMD MmcCmd\r
- )\r
-{\r
- UINTN Mask;\r
-\r
- Mask = BIT_CMD_DATA_EXPECTED | BIT_CMD_READ;\r
- if ((MmcCmd & Mask) == Mask) {\r
- return TRUE;\r
- }\r
- return FALSE;\r
-}\r
-\r
-BOOLEAN\r
-IsPendingWriteCommand (\r
- IN MMC_CMD MmcCmd\r
- )\r
-{\r
- UINTN Mask;\r
-\r
- Mask = BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE;\r
- if ((MmcCmd & Mask) == Mask) {\r
- return TRUE;\r
- }\r
- return FALSE;\r
-}\r
-\r
-EFI_STATUS\r
-SendCommand (\r
- IN MMC_CMD MmcCmd,\r
- IN UINT32 Argument\r
- )\r
-{\r
- UINT32 Data, ErrMask;\r
-\r
- // Wait until MMC is idle\r
- do {\r
- Data = MmioRead32 (DWEMMC_STATUS);\r
- } while (Data & DWEMMC_STS_DATA_BUSY);\r
-\r
- MmioWrite32 (DWEMMC_RINTSTS, ~0);\r
- MmioWrite32 (DWEMMC_CMDARG, Argument);\r
- MmioWrite32 (DWEMMC_CMD, MmcCmd);\r
-\r
- ErrMask = DWEMMC_INT_EBE | DWEMMC_INT_HLE | DWEMMC_INT_RTO |\r
- DWEMMC_INT_RCRC | DWEMMC_INT_RE;\r
- ErrMask |= DWEMMC_INT_DCRC | DWEMMC_INT_DRT | DWEMMC_INT_SBE;\r
- do {\r
- MicroSecondDelay(500);\r
- Data = MmioRead32 (DWEMMC_RINTSTS);\r
-\r
- if (Data & ErrMask) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- if (Data & DWEMMC_INT_DTO) { // Transfer Done\r
- break;\r
- }\r
- } while (!(Data & DWEMMC_INT_CMD_DONE));\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-DwEmmcSendCommand (\r
- IN EFI_MMC_HOST_PROTOCOL *This,\r
- IN MMC_CMD MmcCmd,\r
- IN UINT32 Argument\r
- )\r
-{\r
- UINT32 Cmd = 0;\r
- EFI_STATUS Status = EFI_SUCCESS;\r
-\r
- switch (MMC_GET_INDX(MmcCmd)) {\r
- case MMC_INDX(0):\r
- Cmd = BIT_CMD_SEND_INIT;\r
- break;\r
- case MMC_INDX(1):\r
- Cmd = BIT_CMD_RESPONSE_EXPECT;\r
- break;\r
- case MMC_INDX(2):\r
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE |\r
- BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_SEND_INIT;\r
- break;\r
- case MMC_INDX(3):\r
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |\r
- BIT_CMD_SEND_INIT;\r
- break;\r
- case MMC_INDX(7):\r
- if (Argument)\r
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;\r
- else\r
- Cmd = 0;\r
- break;\r
- case MMC_INDX(8):\r
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |\r
- BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |\r
- BIT_CMD_WAIT_PRVDATA_COMPLETE;\r
- break;\r
- case MMC_INDX(9):\r
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |\r
- BIT_CMD_LONG_RESPONSE;\r
- break;\r
- case MMC_INDX(12):\r
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |\r
- BIT_CMD_STOP_ABORT_CMD;\r
- break;\r
- case MMC_INDX(13):\r
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |\r
- BIT_CMD_WAIT_PRVDATA_COMPLETE;\r
- break;\r
- case MMC_INDX(16):\r
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |\r
- BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |\r
- BIT_CMD_WAIT_PRVDATA_COMPLETE;\r
- break;\r
- case MMC_INDX(17):\r
- case MMC_INDX(18):\r
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |\r
- BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |\r
- BIT_CMD_WAIT_PRVDATA_COMPLETE;\r
- break;\r
- case MMC_INDX(24):\r
- case MMC_INDX(25):\r
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |\r
- BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE |\r
- BIT_CMD_WAIT_PRVDATA_COMPLETE;\r
- break;\r
- case MMC_INDX(30):\r
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |\r
- BIT_CMD_DATA_EXPECTED;\r
- break;\r
- default:\r
- Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;\r
- break;\r
- }\r
-\r
- Cmd |= MMC_GET_INDX(MmcCmd) | BIT_CMD_USE_HOLD_REG | BIT_CMD_START;\r
- if (IsPendingReadCommand (Cmd) || IsPendingWriteCommand (Cmd)) {\r
- mDwEmmcCommand = Cmd;\r
- mDwEmmcArgument = Argument;\r
- } else {\r
- Status = SendCommand (Cmd, Argument);\r
- }\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-DwEmmcReceiveResponse (\r
- IN EFI_MMC_HOST_PROTOCOL *This,\r
- IN MMC_RESPONSE_TYPE Type,\r
- IN UINT32* Buffer\r
- )\r
-{\r
- if (Buffer == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ( (Type == MMC_RESPONSE_TYPE_R1)\r
- || (Type == MMC_RESPONSE_TYPE_R1b)\r
- || (Type == MMC_RESPONSE_TYPE_R3)\r
- || (Type == MMC_RESPONSE_TYPE_R6)\r
- || (Type == MMC_RESPONSE_TYPE_R7))\r
- {\r
- Buffer[0] = MmioRead32 (DWEMMC_RESP0);\r
- } else if (Type == MMC_RESPONSE_TYPE_R2) {\r
- Buffer[0] = MmioRead32 (DWEMMC_RESP0);\r
- Buffer[1] = MmioRead32 (DWEMMC_RESP1);\r
- Buffer[2] = MmioRead32 (DWEMMC_RESP2);\r
- Buffer[3] = MmioRead32 (DWEMMC_RESP3);\r
- }\r
- return EFI_SUCCESS;\r
-}\r
-\r
-VOID\r
-DwEmmcAdjustFifoThreshold (\r
- VOID\r
- )\r
-{\r
- /* DMA multiple transaction size map to reg value as array index */\r
- CONST UINT32 BurstSize[] = {1, 4, 8, 16, 32, 64, 128, 256};\r
- UINT32 BlkDepthInFifo, FifoThreshold, FifoWidth, FifoDepth;\r
- UINT32 BlkSize = DWEMMC_BLOCK_SIZE, Idx = 0, RxWatermark = 1, TxWatermark, TxWatermarkInvers;\r
-\r
- /* Skip FIFO adjustment if we do not have platform FIFO depth info */\r
- FifoDepth = PcdGet32 (PcdDwEmmcDxeFifoDepth);\r
- if (!FifoDepth) {\r
- return;\r
- }\r
-\r
- TxWatermark = FifoDepth / 2;\r
- TxWatermarkInvers = FifoDepth - TxWatermark;\r
-\r
- FifoWidth = DWEMMC_GET_HDATA_WIDTH (MmioRead32 (DWEMMC_HCON));\r
- if (!FifoWidth) {\r
- FifoWidth = 2;\r
- } else if (FifoWidth == 2) {\r
- FifoWidth = 8;\r
- } else {\r
- FifoWidth = 4;\r
- }\r
-\r
- BlkDepthInFifo = BlkSize / FifoWidth;\r
-\r
- Idx = ARRAY_SIZE (BurstSize) - 1;\r
- while (Idx && ((BlkDepthInFifo % BurstSize[Idx]) || (TxWatermarkInvers % BurstSize[Idx]))) {\r
- Idx--;\r
- }\r
-\r
- RxWatermark = BurstSize[Idx] - 1;\r
- FifoThreshold = DWEMMC_DMA_BURST_SIZE (Idx) | DWEMMC_FIFO_TWMARK (TxWatermark)\r
- | DWEMMC_FIFO_RWMARK (RxWatermark);\r
- MmioWrite32 (DWEMMC_FIFOTH, FifoThreshold);\r
-}\r
-\r
-EFI_STATUS\r
-PrepareDmaData (\r
- IN DWEMMC_IDMAC_DESCRIPTOR* IdmacDesc,\r
- IN UINTN Length,\r
- IN UINT32* Buffer\r
- )\r
-{\r
- UINTN Cnt, Blks, Idx, LastIdx;\r
-\r
- Cnt = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;\r
- Blks = (Length + DWEMMC_BLOCK_SIZE - 1) / DWEMMC_BLOCK_SIZE;\r
- Length = DWEMMC_BLOCK_SIZE * Blks;\r
-\r
- for (Idx = 0; Idx < Cnt; Idx++) {\r
- (IdmacDesc + Idx)->Des0 = DWEMMC_IDMAC_DES0_OWN | DWEMMC_IDMAC_DES0_CH |\r
- DWEMMC_IDMAC_DES0_DIC;\r
- (IdmacDesc + Idx)->Des1 = DWEMMC_IDMAC_DES1_BS1(DWEMMC_DMA_BUF_SIZE);\r
- /* Buffer Address */\r
- (IdmacDesc + Idx)->Des2 = (UINT32)((UINTN)Buffer + DWEMMC_DMA_BUF_SIZE * Idx);\r
- /* Next Descriptor Address */\r
- (IdmacDesc + Idx)->Des3 = (UINT32)((UINTN)IdmacDesc +\r
- (sizeof(DWEMMC_IDMAC_DESCRIPTOR) * (Idx + 1)));\r
- }\r
- /* First Descriptor */\r
- IdmacDesc->Des0 |= DWEMMC_IDMAC_DES0_FS;\r
- /* Last Descriptor */\r
- LastIdx = Cnt - 1;\r
- (IdmacDesc + LastIdx)->Des0 |= DWEMMC_IDMAC_DES0_LD;\r
- (IdmacDesc + LastIdx)->Des0 &= ~(DWEMMC_IDMAC_DES0_DIC | DWEMMC_IDMAC_DES0_CH);\r
- (IdmacDesc + LastIdx)->Des1 = DWEMMC_IDMAC_DES1_BS1(Length -\r
- (LastIdx * DWEMMC_DMA_BUF_SIZE));\r
- /* Set the Next field of Last Descriptor */\r
- (IdmacDesc + LastIdx)->Des3 = 0;\r
- MmioWrite32 (DWEMMC_DBADDR, (UINT32)((UINTN)IdmacDesc));\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-VOID\r
-StartDma (\r
- UINTN Length\r
- )\r
-{\r
- UINT32 Data;\r
-\r
- Data = MmioRead32 (DWEMMC_CTRL);\r
- Data |= DWEMMC_CTRL_INT_EN | DWEMMC_CTRL_DMA_EN | DWEMMC_CTRL_IDMAC_EN;\r
- MmioWrite32 (DWEMMC_CTRL, Data);\r
- Data = MmioRead32 (DWEMMC_BMOD);\r
- Data |= DWEMMC_IDMAC_ENABLE | DWEMMC_IDMAC_FB;\r
- MmioWrite32 (DWEMMC_BMOD, Data);\r
-\r
- MmioWrite32 (DWEMMC_BLKSIZ, DWEMMC_BLOCK_SIZE);\r
- MmioWrite32 (DWEMMC_BYTCNT, Length);\r
-}\r
-\r
-EFI_STATUS\r
-DwEmmcReadBlockData (\r
- IN EFI_MMC_HOST_PROTOCOL *This,\r
- IN EFI_LBA Lba,\r
- IN UINTN Length,\r
- IN UINT32* Buffer\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 DescPages, CountPerPage, Count;\r
- EFI_TPL Tpl;\r
-\r
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-\r
- CountPerPage = EFI_PAGE_SIZE / 16;\r
- Count = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;\r
- DescPages = (Count + CountPerPage - 1) / CountPerPage;\r
-\r
- InvalidateDataCacheRange (Buffer, Length);\r
-\r
- Status = PrepareDmaData (gpIdmacDesc, Length, Buffer);\r
- if (EFI_ERROR (Status)) {\r
- goto out;\r
- }\r
-\r
- WriteBackDataCacheRange (gpIdmacDesc, DescPages * EFI_PAGE_SIZE);\r
- StartDma (Length);\r
-\r
- Status = SendCommand (mDwEmmcCommand, mDwEmmcArgument);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "Failed to read data, mDwEmmcCommand:%x, mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand, mDwEmmcArgument, Status));\r
- goto out;\r
- }\r
-out:\r
- // Restore Tpl\r
- gBS->RestoreTPL (Tpl);\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-DwEmmcWriteBlockData (\r
- IN EFI_MMC_HOST_PROTOCOL *This,\r
- IN EFI_LBA Lba,\r
- IN UINTN Length,\r
- IN UINT32* Buffer\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 DescPages, CountPerPage, Count;\r
- EFI_TPL Tpl;\r
-\r
- Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-\r
- CountPerPage = EFI_PAGE_SIZE / 16;\r
- Count = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;\r
- DescPages = (Count + CountPerPage - 1) / CountPerPage;\r
-\r
- WriteBackDataCacheRange (Buffer, Length);\r
-\r
- Status = PrepareDmaData (gpIdmacDesc, Length, Buffer);\r
- if (EFI_ERROR (Status)) {\r
- goto out;\r
- }\r
-\r
- WriteBackDataCacheRange (gpIdmacDesc, DescPages * EFI_PAGE_SIZE);\r
- StartDma (Length);\r
-\r
- Status = SendCommand (mDwEmmcCommand, mDwEmmcArgument);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "Failed to write data, mDwEmmcCommand:%x, mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand, mDwEmmcArgument, Status));\r
- goto out;\r
- }\r
-out:\r
- // Restore Tpl\r
- gBS->RestoreTPL (Tpl);\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-DwEmmcSetIos (\r
- IN EFI_MMC_HOST_PROTOCOL *This,\r
- IN UINT32 BusClockFreq,\r
- IN UINT32 BusWidth,\r
- IN UINT32 TimingMode\r
- )\r
-{\r
- EFI_STATUS Status = EFI_SUCCESS;\r
- UINT32 Data;\r
-\r
- if ((PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz) != 0) &&\r
- (BusClockFreq > PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz))) {\r
- return EFI_UNSUPPORTED;\r
- }\r
- if (TimingMode != EMMCBACKWARD) {\r
- Data = MmioRead32 (DWEMMC_UHSREG);\r
- switch (TimingMode) {\r
- case EMMCHS52DDR1V2:\r
- case EMMCHS52DDR1V8:\r
- Data |= 1 << 16;\r
- break;\r
- case EMMCHS52:\r
- case EMMCHS26:\r
- Data &= ~(1 << 16);\r
- break;\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
- MmioWrite32 (DWEMMC_UHSREG, Data);\r
- }\r
-\r
- switch (BusWidth) {\r
- case 1:\r
- MmioWrite32 (DWEMMC_CTYPE, 0);\r
- break;\r
- case 4:\r
- MmioWrite32 (DWEMMC_CTYPE, 1);\r
- break;\r
- case 8:\r
- MmioWrite32 (DWEMMC_CTYPE, 1 << 16);\r
- break;\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
- if (BusClockFreq) {\r
- Status = DwEmmcSetClock (BusClockFreq);\r
- }\r
- return Status;\r
-}\r
-\r
-BOOLEAN\r
-DwEmmcIsMultiBlock (\r
- IN EFI_MMC_HOST_PROTOCOL *This\r
- )\r
-{\r
- return TRUE;\r
-}\r
-\r
-EFI_MMC_HOST_PROTOCOL gMciHost = {\r
- MMC_HOST_PROTOCOL_REVISION,\r
- DwEmmcIsCardPresent,\r
- DwEmmcIsReadOnly,\r
- DwEmmcBuildDevicePath,\r
- DwEmmcNotifyState,\r
- DwEmmcSendCommand,\r
- DwEmmcReceiveResponse,\r
- DwEmmcReadBlockData,\r
- DwEmmcWriteBlockData,\r
- DwEmmcSetIos,\r
- DwEmmcIsMultiBlock\r
-};\r
-\r
-EFI_STATUS\r
-DwEmmcDxeInitialize (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE Handle;\r
-\r
- Handle = NULL;\r
-\r
- DwEmmcAdjustFifoThreshold ();\r
- gpIdmacDesc = (DWEMMC_IDMAC_DESCRIPTOR *)AllocatePages (DWEMMC_MAX_DESC_PAGES);\r
- if (gpIdmacDesc == NULL) {\r
- return EFI_BUFFER_TOO_SMALL;\r
- }\r
-\r
- DEBUG ((DEBUG_BLKIO, "DwEmmcDxeInitialize()\n"));\r
-\r
- //Publish Component Name, BlockIO protocol interfaces\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Handle,\r
- &gEmbeddedMmcHostProtocolGuid, &gMciHost,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- return EFI_SUCCESS;\r
-}\r