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