]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHci.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Sd / EmmcBlockIoPei / EmmcHci.c
CommitLineData
48555339
FT
1/** @file\r
2\r
54228046 3 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
9d510e61 4 SPDX-License-Identifier: BSD-2-Clause-Patent\r
48555339
FT
5\r
6**/\r
7\r
8#include "EmmcBlockIoPei.h"\r
9\r
10/**\r
11 Read/Write specified EMMC host controller mmio register.\r
12\r
13 @param[in] Address The address of the mmio register to be read/written.\r
14 @param[in] Read A boolean to indicate it's read or write operation.\r
15 @param[in] Count The width of the mmio register in bytes.\r
16 Must be 1, 2 , 4 or 8 bytes.\r
17 @param[in, out] Data For read operations, the destination buffer to store\r
18 the results. For write operations, the source buffer\r
19 to write data from. The caller is responsible for\r
20 having ownership of the data buffer and ensuring its\r
21 size not less than Count bytes.\r
22\r
23 @retval EFI_INVALID_PARAMETER The Address or the Data or the Count is not valid.\r
24 @retval EFI_SUCCESS The read/write operation succeeds.\r
25 @retval Others The read/write operation fails.\r
26\r
27**/\r
28EFI_STATUS\r
29EFIAPI\r
30EmmcPeimHcRwMmio (\r
31 IN UINTN Address,\r
32 IN BOOLEAN Read,\r
33 IN UINT8 Count,\r
34 IN OUT VOID *Data\r
35 )\r
36{\r
37 if ((Address == 0) || (Data == NULL)) {\r
38 return EFI_INVALID_PARAMETER;\r
39 }\r
40\r
41 if ((Count != 1) && (Count != 2) && (Count != 4) && (Count != 8)) {\r
42 return EFI_INVALID_PARAMETER;\r
43 }\r
44\r
45 switch (Count) {\r
46 case 1:\r
47 if (Read) {\r
48 *(UINT8*)Data = MmioRead8 (Address);\r
49 } else {\r
50 MmioWrite8 (Address, *(UINT8*)Data);\r
51 }\r
52 break;\r
53 case 2:\r
54 if (Read) {\r
55 *(UINT16*)Data = MmioRead16 (Address);\r
56 } else {\r
57 MmioWrite16 (Address, *(UINT16*)Data);\r
58 }\r
59 break;\r
60 case 4:\r
61 if (Read) {\r
62 *(UINT32*)Data = MmioRead32 (Address);\r
63 } else {\r
64 MmioWrite32 (Address, *(UINT32*)Data);\r
65 }\r
66 break;\r
67 case 8:\r
68 if (Read) {\r
69 *(UINT64*)Data = MmioRead64 (Address);\r
70 } else {\r
71 MmioWrite64 (Address, *(UINT64*)Data);\r
72 }\r
73 break;\r
74 default:\r
75 ASSERT (FALSE);\r
76 return EFI_INVALID_PARAMETER;\r
77 }\r
78\r
79 return EFI_SUCCESS;\r
80}\r
81\r
82/**\r
83 Do OR operation with the value of the specified EMMC host controller mmio register.\r
84\r
85 @param[in] Address The address of the mmio register to be read/written.\r
86 @param[in] Count The width of the mmio register in bytes.\r
87 Must be 1, 2 , 4 or 8 bytes.\r
88 @param[in] OrData The pointer to the data used to do OR operation.\r
89 The caller is responsible for having ownership of\r
90 the data buffer and ensuring its size not less than\r
91 Count bytes.\r
92\r
93 @retval EFI_INVALID_PARAMETER The Address or the OrData or the Count is not valid.\r
94 @retval EFI_SUCCESS The OR operation succeeds.\r
95 @retval Others The OR operation fails.\r
96\r
97**/\r
98EFI_STATUS\r
99EFIAPI\r
100EmmcPeimHcOrMmio (\r
101 IN UINTN Address,\r
102 IN UINT8 Count,\r
103 IN VOID *OrData\r
104 )\r
105{\r
106 EFI_STATUS Status;\r
107 UINT64 Data;\r
108 UINT64 Or;\r
109\r
110 Status = EmmcPeimHcRwMmio (Address, TRUE, Count, &Data);\r
111 if (EFI_ERROR (Status)) {\r
112 return Status;\r
113 }\r
114\r
115 if (Count == 1) {\r
116 Or = *(UINT8*) OrData;\r
117 } else if (Count == 2) {\r
118 Or = *(UINT16*) OrData;\r
119 } else if (Count == 4) {\r
120 Or = *(UINT32*) OrData;\r
121 } else if (Count == 8) {\r
122 Or = *(UINT64*) OrData;\r
123 } else {\r
124 return EFI_INVALID_PARAMETER;\r
125 }\r
126\r
127 Data |= Or;\r
128 Status = EmmcPeimHcRwMmio (Address, FALSE, Count, &Data);\r
129\r
130 return Status;\r
131}\r
132\r
133/**\r
134 Do AND operation with the value of the specified EMMC host controller mmio register.\r
135\r
136 @param[in] Address The address of the mmio register to be read/written.\r
137 @param[in] Count The width of the mmio register in bytes.\r
138 Must be 1, 2 , 4 or 8 bytes.\r
139 @param[in] AndData The pointer to the data used to do AND operation.\r
140 The caller is responsible for having ownership of\r
141 the data buffer and ensuring its size not less than\r
142 Count bytes.\r
143\r
144 @retval EFI_INVALID_PARAMETER The Address or the AndData or the Count is not valid.\r
145 @retval EFI_SUCCESS The AND operation succeeds.\r
146 @retval Others The AND operation fails.\r
147\r
148**/\r
149EFI_STATUS\r
150EFIAPI\r
151EmmcPeimHcAndMmio (\r
152 IN UINTN Address,\r
153 IN UINT8 Count,\r
154 IN VOID *AndData\r
155 )\r
156{\r
157 EFI_STATUS Status;\r
158 UINT64 Data;\r
159 UINT64 And;\r
160\r
161 Status = EmmcPeimHcRwMmio (Address, TRUE, Count, &Data);\r
162 if (EFI_ERROR (Status)) {\r
163 return Status;\r
164 }\r
165\r
166 if (Count == 1) {\r
167 And = *(UINT8*) AndData;\r
168 } else if (Count == 2) {\r
169 And = *(UINT16*) AndData;\r
170 } else if (Count == 4) {\r
171 And = *(UINT32*) AndData;\r
172 } else if (Count == 8) {\r
173 And = *(UINT64*) AndData;\r
174 } else {\r
175 return EFI_INVALID_PARAMETER;\r
176 }\r
177\r
178 Data &= And;\r
179 Status = EmmcPeimHcRwMmio (Address, FALSE, Count, &Data);\r
180\r
181 return Status;\r
182}\r
183\r
184/**\r
185 Wait for the value of the specified MMIO register set to the test value.\r
186\r
187 @param[in] Address The address of the mmio register to be checked.\r
188 @param[in] Count The width of the mmio register in bytes.\r
189 Must be 1, 2, 4 or 8 bytes.\r
190 @param[in] MaskValue The mask value of memory.\r
191 @param[in] TestValue The test value of memory.\r
192\r
193 @retval EFI_NOT_READY The MMIO register hasn't set to the expected value.\r
194 @retval EFI_SUCCESS The MMIO register has expected value.\r
195 @retval Others The MMIO operation fails.\r
196\r
197**/\r
198EFI_STATUS\r
199EFIAPI\r
200EmmcPeimHcCheckMmioSet (\r
201 IN UINTN Address,\r
202 IN UINT8 Count,\r
203 IN UINT64 MaskValue,\r
204 IN UINT64 TestValue\r
205 )\r
206{\r
207 EFI_STATUS Status;\r
208 UINT64 Value;\r
209\r
210 //\r
211 // Access PCI MMIO space to see if the value is the tested one.\r
212 //\r
213 Value = 0;\r
214 Status = EmmcPeimHcRwMmio (Address, TRUE, Count, &Value);\r
215 if (EFI_ERROR (Status)) {\r
216 return Status;\r
217 }\r
218\r
219 Value &= MaskValue;\r
220\r
221 if (Value == TestValue) {\r
222 return EFI_SUCCESS;\r
223 }\r
224\r
225 return EFI_NOT_READY;\r
226}\r
227\r
228/**\r
229 Wait for the value of the specified MMIO register set to the test value.\r
230\r
231 @param[in] Address The address of the mmio register to wait.\r
232 @param[in] Count The width of the mmio register in bytes.\r
233 Must be 1, 2, 4 or 8 bytes.\r
234 @param[in] MaskValue The mask value of memory.\r
235 @param[in] TestValue The test value of memory.\r
236 @param[in] Timeout The time out value for wait memory set, uses 1\r
237 microsecond as a unit.\r
238\r
239 @retval EFI_TIMEOUT The MMIO register hasn't expected value in timeout\r
240 range.\r
241 @retval EFI_SUCCESS The MMIO register has expected value.\r
242 @retval Others The MMIO operation fails.\r
243\r
244**/\r
245EFI_STATUS\r
246EFIAPI\r
247EmmcPeimHcWaitMmioSet (\r
248 IN UINTN Address,\r
249 IN UINT8 Count,\r
250 IN UINT64 MaskValue,\r
251 IN UINT64 TestValue,\r
252 IN UINT64 Timeout\r
253 )\r
254{\r
255 EFI_STATUS Status;\r
256 BOOLEAN InfiniteWait;\r
257\r
258 if (Timeout == 0) {\r
259 InfiniteWait = TRUE;\r
260 } else {\r
261 InfiniteWait = FALSE;\r
262 }\r
263\r
264 while (InfiniteWait || (Timeout > 0)) {\r
265 Status = EmmcPeimHcCheckMmioSet (\r
266 Address,\r
267 Count,\r
268 MaskValue,\r
269 TestValue\r
270 );\r
271 if (Status != EFI_NOT_READY) {\r
272 return Status;\r
273 }\r
274\r
275 //\r
276 // Stall for 1 microsecond.\r
277 //\r
278 MicroSecondDelay (1);\r
279\r
280 Timeout--;\r
281 }\r
282\r
283 return EFI_TIMEOUT;\r
284}\r
285\r
286/**\r
287 Software reset the specified EMMC host controller and enable all interrupts.\r
288\r
289 @param[in] Bar The mmio base address of the slot to be accessed.\r
290\r
291 @retval EFI_SUCCESS The software reset executes successfully.\r
292 @retval Others The software reset fails.\r
293\r
294**/\r
295EFI_STATUS\r
296EmmcPeimHcReset (\r
297 IN UINTN Bar\r
298 )\r
299{\r
300 EFI_STATUS Status;\r
301 UINT8 SwReset;\r
302\r
303 SwReset = 0xFF;\r
304 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_SW_RST, FALSE, sizeof (SwReset), &SwReset);\r
305\r
306 if (EFI_ERROR (Status)) {\r
307 DEBUG ((EFI_D_ERROR, "EmmcPeimHcReset: write full 1 fails: %r\n", Status));\r
308 return Status;\r
309 }\r
310\r
311 Status = EmmcPeimHcWaitMmioSet (\r
312 Bar + EMMC_HC_SW_RST,\r
313 sizeof (SwReset),\r
314 0xFF,\r
315 0x00,\r
316 EMMC_TIMEOUT\r
317 );\r
318 if (EFI_ERROR (Status)) {\r
319 DEBUG ((EFI_D_INFO, "EmmcPeimHcReset: reset done with %r\n", Status));\r
320 return Status;\r
321 }\r
322 //\r
323 // Enable all interrupt after reset all.\r
324 //\r
325 Status = EmmcPeimHcEnableInterrupt (Bar);\r
326\r
327 return Status;\r
328}\r
329\r
330/**\r
331 Set all interrupt status bits in Normal and Error Interrupt Status Enable\r
332 register.\r
333\r
334 @param[in] Bar The mmio base address of the slot to be accessed.\r
335\r
336 @retval EFI_SUCCESS The operation executes successfully.\r
337 @retval Others The operation fails.\r
338\r
339**/\r
340EFI_STATUS\r
341EmmcPeimHcEnableInterrupt (\r
342 IN UINTN Bar\r
343 )\r
344{\r
345 EFI_STATUS Status;\r
346 UINT16 IntStatus;\r
347\r
348 //\r
349 // Enable all bits in Error Interrupt Status Enable Register\r
350 //\r
351 IntStatus = 0xFFFF;\r
352 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_ERR_INT_STS_EN, FALSE, sizeof (IntStatus), &IntStatus);\r
353 if (EFI_ERROR (Status)) {\r
354 return Status;\r
355 }\r
356 //\r
357 // Enable all bits in Normal Interrupt Status Enable Register\r
358 //\r
359 IntStatus = 0xFFFF;\r
360 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_NOR_INT_STS_EN, FALSE, sizeof (IntStatus), &IntStatus);\r
361\r
362 return Status;\r
363}\r
364\r
365/**\r
366 Get the capability data from the specified slot.\r
367\r
368 @param[in] Bar The mmio base address of the slot to be accessed.\r
369 @param[out] Capability The buffer to store the capability data.\r
370\r
371 @retval EFI_SUCCESS The operation executes successfully.\r
372 @retval Others The operation fails.\r
373\r
374**/\r
375EFI_STATUS\r
376EmmcPeimHcGetCapability (\r
377 IN UINTN Bar,\r
378 OUT EMMC_HC_SLOT_CAP *Capability\r
379 )\r
380{\r
381 EFI_STATUS Status;\r
382 UINT64 Cap;\r
383\r
384 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_CAP, TRUE, sizeof (Cap), &Cap);\r
385 if (EFI_ERROR (Status)) {\r
386 return Status;\r
387 }\r
388\r
389 CopyMem (Capability, &Cap, sizeof (Cap));\r
390\r
391 return EFI_SUCCESS;\r
392}\r
393\r
394/**\r
395 Detect whether there is a EMMC card attached at the specified EMMC host controller\r
396 slot.\r
397\r
398 Refer to SD Host Controller Simplified spec 3.0 Section 3.1 for details.\r
399\r
400 @param[in] Bar The mmio base address of the slot to be accessed.\r
401\r
402 @retval EFI_SUCCESS There is a EMMC card attached.\r
403 @retval EFI_NO_MEDIA There is not a EMMC card attached.\r
404 @retval Others The detection fails.\r
405\r
406**/\r
407EFI_STATUS\r
408EmmcPeimHcCardDetect (\r
409 IN UINTN Bar\r
410 )\r
411{\r
412 EFI_STATUS Status;\r
413 UINT16 Data;\r
414 UINT32 PresentState;\r
415\r
416 //\r
417 // Check Normal Interrupt Status Register\r
418 //\r
419 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_NOR_INT_STS, TRUE, sizeof (Data), &Data);\r
420 if (EFI_ERROR (Status)) {\r
421 return Status;\r
422 }\r
423\r
424 if ((Data & (BIT6 | BIT7)) != 0) {\r
425 //\r
426 // Clear BIT6 and BIT7 by writing 1 to these two bits if set.\r
427 //\r
428 Data &= BIT6 | BIT7;\r
429 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_NOR_INT_STS, FALSE, sizeof (Data), &Data);\r
430 if (EFI_ERROR (Status)) {\r
431 return Status;\r
432 }\r
433 }\r
434\r
435 //\r
436 // Check Present State Register to see if there is a card presented.\r
437 //\r
438 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);\r
439 if (EFI_ERROR (Status)) {\r
440 return Status;\r
441 }\r
442\r
443 if ((PresentState & BIT16) != 0) {\r
444 return EFI_SUCCESS;\r
445 } else {\r
446 return EFI_NO_MEDIA;\r
447 }\r
448}\r
449\r
450/**\r
451 Stop EMMC card clock.\r
452\r
453 Refer to SD Host Controller Simplified spec 3.0 Section 3.2.2 for details.\r
454\r
455 @param[in] Bar The mmio base address of the slot to be accessed.\r
456\r
457 @retval EFI_SUCCESS Succeed to stop EMMC clock.\r
458 @retval Others Fail to stop EMMC clock.\r
459\r
460**/\r
461EFI_STATUS\r
462EmmcPeimHcStopClock (\r
463 IN UINTN Bar\r
464 )\r
465{\r
466 EFI_STATUS Status;\r
467 UINT32 PresentState;\r
468 UINT16 ClockCtrl;\r
469\r
470 //\r
471 // Ensure no SD transactions are occurring on the SD Bus by\r
472 // waiting for Command Inhibit (DAT) and Command Inhibit (CMD)\r
473 // in the Present State register to be 0.\r
474 //\r
475 Status = EmmcPeimHcWaitMmioSet (\r
476 Bar + EMMC_HC_PRESENT_STATE,\r
477 sizeof (PresentState),\r
478 BIT0 | BIT1,\r
479 0,\r
480 EMMC_TIMEOUT\r
481 );\r
482 if (EFI_ERROR (Status)) {\r
483 return Status;\r
484 }\r
485\r
486 //\r
487 // Set SD Clock Enable in the Clock Control register to 0\r
488 //\r
489 ClockCtrl = (UINT16)~BIT2;\r
490 Status = EmmcPeimHcAndMmio (Bar + EMMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);\r
491\r
492 return Status;\r
493}\r
494\r
495/**\r
496 EMMC card clock supply.\r
497\r
498 Refer to SD Host Controller Simplified spec 3.0 Section 3.2.1 for details.\r
499\r
500 @param[in] Bar The mmio base address of the slot to be accessed.\r
501 @param[in] ClockFreq The max clock frequency to be set. The unit is KHz.\r
502\r
503 @retval EFI_SUCCESS The clock is supplied successfully.\r
504 @retval Others The clock isn't supplied successfully.\r
505\r
506**/\r
507EFI_STATUS\r
508EmmcPeimHcClockSupply (\r
509 IN UINTN Bar,\r
510 IN UINT64 ClockFreq\r
511 )\r
512{\r
513 EFI_STATUS Status;\r
514 EMMC_HC_SLOT_CAP Capability;\r
515 UINT32 BaseClkFreq;\r
516 UINT32 SettingFreq;\r
517 UINT32 Divisor;\r
518 UINT32 Remainder;\r
519 UINT16 ControllerVer;\r
520 UINT16 ClockCtrl;\r
521\r
522 //\r
523 // Calculate a divisor for SD clock frequency\r
524 //\r
525 Status = EmmcPeimHcGetCapability (Bar, &Capability);\r
526 if (EFI_ERROR (Status)) {\r
527 return Status;\r
528 }\r
529 ASSERT (Capability.BaseClkFreq != 0);\r
530\r
531 BaseClkFreq = Capability.BaseClkFreq;\r
cb9cb9e2
FT
532\r
533 if (ClockFreq == 0) {\r
48555339
FT
534 return EFI_INVALID_PARAMETER;\r
535 }\r
cb9cb9e2
FT
536\r
537 if (ClockFreq > (BaseClkFreq * 1000)) {\r
538 ClockFreq = BaseClkFreq * 1000;\r
539 }\r
540\r
48555339
FT
541 //\r
542 // Calculate the divisor of base frequency.\r
543 //\r
544 Divisor = 0;\r
545 SettingFreq = BaseClkFreq * 1000;\r
546 while (ClockFreq < SettingFreq) {\r
547 Divisor++;\r
548\r
549 SettingFreq = (BaseClkFreq * 1000) / (2 * Divisor);\r
550 Remainder = (BaseClkFreq * 1000) % (2 * Divisor);\r
551 if ((ClockFreq == SettingFreq) && (Remainder == 0)) {\r
552 break;\r
553 }\r
554 if ((ClockFreq == SettingFreq) && (Remainder != 0)) {\r
555 SettingFreq ++;\r
556 }\r
557 }\r
558\r
559 DEBUG ((EFI_D_INFO, "BaseClkFreq %dMHz Divisor %d ClockFreq %dKhz\n", BaseClkFreq, Divisor, ClockFreq));\r
560\r
561 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);\r
562 if (EFI_ERROR (Status)) {\r
563 return Status;\r
564 }\r
565 //\r
566 // Set SDCLK Frequency Select and Internal Clock Enable fields in Clock Control register.\r
567 //\r
568 if ((ControllerVer & 0xFF) == 2) {\r
569 ASSERT (Divisor <= 0x3FF);\r
570 ClockCtrl = ((Divisor & 0xFF) << 8) | ((Divisor & 0x300) >> 2);\r
571 } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {\r
572 //\r
573 // Only the most significant bit can be used as divisor.\r
574 //\r
575 if (((Divisor - 1) & Divisor) != 0) {\r
576 Divisor = 1 << (HighBitSet32 (Divisor) + 1);\r
577 }\r
578 ASSERT (Divisor <= 0x80);\r
579 ClockCtrl = (Divisor & 0xFF) << 8;\r
580 } else {\r
581 DEBUG ((EFI_D_ERROR, "Unknown SD Host Controller Spec version [0x%x]!!!\n", ControllerVer));\r
582 return EFI_UNSUPPORTED;\r
583 }\r
584\r
585 //\r
586 // Stop bus clock at first\r
587 //\r
588 Status = EmmcPeimHcStopClock (Bar);\r
589 if (EFI_ERROR (Status)) {\r
590 return Status;\r
591 }\r
592\r
593 //\r
594 // Supply clock frequency with specified divisor\r
595 //\r
596 ClockCtrl |= BIT0;\r
597 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_CLOCK_CTRL, FALSE, sizeof (ClockCtrl), &ClockCtrl);\r
598 if (EFI_ERROR (Status)) {\r
599 DEBUG ((EFI_D_ERROR, "Set SDCLK Frequency Select and Internal Clock Enable fields fails\n"));\r
600 return Status;\r
601 }\r
602\r
603 //\r
604 // Wait Internal Clock Stable in the Clock Control register to be 1\r
605 //\r
606 Status = EmmcPeimHcWaitMmioSet (\r
607 Bar + EMMC_HC_CLOCK_CTRL,\r
608 sizeof (ClockCtrl),\r
609 BIT1,\r
610 BIT1,\r
611 EMMC_TIMEOUT\r
612 );\r
613 if (EFI_ERROR (Status)) {\r
614 return Status;\r
615 }\r
616\r
617 //\r
618 // Set SD Clock Enable in the Clock Control register to 1\r
619 //\r
620 ClockCtrl = BIT2;\r
621 Status = EmmcPeimHcOrMmio (Bar + EMMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);\r
622\r
623 return Status;\r
624}\r
625\r
626/**\r
627 EMMC bus power control.\r
628\r
629 Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for details.\r
630\r
631 @param[in] Bar The mmio base address of the slot to be accessed.\r
632 @param[in] PowerCtrl The value setting to the power control register.\r
633\r
634 @retval TRUE There is a EMMC card attached.\r
635 @retval FALSE There is no a EMMC card attached.\r
636\r
637**/\r
638EFI_STATUS\r
639EmmcPeimHcPowerControl (\r
640 IN UINTN Bar,\r
641 IN UINT8 PowerCtrl\r
642 )\r
643{\r
644 EFI_STATUS Status;\r
645\r
646 //\r
647 // Clr SD Bus Power\r
648 //\r
649 PowerCtrl &= (UINT8)~BIT0;\r
650 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_POWER_CTRL, FALSE, sizeof (PowerCtrl), &PowerCtrl);\r
651 if (EFI_ERROR (Status)) {\r
652 return Status;\r
653 }\r
654\r
655 //\r
656 // Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register\r
657 //\r
658 PowerCtrl |= BIT0;\r
659 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_POWER_CTRL, FALSE, sizeof (PowerCtrl), &PowerCtrl);\r
660\r
661 return Status;\r
662}\r
663\r
664/**\r
665 Set the EMMC bus width.\r
666\r
667 Refer to SD Host Controller Simplified spec 3.0 Section 3.4 for details.\r
668\r
669 @param[in] Bar The mmio base address of the slot to be accessed.\r
670 @param[in] BusWidth The bus width used by the EMMC device, it must be 1, 4 or 8.\r
671\r
672 @retval EFI_SUCCESS The bus width is set successfully.\r
673 @retval Others The bus width isn't set successfully.\r
674\r
675**/\r
676EFI_STATUS\r
677EmmcPeimHcSetBusWidth (\r
678 IN UINTN Bar,\r
679 IN UINT16 BusWidth\r
680 )\r
681{\r
682 EFI_STATUS Status;\r
683 UINT8 HostCtrl1;\r
684\r
685 if (BusWidth == 1) {\r
686 HostCtrl1 = (UINT8)~(BIT5 | BIT1);\r
687 Status = EmmcPeimHcAndMmio (Bar + EMMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
688 } else if (BusWidth == 4) {\r
689 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_HOST_CTRL1, TRUE, sizeof (HostCtrl1), &HostCtrl1);\r
690 if (EFI_ERROR (Status)) {\r
691 return Status;\r
692 }\r
693 HostCtrl1 |= BIT1;\r
694 HostCtrl1 &= (UINT8)~BIT5;\r
695 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_HOST_CTRL1, FALSE, sizeof (HostCtrl1), &HostCtrl1);\r
696 } else if (BusWidth == 8) {\r
697 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_HOST_CTRL1, TRUE, sizeof (HostCtrl1), &HostCtrl1);\r
698 if (EFI_ERROR (Status)) {\r
699 return Status;\r
700 }\r
701 HostCtrl1 &= (UINT8)~BIT1;\r
702 HostCtrl1 |= BIT5;\r
703 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_HOST_CTRL1, FALSE, sizeof (HostCtrl1), &HostCtrl1);\r
704 } else {\r
705 ASSERT (FALSE);\r
706 return EFI_INVALID_PARAMETER;\r
707 }\r
708\r
709 return Status;\r
710}\r
711\r
712/**\r
713 Supply EMMC card with lowest clock frequency at initialization.\r
714\r
715 @param[in] Bar The mmio base address of the slot to be accessed.\r
716\r
717 @retval EFI_SUCCESS The clock is supplied successfully.\r
718 @retval Others The clock isn't supplied successfully.\r
719\r
720**/\r
721EFI_STATUS\r
722EmmcPeimHcInitClockFreq (\r
723 IN UINTN Bar\r
724 )\r
725{\r
726 EFI_STATUS Status;\r
727 EMMC_HC_SLOT_CAP Capability;\r
728 UINT32 InitFreq;\r
729\r
730 //\r
731 // Calculate a divisor for SD clock frequency\r
732 //\r
733 Status = EmmcPeimHcGetCapability (Bar, &Capability);\r
734 if (EFI_ERROR (Status)) {\r
735 return Status;\r
736 }\r
737\r
738 if (Capability.BaseClkFreq == 0) {\r
739 //\r
740 // Don't support get Base Clock Frequency information via another method\r
741 //\r
742 return EFI_UNSUPPORTED;\r
743 }\r
744 //\r
745 // Supply 400KHz clock frequency at initialization phase.\r
746 //\r
747 InitFreq = 400;\r
748 Status = EmmcPeimHcClockSupply (Bar, InitFreq);\r
749 return Status;\r
750}\r
751\r
752/**\r
753 Supply EMMC card with maximum voltage at initialization.\r
754\r
755 Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for details.\r
756\r
757 @param[in] Bar The mmio base address of the slot to be accessed.\r
758\r
759 @retval EFI_SUCCESS The voltage is supplied successfully.\r
760 @retval Others The voltage isn't supplied successfully.\r
761\r
762**/\r
763EFI_STATUS\r
764EmmcPeimHcInitPowerVoltage (\r
765 IN UINTN Bar\r
766 )\r
767{\r
768 EFI_STATUS Status;\r
769 EMMC_HC_SLOT_CAP Capability;\r
770 UINT8 MaxVoltage;\r
771 UINT8 HostCtrl2;\r
772\r
773 //\r
774 // Get the support voltage of the Host Controller\r
775 //\r
776 Status = EmmcPeimHcGetCapability (Bar, &Capability);\r
777 if (EFI_ERROR (Status)) {\r
778 return Status;\r
779 }\r
780 //\r
781 // Calculate supported maximum voltage according to SD Bus Voltage Select\r
782 //\r
783 if (Capability.Voltage33 != 0) {\r
784 //\r
785 // Support 3.3V\r
786 //\r
787 MaxVoltage = 0x0E;\r
788 } else if (Capability.Voltage30 != 0) {\r
789 //\r
790 // Support 3.0V\r
791 //\r
792 MaxVoltage = 0x0C;\r
793 } else if (Capability.Voltage18 != 0) {\r
794 //\r
795 // Support 1.8V\r
796 //\r
797 MaxVoltage = 0x0A;\r
798 HostCtrl2 = BIT3;\r
799 Status = EmmcPeimHcOrMmio (Bar + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
800 if (EFI_ERROR (Status)) {\r
801 return Status;\r
802 }\r
803 MicroSecondDelay (5000);\r
804 } else {\r
805 ASSERT (FALSE);\r
806 return EFI_DEVICE_ERROR;\r
807 }\r
808\r
809 //\r
810 // Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register\r
811 //\r
812 Status = EmmcPeimHcPowerControl (Bar, MaxVoltage);\r
813\r
814 return Status;\r
815}\r
816\r
817/**\r
818 Initialize the Timeout Control register with most conservative value at initialization.\r
819\r
820 Refer to SD Host Controller Simplified spec 3.0 Section 2.2.15 for details.\r
821\r
822 @param[in] Bar The mmio base address of the slot to be accessed.\r
823\r
824 @retval EFI_SUCCESS The timeout control register is configured successfully.\r
825 @retval Others The timeout control register isn't configured successfully.\r
826\r
827**/\r
828EFI_STATUS\r
829EmmcPeimHcInitTimeoutCtrl (\r
830 IN UINTN Bar\r
831 )\r
832{\r
833 EFI_STATUS Status;\r
834 UINT8 Timeout;\r
835\r
836 Timeout = 0x0E;\r
837 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_TIMEOUT_CTRL, FALSE, sizeof (Timeout), &Timeout);\r
838\r
839 return Status;\r
840}\r
841\r
842/**\r
843 Initial EMMC host controller with lowest clock frequency, max power and max timeout value\r
844 at initialization.\r
845\r
846 @param[in] Bar The mmio base address of the slot to be accessed.\r
847\r
848 @retval EFI_SUCCESS The host controller is initialized successfully.\r
849 @retval Others The host controller isn't initialized successfully.\r
850\r
851**/\r
852EFI_STATUS\r
853EmmcPeimHcInitHost (\r
854 IN UINTN Bar\r
855 )\r
856{\r
857 EFI_STATUS Status;\r
858\r
859 Status = EmmcPeimHcInitClockFreq (Bar);\r
860 if (EFI_ERROR (Status)) {\r
861 return Status;\r
862 }\r
863\r
864 Status = EmmcPeimHcInitPowerVoltage (Bar);\r
865 if (EFI_ERROR (Status)) {\r
866 return Status;\r
867 }\r
868\r
869 Status = EmmcPeimHcInitTimeoutCtrl (Bar);\r
870 return Status;\r
871}\r
872\r
873/**\r
874 Turn on/off LED.\r
875\r
876 @param[in] Bar The mmio base address of the slot to be accessed.\r
877 @param[in] On The boolean to turn on/off LED.\r
878\r
879 @retval EFI_SUCCESS The LED is turned on/off successfully.\r
880 @retval Others The LED isn't turned on/off successfully.\r
881\r
882**/\r
883EFI_STATUS\r
884EmmcPeimHcLedOnOff (\r
885 IN UINTN Bar,\r
886 IN BOOLEAN On\r
887 )\r
888{\r
889 EFI_STATUS Status;\r
890 UINT8 HostCtrl1;\r
891\r
892 if (On) {\r
893 HostCtrl1 = BIT0;\r
894 Status = EmmcPeimHcOrMmio (Bar + EMMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
895 } else {\r
896 HostCtrl1 = (UINT8)~BIT0;\r
897 Status = EmmcPeimHcAndMmio (Bar + EMMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
898 }\r
899\r
900 return Status;\r
901}\r
902\r
903/**\r
904 Build ADMA descriptor table for transfer.\r
905\r
906 Refer to SD Host Controller Simplified spec 3.0 Section 1.13 for details.\r
907\r
908 @param[in] Trb The pointer to the EMMC_TRB instance.\r
909\r
910 @retval EFI_SUCCESS The ADMA descriptor table is created successfully.\r
911 @retval Others The ADMA descriptor table isn't created successfully.\r
912\r
913**/\r
914EFI_STATUS\r
915BuildAdmaDescTable (\r
916 IN EMMC_TRB *Trb\r
917 )\r
918{\r
919 EFI_PHYSICAL_ADDRESS Data;\r
920 UINT64 DataLen;\r
921 UINT64 Entries;\r
922 UINT32 Index;\r
923 UINT64 Remaining;\r
924 UINT32 Address;\r
925\r
85ad9a6e 926 Data = Trb->DataPhy;\r
48555339
FT
927 DataLen = Trb->DataLen;\r
928 //\r
929 // Only support 32bit ADMA Descriptor Table\r
930 //\r
931 if ((Data >= 0x100000000ul) || ((Data + DataLen) > 0x100000000ul)) {\r
932 return EFI_INVALID_PARAMETER;\r
933 }\r
934 //\r
935 // Address field shall be set on 32-bit boundary (Lower 2-bit is always set to 0)\r
936 // for 32-bit address descriptor table.\r
937 //\r
938 if ((Data & (BIT0 | BIT1)) != 0) {\r
939 DEBUG ((EFI_D_INFO, "The buffer [0x%x] to construct ADMA desc is not aligned to 4 bytes boundary!\n", Data));\r
940 }\r
941\r
942 Entries = DivU64x32 ((DataLen + ADMA_MAX_DATA_PER_LINE - 1), ADMA_MAX_DATA_PER_LINE);\r
943\r
944 Trb->AdmaDescSize = (UINTN)MultU64x32 (Entries, sizeof (EMMC_HC_ADMA_DESC_LINE));\r
945 Trb->AdmaDesc = EmmcPeimAllocateMem (Trb->Slot->Private->Pool, Trb->AdmaDescSize);\r
946 if (Trb->AdmaDesc == NULL) {\r
947 return EFI_OUT_OF_RESOURCES;\r
948 }\r
949\r
950 Remaining = DataLen;\r
951 Address = (UINT32)Data;\r
952 for (Index = 0; Index < Entries; Index++) {\r
953 if (Remaining <= ADMA_MAX_DATA_PER_LINE) {\r
954 Trb->AdmaDesc[Index].Valid = 1;\r
955 Trb->AdmaDesc[Index].Act = 2;\r
956 Trb->AdmaDesc[Index].Length = (UINT16)Remaining;\r
957 Trb->AdmaDesc[Index].Address = Address;\r
958 break;\r
959 } else {\r
960 Trb->AdmaDesc[Index].Valid = 1;\r
961 Trb->AdmaDesc[Index].Act = 2;\r
962 Trb->AdmaDesc[Index].Length = 0;\r
963 Trb->AdmaDesc[Index].Address = Address;\r
964 }\r
965\r
966 Remaining -= ADMA_MAX_DATA_PER_LINE;\r
967 Address += ADMA_MAX_DATA_PER_LINE;\r
968 }\r
969\r
970 //\r
971 // Set the last descriptor line as end of descriptor table\r
972 //\r
973 Trb->AdmaDesc[Index].End = 1;\r
974 return EFI_SUCCESS;\r
975}\r
976\r
977/**\r
978 Create a new TRB for the EMMC cmd request.\r
979\r
980 @param[in] Slot The slot number of the EMMC card to send the command to.\r
981 @param[in] Packet A pointer to the SD command data structure.\r
982\r
983 @return Created Trb or NULL.\r
984\r
985**/\r
986EMMC_TRB *\r
987EmmcPeimCreateTrb (\r
988 IN EMMC_PEIM_HC_SLOT *Slot,\r
989 IN EMMC_COMMAND_PACKET *Packet\r
990 )\r
991{\r
992 EMMC_TRB *Trb;\r
993 EFI_STATUS Status;\r
994 EMMC_HC_SLOT_CAP Capability;\r
85ad9a6e
HW
995 EDKII_IOMMU_OPERATION MapOp;\r
996 UINTN MapLength;\r
48555339
FT
997\r
998 //\r
999 // Calculate a divisor for SD clock frequency\r
1000 //\r
1001 Status = EmmcPeimHcGetCapability (Slot->EmmcHcBase, &Capability);\r
1002 if (EFI_ERROR (Status)) {\r
1003 return NULL;\r
1004 }\r
1005\r
85ad9a6e 1006 Trb = AllocateZeroPool (sizeof (EMMC_TRB));\r
48555339
FT
1007 if (Trb == NULL) {\r
1008 return NULL;\r
1009 }\r
1010\r
1011 Trb->Slot = Slot;\r
1012 Trb->BlockSize = 0x200;\r
1013 Trb->Packet = Packet;\r
1014 Trb->Timeout = Packet->Timeout;\r
1015\r
1016 if ((Packet->InTransferLength != 0) && (Packet->InDataBuffer != NULL)) {\r
1017 Trb->Data = Packet->InDataBuffer;\r
1018 Trb->DataLen = Packet->InTransferLength;\r
1019 Trb->Read = TRUE;\r
1020 } else if ((Packet->OutTransferLength != 0) && (Packet->OutDataBuffer != NULL)) {\r
1021 Trb->Data = Packet->OutDataBuffer;\r
1022 Trb->DataLen = Packet->OutTransferLength;\r
1023 Trb->Read = FALSE;\r
1024 } else if ((Packet->InTransferLength == 0) && (Packet->OutTransferLength == 0)) {\r
1025 Trb->Data = NULL;\r
1026 Trb->DataLen = 0;\r
1027 } else {\r
1028 goto Error;\r
1029 }\r
1030\r
54228046 1031 if ((Trb->DataLen != 0) && (Trb->DataLen < Trb->BlockSize)) {\r
e7e89b08 1032 Trb->BlockSize = (UINT16)Trb->DataLen;\r
48555339
FT
1033 }\r
1034\r
e7e89b08 1035 if (Packet->EmmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK) {\r
48555339 1036 Trb->Mode = EmmcPioMode;\r
e7e89b08 1037 } else {\r
85ad9a6e
HW
1038 if (Trb->Read) {\r
1039 MapOp = EdkiiIoMmuOperationBusMasterWrite;\r
1040 } else {\r
1041 MapOp = EdkiiIoMmuOperationBusMasterRead;\r
1042 }\r
1043\r
1044 if (Trb->DataLen != 0) {\r
1045 MapLength = Trb->DataLen;\r
1046 Status = IoMmuMap (MapOp, Trb->Data, &MapLength, &Trb->DataPhy, &Trb->DataMap);\r
1047\r
1048 if (EFI_ERROR (Status) || (MapLength != Trb->DataLen)) {\r
1049 DEBUG ((DEBUG_ERROR, "EmmcPeimCreateTrb: Fail to map data buffer.\n"));\r
1050 goto Error;\r
1051 }\r
1052 }\r
1053\r
e7e89b08
FT
1054 if (Trb->DataLen == 0) {\r
1055 Trb->Mode = EmmcNoData;\r
1056 } else if (Capability.Adma2 != 0) {\r
1057 Trb->Mode = EmmcAdmaMode;\r
1058 Status = BuildAdmaDescTable (Trb);\r
1059 if (EFI_ERROR (Status)) {\r
1060 goto Error;\r
1061 }\r
1062 } else if (Capability.Sdma != 0) {\r
1063 Trb->Mode = EmmcSdmaMode;\r
1064 } else {\r
1065 Trb->Mode = EmmcPioMode;\r
1066 }\r
48555339 1067 }\r
48555339
FT
1068 return Trb;\r
1069\r
1070Error:\r
1071 EmmcPeimFreeTrb (Trb);\r
1072 return NULL;\r
1073}\r
1074\r
1075/**\r
1076 Free the resource used by the TRB.\r
1077\r
1078 @param[in] Trb The pointer to the EMMC_TRB instance.\r
1079\r
1080**/\r
1081VOID\r
1082EmmcPeimFreeTrb (\r
1083 IN EMMC_TRB *Trb\r
1084 )\r
1085{\r
85ad9a6e
HW
1086 if ((Trb != NULL) && (Trb->DataMap != NULL)) {\r
1087 IoMmuUnmap (Trb->DataMap);\r
1088 }\r
1089\r
48555339
FT
1090 if ((Trb != NULL) && (Trb->AdmaDesc != NULL)) {\r
1091 EmmcPeimFreeMem (Trb->Slot->Private->Pool, Trb->AdmaDesc, Trb->AdmaDescSize);\r
1092 }\r
1093\r
1094 if (Trb != NULL) {\r
85ad9a6e 1095 FreePool (Trb);\r
48555339
FT
1096 }\r
1097 return;\r
1098}\r
1099\r
1100/**\r
1101 Check if the env is ready for execute specified TRB.\r
1102\r
1103 @param[in] Bar The mmio base address of the slot to be accessed.\r
1104 @param[in] Trb The pointer to the EMMC_TRB instance.\r
1105\r
1106 @retval EFI_SUCCESS The env is ready for TRB execution.\r
1107 @retval EFI_NOT_READY The env is not ready for TRB execution.\r
1108 @retval Others Some erros happen.\r
1109\r
1110**/\r
1111EFI_STATUS\r
1112EmmcPeimCheckTrbEnv (\r
1113 IN UINTN Bar,\r
1114 IN EMMC_TRB *Trb\r
1115 )\r
1116{\r
1117 EFI_STATUS Status;\r
1118 EMMC_COMMAND_PACKET *Packet;\r
1119 UINT32 PresentState;\r
1120\r
1121 Packet = Trb->Packet;\r
1122\r
1123 if ((Packet->EmmcCmdBlk->CommandType == EmmcCommandTypeAdtc) ||\r
1124 (Packet->EmmcCmdBlk->ResponseType == EmmcResponceTypeR1b) ||\r
1125 (Packet->EmmcCmdBlk->ResponseType == EmmcResponceTypeR5b)) {\r
1126 //\r
1127 // Wait Command Inhibit (CMD) and Command Inhibit (DAT) in\r
1128 // the Present State register to be 0\r
1129 //\r
1130 PresentState = BIT0 | BIT1;\r
48555339
FT
1131 } else {\r
1132 //\r
1133 // Wait Command Inhibit (CMD) in the Present State register\r
1134 // to be 0\r
1135 //\r
1136 PresentState = BIT0;\r
1137 }\r
1138\r
1139 Status = EmmcPeimHcCheckMmioSet (\r
1140 Bar + EMMC_HC_PRESENT_STATE,\r
1141 sizeof (PresentState),\r
1142 PresentState,\r
1143 0\r
1144 );\r
1145\r
1146 return Status;\r
1147}\r
1148\r
1149/**\r
1150 Wait for the env to be ready for execute specified TRB.\r
1151\r
1152 @param[in] Bar The mmio base address of the slot to be accessed.\r
1153 @param[in] Trb The pointer to the EMMC_TRB instance.\r
1154\r
1155 @retval EFI_SUCCESS The env is ready for TRB execution.\r
1156 @retval EFI_TIMEOUT The env is not ready for TRB execution in time.\r
1157 @retval Others Some erros happen.\r
1158\r
1159**/\r
1160EFI_STATUS\r
1161EmmcPeimWaitTrbEnv (\r
1162 IN UINTN Bar,\r
1163 IN EMMC_TRB *Trb\r
1164 )\r
1165{\r
1166 EFI_STATUS Status;\r
1167 EMMC_COMMAND_PACKET *Packet;\r
1168 UINT64 Timeout;\r
1169 BOOLEAN InfiniteWait;\r
1170\r
1171 //\r
1172 // Wait Command Complete Interrupt Status bit in Normal Interrupt Status Register\r
1173 //\r
1174 Packet = Trb->Packet;\r
1175 Timeout = Packet->Timeout;\r
1176 if (Timeout == 0) {\r
1177 InfiniteWait = TRUE;\r
1178 } else {\r
1179 InfiniteWait = FALSE;\r
1180 }\r
1181\r
1182 while (InfiniteWait || (Timeout > 0)) {\r
1183 //\r
1184 // Check Trb execution result by reading Normal Interrupt Status register.\r
1185 //\r
1186 Status = EmmcPeimCheckTrbEnv (Bar, Trb);\r
1187 if (Status != EFI_NOT_READY) {\r
1188 return Status;\r
1189 }\r
1190 //\r
1191 // Stall for 1 microsecond.\r
1192 //\r
1193 MicroSecondDelay (1);\r
1194\r
1195 Timeout--;\r
1196 }\r
1197\r
1198 return EFI_TIMEOUT;\r
1199}\r
1200\r
1201/**\r
1202 Execute the specified TRB.\r
1203\r
1204 @param[in] Bar The mmio base address of the slot to be accessed.\r
1205 @param[in] Trb The pointer to the EMMC_TRB instance.\r
1206\r
1207 @retval EFI_SUCCESS The TRB is sent to host controller successfully.\r
1208 @retval Others Some erros happen when sending this request to the host controller.\r
1209\r
1210**/\r
1211EFI_STATUS\r
1212EmmcPeimExecTrb (\r
1213 IN UINTN Bar,\r
1214 IN EMMC_TRB *Trb\r
1215 )\r
1216{\r
1217 EFI_STATUS Status;\r
1218 EMMC_COMMAND_PACKET *Packet;\r
1219 UINT16 Cmd;\r
1220 UINT16 IntStatus;\r
1221 UINT32 Argument;\r
1222 UINT16 BlkCount;\r
1223 UINT16 BlkSize;\r
1224 UINT16 TransMode;\r
1225 UINT8 HostCtrl1;\r
1226 UINT32 SdmaAddr;\r
1227 UINT64 AdmaAddr;\r
1228\r
1229 Packet = Trb->Packet;\r
1230 //\r
1231 // Clear all bits in Error Interrupt Status Register\r
1232 //\r
1233 IntStatus = 0xFFFF;\r
1234 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_ERR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);\r
1235 if (EFI_ERROR (Status)) {\r
1236 return Status;\r
1237 }\r
1238 //\r
1239 // Clear all bits in Normal Interrupt Status Register\r
1240 //\r
1241 IntStatus = 0xFFFF;\r
1242 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);\r
1243 if (EFI_ERROR (Status)) {\r
1244 return Status;\r
1245 }\r
1246 //\r
1247 // Set Host Control 1 register DMA Select field\r
1248 //\r
1249 if (Trb->Mode == EmmcAdmaMode) {\r
1250 HostCtrl1 = BIT4;\r
1251 Status = EmmcPeimHcOrMmio (Bar + EMMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
1252 if (EFI_ERROR (Status)) {\r
1253 return Status;\r
1254 }\r
1255 }\r
1256\r
1257 EmmcPeimHcLedOnOff (Bar, TRUE);\r
1258\r
1259 if (Trb->Mode == EmmcSdmaMode) {\r
85ad9a6e 1260 if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {\r
48555339
FT
1261 return EFI_INVALID_PARAMETER;\r
1262 }\r
1263\r
85ad9a6e 1264 SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;\r
48555339
FT
1265 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_SDMA_ADDR, FALSE, sizeof (SdmaAddr), &SdmaAddr);\r
1266 if (EFI_ERROR (Status)) {\r
1267 return Status;\r
1268 }\r
1269 } else if (Trb->Mode == EmmcAdmaMode) {\r
1270 AdmaAddr = (UINT64)(UINTN)Trb->AdmaDesc;\r
1271 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_ADMA_SYS_ADDR, FALSE, sizeof (AdmaAddr), &AdmaAddr);\r
1272 if (EFI_ERROR (Status)) {\r
1273 return Status;\r
1274 }\r
1275 }\r
1276\r
1277 BlkSize = Trb->BlockSize;\r
1278 if (Trb->Mode == EmmcSdmaMode) {\r
1279 //\r
1280 // Set SDMA boundary to be 512K bytes.\r
1281 //\r
1282 BlkSize |= 0x7000;\r
1283 }\r
1284\r
1285 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_BLK_SIZE, FALSE, sizeof (BlkSize), &BlkSize);\r
1286 if (EFI_ERROR (Status)) {\r
1287 return Status;\r
1288 }\r
1289\r
e7e89b08
FT
1290 BlkCount = 0;\r
1291 if (Trb->Mode != EmmcNoData) {\r
1292 //\r
1293 // Calcuate Block Count.\r
1294 //\r
1295 BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);\r
1296 }\r
1297\r
48555339
FT
1298 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);\r
1299 if (EFI_ERROR (Status)) {\r
1300 return Status;\r
1301 }\r
1302\r
1303 Argument = Packet->EmmcCmdBlk->CommandArgument;\r
1304 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_ARG1, FALSE, sizeof (Argument), &Argument);\r
1305 if (EFI_ERROR (Status)) {\r
1306 return Status;\r
1307 }\r
1308\r
1309 TransMode = 0;\r
1310 if (Trb->Mode != EmmcNoData) {\r
1311 if (Trb->Mode != EmmcPioMode) {\r
1312 TransMode |= BIT0;\r
1313 }\r
1314 if (Trb->Read) {\r
1315 TransMode |= BIT4;\r
1316 }\r
e7e89b08 1317 if (BlkCount > 1) {\r
48555339
FT
1318 TransMode |= BIT5 | BIT1;\r
1319 }\r
1320 }\r
1321\r
1322 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_TRANS_MOD, FALSE, sizeof (TransMode), &TransMode);\r
1323 if (EFI_ERROR (Status)) {\r
1324 return Status;\r
1325 }\r
1326\r
1327 Cmd = (UINT16)LShiftU64(Packet->EmmcCmdBlk->CommandIndex, 8);\r
1328 if (Packet->EmmcCmdBlk->CommandType == EmmcCommandTypeAdtc) {\r
1329 Cmd |= BIT5;\r
1330 }\r
1331 //\r
1332 // Convert ResponseType to value\r
1333 //\r
1334 if (Packet->EmmcCmdBlk->CommandType != EmmcCommandTypeBc) {\r
1335 switch (Packet->EmmcCmdBlk->ResponseType) {\r
1336 case EmmcResponceTypeR1:\r
1337 case EmmcResponceTypeR5:\r
1338 case EmmcResponceTypeR6:\r
1339 case EmmcResponceTypeR7:\r
1340 Cmd |= (BIT1 | BIT3 | BIT4);\r
1341 break;\r
1342 case EmmcResponceTypeR2:\r
1343 Cmd |= (BIT0 | BIT3);\r
1344 break;\r
1345 case EmmcResponceTypeR3:\r
1346 case EmmcResponceTypeR4:\r
1347 Cmd |= BIT1;\r
1348 break;\r
1349 case EmmcResponceTypeR1b:\r
1350 case EmmcResponceTypeR5b:\r
1351 Cmd |= (BIT0 | BIT1 | BIT3 | BIT4);\r
1352 break;\r
1353 default:\r
1354 ASSERT (FALSE);\r
1355 break;\r
1356 }\r
1357 }\r
1358 //\r
1359 // Execute cmd\r
1360 //\r
1361 Status = EmmcPeimHcRwMmio (Bar + EMMC_HC_COMMAND, FALSE, sizeof (Cmd), &Cmd);\r
1362 return Status;\r
1363}\r
1364\r
1365/**\r
1366 Check the TRB execution result.\r
1367\r
1368 @param[in] Bar The mmio base address of the slot to be accessed.\r
1369 @param[in] Trb The pointer to the EMMC_TRB instance.\r
1370\r
1371 @retval EFI_SUCCESS The TRB is executed successfully.\r
1372 @retval EFI_NOT_READY The TRB is not completed for execution.\r
1373 @retval Others Some erros happen when executing this request.\r
1374\r
1375**/\r
1376EFI_STATUS\r
1377EmmcPeimCheckTrbResult (\r
1378 IN UINTN Bar,\r
1379 IN EMMC_TRB *Trb\r
1380 )\r
1381{\r
1382 EFI_STATUS Status;\r
1383 EMMC_COMMAND_PACKET *Packet;\r
1384 UINT16 IntStatus;\r
1385 UINT32 Response[4];\r
1386 UINT32 SdmaAddr;\r
1387 UINT8 Index;\r
1388 UINT8 SwReset;\r
e7e89b08 1389 UINT32 PioLength;\r
48555339
FT
1390\r
1391 SwReset = 0;\r
1392 Packet = Trb->Packet;\r
1393 //\r
1394 // Check Trb execution result by reading Normal Interrupt Status register.\r
1395 //\r
1396 Status = EmmcPeimHcRwMmio (\r
1397 Bar + EMMC_HC_NOR_INT_STS,\r
1398 TRUE,\r
1399 sizeof (IntStatus),\r
1400 &IntStatus\r
1401 );\r
1402 if (EFI_ERROR (Status)) {\r
1403 goto Done;\r
1404 }\r
1405 //\r
1406 // Check Transfer Complete bit is set or not.\r
1407 //\r
1408 if ((IntStatus & BIT1) == BIT1) {\r
1409 if ((IntStatus & BIT15) == BIT15) {\r
1410 //\r
1411 // Read Error Interrupt Status register to check if the error is\r
1412 // Data Timeout Error.\r
1413 // If yes, treat it as success as Transfer Complete has higher\r
1414 // priority than Data Timeout Error.\r
1415 //\r
1416 Status = EmmcPeimHcRwMmio (\r
1417 Bar + EMMC_HC_ERR_INT_STS,\r
1418 TRUE,\r
1419 sizeof (IntStatus),\r
1420 &IntStatus\r
1421 );\r
1422 if (!EFI_ERROR (Status)) {\r
1423 if ((IntStatus & BIT4) == BIT4) {\r
1424 Status = EFI_SUCCESS;\r
1425 } else {\r
1426 Status = EFI_DEVICE_ERROR;\r
1427 }\r
1428 }\r
1429 }\r
1430\r
1431 goto Done;\r
1432 }\r
1433 //\r
1434 // Check if there is a error happened during cmd execution.\r
1435 // If yes, then do error recovery procedure to follow SD Host Controller\r
1436 // Simplified Spec 3.0 section 3.10.1.\r
1437 //\r
1438 if ((IntStatus & BIT15) == BIT15) {\r
1439 Status = EmmcPeimHcRwMmio (\r
1440 Bar + EMMC_HC_ERR_INT_STS,\r
1441 TRUE,\r
1442 sizeof (IntStatus),\r
1443 &IntStatus\r
1444 );\r
1445 if (EFI_ERROR (Status)) {\r
1446 goto Done;\r
1447 }\r
1448\r
1449 if ((IntStatus & 0x0F) != 0) {\r
1450 SwReset |= BIT1;\r
1451 }\r
1452 if ((IntStatus & 0xF0) != 0) {\r
1453 SwReset |= BIT2;\r
1454 }\r
1455\r
1456 Status = EmmcPeimHcRwMmio (\r
1457 Bar + EMMC_HC_SW_RST,\r
1458 FALSE,\r
1459 sizeof (SwReset),\r
1460 &SwReset\r
1461 );\r
1462 if (EFI_ERROR (Status)) {\r
1463 goto Done;\r
1464 }\r
1465 Status = EmmcPeimHcWaitMmioSet (\r
1466 Bar + EMMC_HC_SW_RST,\r
1467 sizeof (SwReset),\r
1468 0xFF,\r
1469 0,\r
1470 EMMC_TIMEOUT\r
1471 );\r
1472 if (EFI_ERROR (Status)) {\r
1473 goto Done;\r
1474 }\r
1475\r
1476 Status = EFI_DEVICE_ERROR;\r
1477 goto Done;\r
1478 }\r
1479 //\r
1480 // Check if DMA interrupt is signalled for the SDMA transfer.\r
1481 //\r
1482 if ((Trb->Mode == EmmcSdmaMode) && ((IntStatus & BIT3) == BIT3)) {\r
1483 //\r
1484 // Clear DMA interrupt bit.\r
1485 //\r
1486 IntStatus = BIT3;\r
1487 Status = EmmcPeimHcRwMmio (\r
1488 Bar + EMMC_HC_NOR_INT_STS,\r
1489 FALSE,\r
1490 sizeof (IntStatus),\r
1491 &IntStatus\r
1492 );\r
1493 if (EFI_ERROR (Status)) {\r
1494 goto Done;\r
1495 }\r
1496 //\r
1497 // Update SDMA Address register.\r
1498 //\r
85ad9a6e 1499 SdmaAddr = EMMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, EMMC_SDMA_BOUNDARY);\r
48555339
FT
1500 Status = EmmcPeimHcRwMmio (\r
1501 Bar + EMMC_HC_SDMA_ADDR,\r
1502 FALSE,\r
1503 sizeof (UINT32),\r
1504 &SdmaAddr\r
1505 );\r
1506 if (EFI_ERROR (Status)) {\r
1507 goto Done;\r
1508 }\r
85ad9a6e 1509 Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;\r
48555339
FT
1510 }\r
1511\r
1512 if ((Packet->EmmcCmdBlk->CommandType != EmmcCommandTypeAdtc) &&\r
1513 (Packet->EmmcCmdBlk->ResponseType != EmmcResponceTypeR1b) &&\r
1514 (Packet->EmmcCmdBlk->ResponseType != EmmcResponceTypeR5b)) {\r
1515 if ((IntStatus & BIT0) == BIT0) {\r
1516 Status = EFI_SUCCESS;\r
1517 goto Done;\r
1518 }\r
1519 }\r
1520\r
1521 if (Packet->EmmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK) {\r
e7e89b08
FT
1522 //\r
1523 // When performing tuning procedure (Execute Tuning is set to 1) through PIO mode,\r
1524 // wait Buffer Read Ready bit of Normal Interrupt Status Register to be 1.\r
1525 // Refer to SD Host Controller Simplified Specification 3.0 figure 2-29 for details.\r
1526 //\r
1527 if ((IntStatus & BIT5) == BIT5) {\r
1528 //\r
1529 // Clear Buffer Read Ready interrupt at first.\r
1530 //\r
1531 IntStatus = BIT5;\r
1532 EmmcPeimHcRwMmio (Bar + EMMC_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);\r
1533 //\r
1534 // Read data out from Buffer Port register\r
1535 //\r
1536 for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) {\r
1537 EmmcPeimHcRwMmio (Bar + EMMC_HC_BUF_DAT_PORT, TRUE, 4, (UINT8*)Trb->Data + PioLength);\r
1538 }\r
1539 Status = EFI_SUCCESS;\r
1540 goto Done;\r
1541 }\r
48555339
FT
1542 }\r
1543\r
1544 Status = EFI_NOT_READY;\r
1545Done:\r
1546 //\r
1547 // Get response data when the cmd is executed successfully.\r
1548 //\r
1549 if (!EFI_ERROR (Status)) {\r
1550 if (Packet->EmmcCmdBlk->CommandType != EmmcCommandTypeBc) {\r
1551 for (Index = 0; Index < 4; Index++) {\r
1552 Status = EmmcPeimHcRwMmio (\r
1553 Bar + EMMC_HC_RESPONSE + Index * 4,\r
1554 TRUE,\r
1555 sizeof (UINT32),\r
1556 &Response[Index]\r
1557 );\r
1558 if (EFI_ERROR (Status)) {\r
1559 EmmcPeimHcLedOnOff (Bar, FALSE);\r
1560 return Status;\r
1561 }\r
1562 }\r
1563 CopyMem (Packet->EmmcStatusBlk, Response, sizeof (Response));\r
1564 }\r
1565 }\r
1566\r
1567 if (Status != EFI_NOT_READY) {\r
1568 EmmcPeimHcLedOnOff (Bar, FALSE);\r
1569 }\r
1570\r
1571 return Status;\r
1572}\r
1573\r
1574/**\r
1575 Wait for the TRB execution result.\r
1576\r
1577 @param[in] Bar The mmio base address of the slot to be accessed.\r
1578 @param[in] Trb The pointer to the EMMC_TRB instance.\r
1579\r
1580 @retval EFI_SUCCESS The TRB is executed successfully.\r
1581 @retval Others Some erros happen when executing this request.\r
1582\r
1583**/\r
1584EFI_STATUS\r
1585EmmcPeimWaitTrbResult (\r
1586 IN UINTN Bar,\r
1587 IN EMMC_TRB *Trb\r
1588 )\r
1589{\r
1590 EFI_STATUS Status;\r
1591 EMMC_COMMAND_PACKET *Packet;\r
1592 UINT64 Timeout;\r
1593 BOOLEAN InfiniteWait;\r
1594\r
1595 Packet = Trb->Packet;\r
1596 //\r
1597 // Wait Command Complete Interrupt Status bit in Normal Interrupt Status Register\r
1598 //\r
1599 Timeout = Packet->Timeout;\r
1600 if (Timeout == 0) {\r
1601 InfiniteWait = TRUE;\r
1602 } else {\r
1603 InfiniteWait = FALSE;\r
1604 }\r
1605\r
1606 while (InfiniteWait || (Timeout > 0)) {\r
1607 //\r
1608 // Check Trb execution result by reading Normal Interrupt Status register.\r
1609 //\r
1610 Status = EmmcPeimCheckTrbResult (Bar, Trb);\r
1611 if (Status != EFI_NOT_READY) {\r
1612 return Status;\r
1613 }\r
1614 //\r
1615 // Stall for 1 microsecond.\r
1616 //\r
1617 MicroSecondDelay (1);\r
1618\r
1619 Timeout--;\r
1620 }\r
1621\r
1622 return EFI_TIMEOUT;\r
1623}\r
1624\r
1625/**\r
1626 Sends EMMC command to an EMMC card that is attached to the EMMC controller.\r
1627\r
1628 If Packet is successfully sent to the EMMC card, then EFI_SUCCESS is returned.\r
1629\r
1630 If a device error occurs while sending the Packet, then EFI_DEVICE_ERROR is returned.\r
1631\r
1632 If Slot is not in a valid range for the EMMC controller, then EFI_INVALID_PARAMETER\r
1633 is returned.\r
1634\r
1635 If Packet defines a data command but both InDataBuffer and OutDataBuffer are NULL,\r
1636 EFI_INVALID_PARAMETER is returned.\r
1637\r
1638 @param[in] Slot The slot number of the Emmc card to send the command to.\r
1639 @param[in,out] Packet A pointer to the EMMC command data structure.\r
1640\r
1641 @retval EFI_SUCCESS The EMMC Command Packet was sent by the host.\r
1642 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SD\r
1643 command Packet.\r
1644 @retval EFI_INVALID_PARAMETER Packet, Slot, or the contents of the Packet is invalid.\r
1645 @retval EFI_INVALID_PARAMETER Packet defines a data command but both InDataBuffer and\r
1646 OutDataBuffer are NULL.\r
1647 @retval EFI_NO_MEDIA SD Device not present in the Slot.\r
1648 @retval EFI_UNSUPPORTED The command described by the EMMC Command Packet is not\r
1649 supported by the host controller.\r
1650 @retval EFI_BAD_BUFFER_SIZE The InTransferLength or OutTransferLength exceeds the\r
1651 limit supported by EMMC card ( i.e. if the number of bytes\r
1652 exceed the Last LBA).\r
1653\r
1654**/\r
1655EFI_STATUS\r
1656EFIAPI\r
1657EmmcPeimExecCmd (\r
1658 IN EMMC_PEIM_HC_SLOT *Slot,\r
1659 IN OUT EMMC_COMMAND_PACKET *Packet\r
1660 )\r
1661{\r
1662 EFI_STATUS Status;\r
1663 EMMC_TRB *Trb;\r
1664\r
1665 if (Packet == NULL) {\r
1666 return EFI_INVALID_PARAMETER;\r
1667 }\r
1668\r
1669 if ((Packet->EmmcCmdBlk == NULL) || (Packet->EmmcStatusBlk == NULL)) {\r
1670 return EFI_INVALID_PARAMETER;\r
1671 }\r
1672\r
1673 if ((Packet->OutDataBuffer == NULL) && (Packet->OutTransferLength != 0)) {\r
1674 return EFI_INVALID_PARAMETER;\r
1675 }\r
1676\r
1677 if ((Packet->InDataBuffer == NULL) && (Packet->InTransferLength != 0)) {\r
1678 return EFI_INVALID_PARAMETER;\r
1679 }\r
1680\r
1681 Trb = EmmcPeimCreateTrb (Slot, Packet);\r
1682 if (Trb == NULL) {\r
1683 return EFI_OUT_OF_RESOURCES;\r
1684 }\r
1685\r
1686 Status = EmmcPeimWaitTrbEnv (Slot->EmmcHcBase, Trb);\r
1687 if (EFI_ERROR (Status)) {\r
1688 goto Done;\r
1689 }\r
1690\r
1691 Status = EmmcPeimExecTrb (Slot->EmmcHcBase, Trb);\r
1692 if (EFI_ERROR (Status)) {\r
1693 goto Done;\r
1694 }\r
1695\r
1696 Status = EmmcPeimWaitTrbResult (Slot->EmmcHcBase, Trb);\r
1697 if (EFI_ERROR (Status)) {\r
1698 goto Done;\r
1699 }\r
1700\r
1701Done:\r
1702 EmmcPeimFreeTrb (Trb);\r
1703\r
1704 return Status;\r
1705}\r
1706\r
1707/**\r
1708 Send command GO_IDLE_STATE (CMD0 with argument of 0x00000000) to the device to\r
1709 make it go to Idle State.\r
1710\r
1711 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.\r
1712\r
1713 @param[in] Slot The slot number of the Emmc card to send the command to.\r
1714\r
1715 @retval EFI_SUCCESS The EMMC device is reset correctly.\r
1716 @retval Others The device reset fails.\r
1717\r
1718**/\r
1719EFI_STATUS\r
1720EmmcPeimReset (\r
1721 IN EMMC_PEIM_HC_SLOT *Slot\r
1722 )\r
1723{\r
1724 EMMC_COMMAND_BLOCK EmmcCmdBlk;\r
1725 EMMC_STATUS_BLOCK EmmcStatusBlk;\r
1726 EMMC_COMMAND_PACKET Packet;\r
1727 EFI_STATUS Status;\r
1728\r
1729 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));\r
1730 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));\r
1731 ZeroMem (&Packet, sizeof (Packet));\r
1732\r
1733 Packet.EmmcCmdBlk = &EmmcCmdBlk;\r
1734 Packet.EmmcStatusBlk = &EmmcStatusBlk;\r
1735 Packet.Timeout = EMMC_TIMEOUT;\r
1736\r
1737 EmmcCmdBlk.CommandIndex = EMMC_GO_IDLE_STATE;\r
1738 EmmcCmdBlk.CommandType = EmmcCommandTypeBc;\r
1739 EmmcCmdBlk.ResponseType = 0;\r
1740 EmmcCmdBlk.CommandArgument = 0;\r
1741\r
1742 Status = EmmcPeimExecCmd (Slot, &Packet);\r
1743\r
1744 return Status;\r
1745}\r
1746\r
1747/**\r
1748 Send command SEND_OP_COND to the EMMC device to get the data of the OCR register.\r
1749\r
1750 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.\r
1751\r
1752 @param[in] Slot The slot number of the Emmc card to send the command to.\r
1753 @param[in, out] Argument On input, the argument of SEND_OP_COND is to send to the device.\r
1754 On output, the argument is the value of OCR register.\r
1755\r
1756 @retval EFI_SUCCESS The operation is done correctly.\r
1757 @retval Others The operation fails.\r
1758\r
1759**/\r
1760EFI_STATUS\r
1761EmmcPeimGetOcr (\r
1762 IN EMMC_PEIM_HC_SLOT *Slot,\r
1763 IN OUT UINT32 *Argument\r
1764 )\r
1765{\r
1766 EMMC_COMMAND_BLOCK EmmcCmdBlk;\r
1767 EMMC_STATUS_BLOCK EmmcStatusBlk;\r
1768 EMMC_COMMAND_PACKET Packet;\r
1769 EFI_STATUS Status;\r
1770\r
1771 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));\r
1772 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));\r
1773 ZeroMem (&Packet, sizeof (Packet));\r
1774\r
1775 Packet.EmmcCmdBlk = &EmmcCmdBlk;\r
1776 Packet.EmmcStatusBlk = &EmmcStatusBlk;\r
1777 Packet.Timeout = EMMC_TIMEOUT;\r
1778\r
1779 EmmcCmdBlk.CommandIndex = EMMC_SEND_OP_COND;\r
1780 EmmcCmdBlk.CommandType = EmmcCommandTypeBcr;\r
1781 EmmcCmdBlk.ResponseType = EmmcResponceTypeR3;\r
1782 EmmcCmdBlk.CommandArgument = *Argument;\r
1783\r
1784 Status = EmmcPeimExecCmd (Slot, &Packet);\r
1785 if (!EFI_ERROR (Status)) {\r
1786 //\r
1787 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.\r
1788 //\r
1789 *Argument = EmmcStatusBlk.Resp0;\r
1790 }\r
1791\r
1792 return Status;\r
1793}\r
1794\r
1795/**\r
1796 Broadcast command ALL_SEND_CID to the bus to ask all the EMMC devices to send the\r
1797 data of their CID registers.\r
1798\r
1799 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.\r
1800\r
1801 @param[in] Slot The slot number of the Emmc card to send the command to.\r
1802\r
1803 @retval EFI_SUCCESS The operation is done correctly.\r
1804 @retval Others The operation fails.\r
1805\r
1806**/\r
1807EFI_STATUS\r
1808EmmcPeimGetAllCid (\r
1809 IN EMMC_PEIM_HC_SLOT *Slot\r
1810 )\r
1811{\r
1812 EMMC_COMMAND_BLOCK EmmcCmdBlk;\r
1813 EMMC_STATUS_BLOCK EmmcStatusBlk;\r
1814 EMMC_COMMAND_PACKET Packet;\r
1815 EFI_STATUS Status;\r
1816\r
1817 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));\r
1818 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));\r
1819 ZeroMem (&Packet, sizeof (Packet));\r
1820\r
1821 Packet.EmmcCmdBlk = &EmmcCmdBlk;\r
1822 Packet.EmmcStatusBlk = &EmmcStatusBlk;\r
1823 Packet.Timeout = EMMC_TIMEOUT;\r
1824\r
1825 EmmcCmdBlk.CommandIndex = EMMC_ALL_SEND_CID;\r
1826 EmmcCmdBlk.CommandType = EmmcCommandTypeBcr;\r
1827 EmmcCmdBlk.ResponseType = EmmcResponceTypeR2;\r
1828 EmmcCmdBlk.CommandArgument = 0;\r
1829\r
1830 Status = EmmcPeimExecCmd (Slot, &Packet);\r
1831\r
1832 return Status;\r
1833}\r
1834\r
1835/**\r
1836 Send command SET_RELATIVE_ADDR to the EMMC device to assign a Relative device\r
1837 Address (RCA).\r
1838\r
1839 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.\r
1840\r
1841 @param[in] Slot The slot number of the Emmc card to send the command to.\r
1842 @param[in] Rca The relative device address to be assigned.\r
1843\r
1844 @retval EFI_SUCCESS The operation is done correctly.\r
1845 @retval Others The operation fails.\r
1846\r
1847**/\r
1848EFI_STATUS\r
1849EmmcPeimSetRca (\r
1850 IN EMMC_PEIM_HC_SLOT *Slot,\r
1851 IN UINT32 Rca\r
1852 )\r
1853{\r
1854 EMMC_COMMAND_BLOCK EmmcCmdBlk;\r
1855 EMMC_STATUS_BLOCK EmmcStatusBlk;\r
1856 EMMC_COMMAND_PACKET Packet;\r
1857 EFI_STATUS Status;\r
1858\r
1859 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));\r
1860 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));\r
1861 ZeroMem (&Packet, sizeof (Packet));\r
1862\r
1863 Packet.EmmcCmdBlk = &EmmcCmdBlk;\r
1864 Packet.EmmcStatusBlk = &EmmcStatusBlk;\r
1865 Packet.Timeout = EMMC_TIMEOUT;\r
1866\r
1867 EmmcCmdBlk.CommandIndex = EMMC_SET_RELATIVE_ADDR;\r
1868 EmmcCmdBlk.CommandType = EmmcCommandTypeAc;\r
1869 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;\r
1870 EmmcCmdBlk.CommandArgument = Rca << 16;\r
1871\r
1872 Status = EmmcPeimExecCmd (Slot, &Packet);\r
1873\r
1874 return Status;\r
1875}\r
1876\r
1877/**\r
1878 Send command SEND_CSD to the EMMC device to get the data of the CSD register.\r
1879\r
1880 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.\r
1881\r
1882 @param[in] Slot The slot number of the Emmc card to send the command to.\r
1883 @param[in] Rca The relative device address of selected device.\r
1884 @param[out] Csd The buffer to store the content of the CSD register.\r
1885 Note the caller should ignore the lowest byte of this\r
1886 buffer as the content of this byte is meaningless even\r
1887 if the operation succeeds.\r
1888\r
1889 @retval EFI_SUCCESS The operation is done correctly.\r
1890 @retval Others The operation fails.\r
1891\r
1892**/\r
1893EFI_STATUS\r
1894EmmcPeimGetCsd (\r
1895 IN EMMC_PEIM_HC_SLOT *Slot,\r
1896 IN UINT32 Rca,\r
1897 OUT EMMC_CSD *Csd\r
1898 )\r
1899{\r
1900 EMMC_COMMAND_BLOCK EmmcCmdBlk;\r
1901 EMMC_STATUS_BLOCK EmmcStatusBlk;\r
1902 EMMC_COMMAND_PACKET Packet;\r
1903 EFI_STATUS Status;\r
1904\r
1905 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));\r
1906 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));\r
1907 ZeroMem (&Packet, sizeof (Packet));\r
1908\r
1909 Packet.EmmcCmdBlk = &EmmcCmdBlk;\r
1910 Packet.EmmcStatusBlk = &EmmcStatusBlk;\r
1911 Packet.Timeout = EMMC_TIMEOUT;\r
1912\r
1913 EmmcCmdBlk.CommandIndex = EMMC_SEND_CSD;\r
1914 EmmcCmdBlk.CommandType = EmmcCommandTypeAc;\r
1915 EmmcCmdBlk.ResponseType = EmmcResponceTypeR2;\r
1916 EmmcCmdBlk.CommandArgument = Rca << 16;\r
1917\r
1918 Status = EmmcPeimExecCmd (Slot, &Packet);\r
1919 if (!EFI_ERROR (Status)) {\r
1920 //\r
1921 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.\r
1922 //\r
1923 CopyMem (((UINT8*)Csd) + 1, &EmmcStatusBlk.Resp0, sizeof (EMMC_CSD) - 1);\r
1924 }\r
1925\r
1926 return Status;\r
1927}\r
1928\r
1929/**\r
1930 Send command SELECT_DESELECT_CARD to the EMMC device to select/deselect it.\r
1931\r
1932 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.\r
1933\r
1934 @param[in] Slot The slot number of the Emmc card to send the command to.\r
1935 @param[in] Rca The relative device address of selected device.\r
1936\r
1937 @retval EFI_SUCCESS The operation is done correctly.\r
1938 @retval Others The operation fails.\r
1939\r
1940**/\r
1941EFI_STATUS\r
1942EmmcPeimSelect (\r
1943 IN EMMC_PEIM_HC_SLOT *Slot,\r
1944 IN UINT32 Rca\r
1945 )\r
1946{\r
1947 EMMC_COMMAND_BLOCK EmmcCmdBlk;\r
1948 EMMC_STATUS_BLOCK EmmcStatusBlk;\r
1949 EMMC_COMMAND_PACKET Packet;\r
1950 EFI_STATUS Status;\r
1951\r
1952 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));\r
1953 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));\r
1954 ZeroMem (&Packet, sizeof (Packet));\r
1955\r
1956 Packet.EmmcCmdBlk = &EmmcCmdBlk;\r
1957 Packet.EmmcStatusBlk = &EmmcStatusBlk;\r
1958 Packet.Timeout = EMMC_TIMEOUT;\r
1959\r
1960 EmmcCmdBlk.CommandIndex = EMMC_SELECT_DESELECT_CARD;\r
1961 EmmcCmdBlk.CommandType = EmmcCommandTypeAc;\r
1962 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;\r
1963 EmmcCmdBlk.CommandArgument = Rca << 16;\r
1964\r
1965 Status = EmmcPeimExecCmd (Slot, &Packet);\r
1966\r
1967 return Status;\r
1968}\r
1969\r
1970/**\r
1971 Send command SEND_EXT_CSD to the EMMC device to get the data of the EXT_CSD register.\r
1972\r
1973 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.\r
1974\r
1975 @param[in] Slot The slot number of the Emmc card to send the command to.\r
1976 @param[out] ExtCsd The buffer to store the content of the EXT_CSD register.\r
1977\r
1978 @retval EFI_SUCCESS The operation is done correctly.\r
1979 @retval Others The operation fails.\r
1980\r
1981**/\r
1982EFI_STATUS\r
1983EmmcPeimGetExtCsd (\r
1984 IN EMMC_PEIM_HC_SLOT *Slot,\r
1985 OUT EMMC_EXT_CSD *ExtCsd\r
1986 )\r
1987{\r
1988 EMMC_COMMAND_BLOCK EmmcCmdBlk;\r
1989 EMMC_STATUS_BLOCK EmmcStatusBlk;\r
1990 EMMC_COMMAND_PACKET Packet;\r
1991 EFI_STATUS Status;\r
1992\r
1993 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));\r
1994 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));\r
1995 ZeroMem (&Packet, sizeof (Packet));\r
1996\r
1997 Packet.EmmcCmdBlk = &EmmcCmdBlk;\r
1998 Packet.EmmcStatusBlk = &EmmcStatusBlk;\r
1999 Packet.Timeout = EMMC_TIMEOUT;\r
2000\r
2001 EmmcCmdBlk.CommandIndex = EMMC_SEND_EXT_CSD;\r
2002 EmmcCmdBlk.CommandType = EmmcCommandTypeAdtc;\r
2003 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;\r
2004 EmmcCmdBlk.CommandArgument = 0x00000000;\r
2005\r
2006 Packet.InDataBuffer = ExtCsd;\r
2007 Packet.InTransferLength = sizeof (EMMC_EXT_CSD);\r
2008\r
2009 Status = EmmcPeimExecCmd (Slot, &Packet);\r
2010 return Status;\r
2011}\r
2012\r
2013/**\r
2014 Send command SWITCH to the EMMC device to switch the mode of operation of the\r
2015 selected Device or modifies the EXT_CSD registers.\r
2016\r
2017 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.\r
2018\r
2019 @param[in] Slot The slot number of the Emmc card to send the command to.\r
2020 @param[in] Access The access mode of SWTICH command.\r
2021 @param[in] Index The offset of the field to be access.\r
2022 @param[in] Value The value to be set to the specified field of EXT_CSD register.\r
2023 @param[in] CmdSet The value of CmdSet field of EXT_CSD register.\r
2024\r
2025 @retval EFI_SUCCESS The operation is done correctly.\r
2026 @retval Others The operation fails.\r
2027\r
2028**/\r
2029EFI_STATUS\r
2030EmmcPeimSwitch (\r
2031 IN EMMC_PEIM_HC_SLOT *Slot,\r
2032 IN UINT8 Access,\r
2033 IN UINT8 Index,\r
2034 IN UINT8 Value,\r
2035 IN UINT8 CmdSet\r
2036 )\r
2037{\r
2038 EMMC_COMMAND_BLOCK EmmcCmdBlk;\r
2039 EMMC_STATUS_BLOCK EmmcStatusBlk;\r
2040 EMMC_COMMAND_PACKET Packet;\r
2041 EFI_STATUS Status;\r
2042\r
2043 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));\r
2044 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));\r
2045 ZeroMem (&Packet, sizeof (Packet));\r
2046\r
2047 Packet.EmmcCmdBlk = &EmmcCmdBlk;\r
2048 Packet.EmmcStatusBlk = &EmmcStatusBlk;\r
2049 Packet.Timeout = EMMC_TIMEOUT;\r
2050\r
2051 EmmcCmdBlk.CommandIndex = EMMC_SWITCH;\r
2052 EmmcCmdBlk.CommandType = EmmcCommandTypeAc;\r
2053 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1b;\r
2054 EmmcCmdBlk.CommandArgument = (Access << 24) | (Index << 16) | (Value << 8) | CmdSet;\r
2055\r
2056 Status = EmmcPeimExecCmd (Slot, &Packet);\r
2057\r
2058 return Status;\r
2059}\r
2060\r
2061/**\r
2062 Send command SEND_STATUS to the addressed EMMC device to get its status register.\r
2063\r
2064 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.\r
2065\r
2066 @param[in] Slot The slot number of the Emmc card to send the command to.\r
2067 @param[in] Rca The relative device address of addressed device.\r
2068 @param[out] DevStatus The returned device status.\r
2069\r
2070 @retval EFI_SUCCESS The operation is done correctly.\r
2071 @retval Others The operation fails.\r
2072\r
2073**/\r
2074EFI_STATUS\r
2075EmmcPeimSendStatus (\r
2076 IN EMMC_PEIM_HC_SLOT *Slot,\r
2077 IN UINT32 Rca,\r
2078 OUT UINT32 *DevStatus\r
2079 )\r
2080{\r
2081 EMMC_COMMAND_BLOCK EmmcCmdBlk;\r
2082 EMMC_STATUS_BLOCK EmmcStatusBlk;\r
2083 EMMC_COMMAND_PACKET Packet;\r
2084 EFI_STATUS Status;\r
2085\r
2086 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));\r
2087 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));\r
2088 ZeroMem (&Packet, sizeof (Packet));\r
2089\r
2090 Packet.EmmcCmdBlk = &EmmcCmdBlk;\r
2091 Packet.EmmcStatusBlk = &EmmcStatusBlk;\r
2092 Packet.Timeout = EMMC_TIMEOUT;\r
2093\r
2094 EmmcCmdBlk.CommandIndex = EMMC_SEND_STATUS;\r
2095 EmmcCmdBlk.CommandType = EmmcCommandTypeAc;\r
2096 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;\r
2097 EmmcCmdBlk.CommandArgument = Rca << 16;\r
2098\r
2099 Status = EmmcPeimExecCmd (Slot, &Packet);\r
2100 if (!EFI_ERROR (Status)) {\r
2101 *DevStatus = EmmcStatusBlk.Resp0;\r
2102 }\r
2103\r
2104 return Status;\r
2105}\r
2106\r
2107/**\r
2108 Send command SET_BLOCK_COUNT to the addressed EMMC device to set the number of\r
2109 blocks for the following block read/write cmd.\r
2110\r
2111 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.\r
2112\r
2113 @param[in] Slot The slot number of the Emmc card to send the command to.\r
2114 @param[in] BlockCount The number of the logical block to access.\r
2115\r
2116 @retval EFI_SUCCESS The operation is done correctly.\r
2117 @retval Others The operation fails.\r
2118\r
2119**/\r
2120EFI_STATUS\r
2121EmmcPeimSetBlkCount (\r
2122 IN EMMC_PEIM_HC_SLOT *Slot,\r
2123 IN UINT16 BlockCount\r
2124 )\r
2125{\r
2126 EMMC_COMMAND_BLOCK EmmcCmdBlk;\r
2127 EMMC_STATUS_BLOCK EmmcStatusBlk;\r
2128 EMMC_COMMAND_PACKET Packet;\r
2129 EFI_STATUS Status;\r
2130\r
2131 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));\r
2132 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));\r
2133 ZeroMem (&Packet, sizeof (Packet));\r
2134\r
2135 Packet.EmmcCmdBlk = &EmmcCmdBlk;\r
2136 Packet.EmmcStatusBlk = &EmmcStatusBlk;\r
2137 Packet.Timeout = EMMC_TIMEOUT;\r
2138\r
2139 EmmcCmdBlk.CommandIndex = EMMC_SET_BLOCK_COUNT;\r
2140 EmmcCmdBlk.CommandType = EmmcCommandTypeAc;\r
2141 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;\r
2142 EmmcCmdBlk.CommandArgument = BlockCount;\r
2143\r
2144 Status = EmmcPeimExecCmd (Slot, &Packet);\r
2145\r
2146 return Status;\r
2147}\r
2148\r
2149/**\r
2150 Send command READ_MULTIPLE_BLOCK/WRITE_MULTIPLE_BLOCK to the addressed EMMC device\r
2151 to read/write the specified number of blocks.\r
2152\r
2153 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.\r
2154\r
2155 @param[in] Slot The slot number of the Emmc card to send the command to.\r
2156 @param[in] Lba The logical block address of starting access.\r
2157 @param[in] BlockSize The block size of specified EMMC device partition.\r
2158 @param[in] Buffer The pointer to the transfer buffer.\r
2159 @param[in] BufferSize The size of transfer buffer.\r
2160 @param[in] IsRead Boolean to show the operation direction.\r
2161\r
2162 @retval EFI_SUCCESS The operation is done correctly.\r
2163 @retval Others The operation fails.\r
2164\r
2165**/\r
2166EFI_STATUS\r
2167EmmcPeimRwMultiBlocks (\r
2168 IN EMMC_PEIM_HC_SLOT *Slot,\r
2169 IN EFI_LBA Lba,\r
2170 IN UINT32 BlockSize,\r
2171 IN VOID *Buffer,\r
2172 IN UINTN BufferSize,\r
2173 IN BOOLEAN IsRead\r
2174 )\r
2175{\r
2176 EMMC_COMMAND_BLOCK EmmcCmdBlk;\r
2177 EMMC_STATUS_BLOCK EmmcStatusBlk;\r
2178 EMMC_COMMAND_PACKET Packet;\r
2179 EFI_STATUS Status;\r
2180\r
2181 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));\r
2182 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));\r
2183 ZeroMem (&Packet, sizeof (Packet));\r
2184\r
2185 Packet.EmmcCmdBlk = &EmmcCmdBlk;\r
2186 Packet.EmmcStatusBlk = &EmmcStatusBlk;\r
2187 //\r
2188 // Calculate timeout value through the below formula.\r
2189 // Timeout = (transfer size) / (2MB/s).\r
2190 // Taking 2MB/s as divisor is because it's nearest to the eMMC lowest\r
2191 // transfer speed (2.4MB/s).\r
2192 // Refer to eMMC 5.0 spec section 6.9.1 for details.\r
2193 //\r
2194 Packet.Timeout = (BufferSize / (2 * 1024 * 1024) + 1) * 1000 * 1000;;\r
2195\r
2196 if (IsRead) {\r
2197 Packet.InDataBuffer = Buffer;\r
2198 Packet.InTransferLength = (UINT32)BufferSize;\r
2199\r
2200 EmmcCmdBlk.CommandIndex = EMMC_READ_MULTIPLE_BLOCK;\r
2201 EmmcCmdBlk.CommandType = EmmcCommandTypeAdtc;\r
2202 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;\r
2203 } else {\r
2204 Packet.OutDataBuffer = Buffer;\r
2205 Packet.OutTransferLength = (UINT32)BufferSize;\r
2206\r
2207 EmmcCmdBlk.CommandIndex = EMMC_WRITE_MULTIPLE_BLOCK;\r
2208 EmmcCmdBlk.CommandType = EmmcCommandTypeAdtc;\r
2209 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;\r
2210 }\r
2211\r
2212 if (Slot->SectorAddressing) {\r
2213 EmmcCmdBlk.CommandArgument = (UINT32)Lba;\r
2214 } else {\r
2215 EmmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (Lba, BlockSize);\r
2216 }\r
2217\r
2218 Status = EmmcPeimExecCmd (Slot, &Packet);\r
2219\r
2220 return Status;\r
2221}\r
2222\r
2223/**\r
2224 Send command SEND_TUNING_BLOCK to the EMMC device for HS200 optimal sampling point\r
2225 detection.\r
2226\r
2227 It may be sent up to 40 times until the host finishes the tuning procedure.\r
2228\r
2229 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 for details.\r
2230\r
2231 @param[in] Slot The slot number of the Emmc card to send the command to.\r
2232 @param[in] BusWidth The bus width to work.\r
2233\r
2234 @retval EFI_SUCCESS The operation is done correctly.\r
2235 @retval Others The operation fails.\r
2236\r
2237**/\r
2238EFI_STATUS\r
2239EmmcPeimSendTuningBlk (\r
2240 IN EMMC_PEIM_HC_SLOT *Slot,\r
2241 IN UINT8 BusWidth\r
2242 )\r
2243{\r
2244 EMMC_COMMAND_BLOCK EmmcCmdBlk;\r
2245 EMMC_STATUS_BLOCK EmmcStatusBlk;\r
2246 EMMC_COMMAND_PACKET Packet;\r
2247 EFI_STATUS Status;\r
2248 UINT8 TuningBlock[128];\r
2249\r
2250 ZeroMem (&EmmcCmdBlk, sizeof (EmmcCmdBlk));\r
2251 ZeroMem (&EmmcStatusBlk, sizeof (EmmcStatusBlk));\r
2252 ZeroMem (&Packet, sizeof (Packet));\r
2253\r
2254 Packet.EmmcCmdBlk = &EmmcCmdBlk;\r
2255 Packet.EmmcStatusBlk = &EmmcStatusBlk;\r
2256 Packet.Timeout = EMMC_TIMEOUT;\r
2257\r
2258 EmmcCmdBlk.CommandIndex = EMMC_SEND_TUNING_BLOCK;\r
2259 EmmcCmdBlk.CommandType = EmmcCommandTypeAdtc;\r
2260 EmmcCmdBlk.ResponseType = EmmcResponceTypeR1;\r
2261 EmmcCmdBlk.CommandArgument = 0;\r
2262\r
2263 Packet.InDataBuffer = TuningBlock;\r
2264 if (BusWidth == 8) {\r
2265 Packet.InTransferLength = sizeof (TuningBlock);\r
2266 } else {\r
2267 Packet.InTransferLength = 64;\r
2268 }\r
2269\r
2270 Status = EmmcPeimExecCmd (Slot, &Packet);\r
2271\r
2272 return Status;\r
2273}\r
2274\r
2275/**\r
2276 Tunning the clock to get HS200 optimal sampling point.\r
2277\r
2278 Command SEND_TUNING_BLOCK may be sent up to 40 times until the host finishes the\r
2279 tuning procedure.\r
2280\r
2281 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller\r
2282 Simplified Spec 3.0 section Figure 2-29 for details.\r
2283\r
2284 @param[in] Slot The slot number of the Emmc card to send the command to.\r
2285 @param[in] BusWidth The bus width to work.\r
2286\r
2287 @retval EFI_SUCCESS The operation is done correctly.\r
2288 @retval Others The operation fails.\r
2289\r
2290**/\r
2291EFI_STATUS\r
2292EmmcPeimTuningClkForHs200 (\r
2293 IN EMMC_PEIM_HC_SLOT *Slot,\r
2294 IN UINT8 BusWidth\r
2295 )\r
2296{\r
2297 EFI_STATUS Status;\r
2298 UINT8 HostCtrl2;\r
2299 UINT8 Retry;\r
2300\r
2301 //\r
2302 // Notify the host that the sampling clock tuning procedure starts.\r
2303 //\r
2304 HostCtrl2 = BIT6;\r
2305 Status = EmmcPeimHcOrMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
2306 if (EFI_ERROR (Status)) {\r
2307 return Status;\r
2308 }\r
2309 //\r
2310 // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.\r
2311 //\r
2312 Retry = 0;\r
2313 do {\r
2314 Status = EmmcPeimSendTuningBlk (Slot, BusWidth);\r
2315 if (EFI_ERROR (Status)) {\r
2316 return Status;\r
2317 }\r
2318\r
2319 Status = EmmcPeimHcRwMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);\r
2320 if (EFI_ERROR (Status)) {\r
2321 return Status;\r
2322 }\r
2323\r
8c983d3e 2324 if ((HostCtrl2 & (BIT6 | BIT7)) == 0) {\r
48555339
FT
2325 break;\r
2326 }\r
8c983d3e
FT
2327\r
2328 if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {\r
2329 return EFI_SUCCESS;\r
2330 }\r
48555339
FT
2331 } while (++Retry < 40);\r
2332\r
8c983d3e
FT
2333 DEBUG ((EFI_D_ERROR, "EmmcPeimTuningClkForHs200: Send tuning block fails at %d times with HostCtrl2 %02x\n", Retry, HostCtrl2));\r
2334 //\r
2335 // Abort the tuning procedure and reset the tuning circuit.\r
2336 //\r
2337 HostCtrl2 = (UINT8)~(BIT6 | BIT7);\r
2338 Status = EmmcPeimHcAndMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
2339 if (EFI_ERROR (Status)) {\r
2340 return Status;\r
48555339 2341 }\r
8c983d3e 2342 return EFI_DEVICE_ERROR;\r
48555339
FT
2343}\r
2344\r
2345/**\r
2346 Switch the bus width to specified width.\r
2347\r
2348 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.9 and SD Host Controller\r
2349 Simplified Spec 3.0 section Figure 3-7 for details.\r
2350\r
2351 @param[in] Slot The slot number of the Emmc card to send the command to.\r
2352 @param[in] Rca The relative device address to be assigned.\r
2353 @param[in] IsDdr If TRUE, use dual data rate data simpling method. Otherwise\r
2354 use single data rate data simpling method.\r
2355 @param[in] BusWidth The bus width to be set, it could be 4 or 8.\r
2356\r
2357 @retval EFI_SUCCESS The operation is done correctly.\r
2358 @retval Others The operation fails.\r
2359\r
2360**/\r
2361EFI_STATUS\r
2362EmmcPeimSwitchBusWidth (\r
2363 IN EMMC_PEIM_HC_SLOT *Slot,\r
2364 IN UINT32 Rca,\r
2365 IN BOOLEAN IsDdr,\r
2366 IN UINT8 BusWidth\r
2367 )\r
2368{\r
2369 EFI_STATUS Status;\r
2370 UINT8 Access;\r
2371 UINT8 Index;\r
2372 UINT8 Value;\r
2373 UINT8 CmdSet;\r
2374 UINT32 DevStatus;\r
2375\r
2376 //\r
2377 // Write Byte, the Value field is written into the byte pointed by Index.\r
2378 //\r
2379 Access = 0x03;\r
2380 Index = OFFSET_OF (EMMC_EXT_CSD, BusWidth);\r
2381 if (BusWidth == 4) {\r
2382 Value = 1;\r
2383 } else if (BusWidth == 8) {\r
2384 Value = 2;\r
2385 } else {\r
2386 return EFI_INVALID_PARAMETER;\r
2387 }\r
2388\r
2389 if (IsDdr) {\r
2390 Value += 4;\r
2391 }\r
2392\r
2393 CmdSet = 0;\r
2394 Status = EmmcPeimSwitch (Slot, Access, Index, Value, CmdSet);\r
2395 if (EFI_ERROR (Status)) {\r
2396 return Status;\r
2397 }\r
2398\r
2399 Status = EmmcPeimSendStatus (Slot, Rca, &DevStatus);\r
2400 if (EFI_ERROR (Status)) {\r
2401 return Status;\r
2402 }\r
2403 //\r
2404 // Check the switch operation is really successful or not.\r
2405 //\r
2406 if ((DevStatus & BIT7) != 0) {\r
2407 return EFI_DEVICE_ERROR;\r
2408 }\r
2409\r
2410 Status = EmmcPeimHcSetBusWidth (Slot->EmmcHcBase, BusWidth);\r
2411\r
2412 return Status;\r
2413}\r
2414\r
2415/**\r
2416 Switch the clock frequency to the specified value.\r
2417\r
2418 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6 and SD Host Controller\r
2419 Simplified Spec 3.0 section Figure 3-3 for details.\r
2420\r
2421 @param[in] Slot The slot number of the Emmc card to send the command to.\r
2422 @param[in] Rca The relative device address to be assigned.\r
2423 @param[in] HsTiming The value to be written to HS_TIMING field of EXT_CSD register.\r
2424 @param[in] ClockFreq The max clock frequency to be set, the unit is MHz.\r
2425\r
2426 @retval EFI_SUCCESS The operation is done correctly.\r
2427 @retval Others The operation fails.\r
2428\r
2429**/\r
2430EFI_STATUS\r
2431EmmcPeimSwitchClockFreq (\r
2432 IN EMMC_PEIM_HC_SLOT *Slot,\r
2433 IN UINT32 Rca,\r
2434 IN UINT8 HsTiming,\r
2435 IN UINT32 ClockFreq\r
2436 )\r
2437{\r
2438 EFI_STATUS Status;\r
2439 UINT8 Access;\r
2440 UINT8 Index;\r
2441 UINT8 Value;\r
2442 UINT8 CmdSet;\r
2443 UINT32 DevStatus;\r
2444\r
2445 //\r
2446 // Write Byte, the Value field is written into the byte pointed by Index.\r
2447 //\r
2448 Access = 0x03;\r
2449 Index = OFFSET_OF (EMMC_EXT_CSD, HsTiming);\r
2450 Value = HsTiming;\r
2451 CmdSet = 0;\r
2452\r
2453 Status = EmmcPeimSwitch (Slot, Access, Index, Value, CmdSet);\r
2454 if (EFI_ERROR (Status)) {\r
2455 return Status;\r
2456 }\r
2457\r
2458 Status = EmmcPeimSendStatus (Slot, Rca, &DevStatus);\r
2459 if (EFI_ERROR (Status)) {\r
2460 return Status;\r
2461 }\r
2462 //\r
2463 // Check the switch operation is really successful or not.\r
2464 //\r
2465 if ((DevStatus & BIT7) != 0) {\r
2466 return EFI_DEVICE_ERROR;\r
2467 }\r
2468 //\r
2469 // Convert the clock freq unit from MHz to KHz.\r
2470 //\r
2471 Status = EmmcPeimHcClockSupply (Slot->EmmcHcBase, ClockFreq * 1000);\r
2472\r
2473 return Status;\r
2474}\r
2475\r
2476/**\r
2477 Switch to the High Speed timing according to request.\r
2478\r
2479 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller\r
2480 Simplified Spec 3.0 section Figure 2-29 for details.\r
2481\r
2482 @param[in] Slot The slot number of the Emmc card to send the command to.\r
2483 @param[in] Rca The relative device address to be assigned.\r
2484 @param[in] ClockFreq The max clock frequency to be set.\r
2485 @param[in] IsDdr If TRUE, use dual data rate data simpling method. Otherwise\r
2486 use single data rate data simpling method.\r
2487 @param[in] BusWidth The bus width to be set, it could be 4 or 8.\r
2488\r
2489 @retval EFI_SUCCESS The operation is done correctly.\r
2490 @retval Others The operation fails.\r
2491\r
2492**/\r
2493EFI_STATUS\r
2494EmmcPeimSwitchToHighSpeed (\r
2495 IN EMMC_PEIM_HC_SLOT *Slot,\r
2496 IN UINT32 Rca,\r
2497 IN UINT32 ClockFreq,\r
2498 IN BOOLEAN IsDdr,\r
2499 IN UINT8 BusWidth\r
2500 )\r
2501{\r
2502 EFI_STATUS Status;\r
2503 UINT8 HsTiming;\r
2504 UINT8 HostCtrl1;\r
2505 UINT8 HostCtrl2;\r
2506\r
2507 Status = EmmcPeimSwitchBusWidth (Slot, Rca, IsDdr, BusWidth);\r
2508 if (EFI_ERROR (Status)) {\r
2509 return Status;\r
2510 }\r
2511 //\r
2512 // Set to Hight Speed timing\r
2513 //\r
2514 HostCtrl1 = BIT2;\r
2515 Status = EmmcPeimHcOrMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
2516 if (EFI_ERROR (Status)) {\r
2517 return Status;\r
2518 }\r
2519\r
2520 HostCtrl2 = (UINT8)~0x7;\r
2521 Status = EmmcPeimHcAndMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
2522 if (EFI_ERROR (Status)) {\r
2523 return Status;\r
2524 }\r
2525 if (IsDdr) {\r
2526 HostCtrl2 = BIT2;\r
2527 } else if (ClockFreq == 52) {\r
2528 HostCtrl2 = BIT0;\r
2529 } else {\r
2530 HostCtrl2 = 0;\r
2531 }\r
2532 Status = EmmcPeimHcOrMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
2533 if (EFI_ERROR (Status)) {\r
2534 return Status;\r
2535 }\r
2536\r
2537 HsTiming = 1;\r
2538 Status = EmmcPeimSwitchClockFreq (Slot, Rca, HsTiming, ClockFreq);\r
48555339
FT
2539\r
2540 return Status;\r
2541}\r
2542\r
2543/**\r
2544 Switch to the HS200 timing according to request.\r
2545\r
2546 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller\r
2547 Simplified Spec 3.0 section Figure 2-29 for details.\r
2548\r
2549 @param[in] Slot The slot number of the Emmc card to send the command to.\r
2550 @param[in] Rca The relative device address to be assigned.\r
2551 @param[in] ClockFreq The max clock frequency to be set.\r
2552 @param[in] BusWidth The bus width to be set, it could be 4 or 8.\r
2553\r
2554 @retval EFI_SUCCESS The operation is done correctly.\r
2555 @retval Others The operation fails.\r
2556\r
2557**/\r
2558EFI_STATUS\r
2559EmmcPeimSwitchToHS200 (\r
2560 IN EMMC_PEIM_HC_SLOT *Slot,\r
2561 IN UINT32 Rca,\r
2562 IN UINT32 ClockFreq,\r
2563 IN UINT8 BusWidth\r
2564 )\r
2565{\r
2566 EFI_STATUS Status;\r
2567 UINT8 HsTiming;\r
2568 UINT8 HostCtrl2;\r
2569 UINT16 ClockCtrl;\r
2570\r
2571 if ((BusWidth != 4) && (BusWidth != 8)) {\r
2572 return EFI_INVALID_PARAMETER;\r
2573 }\r
2574\r
2575 Status = EmmcPeimSwitchBusWidth (Slot, Rca, FALSE, BusWidth);\r
2576 if (EFI_ERROR (Status)) {\r
2577 return Status;\r
2578 }\r
2579 //\r
2580 // Set to HS200/SDR104 timing\r
2581 //\r
2582 //\r
2583 // Stop bus clock at first\r
2584 //\r
2585 Status = EmmcPeimHcStopClock (Slot->EmmcHcBase);\r
2586 if (EFI_ERROR (Status)) {\r
2587 return Status;\r
2588 }\r
2589\r
2590 HostCtrl2 = (UINT8)~0x7;\r
2591 Status = EmmcPeimHcAndMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
2592 if (EFI_ERROR (Status)) {\r
2593 return Status;\r
2594 }\r
2595 HostCtrl2 = BIT0 | BIT1;\r
2596 Status = EmmcPeimHcOrMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
2597 if (EFI_ERROR (Status)) {\r
2598 return Status;\r
2599 }\r
2600\r
2601 //\r
2602 // Wait Internal Clock Stable in the Clock Control register to be 1 before set SD Clock Enable bit\r
2603 //\r
2604 Status = EmmcPeimHcWaitMmioSet (\r
2605 Slot->EmmcHcBase + EMMC_HC_CLOCK_CTRL,\r
2606 sizeof (ClockCtrl),\r
2607 BIT1,\r
2608 BIT1,\r
2609 EMMC_TIMEOUT\r
2610 );\r
2611 if (EFI_ERROR (Status)) {\r
2612 return Status;\r
2613 }\r
2614 //\r
2615 // Set SD Clock Enable in the Clock Control register to 1\r
2616 //\r
2617 ClockCtrl = BIT2;\r
2618 Status = EmmcPeimHcOrMmio (Slot->EmmcHcBase + EMMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);\r
2619\r
2620 HsTiming = 2;\r
2621 Status = EmmcPeimSwitchClockFreq (Slot, Rca, HsTiming, ClockFreq);\r
2622 if (EFI_ERROR (Status)) {\r
2623 return Status;\r
2624 }\r
2625\r
2626 Status = EmmcPeimTuningClkForHs200 (Slot, BusWidth);\r
2627\r
2628 return Status;\r
2629}\r
2630\r
2631/**\r
2632 Switch to the HS400 timing according to request.\r
2633\r
2634 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller\r
2635 Simplified Spec 3.0 section Figure 2-29 for details.\r
2636\r
2637 @param[in] Slot The slot number of the Emmc card to send the command to.\r
2638 @param[in] Rca The relative device address to be assigned.\r
2639 @param[in] ClockFreq The max clock frequency to be set.\r
2640\r
2641 @retval EFI_SUCCESS The operation is done correctly.\r
2642 @retval Others The operation fails.\r
2643\r
2644**/\r
2645EFI_STATUS\r
2646EmmcPeimSwitchToHS400 (\r
2647 IN EMMC_PEIM_HC_SLOT *Slot,\r
2648 IN UINT32 Rca,\r
2649 IN UINT32 ClockFreq\r
2650 )\r
2651{\r
2652 EFI_STATUS Status;\r
2653 UINT8 HsTiming;\r
2654 UINT8 HostCtrl2;\r
2655\r
2656 Status = EmmcPeimSwitchToHS200 (Slot, Rca, ClockFreq, 8);\r
2657 if (EFI_ERROR (Status)) {\r
2658 return Status;\r
2659 }\r
2660 //\r
2661 // Set to Hight Speed timing and set the clock frequency to a value less than 52MHz.\r
2662 //\r
2663 HsTiming = 1;\r
2664 Status = EmmcPeimSwitchClockFreq (Slot, Rca, HsTiming, 52);\r
2665 if (EFI_ERROR (Status)) {\r
2666 return Status;\r
2667 }\r
2668 //\r
2669 // HS400 mode must use 8 data lines.\r
2670 //\r
2671 Status = EmmcPeimSwitchBusWidth (Slot, Rca, TRUE, 8);\r
2672 if (EFI_ERROR (Status)) {\r
2673 return Status;\r
2674 }\r
2675 //\r
2676 // Set to HS400 timing\r
2677 //\r
2678 HostCtrl2 = (UINT8)~0x7;\r
2679 Status = EmmcPeimHcAndMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
2680 if (EFI_ERROR (Status)) {\r
2681 return Status;\r
2682 }\r
2683 HostCtrl2 = BIT0 | BIT2;\r
2684 Status = EmmcPeimHcOrMmio (Slot->EmmcHcBase + EMMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
2685 if (EFI_ERROR (Status)) {\r
2686 return Status;\r
2687 }\r
2688\r
2689 HsTiming = 3;\r
2690 Status = EmmcPeimSwitchClockFreq (Slot, Rca, HsTiming, ClockFreq);\r
2691\r
2692 return Status;\r
2693}\r
2694\r
2695/**\r
2696 Switch the high speed timing according to request.\r
2697\r
2698 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller\r
2699 Simplified Spec 3.0 section Figure 2-29 for details.\r
2700\r
2701 @param[in] Slot The slot number of the Emmc card to send the command to.\r
2702 @param[in] Rca The relative device address to be assigned.\r
2703\r
2704 @retval EFI_SUCCESS The operation is done correctly.\r
2705 @retval Others The operation fails.\r
2706\r
2707**/\r
2708EFI_STATUS\r
2709EmmcPeimSetBusMode (\r
2710 IN EMMC_PEIM_HC_SLOT *Slot,\r
2711 IN UINT32 Rca\r
2712 )\r
2713{\r
2714 EFI_STATUS Status;\r
2715 EMMC_HC_SLOT_CAP Capability;\r
2716 UINT8 HsTiming;\r
2717 BOOLEAN IsDdr;\r
2718 UINT32 ClockFreq;\r
2719 UINT8 BusWidth;\r
2720\r
2721 Status = EmmcPeimGetCsd (Slot, Rca, &Slot->Csd);\r
2722 if (EFI_ERROR (Status)) {\r
2723 DEBUG ((EFI_D_ERROR, "EmmcPeimSetBusMode: EmmcPeimGetCsd fails with %r\n", Status));\r
2724 return Status;\r
2725 }\r
2726\r
2727 if ((Slot->Csd.CSizeLow | Slot->Csd.CSizeHigh << 2) == 0xFFF) {\r
2728 Slot->SectorAddressing = TRUE;\r
2729 } else {\r
2730 Slot->SectorAddressing = FALSE;\r
2731 }\r
2732\r
2733 Status = EmmcPeimSelect (Slot, Rca);\r
2734 if (EFI_ERROR (Status)) {\r
2735 DEBUG ((EFI_D_ERROR, "EmmcPeimSetBusMode: EmmcPeimSelect fails with %r\n", Status));\r
2736 return Status;\r
2737 }\r
2738\r
2739 Status = EmmcPeimHcGetCapability (Slot->EmmcHcBase, &Capability);\r
2740 if (EFI_ERROR (Status)) {\r
2741 DEBUG ((EFI_D_ERROR, "EmmcPeimSetBusMode: EmmcPeimHcGetCapability fails with %r\n", Status));\r
2742 return Status;\r
2743 }\r
2744\r
2745 ASSERT (Capability.BaseClkFreq != 0);\r
2746 //\r
2747 // Check if the Host Controller support 8bits bus width.\r
2748 //\r
2749 if (Capability.BusWidth8 != 0) {\r
2750 BusWidth = 8;\r
2751 } else {\r
2752 BusWidth = 4;\r
2753 }\r
2754 //\r
2755 // Get Deivce_Type from EXT_CSD register.\r
2756 //\r
2757 Status = EmmcPeimGetExtCsd (Slot, &Slot->ExtCsd);\r
2758 if (EFI_ERROR (Status)) {\r
2759 DEBUG ((EFI_D_ERROR, "EmmcPeimSetBusMode: EmmcPeimGetExtCsd fails with %r\n", Status));\r
2760 return Status;\r
2761 }\r
2762 //\r
2763 // Calculate supported bus speed/bus width/clock frequency.\r
2764 //\r
2765 HsTiming = 0;\r
2766 IsDdr = FALSE;\r
2767 ClockFreq = 0;\r
2768 if (((Slot->ExtCsd.DeviceType & (BIT4 | BIT5)) != 0) && (Capability.Sdr104 != 0)) {\r
2769 HsTiming = 2;\r
2770 IsDdr = FALSE;\r
2771 ClockFreq = 200;\r
2772 } else if (((Slot->ExtCsd.DeviceType & (BIT2 | BIT3)) != 0) && (Capability.Ddr50 != 0)) {\r
2773 HsTiming = 1;\r
2774 IsDdr = TRUE;\r
2775 ClockFreq = 52;\r
2776 } else if (((Slot->ExtCsd.DeviceType & BIT1) != 0) && (Capability.HighSpeed != 0)) {\r
2777 HsTiming = 1;\r
2778 IsDdr = FALSE;\r
2779 ClockFreq = 52;\r
2780 } else if (((Slot->ExtCsd.DeviceType & BIT0) != 0) && (Capability.HighSpeed != 0)) {\r
2781 HsTiming = 1;\r
2782 IsDdr = FALSE;\r
2783 ClockFreq = 26;\r
2784 }\r
2785 //\r
2786 // Check if both of the device and the host controller support HS400 DDR mode.\r
2787 //\r
2788 if (((Slot->ExtCsd.DeviceType & (BIT6 | BIT7)) != 0) && (Capability.Hs400 != 0)) {\r
2789 //\r
2790 // The host controller supports 8bits bus.\r
2791 //\r
2792 ASSERT (BusWidth == 8);\r
2793 HsTiming = 3;\r
2794 IsDdr = TRUE;\r
2795 ClockFreq = 200;\r
2796 }\r
2797\r
2798 if ((ClockFreq == 0) || (HsTiming == 0)) {\r
2799 //\r
2800 // Continue using default setting.\r
2801 //\r
2802 return EFI_SUCCESS;\r
2803 }\r
2804\r
2805 DEBUG ((EFI_D_INFO, "HsTiming %d ClockFreq %d BusWidth %d Ddr %a\n", HsTiming, ClockFreq, BusWidth, IsDdr ? "TRUE":"FALSE"));\r
2806\r
2807 if (HsTiming == 3) {\r
2808 //\r
2809 // Execute HS400 timing switch procedure\r
2810 //\r
2811 Status = EmmcPeimSwitchToHS400 (Slot, Rca, ClockFreq);\r
2812 } else if (HsTiming == 2) {\r
2813 //\r
2814 // Execute HS200 timing switch procedure\r
2815 //\r
2816 Status = EmmcPeimSwitchToHS200 (Slot, Rca, ClockFreq, BusWidth);\r
2817 } else {\r
2818 //\r
2819 // Execute High Speed timing switch procedure\r
2820 //\r
91ff0f05 2821 Status = EmmcPeimSwitchToHighSpeed (Slot, Rca, ClockFreq, IsDdr, BusWidth);\r
48555339
FT
2822 }\r
2823\r
2824 return Status;\r
2825}\r
2826\r
2827/**\r
2828 Execute EMMC device identification procedure.\r
2829\r
2830 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.\r
2831\r
2832 @param[in] Slot The slot number of the Emmc card to send the command to.\r
2833\r
2834 @retval EFI_SUCCESS There is a EMMC card.\r
2835 @retval Others There is not a EMMC card.\r
2836\r
2837**/\r
2838EFI_STATUS\r
2839EmmcPeimIdentification (\r
2840 IN EMMC_PEIM_HC_SLOT *Slot\r
2841 )\r
2842{\r
2843 EFI_STATUS Status;\r
2844 UINT32 Ocr;\r
2845 UINT32 Rca;\r
ec86d285 2846 UINTN Retry;\r
48555339
FT
2847\r
2848 Status = EmmcPeimReset (Slot);\r
2849 if (EFI_ERROR (Status)) {\r
2850 DEBUG ((EFI_D_ERROR, "EmmcPeimIdentification: EmmcPeimReset fails with %r\n", Status));\r
2851 return Status;\r
2852 }\r
2853\r
ec86d285
FT
2854 Ocr = 0;\r
2855 Retry = 0;\r
48555339
FT
2856 do {\r
2857 Status = EmmcPeimGetOcr (Slot, &Ocr);\r
2858 if (EFI_ERROR (Status)) {\r
2859 DEBUG ((EFI_D_ERROR, "EmmcPeimIdentification: EmmcPeimGetOcr fails with %r\n", Status));\r
2860 return Status;\r
2861 }\r
ec86d285
FT
2862\r
2863 if (Retry++ == 100) {\r
2864 DEBUG ((EFI_D_ERROR, "EmmcPeimIdentification: EmmcPeimGetOcr fails too many times\n"));\r
2865 return EFI_DEVICE_ERROR;\r
2866 }\r
2867 MicroSecondDelay (10 * 1000);\r
48555339
FT
2868 } while ((Ocr & BIT31) == 0);\r
2869\r
2870 Status = EmmcPeimGetAllCid (Slot);\r
2871 if (EFI_ERROR (Status)) {\r
2872 DEBUG ((EFI_D_ERROR, "EmmcPeimIdentification: EmmcPeimGetAllCid fails with %r\n", Status));\r
2873 return Status;\r
2874 }\r
2875 //\r
2876 // Don't support multiple devices on the slot, that is\r
2877 // shared bus slot feature.\r
2878 //\r
2879 Rca = 1;\r
2880 Status = EmmcPeimSetRca (Slot, Rca);\r
2881 if (EFI_ERROR (Status)) {\r
2882 DEBUG ((EFI_D_ERROR, "EmmcPeimIdentification: EmmcPeimSetRca fails with %r\n", Status));\r
2883 return Status;\r
2884 }\r
2885 //\r
2886 // Enter Data Tranfer Mode.\r
2887 //\r
2888 DEBUG ((EFI_D_INFO, "Found a EMMC device at slot [%d], RCA [%d]\n", Slot, Rca));\r
2889\r
2890 Status = EmmcPeimSetBusMode (Slot, Rca);\r
2891\r
2892 return Status;\r
2893}\r
2894\r