2 This file implement the MMC Host Protocol for the DesignWare eMMC.
4 Copyright (c) 2014-2017, Linaro Limited. All rights reserved.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
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>
21 #include <Protocol/MmcHost.h>
25 #define DWEMMC_DESC_PAGE 1
26 #define DWEMMC_BLOCK_SIZE 512
27 #define DWEMMC_DMA_BUF_SIZE (512 * 8)
28 #define DWEMMC_MAX_DESC_PAGES 512
35 } DWEMMC_IDMAC_DESCRIPTOR
;
37 EFI_MMC_HOST_PROTOCOL
*gpMmcHost
;
38 DWEMMC_IDMAC_DESCRIPTOR
*gpIdmacDesc
;
39 EFI_GUID mDwEmmcDevicePathGuid
= EFI_CALLER_ID_GUID
;
40 STATIC UINT32 mDwEmmcCommand
;
41 STATIC UINT32 mDwEmmcArgument
;
45 IN EFI_MMC_HOST_PROTOCOL
*This
,
64 DEBUG ((DEBUG_BLKIO
, "DwEmmcInitialize()"));
70 IN EFI_MMC_HOST_PROTOCOL
*This
78 IN EFI_MMC_HOST_PROTOCOL
*This
85 DwEmmcIsDmaSupported (
86 IN EFI_MMC_HOST_PROTOCOL
*This
93 DwEmmcBuildDevicePath (
94 IN EFI_MMC_HOST_PROTOCOL
*This
,
95 IN EFI_DEVICE_PATH_PROTOCOL
**DevicePath
98 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePathNode
;
100 NewDevicePathNode
= CreateDeviceNode (HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, sizeof (VENDOR_DEVICE_PATH
));
101 CopyGuid (& ((VENDOR_DEVICE_PATH
*)NewDevicePathNode
)->Guid
, &mDwEmmcDevicePathGuid
);
103 *DevicePath
= NewDevicePathNode
;
115 Data
= BIT_CMD_WAIT_PRVDATA_COMPLETE
| BIT_CMD_UPDATE_CLOCK_ONLY
|
117 MmioWrite32 (DWEMMC_CMD
, Data
);
119 Data
= MmioRead32 (DWEMMC_CMD
);
120 if (!(Data
& CMD_START_BIT
)) {
123 Data
= MmioRead32 (DWEMMC_RINTSTS
);
124 if (Data
& DWEMMC_INT_HLE
) {
125 Print (L
"failed to update mmc clock frequency\n");
126 return EFI_DEVICE_ERROR
;
137 UINT32 Divider
, Rate
, Data
;
139 BOOLEAN Found
= FALSE
;
141 for (Divider
= 1; Divider
< 256; Divider
++) {
142 Rate
= PcdGet32 (PcdDwEmmcDxeClockFrequencyInHz
);
143 if ((Rate
/ (2 * Divider
)) <= ClockFreq
) {
148 if (Found
== FALSE
) {
149 return EFI_NOT_FOUND
;
152 // Wait until MMC is idle
154 Data
= MmioRead32 (DWEMMC_STATUS
);
155 } while (Data
& DWEMMC_STS_DATA_BUSY
);
157 // Disable MMC clock first
158 MmioWrite32 (DWEMMC_CLKENA
, 0);
159 Status
= DwEmmcUpdateClock ();
160 ASSERT (!EFI_ERROR (Status
));
162 MmioWrite32 (DWEMMC_CLKDIV
, Divider
);
163 Status
= DwEmmcUpdateClock ();
164 ASSERT (!EFI_ERROR (Status
));
167 MmioWrite32 (DWEMMC_CLKENA
, 1);
168 MmioWrite32 (DWEMMC_CLKSRC
, 0);
169 Status
= DwEmmcUpdateClock ();
170 ASSERT (!EFI_ERROR (Status
));
176 IN EFI_MMC_HOST_PROTOCOL
*This
,
184 case MmcInvalidState
:
185 return EFI_INVALID_PARAMETER
;
186 case MmcHwInitializationState
:
187 MmioWrite32 (DWEMMC_PWREN
, 1);
189 // If device already turn on then restart it
190 Data
= DWEMMC_CTRL_RESET_ALL
;
191 MmioWrite32 (DWEMMC_CTRL
, Data
);
193 // Wait until reset operation finished
194 Data
= MmioRead32 (DWEMMC_CTRL
);
195 } while (Data
& DWEMMC_CTRL_RESET_ALL
);
197 // Setup clock that could not be higher than 400KHz.
198 Status
= DwEmmcSetClock (400000);
199 ASSERT (!EFI_ERROR (Status
));
201 MicroSecondDelay (100);
203 MmioWrite32 (DWEMMC_RINTSTS
, ~0);
204 MmioWrite32 (DWEMMC_INTMASK
, 0);
205 MmioWrite32 (DWEMMC_TMOUT
, ~0);
206 MmioWrite32 (DWEMMC_IDINTEN
, 0);
207 MmioWrite32 (DWEMMC_BMOD
, DWEMMC_IDMAC_SWRESET
);
209 MmioWrite32 (DWEMMC_BLKSIZ
, DWEMMC_BLOCK_SIZE
);
211 Data
= MmioRead32 (DWEMMC_BMOD
);
212 } while (Data
& DWEMMC_IDMAC_SWRESET
);
218 case MmcIdentificationState
:
220 case MmcStandByState
:
222 case MmcTransferState
:
224 case MmcSendingDataState
:
226 case MmcReceiveDataState
:
228 case MmcProgrammingState
:
230 case MmcDisconnectState
:
233 return EFI_INVALID_PARAMETER
;
238 // Need to prepare DMA buffer first before sending commands to MMC card
240 IsPendingReadCommand (
246 Mask
= BIT_CMD_DATA_EXPECTED
| BIT_CMD_READ
;
247 if ((MmcCmd
& Mask
) == Mask
) {
254 IsPendingWriteCommand (
260 Mask
= BIT_CMD_DATA_EXPECTED
| BIT_CMD_WRITE
;
261 if ((MmcCmd
& Mask
) == Mask
) {
273 UINT32 Data
, ErrMask
;
275 // Wait until MMC is idle
277 Data
= MmioRead32 (DWEMMC_STATUS
);
278 } while (Data
& DWEMMC_STS_DATA_BUSY
);
280 MmioWrite32 (DWEMMC_RINTSTS
, ~0);
281 MmioWrite32 (DWEMMC_CMDARG
, Argument
);
282 MmioWrite32 (DWEMMC_CMD
, MmcCmd
);
284 ErrMask
= DWEMMC_INT_EBE
| DWEMMC_INT_HLE
| DWEMMC_INT_RTO
|
285 DWEMMC_INT_RCRC
| DWEMMC_INT_RE
;
286 ErrMask
|= DWEMMC_INT_DCRC
| DWEMMC_INT_DRT
| DWEMMC_INT_SBE
;
288 MicroSecondDelay(500);
289 Data
= MmioRead32 (DWEMMC_RINTSTS
);
291 if (Data
& ErrMask
) {
292 return EFI_DEVICE_ERROR
;
294 if (Data
& DWEMMC_INT_DTO
) { // Transfer Done
297 } while (!(Data
& DWEMMC_INT_CMD_DONE
));
303 IN EFI_MMC_HOST_PROTOCOL
*This
,
309 EFI_STATUS Status
= EFI_SUCCESS
;
311 switch (MMC_GET_INDX(MmcCmd
)) {
313 Cmd
= BIT_CMD_SEND_INIT
;
316 Cmd
= BIT_CMD_RESPONSE_EXPECT
;
319 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_LONG_RESPONSE
|
320 BIT_CMD_CHECK_RESPONSE_CRC
| BIT_CMD_SEND_INIT
;
323 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
328 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
;
333 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
334 BIT_CMD_DATA_EXPECTED
| BIT_CMD_READ
|
335 BIT_CMD_WAIT_PRVDATA_COMPLETE
;
338 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
339 BIT_CMD_LONG_RESPONSE
;
342 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
343 BIT_CMD_STOP_ABORT_CMD
;
346 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
347 BIT_CMD_WAIT_PRVDATA_COMPLETE
;
350 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
351 BIT_CMD_DATA_EXPECTED
| BIT_CMD_READ
|
352 BIT_CMD_WAIT_PRVDATA_COMPLETE
;
356 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
357 BIT_CMD_DATA_EXPECTED
| BIT_CMD_READ
|
358 BIT_CMD_WAIT_PRVDATA_COMPLETE
;
362 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
363 BIT_CMD_DATA_EXPECTED
| BIT_CMD_WRITE
|
364 BIT_CMD_WAIT_PRVDATA_COMPLETE
;
367 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
368 BIT_CMD_DATA_EXPECTED
;
371 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
;
375 Cmd
|= MMC_GET_INDX(MmcCmd
) | BIT_CMD_USE_HOLD_REG
| BIT_CMD_START
;
376 if (IsPendingReadCommand (Cmd
) || IsPendingWriteCommand (Cmd
)) {
377 mDwEmmcCommand
= Cmd
;
378 mDwEmmcArgument
= Argument
;
380 Status
= SendCommand (Cmd
, Argument
);
386 DwEmmcReceiveResponse (
387 IN EFI_MMC_HOST_PROTOCOL
*This
,
388 IN MMC_RESPONSE_TYPE Type
,
392 if (Buffer
== NULL
) {
393 return EFI_INVALID_PARAMETER
;
396 if ( (Type
== MMC_RESPONSE_TYPE_R1
)
397 || (Type
== MMC_RESPONSE_TYPE_R1b
)
398 || (Type
== MMC_RESPONSE_TYPE_R3
)
399 || (Type
== MMC_RESPONSE_TYPE_R6
)
400 || (Type
== MMC_RESPONSE_TYPE_R7
))
402 Buffer
[0] = MmioRead32 (DWEMMC_RESP0
);
403 } else if (Type
== MMC_RESPONSE_TYPE_R2
) {
404 Buffer
[0] = MmioRead32 (DWEMMC_RESP0
);
405 Buffer
[1] = MmioRead32 (DWEMMC_RESP1
);
406 Buffer
[2] = MmioRead32 (DWEMMC_RESP2
);
407 Buffer
[3] = MmioRead32 (DWEMMC_RESP3
);
413 DwEmmcAdjustFifoThreshold (
417 /* DMA multiple transaction size map to reg value as array index */
418 CONST UINT32 BurstSize
[] = {1, 4, 8, 16, 32, 64, 128, 256};
419 UINT32 BlkDepthInFifo
, FifoThreshold
, FifoWidth
, FifoDepth
;
420 UINT32 BlkSize
= DWEMMC_BLOCK_SIZE
, Idx
= 0, RxWatermark
= 1, TxWatermark
, TxWatermarkInvers
;
422 /* Skip FIFO adjustment if we do not have platform FIFO depth info */
423 FifoDepth
= PcdGet32 (PcdDwEmmcDxeFifoDepth
);
428 TxWatermark
= FifoDepth
/ 2;
429 TxWatermarkInvers
= FifoDepth
- TxWatermark
;
431 FifoWidth
= DWEMMC_GET_HDATA_WIDTH (MmioRead32 (DWEMMC_HCON
));
434 } else if (FifoWidth
== 2) {
440 BlkDepthInFifo
= BlkSize
/ FifoWidth
;
442 Idx
= ARRAY_SIZE (BurstSize
) - 1;
443 while (Idx
&& ((BlkDepthInFifo
% BurstSize
[Idx
]) || (TxWatermarkInvers
% BurstSize
[Idx
]))) {
447 RxWatermark
= BurstSize
[Idx
] - 1;
448 FifoThreshold
= DWEMMC_DMA_BURST_SIZE (Idx
) | DWEMMC_FIFO_TWMARK (TxWatermark
)
449 | DWEMMC_FIFO_RWMARK (RxWatermark
);
450 MmioWrite32 (DWEMMC_FIFOTH
, FifoThreshold
);
455 IN DWEMMC_IDMAC_DESCRIPTOR
* IdmacDesc
,
460 UINTN Cnt
, Blks
, Idx
, LastIdx
;
462 Cnt
= (Length
+ DWEMMC_DMA_BUF_SIZE
- 1) / DWEMMC_DMA_BUF_SIZE
;
463 Blks
= (Length
+ DWEMMC_BLOCK_SIZE
- 1) / DWEMMC_BLOCK_SIZE
;
464 Length
= DWEMMC_BLOCK_SIZE
* Blks
;
466 for (Idx
= 0; Idx
< Cnt
; Idx
++) {
467 (IdmacDesc
+ Idx
)->Des0
= DWEMMC_IDMAC_DES0_OWN
| DWEMMC_IDMAC_DES0_CH
|
468 DWEMMC_IDMAC_DES0_DIC
;
469 (IdmacDesc
+ Idx
)->Des1
= DWEMMC_IDMAC_DES1_BS1(DWEMMC_DMA_BUF_SIZE
);
471 (IdmacDesc
+ Idx
)->Des2
= (UINT32
)((UINTN
)Buffer
+ DWEMMC_DMA_BUF_SIZE
* Idx
);
472 /* Next Descriptor Address */
473 (IdmacDesc
+ Idx
)->Des3
= (UINT32
)((UINTN
)IdmacDesc
+
474 (sizeof(DWEMMC_IDMAC_DESCRIPTOR
) * (Idx
+ 1)));
476 /* First Descriptor */
477 IdmacDesc
->Des0
|= DWEMMC_IDMAC_DES0_FS
;
478 /* Last Descriptor */
480 (IdmacDesc
+ LastIdx
)->Des0
|= DWEMMC_IDMAC_DES0_LD
;
481 (IdmacDesc
+ LastIdx
)->Des0
&= ~(DWEMMC_IDMAC_DES0_DIC
| DWEMMC_IDMAC_DES0_CH
);
482 (IdmacDesc
+ LastIdx
)->Des1
= DWEMMC_IDMAC_DES1_BS1(Length
-
483 (LastIdx
* DWEMMC_DMA_BUF_SIZE
));
484 /* Set the Next field of Last Descriptor */
485 (IdmacDesc
+ LastIdx
)->Des3
= 0;
486 MmioWrite32 (DWEMMC_DBADDR
, (UINT32
)((UINTN
)IdmacDesc
));
498 Data
= MmioRead32 (DWEMMC_CTRL
);
499 Data
|= DWEMMC_CTRL_INT_EN
| DWEMMC_CTRL_DMA_EN
| DWEMMC_CTRL_IDMAC_EN
;
500 MmioWrite32 (DWEMMC_CTRL
, Data
);
501 Data
= MmioRead32 (DWEMMC_BMOD
);
502 Data
|= DWEMMC_IDMAC_ENABLE
| DWEMMC_IDMAC_FB
;
503 MmioWrite32 (DWEMMC_BMOD
, Data
);
505 MmioWrite32 (DWEMMC_BLKSIZ
, DWEMMC_BLOCK_SIZE
);
506 MmioWrite32 (DWEMMC_BYTCNT
, Length
);
510 DwEmmcReadBlockData (
511 IN EFI_MMC_HOST_PROTOCOL
*This
,
518 UINT32 DescPages
, CountPerPage
, Count
;
521 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
523 CountPerPage
= EFI_PAGE_SIZE
/ 16;
524 Count
= (Length
+ DWEMMC_DMA_BUF_SIZE
- 1) / DWEMMC_DMA_BUF_SIZE
;
525 DescPages
= (Count
+ CountPerPage
- 1) / CountPerPage
;
527 InvalidateDataCacheRange (Buffer
, Length
);
529 Status
= PrepareDmaData (gpIdmacDesc
, Length
, Buffer
);
530 if (EFI_ERROR (Status
)) {
534 WriteBackDataCacheRange (gpIdmacDesc
, DescPages
* EFI_PAGE_SIZE
);
537 Status
= SendCommand (mDwEmmcCommand
, mDwEmmcArgument
);
538 if (EFI_ERROR (Status
)) {
539 DEBUG ((DEBUG_ERROR
, "Failed to read data, mDwEmmcCommand:%x, mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand
, mDwEmmcArgument
, Status
));
544 gBS
->RestoreTPL (Tpl
);
549 DwEmmcWriteBlockData (
550 IN EFI_MMC_HOST_PROTOCOL
*This
,
557 UINT32 DescPages
, CountPerPage
, Count
;
560 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
562 CountPerPage
= EFI_PAGE_SIZE
/ 16;
563 Count
= (Length
+ DWEMMC_DMA_BUF_SIZE
- 1) / DWEMMC_DMA_BUF_SIZE
;
564 DescPages
= (Count
+ CountPerPage
- 1) / CountPerPage
;
566 WriteBackDataCacheRange (Buffer
, Length
);
568 Status
= PrepareDmaData (gpIdmacDesc
, Length
, Buffer
);
569 if (EFI_ERROR (Status
)) {
573 WriteBackDataCacheRange (gpIdmacDesc
, DescPages
* EFI_PAGE_SIZE
);
576 Status
= SendCommand (mDwEmmcCommand
, mDwEmmcArgument
);
577 if (EFI_ERROR (Status
)) {
578 DEBUG ((DEBUG_ERROR
, "Failed to write data, mDwEmmcCommand:%x, mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand
, mDwEmmcArgument
, Status
));
583 gBS
->RestoreTPL (Tpl
);
589 IN EFI_MMC_HOST_PROTOCOL
*This
,
590 IN UINT32 BusClockFreq
,
595 EFI_STATUS Status
= EFI_SUCCESS
;
598 if ((PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz
) != 0) &&
599 (BusClockFreq
> PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz
))) {
600 return EFI_UNSUPPORTED
;
602 if (TimingMode
!= EMMCBACKWARD
) {
603 Data
= MmioRead32 (DWEMMC_UHSREG
);
604 switch (TimingMode
) {
614 return EFI_UNSUPPORTED
;
616 MmioWrite32 (DWEMMC_UHSREG
, Data
);
621 MmioWrite32 (DWEMMC_CTYPE
, 0);
624 MmioWrite32 (DWEMMC_CTYPE
, 1);
627 MmioWrite32 (DWEMMC_CTYPE
, 1 << 16);
630 return EFI_UNSUPPORTED
;
633 Status
= DwEmmcSetClock (BusClockFreq
);
640 IN EFI_MMC_HOST_PROTOCOL
*This
646 EFI_MMC_HOST_PROTOCOL gMciHost
= {
647 MMC_HOST_PROTOCOL_REVISION
,
650 DwEmmcBuildDevicePath
,
653 DwEmmcReceiveResponse
,
655 DwEmmcWriteBlockData
,
661 DwEmmcDxeInitialize (
662 IN EFI_HANDLE ImageHandle
,
663 IN EFI_SYSTEM_TABLE
*SystemTable
671 DwEmmcAdjustFifoThreshold ();
672 gpIdmacDesc
= (DWEMMC_IDMAC_DESCRIPTOR
*)AllocatePages (DWEMMC_MAX_DESC_PAGES
);
673 if (gpIdmacDesc
== NULL
) {
674 return EFI_BUFFER_TOO_SMALL
;
677 DEBUG ((DEBUG_BLKIO
, "DwEmmcDxeInitialize()\n"));
679 //Publish Component Name, BlockIO protocol interfaces
680 Status
= gBS
->InstallMultipleProtocolInterfaces (
682 &gEfiMmcHostProtocolGuid
, &gMciHost
,
685 ASSERT_EFI_ERROR (Status
);