2 This file implement the MMC Host Protocol for the DesignWare eMMC.
4 Copyright (c) 2014-2017, Linaro Limited. All rights reserved.
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/CacheMaintenanceLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/DevicePathLib.h>
20 #include <Library/IoLib.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/PcdLib.h>
23 #include <Library/TimerLib.h>
24 #include <Library/UefiBootServicesTableLib.h>
25 #include <Library/UefiLib.h>
27 #include <Protocol/MmcHost.h>
31 #define DWEMMC_DESC_PAGE 1
32 #define DWEMMC_BLOCK_SIZE 512
33 #define DWEMMC_DMA_BUF_SIZE (512 * 8)
34 #define DWEMMC_MAX_DESC_PAGES 512
41 } 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
;
51 IN EFI_MMC_HOST_PROTOCOL
*This
,
70 DEBUG ((DEBUG_BLKIO
, "DwEmmcInitialize()"));
76 IN EFI_MMC_HOST_PROTOCOL
*This
84 IN EFI_MMC_HOST_PROTOCOL
*This
91 DwEmmcIsDmaSupported (
92 IN EFI_MMC_HOST_PROTOCOL
*This
99 DwEmmcBuildDevicePath (
100 IN EFI_MMC_HOST_PROTOCOL
*This
,
101 IN EFI_DEVICE_PATH_PROTOCOL
**DevicePath
104 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePathNode
;
106 NewDevicePathNode
= CreateDeviceNode (HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, sizeof (VENDOR_DEVICE_PATH
));
107 CopyGuid (& ((VENDOR_DEVICE_PATH
*)NewDevicePathNode
)->Guid
, &mDwEmmcDevicePathGuid
);
109 *DevicePath
= NewDevicePathNode
;
121 Data
= BIT_CMD_WAIT_PRVDATA_COMPLETE
| BIT_CMD_UPDATE_CLOCK_ONLY
|
123 MmioWrite32 (DWEMMC_CMD
, Data
);
125 Data
= MmioRead32 (DWEMMC_CMD
);
126 if (!(Data
& CMD_START_BIT
)) {
129 Data
= MmioRead32 (DWEMMC_RINTSTS
);
130 if (Data
& DWEMMC_INT_HLE
) {
131 Print (L
"failed to update mmc clock frequency\n");
132 return EFI_DEVICE_ERROR
;
143 UINT32 Divider
, Rate
, Data
;
145 BOOLEAN Found
= FALSE
;
147 for (Divider
= 1; Divider
< 256; Divider
++) {
148 Rate
= PcdGet32 (PcdDwEmmcDxeClockFrequencyInHz
);
149 if ((Rate
/ (2 * Divider
)) <= ClockFreq
) {
154 if (Found
== FALSE
) {
155 return EFI_NOT_FOUND
;
158 // Wait until MMC is idle
160 Data
= MmioRead32 (DWEMMC_STATUS
);
161 } while (Data
& DWEMMC_STS_DATA_BUSY
);
163 // Disable MMC clock first
164 MmioWrite32 (DWEMMC_CLKENA
, 0);
165 Status
= DwEmmcUpdateClock ();
166 ASSERT (!EFI_ERROR (Status
));
168 MmioWrite32 (DWEMMC_CLKDIV
, Divider
);
169 Status
= DwEmmcUpdateClock ();
170 ASSERT (!EFI_ERROR (Status
));
173 MmioWrite32 (DWEMMC_CLKENA
, 1);
174 MmioWrite32 (DWEMMC_CLKSRC
, 0);
175 Status
= DwEmmcUpdateClock ();
176 ASSERT (!EFI_ERROR (Status
));
182 IN EFI_MMC_HOST_PROTOCOL
*This
,
190 case MmcInvalidState
:
191 return EFI_INVALID_PARAMETER
;
192 case MmcHwInitializationState
:
193 MmioWrite32 (DWEMMC_PWREN
, 1);
195 // If device already turn on then restart it
196 Data
= DWEMMC_CTRL_RESET_ALL
;
197 MmioWrite32 (DWEMMC_CTRL
, Data
);
199 // Wait until reset operation finished
200 Data
= MmioRead32 (DWEMMC_CTRL
);
201 } while (Data
& DWEMMC_CTRL_RESET_ALL
);
203 // Setup clock that could not be higher than 400KHz.
204 Status
= DwEmmcSetClock (400000);
205 ASSERT (!EFI_ERROR (Status
));
207 MicroSecondDelay (100);
209 MmioWrite32 (DWEMMC_RINTSTS
, ~0);
210 MmioWrite32 (DWEMMC_INTMASK
, 0);
211 MmioWrite32 (DWEMMC_TMOUT
, ~0);
212 MmioWrite32 (DWEMMC_IDINTEN
, 0);
213 MmioWrite32 (DWEMMC_BMOD
, DWEMMC_IDMAC_SWRESET
);
215 MmioWrite32 (DWEMMC_BLKSIZ
, DWEMMC_BLOCK_SIZE
);
217 Data
= MmioRead32 (DWEMMC_BMOD
);
218 } while (Data
& DWEMMC_IDMAC_SWRESET
);
224 case MmcIdentificationState
:
226 case MmcStandByState
:
228 case MmcTransferState
:
230 case MmcSendingDataState
:
232 case MmcReceiveDataState
:
234 case MmcProgrammingState
:
236 case MmcDisconnectState
:
239 return EFI_INVALID_PARAMETER
;
244 // Need to prepare DMA buffer first before sending commands to MMC card
246 IsPendingReadCommand (
252 Mask
= BIT_CMD_DATA_EXPECTED
| BIT_CMD_READ
;
253 if ((MmcCmd
& Mask
) == Mask
) {
260 IsPendingWriteCommand (
266 Mask
= BIT_CMD_DATA_EXPECTED
| BIT_CMD_WRITE
;
267 if ((MmcCmd
& Mask
) == Mask
) {
279 UINT32 Data
, ErrMask
;
281 // Wait until MMC is idle
283 Data
= MmioRead32 (DWEMMC_STATUS
);
284 } while (Data
& DWEMMC_STS_DATA_BUSY
);
286 MmioWrite32 (DWEMMC_RINTSTS
, ~0);
287 MmioWrite32 (DWEMMC_CMDARG
, Argument
);
288 MmioWrite32 (DWEMMC_CMD
, MmcCmd
);
290 ErrMask
= DWEMMC_INT_EBE
| DWEMMC_INT_HLE
| DWEMMC_INT_RTO
|
291 DWEMMC_INT_RCRC
| DWEMMC_INT_RE
;
292 ErrMask
|= DWEMMC_INT_DCRC
| DWEMMC_INT_DRT
| DWEMMC_INT_SBE
;
294 MicroSecondDelay(500);
295 Data
= MmioRead32 (DWEMMC_RINTSTS
);
297 if (Data
& ErrMask
) {
298 return EFI_DEVICE_ERROR
;
300 if (Data
& DWEMMC_INT_DTO
) { // Transfer Done
303 } while (!(Data
& DWEMMC_INT_CMD_DONE
));
309 IN EFI_MMC_HOST_PROTOCOL
*This
,
315 EFI_STATUS Status
= EFI_SUCCESS
;
317 switch (MMC_GET_INDX(MmcCmd
)) {
319 Cmd
= BIT_CMD_SEND_INIT
;
322 Cmd
= BIT_CMD_RESPONSE_EXPECT
;
325 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_LONG_RESPONSE
|
326 BIT_CMD_CHECK_RESPONSE_CRC
| BIT_CMD_SEND_INIT
;
329 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
334 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
;
339 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
340 BIT_CMD_DATA_EXPECTED
| BIT_CMD_READ
|
341 BIT_CMD_WAIT_PRVDATA_COMPLETE
;
344 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
345 BIT_CMD_LONG_RESPONSE
;
348 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
349 BIT_CMD_STOP_ABORT_CMD
;
352 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
353 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_READ
|
364 BIT_CMD_WAIT_PRVDATA_COMPLETE
;
368 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
369 BIT_CMD_DATA_EXPECTED
| BIT_CMD_WRITE
|
370 BIT_CMD_WAIT_PRVDATA_COMPLETE
;
373 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
|
374 BIT_CMD_DATA_EXPECTED
;
377 Cmd
= BIT_CMD_RESPONSE_EXPECT
| BIT_CMD_CHECK_RESPONSE_CRC
;
381 Cmd
|= MMC_GET_INDX(MmcCmd
) | BIT_CMD_USE_HOLD_REG
| BIT_CMD_START
;
382 if (IsPendingReadCommand (Cmd
) || IsPendingWriteCommand (Cmd
)) {
383 mDwEmmcCommand
= Cmd
;
384 mDwEmmcArgument
= Argument
;
386 Status
= SendCommand (Cmd
, Argument
);
392 DwEmmcReceiveResponse (
393 IN EFI_MMC_HOST_PROTOCOL
*This
,
394 IN MMC_RESPONSE_TYPE Type
,
398 if (Buffer
== NULL
) {
399 return EFI_INVALID_PARAMETER
;
402 if ( (Type
== MMC_RESPONSE_TYPE_R1
)
403 || (Type
== MMC_RESPONSE_TYPE_R1b
)
404 || (Type
== MMC_RESPONSE_TYPE_R3
)
405 || (Type
== MMC_RESPONSE_TYPE_R6
)
406 || (Type
== MMC_RESPONSE_TYPE_R7
))
408 Buffer
[0] = MmioRead32 (DWEMMC_RESP0
);
409 } else if (Type
== MMC_RESPONSE_TYPE_R2
) {
410 Buffer
[0] = MmioRead32 (DWEMMC_RESP0
);
411 Buffer
[1] = MmioRead32 (DWEMMC_RESP1
);
412 Buffer
[2] = MmioRead32 (DWEMMC_RESP2
);
413 Buffer
[3] = MmioRead32 (DWEMMC_RESP3
);
419 DwEmmcAdjustFifoThreshold (
423 /* DMA multiple transaction size map to reg value as array index */
424 CONST UINT32 BurstSize
[] = {1, 4, 8, 16, 32, 64, 128, 256};
425 UINT32 BlkDepthInFifo
, FifoThreshold
, FifoWidth
, FifoDepth
;
426 UINT32 BlkSize
= DWEMMC_BLOCK_SIZE
, Idx
= 0, RxWatermark
= 1, TxWatermark
, TxWatermarkInvers
;
428 /* Skip FIFO adjustment if we do not have platform FIFO depth info */
429 FifoDepth
= PcdGet32 (PcdDwEmmcDxeFifoDepth
);
434 TxWatermark
= FifoDepth
/ 2;
435 TxWatermarkInvers
= FifoDepth
- TxWatermark
;
437 FifoWidth
= DWEMMC_GET_HDATA_WIDTH (MmioRead32 (DWEMMC_HCON
));
440 } else if (FifoWidth
== 2) {
446 BlkDepthInFifo
= BlkSize
/ FifoWidth
;
448 Idx
= ARRAY_SIZE (BurstSize
) - 1;
449 while (Idx
&& ((BlkDepthInFifo
% BurstSize
[Idx
]) || (TxWatermarkInvers
% BurstSize
[Idx
]))) {
453 RxWatermark
= BurstSize
[Idx
] - 1;
454 FifoThreshold
= DWEMMC_DMA_BURST_SIZE (Idx
) | DWEMMC_FIFO_TWMARK (TxWatermark
)
455 | DWEMMC_FIFO_RWMARK (RxWatermark
);
456 MmioWrite32 (DWEMMC_FIFOTH
, FifoThreshold
);
461 IN DWEMMC_IDMAC_DESCRIPTOR
* IdmacDesc
,
466 UINTN Cnt
, Blks
, Idx
, LastIdx
;
468 Cnt
= (Length
+ DWEMMC_DMA_BUF_SIZE
- 1) / DWEMMC_DMA_BUF_SIZE
;
469 Blks
= (Length
+ DWEMMC_BLOCK_SIZE
- 1) / DWEMMC_BLOCK_SIZE
;
470 Length
= DWEMMC_BLOCK_SIZE
* Blks
;
472 for (Idx
= 0; Idx
< Cnt
; Idx
++) {
473 (IdmacDesc
+ Idx
)->Des0
= DWEMMC_IDMAC_DES0_OWN
| DWEMMC_IDMAC_DES0_CH
|
474 DWEMMC_IDMAC_DES0_DIC
;
475 (IdmacDesc
+ Idx
)->Des1
= DWEMMC_IDMAC_DES1_BS1(DWEMMC_DMA_BUF_SIZE
);
477 (IdmacDesc
+ Idx
)->Des2
= (UINT32
)((UINTN
)Buffer
+ DWEMMC_DMA_BUF_SIZE
* Idx
);
478 /* Next Descriptor Address */
479 (IdmacDesc
+ Idx
)->Des3
= (UINT32
)((UINTN
)IdmacDesc
+
480 (sizeof(DWEMMC_IDMAC_DESCRIPTOR
) * (Idx
+ 1)));
482 /* First Descriptor */
483 IdmacDesc
->Des0
|= DWEMMC_IDMAC_DES0_FS
;
484 /* Last Descriptor */
486 (IdmacDesc
+ LastIdx
)->Des0
|= DWEMMC_IDMAC_DES0_LD
;
487 (IdmacDesc
+ LastIdx
)->Des0
&= ~(DWEMMC_IDMAC_DES0_DIC
| DWEMMC_IDMAC_DES0_CH
);
488 (IdmacDesc
+ LastIdx
)->Des1
= DWEMMC_IDMAC_DES1_BS1(Length
-
489 (LastIdx
* DWEMMC_DMA_BUF_SIZE
));
490 /* Set the Next field of Last Descriptor */
491 (IdmacDesc
+ LastIdx
)->Des3
= 0;
492 MmioWrite32 (DWEMMC_DBADDR
, (UINT32
)((UINTN
)IdmacDesc
));
504 Data
= MmioRead32 (DWEMMC_CTRL
);
505 Data
|= DWEMMC_CTRL_INT_EN
| DWEMMC_CTRL_DMA_EN
| DWEMMC_CTRL_IDMAC_EN
;
506 MmioWrite32 (DWEMMC_CTRL
, Data
);
507 Data
= MmioRead32 (DWEMMC_BMOD
);
508 Data
|= DWEMMC_IDMAC_ENABLE
| DWEMMC_IDMAC_FB
;
509 MmioWrite32 (DWEMMC_BMOD
, Data
);
511 MmioWrite32 (DWEMMC_BLKSIZ
, DWEMMC_BLOCK_SIZE
);
512 MmioWrite32 (DWEMMC_BYTCNT
, Length
);
516 DwEmmcReadBlockData (
517 IN EFI_MMC_HOST_PROTOCOL
*This
,
524 UINT32 DescPages
, CountPerPage
, Count
;
527 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
529 CountPerPage
= EFI_PAGE_SIZE
/ 16;
530 Count
= (Length
+ DWEMMC_DMA_BUF_SIZE
- 1) / DWEMMC_DMA_BUF_SIZE
;
531 DescPages
= (Count
+ CountPerPage
- 1) / CountPerPage
;
533 InvalidateDataCacheRange (Buffer
, Length
);
535 Status
= PrepareDmaData (gpIdmacDesc
, Length
, Buffer
);
536 if (EFI_ERROR (Status
)) {
540 WriteBackDataCacheRange (gpIdmacDesc
, DescPages
* EFI_PAGE_SIZE
);
543 Status
= SendCommand (mDwEmmcCommand
, mDwEmmcArgument
);
544 if (EFI_ERROR (Status
)) {
545 DEBUG ((DEBUG_ERROR
, "Failed to read data, mDwEmmcCommand:%x, mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand
, mDwEmmcArgument
, Status
));
550 gBS
->RestoreTPL (Tpl
);
555 DwEmmcWriteBlockData (
556 IN EFI_MMC_HOST_PROTOCOL
*This
,
563 UINT32 DescPages
, CountPerPage
, Count
;
566 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
568 CountPerPage
= EFI_PAGE_SIZE
/ 16;
569 Count
= (Length
+ DWEMMC_DMA_BUF_SIZE
- 1) / DWEMMC_DMA_BUF_SIZE
;
570 DescPages
= (Count
+ CountPerPage
- 1) / CountPerPage
;
572 WriteBackDataCacheRange (Buffer
, Length
);
574 Status
= PrepareDmaData (gpIdmacDesc
, Length
, Buffer
);
575 if (EFI_ERROR (Status
)) {
579 WriteBackDataCacheRange (gpIdmacDesc
, DescPages
* EFI_PAGE_SIZE
);
582 Status
= SendCommand (mDwEmmcCommand
, mDwEmmcArgument
);
583 if (EFI_ERROR (Status
)) {
584 DEBUG ((DEBUG_ERROR
, "Failed to write data, mDwEmmcCommand:%x, mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand
, mDwEmmcArgument
, Status
));
589 gBS
->RestoreTPL (Tpl
);
595 IN EFI_MMC_HOST_PROTOCOL
*This
,
596 IN UINT32 BusClockFreq
,
601 EFI_STATUS Status
= EFI_SUCCESS
;
604 if ((PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz
) != 0) &&
605 (BusClockFreq
> PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz
))) {
606 return EFI_UNSUPPORTED
;
608 if (TimingMode
!= EMMCBACKWARD
) {
609 Data
= MmioRead32 (DWEMMC_UHSREG
);
610 switch (TimingMode
) {
620 return EFI_UNSUPPORTED
;
622 MmioWrite32 (DWEMMC_UHSREG
, Data
);
627 MmioWrite32 (DWEMMC_CTYPE
, 0);
630 MmioWrite32 (DWEMMC_CTYPE
, 1);
633 MmioWrite32 (DWEMMC_CTYPE
, 1 << 16);
636 return EFI_UNSUPPORTED
;
639 Status
= DwEmmcSetClock (BusClockFreq
);
646 IN EFI_MMC_HOST_PROTOCOL
*This
652 EFI_MMC_HOST_PROTOCOL gMciHost
= {
653 MMC_HOST_PROTOCOL_REVISION
,
656 DwEmmcBuildDevicePath
,
659 DwEmmcReceiveResponse
,
661 DwEmmcWriteBlockData
,
667 DwEmmcDxeInitialize (
668 IN EFI_HANDLE ImageHandle
,
669 IN EFI_SYSTEM_TABLE
*SystemTable
677 DwEmmcAdjustFifoThreshold ();
678 gpIdmacDesc
= (DWEMMC_IDMAC_DESCRIPTOR
*)AllocatePages (DWEMMC_MAX_DESC_PAGES
);
679 if (gpIdmacDesc
== NULL
) {
680 return EFI_BUFFER_TOO_SMALL
;
683 DEBUG ((DEBUG_BLKIO
, "DwEmmcDxeInitialize()\n"));
685 //Publish Component Name, BlockIO protocol interfaces
686 Status
= gBS
->InstallMultipleProtocolInterfaces (
688 &gEfiMmcHostProtocolGuid
, &gMciHost
,
691 ASSERT_EFI_ERROR (Status
);