DwEmmcDxe.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. /** @file
  2. This file implement the MMC Host Protocol for the DesignWare eMMC.
  3. WARNING:
  4. This driver fails to follow the UEFI driver model without a good
  5. reason, and only remains in the tree because it is still used by
  6. a small number of platforms. It will be removed when no longer used.
  7. Copyright (c) 2014-2017, Linaro Limited. All rights reserved.
  8. SPDX-License-Identifier: BSD-2-Clause-Patent
  9. **/
  10. #include <Library/BaseMemoryLib.h>
  11. #include <Library/CacheMaintenanceLib.h>
  12. #include <Library/DebugLib.h>
  13. #include <Library/DevicePathLib.h>
  14. #include <Library/IoLib.h>
  15. #include <Library/MemoryAllocationLib.h>
  16. #include <Library/PcdLib.h>
  17. #include <Library/TimerLib.h>
  18. #include <Library/UefiBootServicesTableLib.h>
  19. #include <Library/UefiLib.h>
  20. #include <Protocol/MmcHost.h>
  21. #ifdef CONFIG_DWEMMC
  22. #define PcdDwDxeBaseAddress ((UINT32)PcdGet32 (PcdDwEmmcDxeBaseAddress))
  23. #elif CONFIG_DWSDMMC
  24. #define PcdDwDxeBaseAddress ((UINT32)PcdGet32 (PcdDwSdDxeBaseAddress))
  25. #endif
  26. #include "DwEmmc.h"
  27. #define DWEMMC_DESC_PAGE 1
  28. #define DWEMMC_BLOCK_SIZE 512
  29. #define DWEMMC_DMA_BUF_SIZE (512 * 8)
  30. #define DWEMMC_MAX_DESC_PAGES 512
  31. /* Internal IDMAC interrupt defines */
  32. #define DWMCI_IDINTEN_RI (1 << 1)
  33. #define DWMCI_IDINTEN_TI (1 << 0)
  34. #define DWMCI_IDINTEN_MASK (DWMCI_IDINTEN_TI | \
  35. DWMCI_IDINTEN_RI)
  36. #define DWMCI_DMA_EN (1 << 5)
  37. typedef struct {
  38. UINT32 Des0;
  39. UINT32 Des1;
  40. UINT32 Des2;
  41. UINT32 Des3;
  42. } DWEMMC_IDMAC_DESCRIPTOR;
  43. EFI_MMC_HOST_PROTOCOL *gpMmcHost;
  44. DWEMMC_IDMAC_DESCRIPTOR *gpIdmacDesc;
  45. EFI_GUID mDwEmmcDevicePathGuid = EFI_CALLER_ID_GUID;
  46. STATIC UINT32 mDwEmmcCommand;
  47. STATIC UINT32 mDwEmmcArgument;
  48. STATIC UINT32 app_cmd = 0;
  49. EFI_STATUS
  50. DwEmmcReadBlockData (
  51. IN EFI_MMC_HOST_PROTOCOL *This,
  52. IN EFI_LBA Lba,
  53. IN UINTN Length,
  54. IN UINT32* Buffer
  55. );
  56. BOOLEAN
  57. DwEmmcIsPowerOn (
  58. VOID
  59. )
  60. {
  61. return TRUE;
  62. }
  63. EFI_STATUS
  64. DwEmmcInitialize (
  65. VOID
  66. )
  67. {
  68. DEBUG ((DEBUG_BLKIO, "DwEmmcInitialize()"));
  69. return EFI_SUCCESS;
  70. }
  71. BOOLEAN
  72. DwEmmcIsCardPresent (
  73. IN EFI_MMC_HOST_PROTOCOL *This
  74. )
  75. {
  76. return TRUE;
  77. }
  78. BOOLEAN
  79. DwEmmcIsReadOnly (
  80. IN EFI_MMC_HOST_PROTOCOL *This
  81. )
  82. {
  83. return FALSE;
  84. }
  85. BOOLEAN
  86. DwEmmcIsDmaSupported (
  87. IN EFI_MMC_HOST_PROTOCOL *This
  88. )
  89. {
  90. return TRUE;
  91. }
  92. void mmc_debug_printf()
  93. {
  94. //UINT32 data, data1,
  95. UINT32 addr = 0x16020000;
  96. //data = MmioRead32(0x13020170);
  97. //data1 = MmioRead32(0x13020178);
  98. //DEBUG ((DEBUG_INFO, "\nCLK 0 0x%x clk 1 0x%x\n", data, data1));
  99. for (; addr <= 0x16020098; addr+=4) {
  100. if ((addr & 0xf) == 0x0) {
  101. DEBUG ((DEBUG_INFO,"\naddr 0x%08x:", addr));
  102. }
  103. DEBUG ((DEBUG_INFO, " %08x", MmioRead32(addr)));
  104. }
  105. DEBUG ((DEBUG_INFO, "\n"));
  106. }
  107. EFI_STATUS
  108. DwEmmcBuildDevicePath (
  109. IN EFI_MMC_HOST_PROTOCOL *This,
  110. IN EFI_DEVICE_PATH_PROTOCOL **DevicePath
  111. )
  112. {
  113. EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
  114. NewDevicePathNode = CreateDeviceNode (HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH));
  115. CopyGuid (& ((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &mDwEmmcDevicePathGuid);
  116. *DevicePath = NewDevicePathNode;
  117. return EFI_SUCCESS;
  118. }
  119. EFI_STATUS
  120. DwEmmcUpdateClock (
  121. VOID
  122. )
  123. {
  124. UINT32 Data;
  125. /* CMD_UPDATE_CLK */
  126. Data = BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_UPDATE_CLOCK_ONLY |
  127. BIT_CMD_START;
  128. MmioWrite32 (DWEMMC_CMD, Data);
  129. while (1) {
  130. Data = MmioRead32 (DWEMMC_CMD);
  131. if (!(Data & CMD_START_BIT)) {
  132. break;
  133. }
  134. Data = MmioRead32 (DWEMMC_RINTSTS);
  135. if (Data & DWEMMC_INT_HLE) {
  136. Print (L"failed to update mmc clock frequency\n");
  137. return EFI_DEVICE_ERROR;
  138. }
  139. }
  140. return EFI_SUCCESS;
  141. }
  142. EFI_STATUS
  143. DwEmmcSetClock (
  144. IN UINTN ClockFreq
  145. )
  146. {
  147. UINT32 Divider, Rate, Data;
  148. EFI_STATUS Status;
  149. BOOLEAN Found = FALSE;
  150. for (Divider = 1; Divider < 256; Divider++) {
  151. Rate = PcdGet32 (PcdDwEmmcDxeClockFrequencyInHz);
  152. if ((Rate / (2 * Divider)) <= ClockFreq) {
  153. Found = TRUE;
  154. break;
  155. }
  156. }
  157. if (Found == FALSE) {
  158. return EFI_NOT_FOUND;
  159. }
  160. // Wait until MMC is idle
  161. do {
  162. Data = MmioRead32 (DWEMMC_STATUS);
  163. } while (Data & DWEMMC_STS_DATA_BUSY);
  164. // Disable MMC clock first
  165. MmioWrite32 (DWEMMC_CLKENA, 0);
  166. Status = DwEmmcUpdateClock ();
  167. ASSERT (!EFI_ERROR (Status));
  168. MmioWrite32 (DWEMMC_CLKDIV, Divider);
  169. Status = DwEmmcUpdateClock ();
  170. ASSERT (!EFI_ERROR (Status));
  171. // Enable MMC clock
  172. MmioWrite32 (DWEMMC_CLKENA, 1);
  173. MmioWrite32 (DWEMMC_CLKSRC, 0);
  174. Status = DwEmmcUpdateClock ();
  175. ASSERT (!EFI_ERROR (Status));
  176. return EFI_SUCCESS;
  177. }
  178. EFI_STATUS
  179. DwEmmcNotifyState (
  180. IN EFI_MMC_HOST_PROTOCOL *This,
  181. IN MMC_STATE State
  182. )
  183. {
  184. UINT32 Data;
  185. EFI_STATUS Status;
  186. switch (State) {
  187. case MmcInvalidState:
  188. return EFI_INVALID_PARAMETER;
  189. case MmcHwInitializationState:
  190. MmioWrite32 (DWEMMC_PWREN, 1);
  191. // If device already turn on then restart it
  192. Data = DWEMMC_CTRL_RESET_ALL;
  193. MmioWrite32 (DWEMMC_CTRL, Data);
  194. do {
  195. // Wait until reset operation finished
  196. Data = MmioRead32 (DWEMMC_CTRL);
  197. } while (Data & DWEMMC_CTRL_RESET_ALL);
  198. // Setup clock that could not be higher than 400KHz.
  199. Status = DwEmmcSetClock (400000);
  200. ASSERT (!EFI_ERROR (Status));
  201. // Wait clock stable
  202. MicroSecondDelay (100);
  203. MmioWrite32 (DWEMMC_CTYPE, 0);
  204. MmioWrite32 (DWEMMC_RINTSTS, ~0);
  205. MmioWrite32 (DWEMMC_INTMASK, 0);
  206. MmioWrite32 (DWEMMC_TMOUT, ~0);
  207. MmioWrite32 (DWEMMC_IDINTEN, 0);
  208. MmioWrite32 (DWEMMC_BMOD, DWEMMC_IDMAC_SWRESET);
  209. MmioWrite32 (DWEMMC_BLKSIZ, DWEMMC_BLOCK_SIZE);
  210. do {
  211. Data = MmioRead32 (DWEMMC_BMOD);
  212. } while (Data & DWEMMC_IDMAC_SWRESET);
  213. MmioWrite32 (DWEMMC_IDINTEN, 0x3);
  214. break;
  215. case MmcIdleState:
  216. break;
  217. case MmcReadyState:
  218. break;
  219. case MmcIdentificationState:
  220. break;
  221. case MmcStandByState:
  222. break;
  223. case MmcTransferState:
  224. break;
  225. case MmcSendingDataState:
  226. break;
  227. case MmcReceiveDataState:
  228. break;
  229. case MmcProgrammingState:
  230. break;
  231. case MmcDisconnectState:
  232. break;
  233. default:
  234. return EFI_INVALID_PARAMETER;
  235. }
  236. return EFI_SUCCESS;
  237. }
  238. // Need to prepare DMA buffer first before sending commands to MMC card
  239. BOOLEAN
  240. IsPendingReadCommand (
  241. IN MMC_CMD MmcCmd
  242. )
  243. {
  244. UINTN Mask;
  245. Mask = BIT_CMD_DATA_EXPECTED | BIT_CMD_READ;
  246. if ((MmcCmd & Mask) == Mask) {
  247. return TRUE;
  248. }
  249. return FALSE;
  250. }
  251. BOOLEAN
  252. IsPendingWriteCommand (
  253. IN MMC_CMD MmcCmd
  254. )
  255. {
  256. UINTN Mask;
  257. Mask = BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE;
  258. if ((MmcCmd & Mask) == Mask) {
  259. return TRUE;
  260. }
  261. return FALSE;
  262. }
  263. EFI_STATUS
  264. SendCommand (
  265. IN MMC_CMD MmcCmd,
  266. IN UINT32 Argument
  267. )
  268. {
  269. UINT32 Data, ErrMask;
  270. // Wait until MMC is idle
  271. do {
  272. Data = MmioRead32 (DWEMMC_STATUS);
  273. } while (Data & DWEMMC_STS_DATA_BUSY);
  274. MmioWrite32 (DWEMMC_RINTSTS, ~0);
  275. MmioWrite32 (DWEMMC_CMDARG, Argument);
  276. MmioWrite32 (DWEMMC_CMD, MmcCmd);
  277. //DEBUG ((DEBUG_INFO, "send cmd %d arg %x\n", MmcCmd & 0x3f, Argument));
  278. ErrMask = DWEMMC_INT_EBE | DWEMMC_INT_HLE | DWEMMC_INT_RTO |
  279. DWEMMC_INT_RCRC | DWEMMC_INT_RE;
  280. ErrMask |= DWEMMC_INT_DCRC | DWEMMC_INT_DRT | DWEMMC_INT_SBE;
  281. do {
  282. MicroSecondDelay(500);
  283. Data = MmioRead32 (DWEMMC_RINTSTS);
  284. if (Data & ErrMask) {
  285. return EFI_DEVICE_ERROR;
  286. }
  287. if (Data & DWEMMC_INT_DTO) { // Transfer Done
  288. break;
  289. }
  290. } while (!(Data & DWEMMC_INT_CMD_DONE));
  291. return EFI_SUCCESS;
  292. }
  293. EFI_STATUS
  294. DwEmmcSendCommand (
  295. IN EFI_MMC_HOST_PROTOCOL *This,
  296. IN MMC_CMD MmcCmd,
  297. IN UINT32 Argument
  298. )
  299. {
  300. UINT32 Cmd = 0;
  301. EFI_STATUS Status = EFI_SUCCESS;
  302. switch (MMC_GET_INDX(MmcCmd)) {
  303. case MMC_INDX(0):
  304. Cmd = BIT_CMD_SEND_INIT;
  305. break;
  306. case MMC_INDX(1):
  307. Cmd = BIT_CMD_RESPONSE_EXPECT;
  308. break;
  309. case MMC_INDX(2):
  310. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE |
  311. BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_SEND_INIT;
  312. break;
  313. case MMC_INDX(3):
  314. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
  315. BIT_CMD_SEND_INIT;
  316. break;
  317. case MMC_INDX(7):
  318. if (Argument)
  319. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
  320. else
  321. Cmd = 0;
  322. break;
  323. case MMC_INDX(8):
  324. if (Argument) /* sd */
  325. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
  326. BIT_CMD_WAIT_PRVDATA_COMPLETE;
  327. else /* emmc */
  328. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
  329. BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
  330. BIT_CMD_WAIT_PRVDATA_COMPLETE;
  331. break;
  332. case MMC_INDX(9):
  333. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
  334. BIT_CMD_LONG_RESPONSE;
  335. break;
  336. case MMC_INDX(12):
  337. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
  338. BIT_CMD_STOP_ABORT_CMD;
  339. break;
  340. case MMC_INDX(13):
  341. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
  342. BIT_CMD_WAIT_PRVDATA_COMPLETE;
  343. break;
  344. case MMC_INDX(16):
  345. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
  346. /* BIT_CMD_DATA_EXPECTED | BIT_CMD_READ | */
  347. BIT_CMD_WAIT_PRVDATA_COMPLETE;
  348. break;
  349. case MMC_INDX(6): /* sd */
  350. if (MmcCmd & (1 << 31))
  351. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
  352. BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
  353. BIT_CMD_WAIT_PRVDATA_COMPLETE;
  354. else
  355. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
  356. break;
  357. case MMC_INDX(17):
  358. case MMC_INDX(18):
  359. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
  360. BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
  361. BIT_CMD_WAIT_PRVDATA_COMPLETE;
  362. break;
  363. case MMC_INDX(24):
  364. case MMC_INDX(25):
  365. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
  366. BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE |
  367. BIT_CMD_WAIT_PRVDATA_COMPLETE;
  368. break;
  369. case MMC_INDX(30):
  370. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
  371. BIT_CMD_DATA_EXPECTED;
  372. break;
  373. default:
  374. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
  375. break;
  376. }
  377. if (app_cmd) {
  378. switch (MMC_GET_INDX(MmcCmd)) {
  379. case MMC_INDX(41):
  380. Cmd = BIT_CMD_RESPONSE_EXPECT;
  381. break;
  382. case MMC_INDX(51):
  383. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
  384. BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
  385. BIT_CMD_WAIT_PRVDATA_COMPLETE;
  386. break;
  387. case MMC_INDX(6):
  388. Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
  389. break;
  390. default:
  391. break;
  392. }
  393. }
  394. Cmd |= MMC_GET_INDX(MmcCmd) | BIT_CMD_USE_HOLD_REG | BIT_CMD_START;
  395. if (IsPendingReadCommand (Cmd) || IsPendingWriteCommand (Cmd)) {
  396. mDwEmmcCommand = Cmd;
  397. mDwEmmcArgument = Argument;
  398. } else {
  399. Status = SendCommand (Cmd, Argument);
  400. }
  401. if ((Status == EFI_SUCCESS) && ((MmcCmd & 0x3f) == 55))
  402. app_cmd = 1;
  403. else
  404. app_cmd = 0;
  405. return Status;
  406. }
  407. EFI_STATUS
  408. DwEmmcReceiveResponse (
  409. IN EFI_MMC_HOST_PROTOCOL *This,
  410. IN MMC_RESPONSE_TYPE Type,
  411. IN UINT32* Buffer
  412. )
  413. {
  414. if (Buffer == NULL) {
  415. return EFI_INVALID_PARAMETER;
  416. }
  417. if ( (Type == MMC_RESPONSE_TYPE_R1)
  418. || (Type == MMC_RESPONSE_TYPE_R1b)
  419. || (Type == MMC_RESPONSE_TYPE_R3)
  420. || (Type == MMC_RESPONSE_TYPE_R6)
  421. || (Type == MMC_RESPONSE_TYPE_R7))
  422. {
  423. Buffer[0] = MmioRead32 (DWEMMC_RESP0);
  424. } else if (Type == MMC_RESPONSE_TYPE_R2) {
  425. Buffer[0] = MmioRead32 (DWEMMC_RESP0);
  426. Buffer[1] = MmioRead32 (DWEMMC_RESP1);
  427. Buffer[2] = MmioRead32 (DWEMMC_RESP2);
  428. Buffer[3] = MmioRead32 (DWEMMC_RESP3);
  429. }
  430. return EFI_SUCCESS;
  431. }
  432. VOID
  433. DwEmmcAdjustFifoThreshold (
  434. VOID
  435. )
  436. {
  437. /* DMA multiple transaction size map to reg value as array index */
  438. CONST UINT32 BurstSize[] = {1, 4, 8, 16, 32, 64, 128, 256};
  439. UINT32 BlkDepthInFifo, FifoThreshold, FifoWidth, FifoDepth;
  440. UINT32 BlkSize = DWEMMC_BLOCK_SIZE, Idx = 0, RxWatermark = 1, TxWatermark, TxWatermarkInvers;
  441. /* Skip FIFO adjustment if we do not have platform FIFO depth info */
  442. FifoDepth = PcdGet32 (PcdDwEmmcDxeFifoDepth);
  443. if (!FifoDepth) {
  444. return;
  445. }
  446. TxWatermark = FifoDepth / 2;
  447. TxWatermarkInvers = FifoDepth - TxWatermark;
  448. FifoWidth = DWEMMC_GET_HDATA_WIDTH (MmioRead32 (DWEMMC_HCON));
  449. if (!FifoWidth) {
  450. FifoWidth = 2;
  451. } else if (FifoWidth == 2) {
  452. FifoWidth = 8;
  453. } else {
  454. FifoWidth = 4;
  455. }
  456. BlkDepthInFifo = BlkSize / FifoWidth;
  457. Idx = ARRAY_SIZE (BurstSize) - 1;
  458. while (Idx && ((BlkDepthInFifo % BurstSize[Idx]) || (TxWatermarkInvers % BurstSize[Idx]))) {
  459. Idx--;
  460. }
  461. RxWatermark = BurstSize[Idx] - 1;
  462. FifoThreshold = DWEMMC_DMA_BURST_SIZE (Idx) | DWEMMC_FIFO_TWMARK (TxWatermark)
  463. | DWEMMC_FIFO_RWMARK (RxWatermark);
  464. MmioWrite32 (DWEMMC_FIFOTH, FifoThreshold);
  465. }
  466. EFI_STATUS
  467. PrepareDmaData (
  468. IN DWEMMC_IDMAC_DESCRIPTOR* IdmacDesc,
  469. IN UINTN Length,
  470. IN UINT32* Buffer
  471. )
  472. {
  473. UINTN Cnt, Blks, Idx, LastIdx;
  474. UINT32 Data/* , flag, cnt */;
  475. MmioWrite32 (DWEMMC_CTRL, DWEMMC_CTRL_FIFO_RESET);
  476. do {
  477. // Wait until reset operation finished
  478. Data = MmioRead32 (DWEMMC_CTRL);
  479. } while (Data & DWEMMC_CTRL_RESET_ALL);
  480. MmioWrite32 (DWEMMC_IDSTS, 0xffffffff);
  481. Cnt = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
  482. Blks = (Length + DWEMMC_BLOCK_SIZE - 1) / DWEMMC_BLOCK_SIZE;
  483. //Length = DWEMMC_BLOCK_SIZE * Blks;
  484. for (Idx = 0; Idx < Cnt; Idx++) {
  485. (IdmacDesc + Idx)->Des0 = DWEMMC_IDMAC_DES0_OWN | DWEMMC_IDMAC_DES0_CH |
  486. DWEMMC_IDMAC_DES0_DIC;
  487. (IdmacDesc + Idx)->Des1 = DWEMMC_IDMAC_DES1_BS1(DWEMMC_DMA_BUF_SIZE);
  488. /* Buffer Address */
  489. (IdmacDesc + Idx)->Des2 = (UINT32)((UINTN)Buffer + DWEMMC_DMA_BUF_SIZE * Idx);
  490. /* Next Descriptor Address */
  491. (IdmacDesc + Idx)->Des3 = (UINT32)((UINTN)IdmacDesc +
  492. (sizeof(DWEMMC_IDMAC_DESCRIPTOR) * (Idx + 1)));
  493. }
  494. /* First Descriptor */
  495. IdmacDesc->Des0 |= DWEMMC_IDMAC_DES0_FS;
  496. /* Last Descriptor */
  497. LastIdx = Cnt - 1;
  498. (IdmacDesc + LastIdx)->Des0 |= DWEMMC_IDMAC_DES0_LD;
  499. (IdmacDesc + LastIdx)->Des0 &= ~(DWEMMC_IDMAC_DES0_DIC | DWEMMC_IDMAC_DES0_CH);
  500. (IdmacDesc + LastIdx)->Des1 = DWEMMC_IDMAC_DES1_BS1(Length -
  501. (LastIdx * DWEMMC_DMA_BUF_SIZE));
  502. /* Set the Next field of Last Descriptor */
  503. //(IdmacDesc + LastIdx)->Des3 = 0;
  504. MmioWrite32 (DWEMMC_DBADDR, (UINT32)((UINTN)IdmacDesc));
  505. return EFI_SUCCESS;
  506. }
  507. VOID
  508. StartDma (
  509. UINTN Length
  510. )
  511. {
  512. UINT32 Data;
  513. Data = MmioRead32 (DWEMMC_CTRL);
  514. Data |= DWEMMC_CTRL_DMA_EN | DWEMMC_CTRL_IDMAC_EN;
  515. MmioWrite32 (DWEMMC_CTRL, Data);
  516. Data = MmioRead32 (DWEMMC_BMOD);
  517. Data |= DWEMMC_IDMAC_ENABLE | DWEMMC_IDMAC_FB;
  518. MmioWrite32 (DWEMMC_BMOD, Data);
  519. MmioWrite32 (DWEMMC_BLKSIZ,
  520. (Length < DWEMMC_BLOCK_SIZE) ? Length : DWEMMC_BLOCK_SIZE);
  521. MmioWrite32 (DWEMMC_BYTCNT, Length);
  522. }
  523. EFI_STATUS
  524. DwEmmcWaitDmaComplete (
  525. IN EFI_MMC_HOST_PROTOCOL *This,
  526. IN UINT32 read
  527. )
  528. {
  529. UINT32 mask, Ctrl, timeout = 100000;
  530. EFI_STATUS ret = EFI_SUCCESS;
  531. if (read)
  532. mask = DWMCI_IDINTEN_RI;
  533. else
  534. mask = DWMCI_IDINTEN_TI;
  535. do {
  536. Ctrl = MmioRead32 (DWEMMC_IDSTS);
  537. if (Ctrl & mask)
  538. break;
  539. timeout--;
  540. gBS->Stall(1);
  541. } while (timeout);
  542. if (!timeout) {
  543. DEBUG ((DEBUG_INFO, "wait dma to\n"));
  544. ret = EFI_DEVICE_ERROR;
  545. }
  546. MmioWrite32 (DWEMMC_IDSTS, DWMCI_IDINTEN_MASK);
  547. Ctrl = MmioRead32(DWEMMC_CTRL);
  548. Ctrl &= ~(DWMCI_DMA_EN);
  549. Ctrl = MmioWrite32(DWEMMC_CTRL, Ctrl);
  550. gBS->Stall(100);
  551. return ret;
  552. }
  553. EFI_STATUS
  554. DwEmmcReadBlockData (
  555. IN EFI_MMC_HOST_PROTOCOL *This,
  556. IN EFI_LBA Lba,
  557. IN UINTN Length,
  558. IN UINT32* Buffer
  559. )
  560. {
  561. EFI_STATUS Status;
  562. UINT32 DescPages, CountPerPage, Count;
  563. EFI_TPL Tpl;
  564. Tpl = gBS->RaiseTPL (TPL_NOTIFY);
  565. CountPerPage = EFI_PAGE_SIZE / 16;
  566. Count = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
  567. DescPages = (Count + CountPerPage - 1) / CountPerPage;
  568. InvalidateDataCacheRange (Buffer, Length);
  569. // DEBUG ((DEBUG_INFO, "BUFFER %lx length %x\n", (UINT64)Buffer, Length));
  570. Status = PrepareDmaData (gpIdmacDesc, Length, Buffer);
  571. if (EFI_ERROR (Status)) {
  572. goto out;
  573. }
  574. WriteBackDataCacheRange (gpIdmacDesc, DescPages * EFI_PAGE_SIZE);
  575. StartDma (Length);
  576. Status = SendCommand (mDwEmmcCommand, mDwEmmcArgument);
  577. if (EFI_ERROR (Status)) {
  578. DEBUG ((DEBUG_ERROR, "Failed to read data, mDwEmmcCommand:%x, mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand, mDwEmmcArgument, Status));
  579. goto out;
  580. }
  581. Status = DwEmmcWaitDmaComplete(This, 1);
  582. out:
  583. // Restore Tpl
  584. gBS->RestoreTPL (Tpl);
  585. return Status;
  586. }
  587. EFI_STATUS
  588. DwEmmcWriteBlockData (
  589. IN EFI_MMC_HOST_PROTOCOL *This,
  590. IN EFI_LBA Lba,
  591. IN UINTN Length,
  592. IN UINT32* Buffer
  593. )
  594. {
  595. EFI_STATUS Status;
  596. UINT32 DescPages, CountPerPage, Count;
  597. EFI_TPL Tpl;
  598. Tpl = gBS->RaiseTPL (TPL_NOTIFY);
  599. CountPerPage = EFI_PAGE_SIZE / 16;
  600. Count = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
  601. DescPages = (Count + CountPerPage - 1) / CountPerPage;
  602. WriteBackDataCacheRange (Buffer, Length);
  603. Status = PrepareDmaData (gpIdmacDesc, Length, Buffer);
  604. if (EFI_ERROR (Status)) {
  605. goto out;
  606. }
  607. WriteBackDataCacheRange (gpIdmacDesc, DescPages * EFI_PAGE_SIZE);
  608. StartDma (Length);
  609. Status = SendCommand (mDwEmmcCommand, mDwEmmcArgument);
  610. if (EFI_ERROR (Status)) {
  611. DEBUG ((DEBUG_ERROR, "Failed to write data, mDwEmmcCommand:%x, mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand, mDwEmmcArgument, Status));
  612. goto out;
  613. }
  614. Status = DwEmmcWaitDmaComplete(This, 0);
  615. out:
  616. // Restore Tpl
  617. gBS->RestoreTPL (Tpl);
  618. return Status;
  619. }
  620. EFI_STATUS
  621. DwEmmcSetIos (
  622. IN EFI_MMC_HOST_PROTOCOL *This,
  623. IN UINT32 BusClockFreq,
  624. IN UINT32 BusWidth,
  625. IN UINT32 TimingMode
  626. )
  627. {
  628. EFI_STATUS Status = EFI_SUCCESS;
  629. UINT32 Data;
  630. if ((PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz) != 0) &&
  631. (BusClockFreq > PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz))) {
  632. return EFI_UNSUPPORTED;
  633. }
  634. if (TimingMode != EMMCBACKWARD) {
  635. Data = MmioRead32 (DWEMMC_UHSREG);
  636. switch (TimingMode) {
  637. case EMMCHS52DDR1V2:
  638. case EMMCHS52DDR1V8:
  639. //Data |= 1 << 16;
  640. //break;
  641. return EFI_UNSUPPORTED;
  642. case EMMCHS52:
  643. case EMMCHS26:
  644. Data &= ~(1 << 16);
  645. break;
  646. default:
  647. break;
  648. }
  649. MmioWrite32 (DWEMMC_UHSREG, Data);
  650. }
  651. //DEBUG ((DEBUG_INFO, "Set bus width %d clock %d\n",BusWidth, BusClockFreq));
  652. switch (BusWidth) {
  653. case 1:
  654. MmioWrite32 (DWEMMC_CTYPE, 0);
  655. break;
  656. case 4:
  657. MmioWrite32 (DWEMMC_CTYPE, 1);
  658. break;
  659. case 8:
  660. MmioWrite32 (DWEMMC_CTYPE, 1 << 16);
  661. break;
  662. default:
  663. return EFI_UNSUPPORTED;
  664. }
  665. if (BusClockFreq) {
  666. Status = DwEmmcSetClock (BusClockFreq);
  667. }
  668. return Status;
  669. }
  670. BOOLEAN
  671. DwEmmcIsMultiBlock (
  672. IN EFI_MMC_HOST_PROTOCOL *This
  673. )
  674. {
  675. return TRUE;
  676. }
  677. EFI_MMC_HOST_PROTOCOL gMciHost = {
  678. MMC_HOST_PROTOCOL_REVISION,
  679. DwEmmcIsCardPresent,
  680. DwEmmcIsReadOnly,
  681. DwEmmcBuildDevicePath,
  682. DwEmmcNotifyState,
  683. DwEmmcSendCommand,
  684. DwEmmcReceiveResponse,
  685. DwEmmcReadBlockData,
  686. DwEmmcWriteBlockData,
  687. DwEmmcSetIos,
  688. DwEmmcIsMultiBlock
  689. };
  690. EFI_STATUS
  691. DwEmmcDxeInitialize (
  692. IN EFI_HANDLE ImageHandle,
  693. IN EFI_SYSTEM_TABLE *SystemTable
  694. )
  695. {
  696. EFI_STATUS Status;
  697. EFI_HANDLE Handle;
  698. if (!FixedPcdGetBool (PcdDwPermitObsoleteDrivers)) {
  699. ASSERT (FALSE);
  700. return EFI_UNSUPPORTED;
  701. }
  702. Handle = NULL;
  703. DwEmmcAdjustFifoThreshold ();
  704. gpIdmacDesc = (DWEMMC_IDMAC_DESCRIPTOR *)AllocatePages (DWEMMC_MAX_DESC_PAGES);
  705. if (gpIdmacDesc == NULL) {
  706. return EFI_BUFFER_TOO_SMALL;
  707. }
  708. DEBUG ((DEBUG_BLKIO, "DwEmmcDxeInitialize()\n"));
  709. //Publish Component Name, BlockIO protocol interfaces
  710. Status = gBS->InstallMultipleProtocolInterfaces (
  711. &Handle,
  712. &gEmbeddedMmcHostProtocolGuid, &gMciHost,
  713. NULL
  714. );
  715. ASSERT_EFI_ERROR (Status);
  716. return EFI_SUCCESS;
  717. }