]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Drivers/DwEmmcDxe/DwEmmcDxe.c
0437e30f940f00ea60a86b12308a5f93a13000c9
[mirror_edk2.git] / EmbeddedPkg / Drivers / DwEmmcDxe / DwEmmcDxe.c
1 /** @file
2 This file implement the MMC Host Protocol for the DesignWare eMMC.
3
4 Copyright (c) 2014-2017, Linaro Limited. All rights reserved.
5
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
10
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.
13
14 **/
15
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>
26
27 #include <Protocol/MmcHost.h>
28
29 #include "DwEmmc.h"
30
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
35
36 typedef struct {
37 UINT32 Des0;
38 UINT32 Des1;
39 UINT32 Des2;
40 UINT32 Des3;
41 } DWEMMC_IDMAC_DESCRIPTOR;
42
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
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
57 BOOLEAN
58 DwEmmcIsPowerOn (
59 VOID
60 )
61 {
62 return TRUE;
63 }
64
65 EFI_STATUS
66 DwEmmcInitialize (
67 VOID
68 )
69 {
70 DEBUG ((DEBUG_BLKIO, "DwEmmcInitialize()"));
71 return EFI_SUCCESS;
72 }
73
74 BOOLEAN
75 DwEmmcIsCardPresent (
76 IN EFI_MMC_HOST_PROTOCOL *This
77 )
78 {
79 return TRUE;
80 }
81
82 BOOLEAN
83 DwEmmcIsReadOnly (
84 IN EFI_MMC_HOST_PROTOCOL *This
85 )
86 {
87 return FALSE;
88 }
89
90 BOOLEAN
91 DwEmmcIsDmaSupported (
92 IN EFI_MMC_HOST_PROTOCOL *This
93 )
94 {
95 return TRUE;
96 }
97
98 EFI_STATUS
99 DwEmmcBuildDevicePath (
100 IN EFI_MMC_HOST_PROTOCOL *This,
101 IN EFI_DEVICE_PATH_PROTOCOL **DevicePath
102 )
103 {
104 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
105
106 NewDevicePathNode = CreateDeviceNode (HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH));
107 CopyGuid (& ((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &mDwEmmcDevicePathGuid);
108
109 *DevicePath = NewDevicePathNode;
110 return EFI_SUCCESS;
111 }
112
113 EFI_STATUS
114 DwEmmcUpdateClock (
115 VOID
116 )
117 {
118 UINT32 Data;
119
120 /* CMD_UPDATE_CLK */
121 Data = BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_UPDATE_CLOCK_ONLY |
122 BIT_CMD_START;
123 MmioWrite32 (DWEMMC_CMD, Data);
124 while (1) {
125 Data = MmioRead32 (DWEMMC_CMD);
126 if (!(Data & CMD_START_BIT)) {
127 break;
128 }
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;
133 }
134 }
135 return EFI_SUCCESS;
136 }
137
138 EFI_STATUS
139 DwEmmcSetClock (
140 IN UINTN ClockFreq
141 )
142 {
143 UINT32 Divider, Rate, Data;
144 EFI_STATUS Status;
145 BOOLEAN Found = FALSE;
146
147 for (Divider = 1; Divider < 256; Divider++) {
148 Rate = PcdGet32 (PcdDwEmmcDxeClockFrequencyInHz);
149 if ((Rate / (2 * Divider)) <= ClockFreq) {
150 Found = TRUE;
151 break;
152 }
153 }
154 if (Found == FALSE) {
155 return EFI_NOT_FOUND;
156 }
157
158 // Wait until MMC is idle
159 do {
160 Data = MmioRead32 (DWEMMC_STATUS);
161 } while (Data & DWEMMC_STS_DATA_BUSY);
162
163 // Disable MMC clock first
164 MmioWrite32 (DWEMMC_CLKENA, 0);
165 Status = DwEmmcUpdateClock ();
166 ASSERT (!EFI_ERROR (Status));
167
168 MmioWrite32 (DWEMMC_CLKDIV, Divider);
169 Status = DwEmmcUpdateClock ();
170 ASSERT (!EFI_ERROR (Status));
171
172 // Enable MMC clock
173 MmioWrite32 (DWEMMC_CLKENA, 1);
174 MmioWrite32 (DWEMMC_CLKSRC, 0);
175 Status = DwEmmcUpdateClock ();
176 ASSERT (!EFI_ERROR (Status));
177 return EFI_SUCCESS;
178 }
179
180 EFI_STATUS
181 DwEmmcNotifyState (
182 IN EFI_MMC_HOST_PROTOCOL *This,
183 IN MMC_STATE State
184 )
185 {
186 UINT32 Data;
187 EFI_STATUS Status;
188
189 switch (State) {
190 case MmcInvalidState:
191 return EFI_INVALID_PARAMETER;
192 case MmcHwInitializationState:
193 MmioWrite32 (DWEMMC_PWREN, 1);
194
195 // If device already turn on then restart it
196 Data = DWEMMC_CTRL_RESET_ALL;
197 MmioWrite32 (DWEMMC_CTRL, Data);
198 do {
199 // Wait until reset operation finished
200 Data = MmioRead32 (DWEMMC_CTRL);
201 } while (Data & DWEMMC_CTRL_RESET_ALL);
202
203 // Setup clock that could not be higher than 400KHz.
204 Status = DwEmmcSetClock (400000);
205 ASSERT (!EFI_ERROR (Status));
206 // Wait clock stable
207 MicroSecondDelay (100);
208
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);
214
215 MmioWrite32 (DWEMMC_BLKSIZ, DWEMMC_BLOCK_SIZE);
216 do {
217 Data = MmioRead32 (DWEMMC_BMOD);
218 } while (Data & DWEMMC_IDMAC_SWRESET);
219 break;
220 case MmcIdleState:
221 break;
222 case MmcReadyState:
223 break;
224 case MmcIdentificationState:
225 break;
226 case MmcStandByState:
227 break;
228 case MmcTransferState:
229 break;
230 case MmcSendingDataState:
231 break;
232 case MmcReceiveDataState:
233 break;
234 case MmcProgrammingState:
235 break;
236 case MmcDisconnectState:
237 break;
238 default:
239 return EFI_INVALID_PARAMETER;
240 }
241 return EFI_SUCCESS;
242 }
243
244 // Need to prepare DMA buffer first before sending commands to MMC card
245 BOOLEAN
246 IsPendingReadCommand (
247 IN MMC_CMD MmcCmd
248 )
249 {
250 UINTN Mask;
251
252 Mask = BIT_CMD_DATA_EXPECTED | BIT_CMD_READ;
253 if ((MmcCmd & Mask) == Mask) {
254 return TRUE;
255 }
256 return FALSE;
257 }
258
259 BOOLEAN
260 IsPendingWriteCommand (
261 IN MMC_CMD MmcCmd
262 )
263 {
264 UINTN Mask;
265
266 Mask = BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE;
267 if ((MmcCmd & Mask) == Mask) {
268 return TRUE;
269 }
270 return FALSE;
271 }
272
273 EFI_STATUS
274 SendCommand (
275 IN MMC_CMD MmcCmd,
276 IN UINT32 Argument
277 )
278 {
279 UINT32 Data, ErrMask;
280
281 // Wait until MMC is idle
282 do {
283 Data = MmioRead32 (DWEMMC_STATUS);
284 } while (Data & DWEMMC_STS_DATA_BUSY);
285
286 MmioWrite32 (DWEMMC_RINTSTS, ~0);
287 MmioWrite32 (DWEMMC_CMDARG, Argument);
288 MmioWrite32 (DWEMMC_CMD, MmcCmd);
289
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;
293 do {
294 MicroSecondDelay(500);
295 Data = MmioRead32 (DWEMMC_RINTSTS);
296
297 if (Data & ErrMask) {
298 return EFI_DEVICE_ERROR;
299 }
300 if (Data & DWEMMC_INT_DTO) { // Transfer Done
301 break;
302 }
303 } while (!(Data & DWEMMC_INT_CMD_DONE));
304 return EFI_SUCCESS;
305 }
306
307 EFI_STATUS
308 DwEmmcSendCommand (
309 IN EFI_MMC_HOST_PROTOCOL *This,
310 IN MMC_CMD MmcCmd,
311 IN UINT32 Argument
312 )
313 {
314 UINT32 Cmd = 0;
315 EFI_STATUS Status = EFI_SUCCESS;
316
317 switch (MMC_GET_INDX(MmcCmd)) {
318 case MMC_INDX(0):
319 Cmd = BIT_CMD_SEND_INIT;
320 break;
321 case MMC_INDX(1):
322 Cmd = BIT_CMD_RESPONSE_EXPECT;
323 break;
324 case MMC_INDX(2):
325 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE |
326 BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_SEND_INIT;
327 break;
328 case MMC_INDX(3):
329 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
330 BIT_CMD_SEND_INIT;
331 break;
332 case MMC_INDX(7):
333 if (Argument)
334 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
335 else
336 Cmd = 0;
337 break;
338 case MMC_INDX(8):
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;
342 break;
343 case MMC_INDX(9):
344 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
345 BIT_CMD_LONG_RESPONSE;
346 break;
347 case MMC_INDX(12):
348 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
349 BIT_CMD_STOP_ABORT_CMD;
350 break;
351 case MMC_INDX(13):
352 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
353 BIT_CMD_WAIT_PRVDATA_COMPLETE;
354 break;
355 case MMC_INDX(16):
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;
359 break;
360 case MMC_INDX(17):
361 case MMC_INDX(18):
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;
365 break;
366 case MMC_INDX(24):
367 case MMC_INDX(25):
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;
371 break;
372 case MMC_INDX(30):
373 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
374 BIT_CMD_DATA_EXPECTED;
375 break;
376 default:
377 Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
378 break;
379 }
380
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;
385 } else {
386 Status = SendCommand (Cmd, Argument);
387 }
388 return Status;
389 }
390
391 EFI_STATUS
392 DwEmmcReceiveResponse (
393 IN EFI_MMC_HOST_PROTOCOL *This,
394 IN MMC_RESPONSE_TYPE Type,
395 IN UINT32* Buffer
396 )
397 {
398 if (Buffer == NULL) {
399 return EFI_INVALID_PARAMETER;
400 }
401
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))
407 {
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);
414 }
415 return EFI_SUCCESS;
416 }
417
418 VOID
419 DwEmmcAdjustFifoThreshold (
420 VOID
421 )
422 {
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;
427
428 /* Skip FIFO adjustment if we do not have platform FIFO depth info */
429 FifoDepth = PcdGet32 (PcdDwEmmcDxeFifoDepth);
430 if (!FifoDepth) {
431 return;
432 }
433
434 TxWatermark = FifoDepth / 2;
435 TxWatermarkInvers = FifoDepth - TxWatermark;
436
437 FifoWidth = DWEMMC_GET_HDATA_WIDTH (MmioRead32 (DWEMMC_HCON));
438 if (!FifoWidth) {
439 FifoWidth = 2;
440 } else if (FifoWidth == 2) {
441 FifoWidth = 8;
442 } else {
443 FifoWidth = 4;
444 }
445
446 BlkDepthInFifo = BlkSize / FifoWidth;
447
448 Idx = ARRAY_SIZE (BurstSize) - 1;
449 while (Idx && ((BlkDepthInFifo % BurstSize[Idx]) || (TxWatermarkInvers % BurstSize[Idx]))) {
450 Idx--;
451 }
452
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);
457 }
458
459 EFI_STATUS
460 PrepareDmaData (
461 IN DWEMMC_IDMAC_DESCRIPTOR* IdmacDesc,
462 IN UINTN Length,
463 IN UINT32* Buffer
464 )
465 {
466 UINTN Cnt, Blks, Idx, LastIdx;
467
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;
471
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);
476 /* Buffer Address */
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)));
481 }
482 /* First Descriptor */
483 IdmacDesc->Des0 |= DWEMMC_IDMAC_DES0_FS;
484 /* Last Descriptor */
485 LastIdx = Cnt - 1;
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));
493
494 return EFI_SUCCESS;
495 }
496
497 VOID
498 StartDma (
499 UINTN Length
500 )
501 {
502 UINT32 Data;
503
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);
510
511 MmioWrite32 (DWEMMC_BLKSIZ, DWEMMC_BLOCK_SIZE);
512 MmioWrite32 (DWEMMC_BYTCNT, Length);
513 }
514
515 EFI_STATUS
516 DwEmmcReadBlockData (
517 IN EFI_MMC_HOST_PROTOCOL *This,
518 IN EFI_LBA Lba,
519 IN UINTN Length,
520 IN UINT32* Buffer
521 )
522 {
523 EFI_STATUS Status;
524 UINT32 DescPages, CountPerPage, Count;
525 EFI_TPL Tpl;
526
527 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
528
529 CountPerPage = EFI_PAGE_SIZE / 16;
530 Count = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
531 DescPages = (Count + CountPerPage - 1) / CountPerPage;
532
533 InvalidateDataCacheRange (Buffer, Length);
534
535 Status = PrepareDmaData (gpIdmacDesc, Length, Buffer);
536 if (EFI_ERROR (Status)) {
537 goto out;
538 }
539
540 WriteBackDataCacheRange (gpIdmacDesc, DescPages * EFI_PAGE_SIZE);
541 StartDma (Length);
542
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));
546 goto out;
547 }
548 out:
549 // Restore Tpl
550 gBS->RestoreTPL (Tpl);
551 return Status;
552 }
553
554 EFI_STATUS
555 DwEmmcWriteBlockData (
556 IN EFI_MMC_HOST_PROTOCOL *This,
557 IN EFI_LBA Lba,
558 IN UINTN Length,
559 IN UINT32* Buffer
560 )
561 {
562 EFI_STATUS Status;
563 UINT32 DescPages, CountPerPage, Count;
564 EFI_TPL Tpl;
565
566 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
567
568 CountPerPage = EFI_PAGE_SIZE / 16;
569 Count = (Length + DWEMMC_DMA_BUF_SIZE - 1) / DWEMMC_DMA_BUF_SIZE;
570 DescPages = (Count + CountPerPage - 1) / CountPerPage;
571
572 WriteBackDataCacheRange (Buffer, Length);
573
574 Status = PrepareDmaData (gpIdmacDesc, Length, Buffer);
575 if (EFI_ERROR (Status)) {
576 goto out;
577 }
578
579 WriteBackDataCacheRange (gpIdmacDesc, DescPages * EFI_PAGE_SIZE);
580 StartDma (Length);
581
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));
585 goto out;
586 }
587 out:
588 // Restore Tpl
589 gBS->RestoreTPL (Tpl);
590 return Status;
591 }
592
593 EFI_STATUS
594 DwEmmcSetIos (
595 IN EFI_MMC_HOST_PROTOCOL *This,
596 IN UINT32 BusClockFreq,
597 IN UINT32 BusWidth,
598 IN UINT32 TimingMode
599 )
600 {
601 EFI_STATUS Status = EFI_SUCCESS;
602 UINT32 Data;
603
604 if ((PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz) != 0) &&
605 (BusClockFreq > PcdGet32 (PcdDwEmmcDxeMaxClockFreqInHz))) {
606 return EFI_UNSUPPORTED;
607 }
608 if (TimingMode != EMMCBACKWARD) {
609 Data = MmioRead32 (DWEMMC_UHSREG);
610 switch (TimingMode) {
611 case EMMCHS52DDR1V2:
612 case EMMCHS52DDR1V8:
613 Data |= 1 << 16;
614 break;
615 case EMMCHS52:
616 case EMMCHS26:
617 Data &= ~(1 << 16);
618 break;
619 default:
620 return EFI_UNSUPPORTED;
621 }
622 MmioWrite32 (DWEMMC_UHSREG, Data);
623 }
624
625 switch (BusWidth) {
626 case 1:
627 MmioWrite32 (DWEMMC_CTYPE, 0);
628 break;
629 case 4:
630 MmioWrite32 (DWEMMC_CTYPE, 1);
631 break;
632 case 8:
633 MmioWrite32 (DWEMMC_CTYPE, 1 << 16);
634 break;
635 default:
636 return EFI_UNSUPPORTED;
637 }
638 if (BusClockFreq) {
639 Status = DwEmmcSetClock (BusClockFreq);
640 }
641 return Status;
642 }
643
644 BOOLEAN
645 DwEmmcIsMultiBlock (
646 IN EFI_MMC_HOST_PROTOCOL *This
647 )
648 {
649 return TRUE;
650 }
651
652 EFI_MMC_HOST_PROTOCOL gMciHost = {
653 MMC_HOST_PROTOCOL_REVISION,
654 DwEmmcIsCardPresent,
655 DwEmmcIsReadOnly,
656 DwEmmcBuildDevicePath,
657 DwEmmcNotifyState,
658 DwEmmcSendCommand,
659 DwEmmcReceiveResponse,
660 DwEmmcReadBlockData,
661 DwEmmcWriteBlockData,
662 DwEmmcSetIos,
663 DwEmmcIsMultiBlock
664 };
665
666 EFI_STATUS
667 DwEmmcDxeInitialize (
668 IN EFI_HANDLE ImageHandle,
669 IN EFI_SYSTEM_TABLE *SystemTable
670 )
671 {
672 EFI_STATUS Status;
673 EFI_HANDLE Handle;
674
675 Handle = NULL;
676
677 DwEmmcAdjustFifoThreshold ();
678 gpIdmacDesc = (DWEMMC_IDMAC_DESCRIPTOR *)AllocatePages (DWEMMC_MAX_DESC_PAGES);
679 if (gpIdmacDesc == NULL) {
680 return EFI_BUFFER_TOO_SMALL;
681 }
682
683 DEBUG ((DEBUG_BLKIO, "DwEmmcDxeInitialize()\n"));
684
685 //Publish Component Name, BlockIO protocol interfaces
686 Status = gBS->InstallMultipleProtocolInterfaces (
687 &Handle,
688 &gEfiMmcHostProtocolGuid, &gMciHost,
689 NULL
690 );
691 ASSERT_EFI_ERROR (Status);
692
693 return EFI_SUCCESS;
694 }