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