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
);
420 IN DWEMMC_IDMAC_DESCRIPTOR
* IdmacDesc
,
425 UINTN Cnt
, Blks
, Idx
, LastIdx
;
427 Cnt
= (Length
+ DWEMMC_DMA_BUF_SIZE
- 1) / DWEMMC_DMA_BUF_SIZE
;
428 Blks
= (Length
+ DWEMMC_BLOCK_SIZE
- 1) / DWEMMC_BLOCK_SIZE
;
429 Length
= DWEMMC_BLOCK_SIZE
* Blks
;
431 for (Idx
= 0; Idx
< Cnt
; Idx
++) {
432 (IdmacDesc
+ Idx
)->Des0
= DWEMMC_IDMAC_DES0_OWN
| DWEMMC_IDMAC_DES0_CH
|
433 DWEMMC_IDMAC_DES0_DIC
;
434 (IdmacDesc
+ Idx
)->Des1
= DWEMMC_IDMAC_DES1_BS1(DWEMMC_DMA_BUF_SIZE
);
436 (IdmacDesc
+ Idx
)->Des2
= (UINT32
)((UINTN
)Buffer
+ DWEMMC_DMA_BUF_SIZE
* Idx
);
437 /* Next Descriptor Address */
438 (IdmacDesc
+ Idx
)->Des3
= (UINT32
)((UINTN
)IdmacDesc
+
439 (sizeof(DWEMMC_IDMAC_DESCRIPTOR
) * (Idx
+ 1)));
441 /* First Descriptor */
442 IdmacDesc
->Des0
|= DWEMMC_IDMAC_DES0_FS
;
443 /* Last Descriptor */
445 (IdmacDesc
+ LastIdx
)->Des0
|= DWEMMC_IDMAC_DES0_LD
;
446 (IdmacDesc
+ LastIdx
)->Des0
&= ~(DWEMMC_IDMAC_DES0_DIC
| DWEMMC_IDMAC_DES0_CH
);
447 (IdmacDesc
+ LastIdx
)->Des1
= DWEMMC_IDMAC_DES1_BS1(Length
-
448 (LastIdx
* DWEMMC_DMA_BUF_SIZE
));
449 /* Set the Next field of Last Descriptor */
450 (IdmacDesc
+ LastIdx
)->Des3
= 0;
451 MmioWrite32 (DWEMMC_DBADDR
, (UINT32
)((UINTN
)IdmacDesc
));
463 Data
= MmioRead32 (DWEMMC_CTRL
);
464 Data
|= DWEMMC_CTRL_INT_EN
| DWEMMC_CTRL_DMA_EN
| DWEMMC_CTRL_IDMAC_EN
;
465 MmioWrite32 (DWEMMC_CTRL
, Data
);
466 Data
= MmioRead32 (DWEMMC_BMOD
);
467 Data
|= DWEMMC_IDMAC_ENABLE
| DWEMMC_IDMAC_FB
;
468 MmioWrite32 (DWEMMC_BMOD
, Data
);
470 MmioWrite32 (DWEMMC_BLKSIZ
, DWEMMC_BLOCK_SIZE
);
471 MmioWrite32 (DWEMMC_BYTCNT
, Length
);
475 DwEmmcReadBlockData (
476 IN EFI_MMC_HOST_PROTOCOL
*This
,
483 UINT32 DescPages
, CountPerPage
, Count
;
486 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
488 CountPerPage
= EFI_PAGE_SIZE
/ 16;
489 Count
= (Length
+ DWEMMC_DMA_BUF_SIZE
- 1) / DWEMMC_DMA_BUF_SIZE
;
490 DescPages
= (Count
+ CountPerPage
- 1) / CountPerPage
;
492 InvalidateDataCacheRange (Buffer
, Length
);
494 Status
= PrepareDmaData (gpIdmacDesc
, Length
, Buffer
);
495 if (EFI_ERROR (Status
)) {
499 WriteBackDataCacheRange (gpIdmacDesc
, DescPages
* EFI_PAGE_SIZE
);
502 Status
= SendCommand (mDwEmmcCommand
, mDwEmmcArgument
);
503 if (EFI_ERROR (Status
)) {
504 DEBUG ((DEBUG_ERROR
, "Failed to read data, mDwEmmcCommand:%x, mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand
, mDwEmmcArgument
, Status
));
509 gBS
->RestoreTPL (Tpl
);
514 DwEmmcWriteBlockData (
515 IN EFI_MMC_HOST_PROTOCOL
*This
,
522 UINT32 DescPages
, CountPerPage
, Count
;
525 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
527 CountPerPage
= EFI_PAGE_SIZE
/ 16;
528 Count
= (Length
+ DWEMMC_DMA_BUF_SIZE
- 1) / DWEMMC_DMA_BUF_SIZE
;
529 DescPages
= (Count
+ CountPerPage
- 1) / CountPerPage
;
531 WriteBackDataCacheRange (Buffer
, Length
);
533 Status
= PrepareDmaData (gpIdmacDesc
, Length
, Buffer
);
534 if (EFI_ERROR (Status
)) {
538 WriteBackDataCacheRange (gpIdmacDesc
, DescPages
* EFI_PAGE_SIZE
);
541 Status
= SendCommand (mDwEmmcCommand
, mDwEmmcArgument
);
542 if (EFI_ERROR (Status
)) {
543 DEBUG ((DEBUG_ERROR
, "Failed to write data, mDwEmmcCommand:%x, mDwEmmcArgument:%x, Status:%r\n", mDwEmmcCommand
, mDwEmmcArgument
, Status
));
548 gBS
->RestoreTPL (Tpl
);
554 IN EFI_MMC_HOST_PROTOCOL
*This
,
555 IN UINT32 BusClockFreq
,
560 EFI_STATUS Status
= EFI_SUCCESS
;
563 if ((PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz
) != 0) &&
564 (BusClockFreq
> PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz
))) {
565 return EFI_UNSUPPORTED
;
567 if (TimingMode
!= EMMCBACKWARD
) {
568 Data
= MmioRead32 (DWEMMC_UHSREG
);
569 switch (TimingMode
) {
579 return EFI_UNSUPPORTED
;
581 MmioWrite32 (DWEMMC_UHSREG
, Data
);
586 MmioWrite32 (DWEMMC_CTYPE
, 0);
589 MmioWrite32 (DWEMMC_CTYPE
, 1);
592 MmioWrite32 (DWEMMC_CTYPE
, 1 << 16);
595 return EFI_UNSUPPORTED
;
598 Status
= DwEmmcSetClock (BusClockFreq
);
605 IN EFI_MMC_HOST_PROTOCOL
*This
611 EFI_MMC_HOST_PROTOCOL gMciHost
= {
612 MMC_HOST_PROTOCOL_REVISION
,
615 DwEmmcBuildDevicePath
,
618 DwEmmcReceiveResponse
,
620 DwEmmcWriteBlockData
,
626 DwEmmcDxeInitialize (
627 IN EFI_HANDLE ImageHandle
,
628 IN EFI_SYSTEM_TABLE
*SystemTable
636 gpIdmacDesc
= (DWEMMC_IDMAC_DESCRIPTOR
*)AllocatePages (DWEMMC_MAX_DESC_PAGES
);
637 if (gpIdmacDesc
== NULL
) {
638 return EFI_BUFFER_TOO_SMALL
;
641 DEBUG ((DEBUG_BLKIO
, "DwEmmcDxeInitialize()\n"));
643 //Publish Component Name, BlockIO protocol interfaces
644 Status
= gBS
->InstallMultipleProtocolInterfaces (
646 &gEfiMmcHostProtocolGuid
, &gMciHost
,
649 ASSERT_EFI_ERROR (Status
);