]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[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
9d510e61 4 SPDX-License-Identifier: BSD-2-Clause-Patent\r
48555339
FT
5\r
6**/\r
7\r
8#include "SdBlockIoPei.h"\r
9\r
10/**\r
11 Read/Write specified SD 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
30SdPeimHcRwMmio (\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 SD 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
100SdPeimHcOrMmio (\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 = SdPeimHcRwMmio (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 = SdPeimHcRwMmio (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 SD 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
151SdPeimHcAndMmio (\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 = SdPeimHcRwMmio (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 = SdPeimHcRwMmio (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
200SdPeimHcCheckMmioSet (\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 = SdPeimHcRwMmio (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
247SdPeimHcWaitMmioSet (\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 = SdPeimHcCheckMmioSet (\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 SD 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
296SdPeimHcReset (\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 = SdPeimHcRwMmio (Bar + SD_HC_SW_RST, FALSE, sizeof (SwReset), &SwReset);\r
305\r
306 if (EFI_ERROR (Status)) {\r
307 DEBUG ((EFI_D_ERROR, "SdPeimHcReset: write full 1 fails: %r\n", Status));\r
308 return Status;\r
309 }\r
310\r
311 Status = SdPeimHcWaitMmioSet (\r
312 Bar + SD_HC_SW_RST,\r
313 sizeof (SwReset),\r
314 0xFF,\r
315 0x00,\r
316 SD_TIMEOUT\r
317 );\r
318 if (EFI_ERROR (Status)) {\r
319 DEBUG ((EFI_D_INFO, "SdPeimHcReset: 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 = SdPeimHcEnableInterrupt (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
341SdPeimHcEnableInterrupt (\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 = SdPeimHcRwMmio (Bar + SD_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 = SdPeimHcRwMmio (Bar + SD_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
376SdPeimHcGetCapability (\r
377 IN UINTN Bar,\r
378 OUT SD_HC_SLOT_CAP *Capability\r
379 )\r
380{\r
381 EFI_STATUS Status;\r
382 UINT64 Cap;\r
383\r
384 Status = SdPeimHcRwMmio (Bar + SD_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 SD card attached at the specified SD 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 SD card attached.\r
403 @retval EFI_NO_MEDIA There is not a SD card attached.\r
404 @retval Others The detection fails.\r
405\r
406**/\r
407EFI_STATUS\r
408SdPeimHcCardDetect (\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 = SdPeimHcRwMmio (Bar + SD_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 = SdPeimHcRwMmio (Bar + SD_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 = SdPeimHcRwMmio (Bar + SD_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 SD 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 SD clock.\r
458 @retval Others Fail to stop SD clock.\r
459\r
460**/\r
461EFI_STATUS\r
462SdPeimHcStopClock (\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 = SdPeimHcWaitMmioSet (\r
476 Bar + SD_HC_PRESENT_STATE,\r
477 sizeof (PresentState),\r
478 BIT0 | BIT1,\r
479 0,\r
480 SD_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 = SdPeimHcAndMmio (Bar + SD_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);\r
491\r
492 return Status;\r
493}\r
494\r
495/**\r
496 SD 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
508SdPeimHcClockSupply (\r
509 IN UINTN Bar,\r
510 IN UINT64 ClockFreq\r
511 )\r
512{\r
513 EFI_STATUS Status;\r
514 SD_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 = SdPeimHcGetCapability (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 = SdPeimHcRwMmio (Bar + SD_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 = SdPeimHcStopClock (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 = SdPeimHcRwMmio (Bar + SD_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 = SdPeimHcWaitMmioSet (\r
607 Bar + SD_HC_CLOCK_CTRL,\r
608 sizeof (ClockCtrl),\r
609 BIT1,\r
610 BIT1,\r
611 SD_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 = SdPeimHcOrMmio (Bar + SD_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);\r
622\r
623 return Status;\r
624}\r
625\r
626/**\r
627 SD 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 SD card attached.\r
635 @retval FALSE There is no a SD card attached.\r
636\r
637**/\r
638EFI_STATUS\r
639SdPeimHcPowerControl (\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 = SdPeimHcRwMmio (Bar + SD_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 = SdPeimHcRwMmio (Bar + SD_HC_POWER_CTRL, FALSE, sizeof (PowerCtrl), &PowerCtrl);\r
660\r
661 return Status;\r
662}\r
663\r
664/**\r
665 Set the SD 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 SD 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
677SdPeimHcSetBusWidth (\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 = SdPeimHcAndMmio (Bar + SD_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
688 } else if (BusWidth == 4) {\r
689 Status = SdPeimHcRwMmio (Bar + SD_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 = SdPeimHcRwMmio (Bar + SD_HC_HOST_CTRL1, FALSE, sizeof (HostCtrl1), &HostCtrl1);\r
696 } else if (BusWidth == 8) {\r
697 Status = SdPeimHcRwMmio (Bar + SD_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 = SdPeimHcRwMmio (Bar + SD_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 SD 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
722SdPeimHcInitClockFreq (\r
723 IN UINTN Bar\r
724 )\r
725{\r
726 EFI_STATUS Status;\r
727 SD_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 = SdPeimHcGetCapability (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 = SdPeimHcClockSupply (Bar, InitFreq);\r
749 return Status;\r
750}\r
751\r
752/**\r
753 Supply SD 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
764SdPeimHcInitPowerVoltage (\r
765 IN UINTN Bar\r
766 )\r
767{\r
768 EFI_STATUS Status;\r
769 SD_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 = SdPeimHcGetCapability (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 = SdPeimHcOrMmio (Bar + SD_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 = SdPeimHcPowerControl (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
829SdPeimHcInitTimeoutCtrl (\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 = SdPeimHcRwMmio (Bar + SD_HC_TIMEOUT_CTRL, FALSE, sizeof (Timeout), &Timeout);\r
838\r
839 return Status;\r
840}\r
841\r
842/**\r
843 Initial SD 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
853SdPeimHcInitHost (\r
854 IN UINTN Bar\r
855 )\r
856{\r
857 EFI_STATUS Status;\r
858\r
859 Status = SdPeimHcInitClockFreq (Bar);\r
860 if (EFI_ERROR (Status)) {\r
861 return Status;\r
862 }\r
863\r
864 Status = SdPeimHcInitPowerVoltage (Bar);\r
865 if (EFI_ERROR (Status)) {\r
866 return Status;\r
867 }\r
868\r
869 Status = SdPeimHcInitTimeoutCtrl (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
884SdPeimHcLedOnOff (\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 = SdPeimHcOrMmio (Bar + SD_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
895 } else {\r
896 HostCtrl1 = (UINT8)~BIT0;\r
897 Status = SdPeimHcAndMmio (Bar + SD_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 SD_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 SD_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
77af8668 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 (SD_HC_ADMA_DESC_LINE));\r
945 Trb->AdmaDesc = SdPeimAllocateMem (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 SD cmd request.\r
979\r
980 @param[in] Slot The slot number of the SD 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
986SD_TRB *\r
987SdPeimCreateTrb (\r
988 IN SD_PEIM_HC_SLOT *Slot,\r
989 IN SD_COMMAND_PACKET *Packet\r
990 )\r
991{\r
992 SD_TRB *Trb;\r
993 EFI_STATUS Status;\r
994 SD_HC_SLOT_CAP Capability;\r
77af8668
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 = SdPeimHcGetCapability (Slot->SdHcBase, &Capability);\r
1002 if (EFI_ERROR (Status)) {\r
1003 return NULL;\r
1004 }\r
1005\r
77af8668 1006 Trb = AllocateZeroPool (sizeof (SD_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->SdCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK) {\r
48555339 1036 Trb->Mode = SdPioMode;\r
e7e89b08 1037 } else {\r
77af8668
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, "SdPeimCreateTrb: 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 = SdNoData;\r
1056 } else if (Capability.Adma2 != 0) {\r
1057 Trb->Mode = SdAdmaMode;\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 = SdSdmaMode;\r
1064 } else {\r
1065 Trb->Mode = SdPioMode;\r
1066 }\r
48555339 1067 }\r
48555339
FT
1068 return Trb;\r
1069\r
1070Error:\r
1071 SdPeimFreeTrb (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 SD_TRB instance.\r
1079\r
1080**/\r
1081VOID\r
1082SdPeimFreeTrb (\r
1083 IN SD_TRB *Trb\r
1084 )\r
1085{\r
77af8668
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 SdPeimFreeMem (Trb->Slot->Private->Pool, Trb->AdmaDesc, Trb->AdmaDescSize);\r
1092 }\r
1093\r
1094 if (Trb != NULL) {\r
77af8668 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 SD_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
1112SdPeimCheckTrbEnv (\r
1113 IN UINTN Bar,\r
1114 IN SD_TRB *Trb\r
1115 )\r
1116{\r
1117 EFI_STATUS Status;\r
1118 SD_COMMAND_PACKET *Packet;\r
1119 UINT32 PresentState;\r
1120\r
1121 Packet = Trb->Packet;\r
1122\r
1123 if ((Packet->SdCmdBlk->CommandType == SdCommandTypeAdtc) ||\r
1124 (Packet->SdCmdBlk->ResponseType == SdResponseTypeR1b) ||\r
1125 (Packet->SdCmdBlk->ResponseType == SdResponseTypeR5b)) {\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 = SdPeimHcCheckMmioSet (\r
1140 Bar + SD_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 SD_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
1161SdPeimWaitTrbEnv (\r
1162 IN UINTN Bar,\r
1163 IN SD_TRB *Trb\r
1164 )\r
1165{\r
1166 EFI_STATUS Status;\r
1167 SD_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 = SdPeimCheckTrbEnv (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 SD_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
1212SdPeimExecTrb (\r
1213 IN UINTN Bar,\r
1214 IN SD_TRB *Trb\r
1215 )\r
1216{\r
1217 EFI_STATUS Status;\r
1218 SD_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 = SdPeimHcRwMmio (Bar + SD_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 = SdPeimHcRwMmio (Bar + SD_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 == SdAdmaMode) {\r
1250 HostCtrl1 = BIT4;\r
1251 Status = SdPeimHcOrMmio (Bar + SD_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
1252 if (EFI_ERROR (Status)) {\r
1253 return Status;\r
1254 }\r
1255 }\r
1256\r
1257 SdPeimHcLedOnOff (Bar, TRUE);\r
1258\r
1259 if (Trb->Mode == SdSdmaMode) {\r
77af8668 1260 if ((UINT64)(UINTN)Trb->DataPhy >= 0x100000000ul) {\r
48555339
FT
1261 return EFI_INVALID_PARAMETER;\r
1262 }\r
1263\r
77af8668 1264 SdmaAddr = (UINT32)(UINTN)Trb->DataPhy;\r
48555339
FT
1265 Status = SdPeimHcRwMmio (Bar + SD_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 == SdAdmaMode) {\r
1270 AdmaAddr = (UINT64)(UINTN)Trb->AdmaDesc;\r
1271 Status = SdPeimHcRwMmio (Bar + SD_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 == SdSdmaMode) {\r
1279 //\r
1280 // Set SDMA boundary to be 512K bytes.\r
1281 //\r
1282 BlkSize |= 0x7000;\r
1283 }\r
1284\r
1285 Status = SdPeimHcRwMmio (Bar + SD_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 != SdNoData) {\r
1292 //\r
1293 // Calcuate Block Count.\r
1294 //\r
1295 BlkCount = (UINT16)(Trb->DataLen / Trb->BlockSize);\r
1296 }\r
48555339
FT
1297 Status = SdPeimHcRwMmio (Bar + SD_HC_BLK_COUNT, FALSE, sizeof (BlkCount), &BlkCount);\r
1298 if (EFI_ERROR (Status)) {\r
1299 return Status;\r
1300 }\r
1301\r
1302 Argument = Packet->SdCmdBlk->CommandArgument;\r
1303 Status = SdPeimHcRwMmio (Bar + SD_HC_ARG1, FALSE, sizeof (Argument), &Argument);\r
1304 if (EFI_ERROR (Status)) {\r
1305 return Status;\r
1306 }\r
1307\r
1308 TransMode = 0;\r
1309 if (Trb->Mode != SdNoData) {\r
1310 if (Trb->Mode != SdPioMode) {\r
1311 TransMode |= BIT0;\r
1312 }\r
1313 if (Trb->Read) {\r
1314 TransMode |= BIT4;\r
1315 }\r
e7e89b08 1316 if (BlkCount > 1) {\r
48555339
FT
1317 TransMode |= BIT5 | BIT1;\r
1318 }\r
e7e89b08
FT
1319 //\r
1320 // SD memory card needs to use AUTO CMD12 feature.\r
1321 //\r
48555339
FT
1322 if (BlkCount > 1) {\r
1323 TransMode |= BIT2;\r
1324 }\r
1325 }\r
1326\r
1327 Status = SdPeimHcRwMmio (Bar + SD_HC_TRANS_MOD, FALSE, sizeof (TransMode), &TransMode);\r
1328 if (EFI_ERROR (Status)) {\r
1329 return Status;\r
1330 }\r
1331\r
1332 Cmd = (UINT16)LShiftU64(Packet->SdCmdBlk->CommandIndex, 8);\r
1333 if (Packet->SdCmdBlk->CommandType == SdCommandTypeAdtc) {\r
1334 Cmd |= BIT5;\r
1335 }\r
1336 //\r
1337 // Convert ResponseType to value\r
1338 //\r
1339 if (Packet->SdCmdBlk->CommandType != SdCommandTypeBc) {\r
1340 switch (Packet->SdCmdBlk->ResponseType) {\r
1341 case SdResponseTypeR1:\r
1342 case SdResponseTypeR5:\r
1343 case SdResponseTypeR6:\r
1344 case SdResponseTypeR7:\r
1345 Cmd |= (BIT1 | BIT3 | BIT4);\r
1346 break;\r
1347 case SdResponseTypeR2:\r
1348 Cmd |= (BIT0 | BIT3);\r
1349 break;\r
1350 case SdResponseTypeR3:\r
1351 case SdResponseTypeR4:\r
1352 Cmd |= BIT1;\r
1353 break;\r
1354 case SdResponseTypeR1b:\r
1355 case SdResponseTypeR5b:\r
1356 Cmd |= (BIT0 | BIT1 | BIT3 | BIT4);\r
1357 break;\r
1358 default:\r
1359 ASSERT (FALSE);\r
1360 break;\r
1361 }\r
1362 }\r
1363 //\r
1364 // Execute cmd\r
1365 //\r
1366 Status = SdPeimHcRwMmio (Bar + SD_HC_COMMAND, FALSE, sizeof (Cmd), &Cmd);\r
1367 return Status;\r
1368}\r
1369\r
1370/**\r
1371 Check the TRB execution result.\r
1372\r
1373 @param[in] Bar The mmio base address of the slot to be accessed.\r
1374 @param[in] Trb The pointer to the SD_TRB instance.\r
1375\r
1376 @retval EFI_SUCCESS The TRB is executed successfully.\r
1377 @retval EFI_NOT_READY The TRB is not completed for execution.\r
1378 @retval Others Some erros happen when executing this request.\r
1379\r
1380**/\r
1381EFI_STATUS\r
1382SdPeimCheckTrbResult (\r
1383 IN UINTN Bar,\r
1384 IN SD_TRB *Trb\r
1385 )\r
1386{\r
1387 EFI_STATUS Status;\r
1388 SD_COMMAND_PACKET *Packet;\r
1389 UINT16 IntStatus;\r
1390 UINT32 Response[4];\r
1391 UINT32 SdmaAddr;\r
1392 UINT8 Index;\r
1393 UINT8 SwReset;\r
e7e89b08 1394 UINT32 PioLength;\r
48555339
FT
1395\r
1396 SwReset = 0;\r
1397 Packet = Trb->Packet;\r
1398 //\r
1399 // Check Trb execution result by reading Normal Interrupt Status register.\r
1400 //\r
1401 Status = SdPeimHcRwMmio (\r
1402 Bar + SD_HC_NOR_INT_STS,\r
1403 TRUE,\r
1404 sizeof (IntStatus),\r
1405 &IntStatus\r
1406 );\r
1407 if (EFI_ERROR (Status)) {\r
1408 goto Done;\r
1409 }\r
1410 //\r
1411 // Check Transfer Complete bit is set or not.\r
1412 //\r
1413 if ((IntStatus & BIT1) == BIT1) {\r
1414 if ((IntStatus & BIT15) == BIT15) {\r
1415 //\r
1416 // Read Error Interrupt Status register to check if the error is\r
1417 // Data Timeout Error.\r
1418 // If yes, treat it as success as Transfer Complete has higher\r
1419 // priority than Data Timeout Error.\r
1420 //\r
1421 Status = SdPeimHcRwMmio (\r
1422 Bar + SD_HC_ERR_INT_STS,\r
1423 TRUE,\r
1424 sizeof (IntStatus),\r
1425 &IntStatus\r
1426 );\r
1427 if (!EFI_ERROR (Status)) {\r
1428 if ((IntStatus & BIT4) == BIT4) {\r
1429 Status = EFI_SUCCESS;\r
1430 } else {\r
1431 Status = EFI_DEVICE_ERROR;\r
1432 }\r
1433 }\r
1434 }\r
1435\r
1436 goto Done;\r
1437 }\r
1438 //\r
1439 // Check if there is a error happened during cmd execution.\r
1440 // If yes, then do error recovery procedure to follow SD Host Controller\r
1441 // Simplified Spec 3.0 section 3.10.1.\r
1442 //\r
1443 if ((IntStatus & BIT15) == BIT15) {\r
1444 Status = SdPeimHcRwMmio (\r
1445 Bar + SD_HC_ERR_INT_STS,\r
1446 TRUE,\r
1447 sizeof (IntStatus),\r
1448 &IntStatus\r
1449 );\r
1450 if (EFI_ERROR (Status)) {\r
1451 goto Done;\r
1452 }\r
1453\r
1454 if ((IntStatus & 0x0F) != 0) {\r
1455 SwReset |= BIT1;\r
1456 }\r
1457 if ((IntStatus & 0xF0) != 0) {\r
1458 SwReset |= BIT2;\r
1459 }\r
1460\r
1461 Status = SdPeimHcRwMmio (\r
1462 Bar + SD_HC_SW_RST,\r
1463 FALSE,\r
1464 sizeof (SwReset),\r
1465 &SwReset\r
1466 );\r
1467 if (EFI_ERROR (Status)) {\r
1468 goto Done;\r
1469 }\r
1470 Status = SdPeimHcWaitMmioSet (\r
1471 Bar + SD_HC_SW_RST,\r
1472 sizeof (SwReset),\r
1473 0xFF,\r
1474 0,\r
1475 SD_TIMEOUT\r
1476 );\r
1477 if (EFI_ERROR (Status)) {\r
1478 goto Done;\r
1479 }\r
1480\r
1481 Status = EFI_DEVICE_ERROR;\r
1482 goto Done;\r
1483 }\r
1484 //\r
1485 // Check if DMA interrupt is signalled for the SDMA transfer.\r
1486 //\r
1487 if ((Trb->Mode == SdSdmaMode) && ((IntStatus & BIT3) == BIT3)) {\r
1488 //\r
1489 // Clear DMA interrupt bit.\r
1490 //\r
1491 IntStatus = BIT3;\r
1492 Status = SdPeimHcRwMmio (\r
1493 Bar + SD_HC_NOR_INT_STS,\r
1494 FALSE,\r
1495 sizeof (IntStatus),\r
1496 &IntStatus\r
1497 );\r
1498 if (EFI_ERROR (Status)) {\r
1499 goto Done;\r
1500 }\r
1501 //\r
1502 // Update SDMA Address register.\r
1503 //\r
77af8668 1504 SdmaAddr = SD_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, SD_SDMA_BOUNDARY);\r
48555339
FT
1505 Status = SdPeimHcRwMmio (\r
1506 Bar + SD_HC_SDMA_ADDR,\r
1507 FALSE,\r
1508 sizeof (UINT32),\r
1509 &SdmaAddr\r
1510 );\r
1511 if (EFI_ERROR (Status)) {\r
1512 goto Done;\r
1513 }\r
77af8668 1514 Trb->DataPhy = (UINT32)(UINTN)SdmaAddr;\r
48555339
FT
1515 }\r
1516\r
1517 if ((Packet->SdCmdBlk->CommandType != SdCommandTypeAdtc) &&\r
1518 (Packet->SdCmdBlk->ResponseType != SdResponseTypeR1b) &&\r
1519 (Packet->SdCmdBlk->ResponseType != SdResponseTypeR5b)) {\r
1520 if ((IntStatus & BIT0) == BIT0) {\r
1521 Status = EFI_SUCCESS;\r
1522 goto Done;\r
1523 }\r
1524 }\r
1525\r
1526 if (Packet->SdCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK) {\r
e7e89b08
FT
1527 //\r
1528 // When performing tuning procedure (Execute Tuning is set to 1) through PIO mode,\r
1529 // wait Buffer Read Ready bit of Normal Interrupt Status Register to be 1.\r
1530 // Refer to SD Host Controller Simplified Specification 3.0 figure 2-29 for details.\r
1531 //\r
1532 if ((IntStatus & BIT5) == BIT5) {\r
1533 //\r
1534 // Clear Buffer Read Ready interrupt at first.\r
1535 //\r
1536 IntStatus = BIT5;\r
1537 SdPeimHcRwMmio (Bar + SD_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);\r
1538 //\r
1539 // Read data out from Buffer Port register\r
1540 //\r
1541 for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) {\r
1542 SdPeimHcRwMmio (Bar + SD_HC_BUF_DAT_PORT, TRUE, 4, (UINT8*)Trb->Data + PioLength);\r
1543 }\r
1544 Status = EFI_SUCCESS;\r
1545 goto Done;\r
1546 }\r
48555339
FT
1547 }\r
1548\r
1549 Status = EFI_NOT_READY;\r
1550Done:\r
1551 //\r
1552 // Get response data when the cmd is executed successfully.\r
1553 //\r
1554 if (!EFI_ERROR (Status)) {\r
1555 if (Packet->SdCmdBlk->CommandType != SdCommandTypeBc) {\r
1556 for (Index = 0; Index < 4; Index++) {\r
1557 Status = SdPeimHcRwMmio (\r
1558 Bar + SD_HC_RESPONSE + Index * 4,\r
1559 TRUE,\r
1560 sizeof (UINT32),\r
1561 &Response[Index]\r
1562 );\r
1563 if (EFI_ERROR (Status)) {\r
1564 SdPeimHcLedOnOff (Bar, FALSE);\r
1565 return Status;\r
1566 }\r
1567 }\r
1568 CopyMem (Packet->SdStatusBlk, Response, sizeof (Response));\r
1569 }\r
1570 }\r
1571\r
1572 if (Status != EFI_NOT_READY) {\r
1573 SdPeimHcLedOnOff (Bar, FALSE);\r
1574 }\r
1575\r
1576 return Status;\r
1577}\r
1578\r
1579/**\r
1580 Wait for the TRB execution result.\r
1581\r
1582 @param[in] Bar The mmio base address of the slot to be accessed.\r
1583 @param[in] Trb The pointer to the SD_TRB instance.\r
1584\r
1585 @retval EFI_SUCCESS The TRB is executed successfully.\r
1586 @retval Others Some erros happen when executing this request.\r
1587\r
1588**/\r
1589EFI_STATUS\r
1590SdPeimWaitTrbResult (\r
1591 IN UINTN Bar,\r
1592 IN SD_TRB *Trb\r
1593 )\r
1594{\r
1595 EFI_STATUS Status;\r
1596 SD_COMMAND_PACKET *Packet;\r
1597 UINT64 Timeout;\r
1598 BOOLEAN InfiniteWait;\r
1599\r
1600 Packet = Trb->Packet;\r
1601 //\r
1602 // Wait Command Complete Interrupt Status bit in Normal Interrupt Status Register\r
1603 //\r
1604 Timeout = Packet->Timeout;\r
1605 if (Timeout == 0) {\r
1606 InfiniteWait = TRUE;\r
1607 } else {\r
1608 InfiniteWait = FALSE;\r
1609 }\r
1610\r
1611 while (InfiniteWait || (Timeout > 0)) {\r
1612 //\r
1613 // Check Trb execution result by reading Normal Interrupt Status register.\r
1614 //\r
1615 Status = SdPeimCheckTrbResult (Bar, Trb);\r
1616 if (Status != EFI_NOT_READY) {\r
1617 return Status;\r
1618 }\r
1619 //\r
1620 // Stall for 1 microsecond.\r
1621 //\r
1622 MicroSecondDelay (1);\r
1623\r
1624 Timeout--;\r
1625 }\r
1626\r
1627 return EFI_TIMEOUT;\r
1628}\r
1629\r
1630/**\r
1631 Sends SD command to an SD card that is attached to the SD controller.\r
1632\r
1633 If Packet is successfully sent to the SD card, then EFI_SUCCESS is returned.\r
1634\r
1635 If a device error occurs while sending the Packet, then EFI_DEVICE_ERROR is returned.\r
1636\r
1637 If Slot is not in a valid range for the SD controller, then EFI_INVALID_PARAMETER\r
1638 is returned.\r
1639\r
1640 If Packet defines a data command but both InDataBuffer and OutDataBuffer are NULL,\r
1641 EFI_INVALID_PARAMETER is returned.\r
1642\r
1643 @param[in] Slot The slot number of the Sd card to send the command to.\r
1644 @param[in,out] Packet A pointer to the SD command data structure.\r
1645\r
1646 @retval EFI_SUCCESS The SD Command Packet was sent by the host.\r
1647 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SD\r
1648 command Packet.\r
1649 @retval EFI_INVALID_PARAMETER Packet, Slot, or the contents of the Packet is invalid.\r
1650 @retval EFI_INVALID_PARAMETER Packet defines a data command but both InDataBuffer and\r
1651 OutDataBuffer are NULL.\r
1652 @retval EFI_NO_MEDIA SD Device not present in the Slot.\r
1653 @retval EFI_UNSUPPORTED The command described by the SD Command Packet is not\r
1654 supported by the host controller.\r
1655 @retval EFI_BAD_BUFFER_SIZE The InTransferLength or OutTransferLength exceeds the\r
1656 limit supported by SD card ( i.e. if the number of bytes\r
1657 exceed the Last LBA).\r
1658\r
1659**/\r
1660EFI_STATUS\r
1661EFIAPI\r
1662SdPeimExecCmd (\r
1663 IN SD_PEIM_HC_SLOT *Slot,\r
1664 IN OUT SD_COMMAND_PACKET *Packet\r
1665 )\r
1666{\r
1667 EFI_STATUS Status;\r
1668 SD_TRB *Trb;\r
1669\r
1670 if (Packet == NULL) {\r
1671 return EFI_INVALID_PARAMETER;\r
1672 }\r
1673\r
1674 if ((Packet->SdCmdBlk == NULL) || (Packet->SdStatusBlk == NULL)) {\r
1675 return EFI_INVALID_PARAMETER;\r
1676 }\r
1677\r
1678 if ((Packet->OutDataBuffer == NULL) && (Packet->OutTransferLength != 0)) {\r
1679 return EFI_INVALID_PARAMETER;\r
1680 }\r
1681\r
1682 if ((Packet->InDataBuffer == NULL) && (Packet->InTransferLength != 0)) {\r
1683 return EFI_INVALID_PARAMETER;\r
1684 }\r
1685\r
1686 Trb = SdPeimCreateTrb (Slot, Packet);\r
1687 if (Trb == NULL) {\r
1688 return EFI_OUT_OF_RESOURCES;\r
1689 }\r
1690\r
1691 Status = SdPeimWaitTrbEnv (Slot->SdHcBase, Trb);\r
1692 if (EFI_ERROR (Status)) {\r
1693 goto Done;\r
1694 }\r
1695\r
1696 Status = SdPeimExecTrb (Slot->SdHcBase, Trb);\r
1697 if (EFI_ERROR (Status)) {\r
1698 goto Done;\r
1699 }\r
1700\r
1701 Status = SdPeimWaitTrbResult (Slot->SdHcBase, Trb);\r
1702 if (EFI_ERROR (Status)) {\r
1703 goto Done;\r
1704 }\r
1705\r
1706Done:\r
1707 SdPeimFreeTrb (Trb);\r
1708\r
1709 return Status;\r
1710}\r
1711\r
1712/**\r
1713 Send command GO_IDLE_STATE to the device to make it go to Idle State.\r
1714\r
1715 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
1716\r
1717 @param[in] Slot The slot number of the SD card to send the command to.\r
1718\r
1719 @retval EFI_SUCCESS The SD device is reset correctly.\r
1720 @retval Others The device reset fails.\r
1721\r
1722**/\r
1723EFI_STATUS\r
1724SdPeimReset (\r
1725 IN SD_PEIM_HC_SLOT *Slot\r
1726 )\r
1727{\r
1728 SD_COMMAND_BLOCK SdCmdBlk;\r
1729 SD_STATUS_BLOCK SdStatusBlk;\r
1730 SD_COMMAND_PACKET Packet;\r
1731 EFI_STATUS Status;\r
1732\r
1733 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
1734 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
1735 ZeroMem (&Packet, sizeof (Packet));\r
1736\r
1737 Packet.SdCmdBlk = &SdCmdBlk;\r
1738 Packet.SdStatusBlk = &SdStatusBlk;\r
1739 Packet.Timeout = SD_TIMEOUT;\r
1740\r
1741 SdCmdBlk.CommandIndex = SD_GO_IDLE_STATE;\r
1742 SdCmdBlk.CommandType = SdCommandTypeBc;\r
1743 SdCmdBlk.ResponseType = 0;\r
1744 SdCmdBlk.CommandArgument = 0;\r
1745\r
1746 Status = SdPeimExecCmd (Slot, &Packet);\r
1747\r
1748 return Status;\r
1749}\r
1750\r
1751/**\r
1752 Send command SEND_IF_COND to the device to inquiry the SD Memory Card interface\r
1753 condition.\r
1754\r
1755 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
1756\r
1757 @param[in] Slot The slot number of the SD card to send the command to.\r
1758 @param[in] SupplyVoltage The supplied voltage by the host.\r
1759 @param[in] CheckPattern The check pattern to be sent to the device.\r
1760\r
1761 @retval EFI_SUCCESS The operation is done correctly.\r
1762 @retval Others The operation fails.\r
1763\r
1764**/\r
1765EFI_STATUS\r
1766SdPeimVoltageCheck (\r
1767 IN SD_PEIM_HC_SLOT *Slot,\r
1768 IN UINT8 SupplyVoltage,\r
1769 IN UINT8 CheckPattern\r
1770 )\r
1771{\r
1772 SD_COMMAND_BLOCK SdCmdBlk;\r
1773 SD_STATUS_BLOCK SdStatusBlk;\r
1774 SD_COMMAND_PACKET Packet;\r
1775 EFI_STATUS Status;\r
1776\r
1777 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
1778 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
1779 ZeroMem (&Packet, sizeof (Packet));\r
1780\r
1781 Packet.SdCmdBlk = &SdCmdBlk;\r
1782 Packet.SdStatusBlk = &SdStatusBlk;\r
1783 Packet.Timeout = SD_TIMEOUT;\r
1784\r
1785 SdCmdBlk.CommandIndex = SD_SEND_IF_COND;\r
1786 SdCmdBlk.CommandType = SdCommandTypeBcr;\r
1787 SdCmdBlk.ResponseType = SdResponseTypeR7;\r
1788 SdCmdBlk.CommandArgument = (SupplyVoltage << 8) | CheckPattern;\r
1789\r
1790 Status = SdPeimExecCmd (Slot, &Packet);\r
1791 if (!EFI_ERROR (Status)) {\r
1792 if (SdStatusBlk.Resp0 != SdCmdBlk.CommandArgument) {\r
1793 return EFI_DEVICE_ERROR;\r
1794 }\r
1795 }\r
1796\r
1797 return Status;\r
1798}\r
1799\r
1800/**\r
1801 Send command SDIO_SEND_OP_COND to the device to see whether it is SDIO device.\r
1802\r
1803 Refer to SDIO Simplified Spec 3 Section 3.2 for details.\r
1804\r
1805 @param[in] Slot The slot number of the SD card to send the command to.\r
1806 @param[in] VoltageWindow The supply voltage window.\r
1807 @param[in] S18r The boolean to show if it should switch to 1.8v.\r
1808\r
1809 @retval EFI_SUCCESS The operation is done correctly.\r
1810 @retval Others The operation fails.\r
1811\r
1812**/\r
1813EFI_STATUS\r
1814SdioSendOpCond (\r
1815 IN SD_PEIM_HC_SLOT *Slot,\r
1816 IN UINT32 VoltageWindow,\r
1817 IN BOOLEAN S18r\r
1818 )\r
1819{\r
1820 SD_COMMAND_BLOCK SdCmdBlk;\r
1821 SD_STATUS_BLOCK SdStatusBlk;\r
1822 SD_COMMAND_PACKET Packet;\r
1823 EFI_STATUS Status;\r
1824 UINT32 Switch;\r
1825\r
1826 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
1827 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
1828 ZeroMem (&Packet, sizeof (Packet));\r
1829\r
1830 Packet.SdCmdBlk = &SdCmdBlk;\r
1831 Packet.SdStatusBlk = &SdStatusBlk;\r
1832 Packet.Timeout = SD_TIMEOUT;\r
1833\r
1834 SdCmdBlk.CommandIndex = SDIO_SEND_OP_COND;\r
1835 SdCmdBlk.CommandType = SdCommandTypeBcr;\r
1836 SdCmdBlk.ResponseType = SdResponseTypeR4;\r
1837\r
1838 Switch = S18r ? BIT24 : 0;\r
1839\r
1840 SdCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch;\r
1841\r
1842 Status = SdPeimExecCmd (Slot, &Packet);\r
1843\r
1844 return Status;\r
1845}\r
1846\r
1847/**\r
1848 Send command SD_SEND_OP_COND to the device to see whether it is SDIO device.\r
1849\r
1850 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
1851\r
1852 @param[in] Slot The slot number of the SD card to send the command to.\r
1853 @param[in] Rca The relative device address of addressed device.\r
1854 @param[in] VoltageWindow The supply voltage window.\r
1855 @param[in] S18r The boolean to show if it should switch to 1.8v.\r
1856 @param[in] Xpc The boolean to show if it should provide 0.36w power control.\r
1857 @param[in] Hcs The boolean to show if it support host capacity info.\r
1858 @param[out] Ocr The buffer to store returned OCR register value.\r
1859\r
1860\r
1861 @retval EFI_SUCCESS The operation is done correctly.\r
1862 @retval Others The operation fails.\r
1863\r
1864**/\r
1865EFI_STATUS\r
1866SdPeimSendOpCond (\r
1867 IN SD_PEIM_HC_SLOT *Slot,\r
1868 IN UINT16 Rca,\r
1869 IN UINT32 VoltageWindow,\r
1870 IN BOOLEAN S18r,\r
1871 IN BOOLEAN Xpc,\r
1872 IN BOOLEAN Hcs,\r
1873 OUT UINT32 *Ocr\r
1874 )\r
1875{\r
1876 SD_COMMAND_BLOCK SdCmdBlk;\r
1877 SD_STATUS_BLOCK SdStatusBlk;\r
1878 SD_COMMAND_PACKET Packet;\r
1879 EFI_STATUS Status;\r
1880 UINT32 Switch;\r
1881 UINT32 MaxPower;\r
1882 UINT32 HostCapacity;\r
1883\r
1884 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
1885 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
1886 ZeroMem (&Packet, sizeof (Packet));\r
1887\r
1888 Packet.SdCmdBlk = &SdCmdBlk;\r
1889 Packet.SdStatusBlk = &SdStatusBlk;\r
1890 Packet.Timeout = SD_TIMEOUT;\r
1891\r
1892 SdCmdBlk.CommandIndex = SD_APP_CMD;\r
1893 SdCmdBlk.CommandType = SdCommandTypeAc;\r
1894 SdCmdBlk.ResponseType = SdResponseTypeR1;\r
1895 SdCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
1896\r
1897 Status = SdPeimExecCmd (Slot, &Packet);\r
1898 if (EFI_ERROR (Status)) {\r
1899 return Status;\r
1900 }\r
1901\r
1902 SdCmdBlk.CommandIndex = SD_SEND_OP_COND;\r
1903 SdCmdBlk.CommandType = SdCommandTypeBcr;\r
1904 SdCmdBlk.ResponseType = SdResponseTypeR3;\r
1905\r
1906 Switch = S18r ? BIT24 : 0;\r
1907 MaxPower = Xpc ? BIT28 : 0;\r
1908 HostCapacity = Hcs ? BIT30 : 0;\r
1909 SdCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch | MaxPower | HostCapacity;\r
1910\r
1911 Status = SdPeimExecCmd (Slot, &Packet);\r
1912 if (!EFI_ERROR (Status)) {\r
1913 //\r
1914 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.\r
1915 //\r
1916 *Ocr = SdStatusBlk.Resp0;\r
1917 }\r
1918\r
1919 return Status;\r
1920}\r
1921\r
1922/**\r
1923 Broadcast command ALL_SEND_CID to the bus to ask all the SD devices to send the\r
1924 data of their CID registers.\r
1925\r
1926 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
1927\r
1928 @param[in] Slot The slot number of the SD card to send the command to.\r
1929\r
1930 @retval EFI_SUCCESS The operation is done correctly.\r
1931 @retval Others The operation fails.\r
1932\r
1933**/\r
1934EFI_STATUS\r
1935SdPeimAllSendCid (\r
1936 IN SD_PEIM_HC_SLOT *Slot\r
1937 )\r
1938{\r
1939 SD_COMMAND_BLOCK SdCmdBlk;\r
1940 SD_STATUS_BLOCK SdStatusBlk;\r
1941 SD_COMMAND_PACKET Packet;\r
1942 EFI_STATUS Status;\r
1943\r
1944 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
1945 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
1946 ZeroMem (&Packet, sizeof (Packet));\r
1947\r
1948 Packet.SdCmdBlk = &SdCmdBlk;\r
1949 Packet.SdStatusBlk = &SdStatusBlk;\r
1950 Packet.Timeout = SD_TIMEOUT;\r
1951\r
1952 SdCmdBlk.CommandIndex = SD_ALL_SEND_CID;\r
1953 SdCmdBlk.CommandType = SdCommandTypeBcr;\r
1954 SdCmdBlk.ResponseType = SdResponseTypeR2;\r
1955 SdCmdBlk.CommandArgument = 0;\r
1956\r
1957 Status = SdPeimExecCmd (Slot, &Packet);\r
1958\r
1959 return Status;\r
1960}\r
1961\r
1962/**\r
1963 Send command SET_RELATIVE_ADDR to the SD device to assign a Relative device\r
1964 Address (RCA).\r
1965\r
1966 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
1967\r
1968 @param[in] Slot The slot number of the SD card to send the command to.\r
1969 @param[out] Rca The relative device address to be assigned.\r
1970\r
1971 @retval EFI_SUCCESS The operation is done correctly.\r
1972 @retval Others The operation fails.\r
1973\r
1974**/\r
1975EFI_STATUS\r
1976SdPeimSetRca (\r
1977 IN SD_PEIM_HC_SLOT *Slot,\r
1978 OUT UINT16 *Rca\r
1979 )\r
1980{\r
1981 SD_COMMAND_BLOCK SdCmdBlk;\r
1982 SD_STATUS_BLOCK SdStatusBlk;\r
1983 SD_COMMAND_PACKET Packet;\r
1984 EFI_STATUS Status;\r
1985\r
1986 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
1987 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
1988 ZeroMem (&Packet, sizeof (Packet));\r
1989\r
1990 Packet.SdCmdBlk = &SdCmdBlk;\r
1991 Packet.SdStatusBlk = &SdStatusBlk;\r
1992 Packet.Timeout = SD_TIMEOUT;\r
1993\r
1994 SdCmdBlk.CommandIndex = SD_SET_RELATIVE_ADDR;\r
1995 SdCmdBlk.CommandType = SdCommandTypeBcr;\r
1996 SdCmdBlk.ResponseType = SdResponseTypeR6;\r
1997\r
1998 Status = SdPeimExecCmd (Slot, &Packet);\r
1999 if (!EFI_ERROR (Status)) {\r
2000 *Rca = (UINT16)(SdStatusBlk.Resp0 >> 16);\r
2001 }\r
2002\r
2003 return Status;\r
2004}\r
2005\r
2006/**\r
2007 Send command SEND_CSD to the SD device to get the data of the CSD register.\r
2008\r
2009 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
2010\r
2011 @param[in] Slot The slot number of the SD card to send the command to.\r
2012 @param[in] Rca The relative device address of selected device.\r
2013 @param[out] Csd The buffer to store the content of the CSD register.\r
2014 Note the caller should ignore the lowest byte of this\r
2015 buffer as the content of this byte is meaningless even\r
2016 if the operation succeeds.\r
2017\r
2018 @retval EFI_SUCCESS The operation is done correctly.\r
2019 @retval Others The operation fails.\r
2020\r
2021**/\r
2022EFI_STATUS\r
2023SdPeimGetCsd (\r
2024 IN SD_PEIM_HC_SLOT *Slot,\r
2025 IN UINT16 Rca,\r
2026 OUT SD_CSD *Csd\r
2027 )\r
2028{\r
2029 SD_COMMAND_BLOCK SdCmdBlk;\r
2030 SD_STATUS_BLOCK SdStatusBlk;\r
2031 SD_COMMAND_PACKET Packet;\r
2032 EFI_STATUS Status;\r
2033\r
2034 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
2035 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
2036 ZeroMem (&Packet, sizeof (Packet));\r
2037\r
2038 Packet.SdCmdBlk = &SdCmdBlk;\r
2039 Packet.SdStatusBlk = &SdStatusBlk;\r
2040 Packet.Timeout = SD_TIMEOUT;\r
2041\r
2042 SdCmdBlk.CommandIndex = SD_SEND_CSD;\r
2043 SdCmdBlk.CommandType = SdCommandTypeAc;\r
2044 SdCmdBlk.ResponseType = SdResponseTypeR2;\r
2045 SdCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
2046\r
2047 Status = SdPeimExecCmd (Slot, &Packet);\r
2048 if (!EFI_ERROR (Status)) {\r
2049 //\r
2050 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.\r
2051 //\r
2052 CopyMem (((UINT8*)Csd) + 1, &SdStatusBlk.Resp0, sizeof (SD_CSD) - 1);\r
2053 }\r
2054\r
2055 return Status;\r
2056}\r
2057\r
2058/**\r
2059 Send command SELECT_DESELECT_CARD to the SD device to select/deselect it.\r
2060\r
2061 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
2062\r
2063 @param[in] Slot The slot number of the SD card to send the command to.\r
2064 @param[in] Rca The relative device address of selected device.\r
2065\r
2066 @retval EFI_SUCCESS The operation is done correctly.\r
2067 @retval Others The operation fails.\r
2068\r
2069**/\r
2070EFI_STATUS\r
2071SdPeimSelect (\r
2072 IN SD_PEIM_HC_SLOT *Slot,\r
2073 IN UINT16 Rca\r
2074 )\r
2075{\r
2076 SD_COMMAND_BLOCK SdCmdBlk;\r
2077 SD_STATUS_BLOCK SdStatusBlk;\r
2078 SD_COMMAND_PACKET Packet;\r
2079 EFI_STATUS Status;\r
2080\r
2081 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
2082 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
2083 ZeroMem (&Packet, sizeof (Packet));\r
2084\r
2085 Packet.SdCmdBlk = &SdCmdBlk;\r
2086 Packet.SdStatusBlk = &SdStatusBlk;\r
2087 Packet.Timeout = SD_TIMEOUT;\r
2088\r
2089 SdCmdBlk.CommandIndex = SD_SELECT_DESELECT_CARD;\r
2090 SdCmdBlk.CommandType = SdCommandTypeAc;\r
2091 SdCmdBlk.ResponseType = SdResponseTypeR1b;\r
2092 SdCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
2093\r
2094 Status = SdPeimExecCmd (Slot, &Packet);\r
2095\r
2096 return Status;\r
2097}\r
2098\r
2099/**\r
2100 Send command VOLTAGE_SWITCH to the SD device to switch the voltage of the device.\r
2101\r
2102 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
2103\r
2104 @param[in] Slot The slot number of the SD card to send the command to.\r
2105\r
2106 @retval EFI_SUCCESS The operation is done correctly.\r
2107 @retval Others The operation fails.\r
2108\r
2109**/\r
2110EFI_STATUS\r
2111SdPeimVoltageSwitch (\r
2112 IN SD_PEIM_HC_SLOT *Slot\r
2113 )\r
2114{\r
2115 SD_COMMAND_BLOCK SdCmdBlk;\r
2116 SD_STATUS_BLOCK SdStatusBlk;\r
2117 SD_COMMAND_PACKET Packet;\r
2118 EFI_STATUS Status;\r
2119\r
2120 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
2121 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
2122 ZeroMem (&Packet, sizeof (Packet));\r
2123\r
2124 Packet.SdCmdBlk = &SdCmdBlk;\r
2125 Packet.SdStatusBlk = &SdStatusBlk;\r
2126 Packet.Timeout = SD_TIMEOUT;\r
2127\r
2128 SdCmdBlk.CommandIndex = SD_VOLTAGE_SWITCH;\r
2129 SdCmdBlk.CommandType = SdCommandTypeAc;\r
2130 SdCmdBlk.ResponseType = SdResponseTypeR1;\r
2131 SdCmdBlk.CommandArgument = 0;\r
2132\r
2133 Status = SdPeimExecCmd (Slot, &Packet);\r
2134\r
2135 return Status;\r
2136}\r
2137\r
2138/**\r
2139 Send command SET_BUS_WIDTH to the SD device to set the bus width.\r
2140\r
2141 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
2142\r
2143 @param[in] Slot The slot number of the SD card to send the command to.\r
2144 @param[in] Rca The relative device address of addressed device.\r
2145 @param[in] BusWidth The bus width to be set, it could be 1 or 4.\r
2146\r
2147 @retval EFI_SUCCESS The operation is done correctly.\r
2148 @retval Others The operation fails.\r
2149\r
2150**/\r
2151EFI_STATUS\r
2152SdPeimSetBusWidth (\r
2153 IN SD_PEIM_HC_SLOT *Slot,\r
2154 IN UINT16 Rca,\r
2155 IN UINT8 BusWidth\r
2156 )\r
2157{\r
2158 SD_COMMAND_BLOCK SdCmdBlk;\r
2159 SD_STATUS_BLOCK SdStatusBlk;\r
2160 SD_COMMAND_PACKET Packet;\r
2161 EFI_STATUS Status;\r
2162 UINT8 Value;\r
2163\r
2164 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
2165 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
2166 ZeroMem (&Packet, sizeof (Packet));\r
2167\r
2168 Packet.SdCmdBlk = &SdCmdBlk;\r
2169 Packet.SdStatusBlk = &SdStatusBlk;\r
2170 Packet.Timeout = SD_TIMEOUT;\r
2171\r
2172 SdCmdBlk.CommandIndex = SD_APP_CMD;\r
2173 SdCmdBlk.CommandType = SdCommandTypeAc;\r
2174 SdCmdBlk.ResponseType = SdResponseTypeR1;\r
2175 SdCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
2176\r
2177 Status = SdPeimExecCmd (Slot, &Packet);\r
2178 if (EFI_ERROR (Status)) {\r
2179 return Status;\r
2180 }\r
2181\r
2182 SdCmdBlk.CommandIndex = SD_SET_BUS_WIDTH;\r
2183 SdCmdBlk.CommandType = SdCommandTypeAc;\r
2184 SdCmdBlk.ResponseType = SdResponseTypeR1;\r
2185\r
2186 if (BusWidth == 1) {\r
2187 Value = 0;\r
2188 } else if (BusWidth == 4) {\r
2189 Value = 2;\r
2190 } else {\r
2191 return EFI_INVALID_PARAMETER;\r
2192 }\r
2193 SdCmdBlk.CommandArgument = Value & 0x3;\r
2194\r
2195 Status = SdPeimExecCmd (Slot, &Packet);\r
2196\r
2197 return Status;\r
2198}\r
2199\r
2200/**\r
2201 Send command SWITCH_FUNC to the SD device to check switchable function or switch card function.\r
2202\r
2203 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
2204\r
2205 @param[in] Slot The slot number of the SD card to send the command to.\r
2206 @param[in] AccessMode The value for access mode group.\r
2207 @param[in] CommandSystem The value for command set group.\r
2208 @param[in] DriveStrength The value for drive length group.\r
2209 @param[in] PowerLimit The value for power limit group.\r
2210 @param[in] Mode Switch or check function.\r
6263ae93 2211 @param[out] SwitchResp The return switch function status.\r
48555339
FT
2212\r
2213 @retval EFI_SUCCESS The operation is done correctly.\r
2214 @retval Others The operation fails.\r
2215\r
2216**/\r
2217EFI_STATUS\r
2218SdPeimSwitch (\r
6263ae93
FT
2219 IN SD_PEIM_HC_SLOT *Slot,\r
2220 IN UINT8 AccessMode,\r
2221 IN UINT8 CommandSystem,\r
2222 IN UINT8 DriveStrength,\r
2223 IN UINT8 PowerLimit,\r
2224 IN BOOLEAN Mode,\r
2225 OUT UINT8 *SwitchResp\r
48555339
FT
2226 )\r
2227{\r
2228 SD_COMMAND_BLOCK SdCmdBlk;\r
2229 SD_STATUS_BLOCK SdStatusBlk;\r
2230 SD_COMMAND_PACKET Packet;\r
2231 EFI_STATUS Status;\r
2232 UINT32 ModeValue;\r
48555339
FT
2233\r
2234 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
2235 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
2236 ZeroMem (&Packet, sizeof (Packet));\r
2237\r
2238 Packet.SdCmdBlk = &SdCmdBlk;\r
2239 Packet.SdStatusBlk = &SdStatusBlk;\r
2240 Packet.Timeout = SD_TIMEOUT;\r
2241\r
2242 SdCmdBlk.CommandIndex = SD_SWITCH_FUNC;\r
2243 SdCmdBlk.CommandType = SdCommandTypeAdtc;\r
2244 SdCmdBlk.ResponseType = SdResponseTypeR1;\r
2245\r
2246 ModeValue = Mode ? BIT31 : 0;\r
2247 SdCmdBlk.CommandArgument = (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \\r
2248 ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \\r
2249 ModeValue;\r
6263ae93
FT
2250 Packet.InDataBuffer = SwitchResp;\r
2251 Packet.InTransferLength = 64;\r
48555339
FT
2252\r
2253 Status = SdPeimExecCmd (Slot, &Packet);\r
2254\r
2255 return Status;\r
2256}\r
2257\r
2258/**\r
2259 Send command SEND_STATUS to the addressed SD device to get its status register.\r
2260\r
2261 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
2262\r
2263 @param[in] Slot The slot number of the SD card to send the command to.\r
2264 @param[in] Rca The relative device address of addressed device.\r
2265 @param[out] DevStatus The returned device status.\r
2266\r
2267 @retval EFI_SUCCESS The operation is done correctly.\r
2268 @retval Others The operation fails.\r
2269\r
2270**/\r
2271EFI_STATUS\r
2272SdPeimSendStatus (\r
2273 IN SD_PEIM_HC_SLOT *Slot,\r
2274 IN UINT16 Rca,\r
2275 OUT UINT32 *DevStatus\r
2276 )\r
2277{\r
2278 SD_COMMAND_BLOCK SdCmdBlk;\r
2279 SD_STATUS_BLOCK SdStatusBlk;\r
2280 SD_COMMAND_PACKET Packet;\r
2281 EFI_STATUS Status;\r
2282\r
2283 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
2284 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
2285 ZeroMem (&Packet, sizeof (Packet));\r
2286\r
2287 Packet.SdCmdBlk = &SdCmdBlk;\r
2288 Packet.SdStatusBlk = &SdStatusBlk;\r
2289 Packet.Timeout = SD_TIMEOUT;\r
2290\r
2291 SdCmdBlk.CommandIndex = SD_SEND_STATUS;\r
2292 SdCmdBlk.CommandType = SdCommandTypeAc;\r
2293 SdCmdBlk.ResponseType = SdResponseTypeR1;\r
2294 SdCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
2295\r
2296 Status = SdPeimExecCmd (Slot, &Packet);\r
2297 if (!EFI_ERROR (Status)) {\r
2298 *DevStatus = SdStatusBlk.Resp0;\r
2299 }\r
2300\r
2301 return Status;\r
2302}\r
2303\r
2304/**\r
2305 Send command READ_SINGLE_BLOCK/WRITE_SINGLE_BLOCK to the addressed SD device\r
2306 to read/write the specified number of blocks.\r
2307\r
2308 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
2309\r
2310 @param[in] Slot The slot number of the SD card to send the command to.\r
2311 @param[in] Lba The logical block address of starting access.\r
2312 @param[in] BlockSize The block size of specified SD device partition.\r
2313 @param[in] Buffer The pointer to the transfer buffer.\r
2314 @param[in] BufferSize The size of transfer buffer.\r
2315 @param[in] IsRead Boolean to show the operation direction.\r
2316\r
2317 @retval EFI_SUCCESS The operation is done correctly.\r
2318 @retval Others The operation fails.\r
2319\r
2320**/\r
2321EFI_STATUS\r
2322SdPeimRwSingleBlock (\r
2323 IN SD_PEIM_HC_SLOT *Slot,\r
2324 IN EFI_LBA Lba,\r
2325 IN UINT32 BlockSize,\r
2326 IN VOID *Buffer,\r
2327 IN UINTN BufferSize,\r
2328 IN BOOLEAN IsRead\r
2329 )\r
2330{\r
2331 SD_COMMAND_BLOCK SdCmdBlk;\r
2332 SD_STATUS_BLOCK SdStatusBlk;\r
2333 SD_COMMAND_PACKET Packet;\r
2334 EFI_STATUS Status;\r
2335\r
2336 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
2337 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
2338 ZeroMem (&Packet, sizeof (Packet));\r
2339\r
2340 Packet.SdCmdBlk = &SdCmdBlk;\r
2341 Packet.SdStatusBlk = &SdStatusBlk;\r
2342 //\r
2343 // Calculate timeout value through the below formula.\r
2344 // Timeout = (transfer size) / (2MB/s).\r
2345 // Taking 2MB/s as divisor is because it's the lowest\r
2346 // transfer speed of class 2.\r
2347 //\r
2348 Packet.Timeout = (BufferSize / (2 * 1024 * 1024) + 1) * 1000 * 1000;;\r
2349\r
2350 if (IsRead) {\r
2351 Packet.InDataBuffer = Buffer;\r
2352 Packet.InTransferLength = (UINT32)BufferSize;\r
2353\r
2354 SdCmdBlk.CommandIndex = SD_READ_SINGLE_BLOCK;\r
2355 SdCmdBlk.CommandType = SdCommandTypeAdtc;\r
2356 SdCmdBlk.ResponseType = SdResponseTypeR1;\r
2357 } else {\r
2358 Packet.OutDataBuffer = Buffer;\r
2359 Packet.OutTransferLength = (UINT32)BufferSize;\r
2360\r
2361 SdCmdBlk.CommandIndex = SD_WRITE_SINGLE_BLOCK;\r
2362 SdCmdBlk.CommandType = SdCommandTypeAdtc;\r
2363 SdCmdBlk.ResponseType = SdResponseTypeR1;\r
2364 }\r
2365\r
2366 if (Slot->SectorAddressing) {\r
2367 SdCmdBlk.CommandArgument = (UINT32)Lba;\r
2368 } else {\r
2369 SdCmdBlk.CommandArgument = (UINT32)MultU64x32 (Lba, BlockSize);\r
2370 }\r
2371\r
2372 Status = SdPeimExecCmd (Slot, &Packet);\r
2373\r
2374 return Status;\r
2375}\r
2376\r
2377/**\r
2378 Send command READ_MULTIPLE_BLOCK/WRITE_MULTIPLE_BLOCK to the addressed SD device\r
2379 to read/write the specified number of blocks.\r
2380\r
2381 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
2382\r
2383 @param[in] Slot The slot number of the SD card to send the command to.\r
2384 @param[in] Lba The logical block address of starting access.\r
2385 @param[in] BlockSize The block size of specified SD device partition.\r
2386 @param[in] Buffer The pointer to the transfer buffer.\r
2387 @param[in] BufferSize The size of transfer buffer.\r
2388 @param[in] IsRead Boolean to show the operation direction.\r
2389\r
2390 @retval EFI_SUCCESS The operation is done correctly.\r
2391 @retval Others The operation fails.\r
2392\r
2393**/\r
2394EFI_STATUS\r
2395SdPeimRwMultiBlocks (\r
2396 IN SD_PEIM_HC_SLOT *Slot,\r
2397 IN EFI_LBA Lba,\r
2398 IN UINT32 BlockSize,\r
2399 IN VOID *Buffer,\r
2400 IN UINTN BufferSize,\r
2401 IN BOOLEAN IsRead\r
2402 )\r
2403{\r
2404 SD_COMMAND_BLOCK SdCmdBlk;\r
2405 SD_STATUS_BLOCK SdStatusBlk;\r
2406 SD_COMMAND_PACKET Packet;\r
2407 EFI_STATUS Status;\r
2408\r
2409 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
2410 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
2411 ZeroMem (&Packet, sizeof (Packet));\r
2412\r
2413 Packet.SdCmdBlk = &SdCmdBlk;\r
2414 Packet.SdStatusBlk = &SdStatusBlk;\r
2415 //\r
2416 // Calculate timeout value through the below formula.\r
2417 // Timeout = (transfer size) / (2MB/s).\r
2418 // Taking 2MB/s as divisor is because it's the lowest\r
2419 // transfer speed of class 2.\r
2420 //\r
2421 Packet.Timeout = (BufferSize / (2 * 1024 * 1024) + 1) * 1000 * 1000;;\r
2422\r
2423 if (IsRead) {\r
2424 Packet.InDataBuffer = Buffer;\r
2425 Packet.InTransferLength = (UINT32)BufferSize;\r
2426\r
2427 SdCmdBlk.CommandIndex = SD_READ_MULTIPLE_BLOCK;\r
2428 SdCmdBlk.CommandType = SdCommandTypeAdtc;\r
2429 SdCmdBlk.ResponseType = SdResponseTypeR1;\r
2430 } else {\r
2431 Packet.OutDataBuffer = Buffer;\r
2432 Packet.OutTransferLength = (UINT32)BufferSize;\r
2433\r
2434 SdCmdBlk.CommandIndex = SD_WRITE_MULTIPLE_BLOCK;\r
2435 SdCmdBlk.CommandType = SdCommandTypeAdtc;\r
2436 SdCmdBlk.ResponseType = SdResponseTypeR1;\r
2437 }\r
2438\r
2439 if (Slot->SectorAddressing) {\r
2440 SdCmdBlk.CommandArgument = (UINT32)Lba;\r
2441 } else {\r
2442 SdCmdBlk.CommandArgument = (UINT32)MultU64x32 (Lba, BlockSize);\r
2443 }\r
2444\r
2445 Status = SdPeimExecCmd (Slot, &Packet);\r
2446\r
2447 return Status;\r
2448}\r
2449\r
2450/**\r
2451 Send command SEND_TUNING_BLOCK to the SD device for SDR104/SDR50 optimal sampling point\r
2452 detection.\r
2453\r
2454 It may be sent up to 40 times until the host finishes the tuning procedure.\r
2455\r
2456 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
2457\r
2458 @param[in] Slot The slot number of the SD card to send the command to.\r
2459\r
2460 @retval EFI_SUCCESS The operation is done correctly.\r
2461 @retval Others The operation fails.\r
2462\r
2463**/\r
2464EFI_STATUS\r
2465SdPeimSendTuningBlk (\r
2466 IN SD_PEIM_HC_SLOT *Slot\r
2467 )\r
2468{\r
2469 SD_COMMAND_BLOCK SdCmdBlk;\r
2470 SD_STATUS_BLOCK SdStatusBlk;\r
2471 SD_COMMAND_PACKET Packet;\r
2472 EFI_STATUS Status;\r
2473 UINT8 TuningBlock[64];\r
2474\r
2475 ZeroMem (&SdCmdBlk, sizeof (SdCmdBlk));\r
2476 ZeroMem (&SdStatusBlk, sizeof (SdStatusBlk));\r
2477 ZeroMem (&Packet, sizeof (Packet));\r
2478\r
2479 Packet.SdCmdBlk = &SdCmdBlk;\r
2480 Packet.SdStatusBlk = &SdStatusBlk;\r
2481 Packet.Timeout = SD_TIMEOUT;\r
2482\r
2483 SdCmdBlk.CommandIndex = SD_SEND_TUNING_BLOCK;\r
2484 SdCmdBlk.CommandType = SdCommandTypeAdtc;\r
2485 SdCmdBlk.ResponseType = SdResponseTypeR1;\r
2486 SdCmdBlk.CommandArgument = 0;\r
2487\r
2488 Packet.InDataBuffer = TuningBlock;\r
2489 Packet.InTransferLength = sizeof (TuningBlock);\r
2490\r
2491 Status = SdPeimExecCmd (Slot, &Packet);\r
2492\r
2493 return Status;\r
2494}\r
2495\r
2496/**\r
2497 Tunning the sampling point of SDR104 or SDR50 bus speed mode.\r
2498\r
2499 Command SD_SEND_TUNING_BLOCK may be sent up to 40 times until the host finishes the\r
2500 tuning procedure.\r
2501\r
2502 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and SD Host Controller\r
2503 Simplified Spec 3.0 Figure 2-29 for details.\r
2504\r
2505 @param[in] Slot The slot number of the SD card to send the command to.\r
2506\r
2507 @retval EFI_SUCCESS The operation is done correctly.\r
2508 @retval Others The operation fails.\r
2509\r
2510**/\r
2511EFI_STATUS\r
2512SdPeimTuningClock (\r
2513 IN SD_PEIM_HC_SLOT *Slot\r
2514 )\r
2515{\r
2516 EFI_STATUS Status;\r
2517 UINT8 HostCtrl2;\r
2518 UINT8 Retry;\r
2519\r
2520 //\r
2521 // Notify the host that the sampling clock tuning procedure starts.\r
2522 //\r
2523 HostCtrl2 = BIT6;\r
2524 Status = SdPeimHcOrMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
2525 if (EFI_ERROR (Status)) {\r
2526 return Status;\r
2527 }\r
2528 //\r
2529 // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.\r
2530 //\r
2531 Retry = 0;\r
2532 do {\r
2533 Status = SdPeimSendTuningBlk (Slot);\r
2534 if (EFI_ERROR (Status)) {\r
2535 return Status;\r
2536 }\r
2537\r
2538 Status = SdPeimHcRwMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);\r
2539 if (EFI_ERROR (Status)) {\r
2540 return Status;\r
2541 }\r
2542\r
8c983d3e 2543 if ((HostCtrl2 & (BIT6 | BIT7)) == 0) {\r
48555339
FT
2544 break;\r
2545 }\r
8c983d3e
FT
2546\r
2547 if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {\r
2548 return EFI_SUCCESS;\r
2549 }\r
48555339
FT
2550 } while (++Retry < 40);\r
2551\r
8c983d3e
FT
2552 DEBUG ((EFI_D_ERROR, "SdPeimTuningClock: Send tuning block fails at %d times with HostCtrl2 %02x\n", Retry, HostCtrl2));\r
2553 //\r
2554 // Abort the tuning procedure and reset the tuning circuit.\r
2555 //\r
2556 HostCtrl2 = (UINT8)~(BIT6 | BIT7);\r
2557 Status = SdPeimHcAndMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
2558 if (EFI_ERROR (Status)) {\r
2559 return Status;\r
48555339 2560 }\r
8c983d3e 2561 return EFI_DEVICE_ERROR;\r
48555339
FT
2562}\r
2563\r
2564/**\r
2565 Switch the bus width to specified width.\r
2566\r
2567 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and\r
2568 SD Host Controller Simplified Spec 3.0 section Figure 3-7 for details.\r
2569\r
2570 @param[in] Slot The slot number of the SD card to send the command to.\r
2571 @param[in] Rca The relative device address to be assigned.\r
2572 @param[in] BusWidth The bus width to be set, it could be 4 or 8.\r
2573\r
2574 @retval EFI_SUCCESS The operation is done correctly.\r
2575 @retval Others The operation fails.\r
2576\r
2577**/\r
2578EFI_STATUS\r
2579SdPeimSwitchBusWidth (\r
2580 IN SD_PEIM_HC_SLOT *Slot,\r
2581 IN UINT16 Rca,\r
2582 IN UINT8 BusWidth\r
2583 )\r
2584{\r
2585 EFI_STATUS Status;\r
2586 UINT32 DevStatus;\r
2587\r
2588 Status = SdPeimSetBusWidth (Slot, Rca, BusWidth);\r
2589 if (EFI_ERROR (Status)) {\r
2590 return Status;\r
2591 }\r
2592\r
2593 Status = SdPeimSendStatus (Slot, Rca, &DevStatus);\r
2594 if (EFI_ERROR (Status)) {\r
2595 return Status;\r
2596 }\r
2597 //\r
2598 // Check the switch operation is really successful or not.\r
2599 //\r
2600 if ((DevStatus >> 16) != 0) {\r
2601 return EFI_DEVICE_ERROR;\r
2602 }\r
2603\r
2604 Status = SdPeimHcSetBusWidth (Slot->SdHcBase, BusWidth);\r
2605\r
2606 return Status;\r
2607}\r
2608\r
2609/**\r
2610 Switch the high speed timing according to request.\r
2611\r
2612 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and\r
2613 SD Host Controller Simplified Spec 3.0 section Figure 2-29 for details.\r
2614\r
2615 @param[in] Slot The slot number of the SD card to send the command to.\r
2616 @param[in] Rca The relative device address to be assigned.\r
2617 @param[in] S18a The boolean to show if it's a UHS-I SD card.\r
2618\r
2619 @retval EFI_SUCCESS The operation is done correctly.\r
2620 @retval Others The operation fails.\r
2621\r
2622**/\r
2623EFI_STATUS\r
2624SdPeimSetBusMode (\r
2625 IN SD_PEIM_HC_SLOT *Slot,\r
2626 IN UINT16 Rca,\r
2627 IN BOOLEAN S18a\r
2628 )\r
2629{\r
2630 EFI_STATUS Status;\r
2631 SD_HC_SLOT_CAP Capability;\r
2632 UINT32 ClockFreq;\r
2633 UINT8 BusWidth;\r
2634 UINT8 AccessMode;\r
2635 UINT8 HostCtrl1;\r
2636 UINT8 HostCtrl2;\r
6263ae93 2637 UINT8 SwitchResp[64];\r
48555339
FT
2638\r
2639 Status = SdPeimGetCsd (Slot, Rca, &Slot->Csd);\r
2640 if (EFI_ERROR (Status)) {\r
2641 DEBUG ((EFI_D_ERROR, "SdPeimSetBusMode: SdPeimGetCsd fails with %r\n", Status));\r
2642 return Status;\r
2643 }\r
2644\r
2645 Status = SdPeimHcGetCapability (Slot->SdHcBase, &Capability);\r
2646 if (EFI_ERROR (Status)) {\r
2647 return Status;\r
2648 }\r
2649\r
2650 Status = SdPeimSelect (Slot, Rca);\r
2651 if (EFI_ERROR (Status)) {\r
2652 DEBUG ((EFI_D_ERROR, "SdPeimSetBusMode: SdPeimSelect fails with %r\n", Status));\r
2653 return Status;\r
2654 }\r
2655\r
2656 BusWidth = 4;\r
2657 Status = SdPeimSwitchBusWidth (Slot, Rca, BusWidth);\r
2658 if (EFI_ERROR (Status)) {\r
2659 DEBUG ((EFI_D_ERROR, "SdPeimSetBusMode: SdPeimSwitchBusWidth fails with %r\n", Status));\r
2660 return Status;\r
2661 }\r
2662\r
2663 //\r
6263ae93
FT
2664 // Get the supported bus speed from SWITCH cmd return data group #1.\r
2665 //\r
a00df2e5 2666 ZeroMem (SwitchResp, sizeof (SwitchResp));\r
6263ae93
FT
2667 Status = SdPeimSwitch (Slot, 0xF, 0xF, 0xF, 0xF, FALSE, SwitchResp);\r
2668 if (EFI_ERROR (Status)) {\r
2669 return Status;\r
2670 }\r
2671 //\r
2672 // Calculate supported bus speed/bus width/clock frequency by host and device capability.\r
48555339
FT
2673 //\r
2674 ClockFreq = 0;\r
6263ae93 2675 if (S18a && (Capability.Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {\r
48555339
FT
2676 ClockFreq = 208;\r
2677 AccessMode = 3;\r
6263ae93 2678 } else if (S18a && (Capability.Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {\r
48555339
FT
2679 ClockFreq = 100;\r
2680 AccessMode = 2;\r
6263ae93 2681 } else if (S18a && (Capability.Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {\r
48555339
FT
2682 ClockFreq = 50;\r
2683 AccessMode = 4;\r
6263ae93 2684 } else if ((SwitchResp[13] & BIT1) != 0) {\r
48555339
FT
2685 ClockFreq = 50;\r
2686 AccessMode = 1;\r
6263ae93
FT
2687 } else {\r
2688 ClockFreq = 25;\r
2689 AccessMode = 0;\r
48555339
FT
2690 }\r
2691\r
6263ae93 2692 DEBUG ((EFI_D_INFO, "SdPeimSetBusMode: AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));\r
48555339 2693\r
6263ae93 2694 Status = SdPeimSwitch (Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);\r
48555339
FT
2695 if (EFI_ERROR (Status)) {\r
2696 DEBUG ((EFI_D_ERROR, "SdPeimSetBusMode: SdPeimSwitch fails with %r\n", Status));\r
2697 return Status;\r
2698 }\r
2699\r
6263ae93
FT
2700 if ((SwitchResp[16] & 0xF) != AccessMode) {\r
2701 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
2702 return EFI_DEVICE_ERROR;\r
2703 }\r
48555339
FT
2704 //\r
2705 // Set to Hight Speed timing\r
2706 //\r
2707 if (AccessMode == 1) {\r
2708 HostCtrl1 = BIT2;\r
2709 Status = SdPeimHcOrMmio (Slot->SdHcBase + SD_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
2710 if (EFI_ERROR (Status)) {\r
2711 return Status;\r
2712 }\r
2713 }\r
2714\r
2715 HostCtrl2 = (UINT8)~0x7;\r
2716 Status = SdPeimHcAndMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
2717 if (EFI_ERROR (Status)) {\r
2718 return Status;\r
2719 }\r
2720 HostCtrl2 = AccessMode;\r
2721 Status = SdPeimHcOrMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
2722 if (EFI_ERROR (Status)) {\r
2723 return Status;\r
2724 }\r
2725\r
2726 Status = SdPeimHcClockSupply (Slot->SdHcBase, ClockFreq * 1000);\r
2727 if (EFI_ERROR (Status)) {\r
2728 DEBUG ((EFI_D_ERROR, "SdPeimSetBusMode: SdPeimHcClockSupply %r\n", Status));\r
2729 return Status;\r
2730 }\r
2731\r
2732 if ((AccessMode == 3) || ((AccessMode == 2) && (Capability.TuningSDR50 != 0))) {\r
2733 Status = SdPeimTuningClock (Slot);\r
2734 if (EFI_ERROR (Status)) {\r
2735 DEBUG ((EFI_D_ERROR, "SdPeimSetBusMode: SdPeimTuningClock fails with %r\n", Status));\r
2736 return Status;\r
2737 }\r
2738 }\r
2739\r
2740 DEBUG ((EFI_D_INFO, "SdPeimSetBusMode: SdPeimSetBusMode %r\n", Status));\r
2741\r
2742 return Status;\r
2743}\r
2744\r
2745/**\r
2746 Execute SD device identification procedure.\r
2747\r
2748 Refer to SD Physical Layer Simplified Spec 4.1 Section 3.6 for details.\r
2749\r
2750 @param[in] Slot The slot number of the SD card to send the command to.\r
2751\r
2752 @retval EFI_SUCCESS There is a SD card.\r
2753 @retval Others There is not a SD card.\r
2754\r
2755**/\r
2756EFI_STATUS\r
2757SdPeimIdentification (\r
2758 IN SD_PEIM_HC_SLOT *Slot\r
2759 )\r
2760{\r
2761 EFI_STATUS Status;\r
2762 UINT32 Ocr;\r
2763 UINT16 Rca;\r
2764 BOOLEAN Xpc;\r
2765 BOOLEAN S18r;\r
2766 UINT64 MaxCurrent;\r
2767 UINT64 Current;\r
2768 UINT16 ControllerVer;\r
2769 UINT8 PowerCtrl;\r
2770 UINT32 PresentState;\r
2771 UINT8 HostCtrl2;\r
2772 SD_HC_SLOT_CAP Capability;\r
ec86d285 2773 UINTN Retry;\r
48555339
FT
2774 //\r
2775 // 1. Send Cmd0 to the device\r
2776 //\r
2777 Status = SdPeimReset (Slot);\r
2778 if (EFI_ERROR (Status)) {\r
2779 DEBUG ((EFI_D_ERROR, "SdPeimIdentification: Executing Cmd0 fails with %r\n", Status));\r
2780 return Status;\r
2781 }\r
2782 //\r
2783 // 2. Send Cmd8 to the device\r
2784 //\r
2785 Status = SdPeimVoltageCheck (Slot, 0x1, 0xFF);\r
2786 if (EFI_ERROR (Status)) {\r
2787 DEBUG ((EFI_D_ERROR, "SdPeimIdentification: Executing Cmd8 fails with %r\n", Status));\r
2788 return Status;\r
2789 }\r
2790 //\r
2791 // 3. Send SDIO Cmd5 to the device to the SDIO device OCR register.\r
2792 //\r
2793 Status = SdioSendOpCond (Slot, 0, FALSE);\r
2794 if (!EFI_ERROR (Status)) {\r
2795 DEBUG ((EFI_D_ERROR, "SdPeimIdentification: Found SDIO device, ignore it as we don't support\n"));\r
2796 return EFI_DEVICE_ERROR;\r
2797 }\r
2798 //\r
2799 // 4. Send Acmd41 with voltage window 0 to the device\r
2800 //\r
2801 Status = SdPeimSendOpCond (Slot, 0, 0, FALSE, FALSE, FALSE, &Ocr);\r
2802 if (EFI_ERROR (Status)) {\r
2803 DEBUG ((EFI_D_ERROR, "SdPeimIdentification: Executing SdPeimSendOpCond fails with %r\n", Status));\r
2804 return EFI_DEVICE_ERROR;\r
2805 }\r
2806\r
2807 Status = SdPeimHcGetCapability (Slot->SdHcBase, &Capability);\r
2808 if (EFI_ERROR (Status)) {\r
2809 return Status;\r
2810 }\r
2811\r
2812 Status = SdPeimHcRwMmio (Slot->SdHcBase + SD_HC_MAX_CURRENT_CAP, TRUE, sizeof (Current), &Current);\r
2813 if (EFI_ERROR (Status)) {\r
2814 return Status;\r
2815 }\r
2816\r
2817 if (Capability.Voltage33 != 0) {\r
2818 //\r
2819 // Support 3.3V\r
2820 //\r
2821 MaxCurrent = ((UINT32)Current & 0xFF) * 4;\r
2822 } else if (Capability.Voltage30 != 0) {\r
2823 //\r
2824 // Support 3.0V\r
2825 //\r
2826 MaxCurrent = (((UINT32)Current >> 8) & 0xFF) * 4;\r
2827 } else if (Capability.Voltage18 != 0) {\r
2828 //\r
2829 // Support 1.8V\r
2830 //\r
2831 MaxCurrent = (((UINT32)Current >> 16) & 0xFF) * 4;\r
2832 } else {\r
2833 ASSERT (FALSE);\r
2834 return EFI_DEVICE_ERROR;\r
2835 }\r
2836\r
2837 if (MaxCurrent >= 150) {\r
2838 Xpc = TRUE;\r
2839 } else {\r
2840 Xpc = FALSE;\r
2841 }\r
2842\r
2843 Status = SdPeimHcRwMmio (Slot->SdHcBase + SD_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);\r
2844 if (EFI_ERROR (Status)) {\r
2845 return Status;\r
2846 }\r
2847\r
2848 if ((ControllerVer & 0xFF) == 2) {\r
2849 S18r = TRUE;\r
2850 } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {\r
2851 S18r = FALSE;\r
2852 } else {\r
2853 ASSERT (FALSE);\r
2854 return EFI_UNSUPPORTED;\r
2855 }\r
2856 //\r
2857 // 5. Repeatly send Acmd41 with supply voltage window to the device.\r
2858 // Note here we only support the cards complied with SD physical\r
2859 // layer simplified spec version 2.0 and version 3.0 and above.\r
2860 //\r
ec86d285
FT
2861 Ocr = 0;\r
2862 Retry = 0;\r
48555339
FT
2863 do {\r
2864 Status = SdPeimSendOpCond (Slot, 0, Ocr, S18r, Xpc, TRUE, &Ocr);\r
2865 if (EFI_ERROR (Status)) {\r
2866 DEBUG ((EFI_D_ERROR, "SdPeimIdentification: SdPeimSendOpCond fails with %r Ocr %x, S18r %x, Xpc %x\n", Status, Ocr, S18r, Xpc));\r
2867 return EFI_DEVICE_ERROR;\r
2868 }\r
ec86d285
FT
2869\r
2870 if (Retry++ == 100) {\r
2871 DEBUG ((EFI_D_ERROR, "SdPeimIdentification: SdPeimSendOpCond fails too many times\n"));\r
2872 return EFI_DEVICE_ERROR;\r
2873 }\r
2874 MicroSecondDelay (10 * 1000);\r
48555339
FT
2875 } while ((Ocr & BIT31) == 0);\r
2876\r
2877 //\r
2878 // 6. If the S18a bit is set and the Host Controller supports 1.8V signaling\r
2879 // (One of support bits is set to 1: SDR50, SDR104 or DDR50 in the\r
2880 // Capabilities register), switch its voltage to 1.8V.\r
2881 //\r
2882 if ((Capability.Sdr50 != 0 ||\r
2883 Capability.Sdr104 != 0 ||\r
2884 Capability.Ddr50 != 0) &&\r
2885 ((Ocr & BIT24) != 0)) {\r
2886 Status = SdPeimVoltageSwitch (Slot);\r
2887 if (EFI_ERROR (Status)) {\r
2888 DEBUG ((EFI_D_ERROR, "SdPeimIdentification: Executing SdPeimVoltageSwitch fails with %r\n", Status));\r
2889 Status = EFI_DEVICE_ERROR;\r
2890 goto Error;\r
2891 } else {\r
2892 Status = SdPeimHcStopClock (Slot->SdHcBase);\r
2893 if (EFI_ERROR (Status)) {\r
2894 Status = EFI_DEVICE_ERROR;\r
2895 goto Error;\r
2896 }\r
2897\r
2898 SdPeimHcRwMmio (Slot->SdHcBase + SD_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);\r
2899 if (((PresentState >> 20) & 0xF) != 0) {\r
2900 DEBUG ((EFI_D_ERROR, "SdPeimIdentification: SwitchVoltage fails with PresentState = 0x%x\n", PresentState));\r
2901 Status = EFI_DEVICE_ERROR;\r
2902 goto Error;\r
2903 }\r
2904 HostCtrl2 = BIT3;\r
2905 SdPeimHcOrMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
2906\r
2907 MicroSecondDelay (5000);\r
2908\r
2909 SdPeimHcRwMmio (Slot->SdHcBase + SD_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);\r
2910 if ((HostCtrl2 & BIT3) == 0) {\r
2911 DEBUG ((EFI_D_ERROR, "SdPeimIdentification: SwitchVoltage fails with HostCtrl2 = 0x%x\n", HostCtrl2));\r
2912 Status = EFI_DEVICE_ERROR;\r
2913 goto Error;\r
2914 }\r
2915\r
2916 SdPeimHcInitClockFreq (Slot->SdHcBase);\r
2917\r
2a8b78cf 2918 MicroSecondDelay (1000);\r
48555339
FT
2919\r
2920 SdPeimHcRwMmio (Slot->SdHcBase + SD_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);\r
2921 if (((PresentState >> 20) & 0xF) != 0xF) {\r
2922 DEBUG ((EFI_D_ERROR, "SdPeimIdentification: SwitchVoltage fails with PresentState = 0x%x, It should be 0xF\n", PresentState));\r
2923 Status = EFI_DEVICE_ERROR;\r
2924 goto Error;\r
2925 }\r
2926 }\r
2927 DEBUG ((EFI_D_INFO, "SdPeimIdentification: Switch to 1.8v signal voltage success\n"));\r
2928 }\r
2929\r
2930 Status = SdPeimAllSendCid (Slot);\r
2931 if (EFI_ERROR (Status)) {\r
2932 DEBUG ((EFI_D_ERROR, "SdPeimIdentification: Executing SdPeimAllSendCid fails with %r\n", Status));\r
2933 return Status;\r
2934 }\r
2935\r
2936 Status = SdPeimSetRca (Slot, &Rca);\r
2937 if (EFI_ERROR (Status)) {\r
2938 DEBUG ((EFI_D_ERROR, "SdPeimIdentification: Executing SdPeimSetRca fails with %r\n", Status));\r
2939 return Status;\r
2940 }\r
2941 //\r
2942 // Enter Data Tranfer Mode.\r
2943 //\r
2944 DEBUG ((EFI_D_INFO, "Found a SD device at slot [%d]\n", Slot));\r
2945\r
2946 Status = SdPeimSetBusMode (Slot, Rca, ((Ocr & BIT24) != 0));\r
2947\r
2948 return Status;\r
2949\r
2950Error:\r
2951 //\r
2952 // Set SD Bus Power = 0\r
2953 //\r
2954 PowerCtrl = (UINT8)~BIT0;\r
2955 Status = SdPeimHcAndMmio (Slot->SdHcBase + SD_HC_POWER_CTRL, sizeof (PowerCtrl), &PowerCtrl);\r
2956 return EFI_DEVICE_ERROR;\r
2957}\r