]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDTransfer.c
QuarkSocPkg: Add new package for Quark SoC X1000
[mirror_edk2.git] / QuarkSocPkg / QuarkSouthCluster / Sdio / Dxe / SDMediaDeviceDxe / MMCSDTransfer.c
CommitLineData
9b6bbcdb
MK
1/** @file\r
2\r
3MMC/SD transfer specific functions\r
4\r
5Copyright (c) 2013-2015 Intel Corporation.\r
6\r
7This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "SDMediaDevice.h"\r
18\r
19/**\r
20 Check card status, print the debug info and check the error\r
21\r
22 @param Status Status got from card status register.\r
23\r
24 @retval EFI_SUCCESS\r
25 @retval EFI_DEVICE_ERROR\r
26\r
27**/\r
28EFI_STATUS\r
29CheckCardStatus (\r
30 IN UINT32 Status\r
31 )\r
32{\r
33 CARD_STATUS *CardStatus;\r
34 CardStatus = (CARD_STATUS*)(&Status);\r
35\r
36 if (CardStatus->ADDRESS_OUT_OF_RANGE) {\r
37 DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_OUT_OF_RANGE\n"));\r
38 }\r
39\r
40 if (CardStatus->ADDRESS_MISALIGN) {\r
41 DEBUG ((EFI_D_ERROR, "CardStatus: ADDRESS_MISALIGN\n"));\r
42 }\r
43\r
44 if (CardStatus->BLOCK_LEN_ERROR) {\r
45 DEBUG ((EFI_D_ERROR, "CardStatus: BLOCK_LEN_ERROR\n"));\r
46 }\r
47\r
48 if (CardStatus->ERASE_SEQ_ERROR) {\r
49 DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_SEQ_ERROR\n"));\r
50 }\r
51\r
52 if (CardStatus->ERASE_PARAM) {\r
53 DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_PARAM\n"));\r
54 }\r
55\r
56 if (CardStatus->WP_VIOLATION) {\r
57 DEBUG ((EFI_D_ERROR, "CardStatus: WP_VIOLATION\n"));\r
58 }\r
59\r
60 if (CardStatus->CARD_IS_LOCKED) {\r
61 DEBUG ((EFI_D_ERROR, "CardStatus: CARD_IS_LOCKED\n"));\r
62 }\r
63\r
64 if (CardStatus->LOCK_UNLOCK_FAILED) {\r
65 DEBUG ((EFI_D_ERROR, "CardStatus: LOCK_UNLOCK_FAILED\n"));\r
66 }\r
67\r
68 if (CardStatus->COM_CRC_ERROR) {\r
69 DEBUG ((EFI_D_ERROR, "CardStatus: COM_CRC_ERROR\n"));\r
70 }\r
71\r
72 if (CardStatus->ILLEGAL_COMMAND) {\r
73 DEBUG ((EFI_D_ERROR, "CardStatus: ILLEGAL_COMMAND\n"));\r
74 }\r
75\r
76 if (CardStatus->CARD_ECC_FAILED) {\r
77 DEBUG ((EFI_D_ERROR, "CardStatus: CARD_ECC_FAILED\n"));\r
78 }\r
79\r
80 if (CardStatus->CC_ERROR) {\r
81 DEBUG ((EFI_D_ERROR, "CardStatus: CC_ERROR\n"));\r
82 }\r
83\r
84 if (CardStatus->ERROR) {\r
85 DEBUG ((EFI_D_ERROR, "CardStatus: ERROR\n"));\r
86 }\r
87\r
88 if (CardStatus->UNDERRUN) {\r
89 DEBUG ((EFI_D_ERROR, "CardStatus: UNDERRUN\n"));\r
90 }\r
91\r
92 if (CardStatus->OVERRUN) {\r
93 DEBUG ((EFI_D_ERROR, "CardStatus: OVERRUN\n"));\r
94 }\r
95\r
96 if (CardStatus->CID_CSD_OVERWRITE) {\r
97 DEBUG ((EFI_D_ERROR, "CardStatus: CID_CSD_OVERWRITE\n"));\r
98 }\r
99\r
100 if (CardStatus->WP_ERASE_SKIP) {\r
101 DEBUG ((EFI_D_ERROR, "CardStatus: WP_ERASE_SKIP\n"));\r
102 }\r
103\r
104 if (CardStatus->ERASE_RESET) {\r
105 DEBUG ((EFI_D_ERROR, "CardStatus: ERASE_RESET\n"));\r
106 }\r
107\r
108 if (CardStatus->SWITCH_ERROR) {\r
109 DEBUG ((EFI_D_ERROR, "CardStatus: SWITCH_ERROR\n"));\r
110 }\r
111\r
112 if ((Status & 0xFCFFA080) != 0) {\r
113 return EFI_DEVICE_ERROR;\r
114 }\r
115\r
116 return EFI_SUCCESS;\r
117}\r
118\r
119/**\r
120 Send command by using Host IO protocol\r
121\r
122 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.\r
123 @param CommandIndex The command index to set the command index field of command register.\r
124 @param Argument Command argument to set the argument field of command register.\r
125 @param DataType TRANSFER_TYPE, indicates no data, data in or data out.\r
126 @param Buffer Contains the data read from / write to the device.\r
127 @param BufferSize The size of the buffer.\r
128 @param ResponseType RESPONSE_TYPE.\r
129 @param TimeOut Time out value in 1 ms unit.\r
130 @param ResponseData Depending on the ResponseType, such as CSD or card status.\r
131\r
132 @retval EFI_SUCCESS\r
133 @retval EFI_INVALID_PARAMETER\r
134 @retval EFI_UNSUPPORTED\r
135 @retval EFI_DEVICE_ERROR\r
136\r
137**/\r
138EFI_STATUS\r
139SendCommand (\r
140 IN CARD_DATA *CardData,\r
141 IN UINT16 CommandIndex,\r
142 IN UINT32 Argument,\r
143 IN TRANSFER_TYPE DataType,\r
144 IN UINT8 *Buffer, OPTIONAL\r
145 IN UINT32 BufferSize,\r
146 IN RESPONSE_TYPE ResponseType,\r
147 IN UINT32 TimeOut,\r
148 OUT UINT32 *ResponseData\r
149 )\r
150{\r
151\r
152 EFI_STATUS Status;\r
153 EFI_SD_HOST_IO_PROTOCOL *SDHostIo;\r
154 SDHostIo = CardData->SDHostIo;\r
155 if (CardData->CardType != MMCCard && CardData->CardType != MMCCardHighCap) {\r
156 CommandIndex |= AUTO_CMD12_ENABLE;\r
157 }\r
158\r
159 Status = SDHostIo->SendCommand (\r
160 SDHostIo,\r
161 CommandIndex,\r
162 Argument,\r
163 DataType,\r
164 Buffer,\r
165 BufferSize,\r
166 ResponseType,\r
167 TimeOut,\r
168 ResponseData\r
169 );\r
170 if (!EFI_ERROR (Status)) {\r
171 if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) {\r
172 ASSERT(ResponseData != NULL);\r
173 Status = CheckCardStatus (*ResponseData);\r
174 }\r
175 } else {\r
176 SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD);\r
177 }\r
178\r
179 return Status;\r
180}\r
181\r
182/**\r
183 Send the card APP_CMD command with the following command indicated by CommandIndex\r
184\r
185 @param CardData Pointer to CARD_DATA.\r
186 @param CommandIndex The command index to set the command index field of command register.\r
187 @param Argument Command argument to set the argument field of command register.\r
188 @param DataType TRANSFER_TYPE, indicates no data, data in or data out.\r
189 @param Buffer Contains the data read from / write to the device.\r
190 @param BufferSize The size of the buffer.\r
191 @param ResponseType RESPONSE_TYPE.\r
192 @param TimeOut Time out value in 1 ms unit.\r
193 @param ResponseData Depending on the ResponseType, such as CSD or card status.\r
194\r
195 @retval EFI_SUCCESS\r
196 @retval EFI_INVALID_PARAMETER\r
197 @retval EFI_UNSUPPORTED\r
198 @retval EFI_DEVICE_ERROR\r
199\r
200**/\r
201EFI_STATUS\r
202SendAppCommand (\r
203 IN CARD_DATA *CardData,\r
204 IN UINT16 CommandIndex,\r
205 IN UINT32 Argument,\r
206 IN TRANSFER_TYPE DataType,\r
207 IN UINT8 *Buffer, OPTIONAL\r
208 IN UINT32 BufferSize,\r
209 IN RESPONSE_TYPE ResponseType,\r
210 IN UINT32 TimeOut,\r
211 OUT UINT32 *ResponseData\r
212 )\r
213{\r
214\r
215 EFI_STATUS Status;\r
216 EFI_SD_HOST_IO_PROTOCOL *SDHostIo;\r
217 UINT8 Index;\r
218\r
219 SDHostIo = CardData->SDHostIo;\r
220 Status = EFI_SUCCESS;\r
221\r
222 for (Index = 0; Index < 2; Index++) {\r
223 Status = SDHostIo->SendCommand (\r
224 SDHostIo,\r
225 APP_CMD,\r
226 (CardData->Address << 16),\r
227 NoData,\r
228 NULL,\r
229 0,\r
230 ResponseR1,\r
231 TIMEOUT_COMMAND,\r
232 (UINT32*)&(CardData->CardStatus)\r
233 );\r
234 if (!EFI_ERROR (Status)) {\r
235 Status = CheckCardStatus (*(UINT32*)&(CardData->CardStatus));\r
236 if (CardData->CardStatus.SAPP_CMD != 1) {\r
237 Status = EFI_DEVICE_ERROR;\r
238 }\r
239 if (!EFI_ERROR (Status)) {\r
240 break;\r
241 }\r
242 } else {\r
243 SDHostIo->ResetSDHost (SDHostIo, Reset_Auto);\r
244 }\r
245 }\r
246\r
247 if (EFI_ERROR (Status)) {\r
248 return Status;\r
249 }\r
250 if (CardData->CardType != MMCCard && CardData->CardType != MMCCardHighCap) {\r
251 CommandIndex |= AUTO_CMD12_ENABLE;\r
252 }\r
253\r
254 Status = SDHostIo->SendCommand (\r
255 SDHostIo,\r
256 CommandIndex,\r
257 Argument,\r
258 DataType,\r
259 Buffer,\r
260 BufferSize,\r
261 ResponseType,\r
262 TimeOut,\r
263 ResponseData\r
264 );\r
265 if (!EFI_ERROR (Status)) {\r
266 if (ResponseType == ResponseR1 || ResponseType == ResponseR1b) {\r
267 ASSERT(ResponseData != NULL);\r
268 Status = CheckCardStatus (*ResponseData);\r
269 }\r
270 } else {\r
271 SDHostIo->ResetSDHost (SDHostIo, Reset_Auto);\r
272 }\r
273\r
274 return Status;\r
275}\r
276\r
277\r
278/**\r
279 Send the card FAST_IO command\r
280\r
281 @param CardData Pointer to CARD_DATA.\r
282 @param RegisterAddress Register Address.\r
283 @param RegisterData Pointer to register Data.\r
284 @param Write TRUE for write, FALSE for read.\r
285\r
286 @retval EFI_SUCCESS\r
287 @retval EFI_UNSUPPORTED\r
288 @retval EFI_INVALID_PARAMETER\r
289 @retval EFI_DEVICE_ERROR\r
290\r
291**/\r
292EFI_STATUS\r
293FastIO (\r
294 IN CARD_DATA *CardData,\r
295 IN UINT8 RegisterAddress,\r
296 IN OUT UINT8 *RegisterData,\r
297 IN BOOLEAN Write\r
298 )\r
299{\r
300 EFI_STATUS Status;\r
301 UINT32 Argument;\r
302 UINT32 Data;\r
303\r
304 Status = EFI_SUCCESS;\r
305\r
306 if (RegisterData == NULL) {\r
307 Status = EFI_INVALID_PARAMETER;\r
308 goto Exit;\r
309 }\r
310\r
311 Argument = (CardData->Address << 16) | (RegisterAddress << 8);\r
312 if (Write) {\r
313 Argument |= BIT15 | (*RegisterData);\r
314 }\r
315\r
316 Status = SendCommand (\r
317 CardData,\r
318 FAST_IO,\r
319 Argument,\r
320 NoData,\r
321 NULL,\r
322 0,\r
323 ResponseR4,\r
324 TIMEOUT_COMMAND,\r
325 &Data\r
326 );\r
327 if (EFI_ERROR (Status)) {\r
328 goto Exit;\r
329 }\r
330\r
331 if ((Data & BIT15) == 0) {\r
332 Status = EFI_DEVICE_ERROR;\r
333 goto Exit;\r
334 }\r
335\r
336 if (!Write) {\r
337 *RegisterData = (UINT8)Data;\r
338 }\r
339\r
340Exit:\r
341 return Status;\r
342}\r
343\r
344/**\r
345 Send the card GO_INACTIVE_STATE command.\r
346\r
347 @param CardData Pointer to CARD_DATA.\r
348\r
349 @return EFI_SUCCESS\r
350 @return others\r
351\r
352**/\r
353EFI_STATUS\r
354PutCardInactive (\r
355 IN CARD_DATA *CardData\r
356 )\r
357{\r
358 EFI_STATUS Status;\r
359\r
360\r
361 Status = SendCommand (\r
362 CardData,\r
363 GO_INACTIVE_STATE,\r
364 (CardData->Address << 16),\r
365 NoData,\r
366 NULL,\r
367 0,\r
368 ResponseNo,\r
369 TIMEOUT_COMMAND,\r
370 NULL\r
371 );\r
372\r
373 return Status;\r
374\r
375}\r
376\r
377/**\r
378 Get card interested information for CSD rergister\r
379\r
380 @param CardData Pointer to CARD_DATA.\r
381\r
382 @retval EFI_SUCCESS\r
383 @retval EFI_UNSUPPORTED\r
384 @retval EFI_INVALID_PARAMETER\r
385\r
386**/\r
387EFI_STATUS\r
388CaculateCardParameter (\r
389 IN CARD_DATA *CardData\r
390 )\r
391{\r
392 EFI_STATUS Status;\r
393 UINT32 Frequency;\r
394 UINT32 Multiple;\r
395 UINT32 CSize;\r
396 CSD_SDV2 *CsdSDV2;\r
397\r
398 Status = EFI_SUCCESS;\r
399\r
400 switch (CardData->CSDRegister.TRAN_SPEED & 0x7) {\r
401 case 0:\r
402 Frequency = 100 * 1000;\r
403 break;\r
404\r
405 case 1:\r
406 Frequency = 1 * 1000 * 1000;\r
407 break;\r
408\r
409 case 2:\r
410 Frequency = 10 * 1000 * 1000;\r
411 break;\r
412\r
413 case 3:\r
414 Frequency = 100 * 1000 * 1000;\r
415 break;\r
416\r
417 default:\r
418 Status = EFI_INVALID_PARAMETER;\r
419 goto Exit;\r
420 }\r
421\r
422 switch ((CardData->CSDRegister.TRAN_SPEED >> 3) & 0xF) {\r
423 case 1:\r
424 Multiple = 10;\r
425 break;\r
426\r
427 case 2:\r
428 Multiple = 12;\r
429 break;\r
430\r
431 case 3:\r
432 Multiple = 13;\r
433 break;\r
434\r
435 case 4:\r
436 Multiple = 15;\r
437 break;\r
438\r
439 case 5:\r
440 Multiple = 20;\r
441 break;\r
442\r
443 case 6:\r
444 if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {\r
445 Multiple = 26;\r
446 } else {\r
447 Multiple = 25;\r
448 }\r
449 break;\r
450\r
451 case 7:\r
452 Multiple = 30;\r
453 break;\r
454\r
455 case 8:\r
456 Multiple = 35;\r
457 break;\r
458\r
459 case 9:\r
460 Multiple = 40;\r
461 break;\r
462\r
463 case 10:\r
464 Multiple = 45;\r
465 break;\r
466\r
467 case 11:\r
468 if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {\r
469 Multiple = 52;\r
470 } else {\r
471 Multiple = 50;\r
472 }\r
473 break;\r
474\r
475 case 12:\r
476 Multiple = 55;\r
477 break;\r
478\r
479 case 13:\r
480 Multiple = 60;\r
481 break;\r
482\r
483 case 14:\r
484 Multiple = 70;\r
485 break;\r
486\r
487 case 15:\r
488 Multiple = 80;\r
489 break;\r
490\r
491 default:\r
492 Status = EFI_INVALID_PARAMETER;\r
493 goto Exit;\r
494 }\r
495\r
496 Frequency = Frequency * Multiple / 10;\r
497 CardData->MaxFrequency = Frequency;\r
498\r
499 CardData->BlockLen = 1 << CardData->CSDRegister.READ_BL_LEN;\r
500\r
501 if (CardData->CardType == SDMemoryCard2High) {\r
502 ASSERT(CardData->CSDRegister.CSD_STRUCTURE == 1);\r
503 CsdSDV2 = (CSD_SDV2*)&CardData->CSDRegister;\r
504 //\r
505 // The SD Spec 2.0 says (CSize + 1) * 512K is the total size, so block numbber is (CSize + 1) * 1K\r
506 // the K here means 1024 not 1000\r
507 //\r
508 CardData->BlockNumber = DivU64x32 (MultU64x32 (CsdSDV2->C_SIZE + 1, 512 * 1024) , CardData->BlockLen);\r
509 } else {\r
510 //\r
511 // For MMC card > 2G, the block number will be recaculate later\r
512 //\r
513 CSize = CardData->CSDRegister.C_SIZELow2 | (CardData->CSDRegister.C_SIZEHigh10 << 2);\r
514 CardData->BlockNumber = MultU64x32 (LShiftU64 (1, CardData->CSDRegister.C_SIZE_MULT + 2), CSize + 1);\r
515 }\r
516\r
517 //\r
518 //For >= 2G card, BlockLen may be 1024, but the transfer size is still 512 bytes\r
519 //\r
520 if (CardData->BlockLen > 512) {\r
521 CardData->BlockNumber = DivU64x32 (MultU64x32 (CardData->BlockNumber, CardData->BlockLen), 512);\r
522 CardData->BlockLen = 512;\r
523 }\r
524\r
525 DEBUG((\r
526 EFI_D_INFO,\r
527 "CalculateCardParameter: Card Size: 0x%lx\n", MultU64x32 (CardData->BlockNumber, CardData->BlockLen)\r
528 ));\r
529\r
530Exit:\r
531 return Status;\r
532}\r
533\r
534/**\r
535 Test the bus width setting for MMC card.It is used only for verification purpose.\r
536\r
537 @param CardData Pointer to CARD_DATA.\r
538 @param Width 1, 4, 8 bits.\r
539\r
540 @retval EFI_SUCCESS\r
541 @retval EFI_UNSUPPORTED\r
542 @retval EFI_INVALID_PARAMETER\r
543\r
544**/\r
545EFI_STATUS\r
546MMCCardBusWidthTest (\r
547 IN CARD_DATA *CardData,\r
548 IN UINT32 Width\r
549 )\r
550{\r
551 EFI_STATUS Status;\r
552 UINT64 Data;\r
553 UINT64 Value;\r
554\r
555 ASSERT(CardData != NULL);\r
556\r
557\r
558 Value = 0;\r
559\r
560 switch (Width) {\r
561 case 1:\r
562 Data = 0x80;\r
563 break;\r
564\r
565 case 4:\r
566 Data = 0x5A;\r
567 break;\r
568\r
569 case 8:\r
570 Data = 0xAA55;\r
571 break;\r
572\r
573 default:\r
574 Status = EFI_INVALID_PARAMETER;\r
575 goto Exit;\r
576 }\r
577\r
578 CopyMem (CardData->AlignedBuffer, &Data, Width);\r
579 Status = SendCommand (\r
580 CardData,\r
581 BUSTEST_W,\r
582 0,\r
583 OutData,\r
584 CardData->AlignedBuffer,\r
585 Width,\r
586 ResponseR1,\r
587 TIMEOUT_COMMAND,\r
588 (UINT32*)&(CardData->CardStatus)\r
589 );\r
590 if (EFI_ERROR (Status)) {\r
591 DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest:SendCommand BUSTEST_W 0x%x\n", *(UINT32*)&(CardData->CardStatus)));\r
592 goto Exit;\r
593 }\r
594\r
595 gBS->Stall (10 * 1000);\r
596\r
597 Data = 0;\r
598\r
599 Status = SendCommand (\r
600 CardData,\r
601 BUSTEST_R,\r
602 0,\r
603 InData,\r
604 CardData->AlignedBuffer,\r
605 Width,\r
606 ResponseR1,\r
607 TIMEOUT_COMMAND,\r
608 (UINT32*)&(CardData->CardStatus)\r
609 );\r
610 if (EFI_ERROR (Status)) {\r
611 DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest:SendCommand BUSTEST_R 0x%x\n", *(UINT32*)&(CardData->CardStatus)));\r
612 goto Exit;\r
613 }\r
614 CopyMem (&Data, CardData->AlignedBuffer, Width);\r
615\r
616 switch (Width) {\r
617 case 1:\r
618 Value = (~(Data ^ 0x80)) & 0xC0;\r
619 break;\r
620 case 4:\r
621 Value = (~(Data ^ 0x5A)) & 0xFF;\r
622 break;\r
623 case 8:\r
624 Value = (~(Data ^ 0xAA55)) & 0xFFFF;\r
625 break;\r
626 }\r
627\r
628 if (Value == 0) {\r
629 Status = EFI_SUCCESS;\r
630 } else {\r
631 Status = EFI_UNSUPPORTED;\r
632 }\r
633\r
634\r
635Exit:\r
636 return Status;\r
637}\r
638\r
639/**\r
640 This function can detect these card types:\r
641 1. MMC card\r
642 2. SD 1.1 card\r
643 3. SD 2.0 standard card\r
644 3. SD 2.0 high capacity card\r
645\r
646 @param CardData Pointer to CARD_DATA.\r
647\r
648 @return EFI_SUCCESS\r
649 @return others\r
650\r
651**/\r
652EFI_STATUS\r
653GetCardType (\r
654 IN CARD_DATA *CardData\r
655 )\r
656{\r
657 EFI_STATUS Status;\r
658 EFI_SD_HOST_IO_PROTOCOL *SDHostIo;\r
659 UINT32 Argument;\r
660 UINT32 ResponseData;\r
661 UINT32 Count;\r
662 BOOLEAN SDCommand8Support;\r
663\r
664\r
665 SDHostIo = CardData->SDHostIo;\r
666\r
667 //\r
668 // Reset the card\r
669 //\r
670 Status = SendCommand (\r
671 CardData,\r
672 GO_IDLE_STATE,\r
673 0,\r
674 NoData,\r
675 NULL,\r
676 0,\r
677 ResponseNo,\r
678 TIMEOUT_COMMAND,\r
679 NULL\r
680 );\r
681 if (EFI_ERROR (Status)) {\r
682 DEBUG((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status));\r
683 goto Exit;\r
684 }\r
685\r
686 //\r
687 //No spec requirment, can be adjusted\r
688 //\r
689 gBS->Stall (10 * 1000);\r
690\r
691\r
692 //\r
693 // Only 2.7V - 3.6V is supported for SD2.0, only SD 2.0 card can pass\r
694 // MMC and SD1.1 card will fail this command\r
695 //\r
696 Argument = (VOLTAGE_27_36 << 8) | CHECK_PATTERN;\r
697 ResponseData = 0;\r
698 SDCommand8Support = FALSE;\r
699\r
700 Status = SendCommand (\r
701 CardData,\r
702 SEND_IF_COND,\r
703 Argument,\r
704 NoData,\r
705 NULL,\r
706 0,\r
707 ResponseR7,\r
708 TIMEOUT_COMMAND,\r
709 &ResponseData\r
710 );\r
711\r
712 if (EFI_ERROR (Status)) {\r
713 if (Status != EFI_TIMEOUT) {\r
714 DEBUG((EFI_D_ERROR, "SEND_IF_COND Fail, none time out error\n"));\r
715 goto Exit;\r
716 }\r
717 } else {\r
718 if (ResponseData != Argument) {\r
719 DEBUG((EFI_D_ERROR, "SEND_IF_COND Fail, respond data does not match send data\n"));\r
720 Status = EFI_DEVICE_ERROR;\r
721 goto Exit;\r
722 }\r
723 SDCommand8Support = TRUE;\r
724 }\r
725\r
726\r
727 Argument = 0;\r
728 if (SDHostIo->HostCapability.V30Support == TRUE) {\r
729 Argument |= BIT17 | BIT18;\r
730 } else if (SDHostIo->HostCapability.V33Support == TRUE) {\r
731 Argument |= BIT20 | BIT21;\r
732 }\r
733\r
734 if (SDCommand8Support) {\r
735 //\r
736 //If command SD_SEND_OP_COND sucessed, it should be set.\r
737 // SD 1.1 card will ignore it\r
738 // SD 2.0 standard card will repsond with CCS 0, SD high capacity card will respond with CCS 1\r
739 // CCS is BIT30 of OCR\r
740 Argument |= BIT30;\r
741 }\r
742\r
743\r
744 Count = 20;\r
745 //\r
746 //Only SD card will respond to this command, and spec says the card only checks condition at first ACMD41 command\r
747 //\r
748 do {\r
749 Status = SendAppCommand (\r
750 CardData,\r
751 SD_SEND_OP_COND,\r
752 Argument,\r
753 NoData,\r
754 NULL,\r
755 0,\r
756 ResponseR3,\r
757 TIMEOUT_COMMAND,\r
758 (UINT32*)&(CardData->OCRRegister)\r
759 );\r
760 if (EFI_ERROR (Status)) {\r
761 if ((Status == EFI_TIMEOUT) && (!SDCommand8Support)) {\r
762 CardData->CardType = MMCCard;\r
763 Status = EFI_SUCCESS;\r
764 DEBUG((EFI_D_INFO, "SD_SEND_OP_COND, MMC card was identified\n"));\r
765 } else {\r
766 //\r
767 // Not as expected, MMC card should has no response, which means timeout.\r
768 // SD card should pass this command\r
769 //\r
770 DEBUG((EFI_D_ERROR, "SD_SEND_OP_COND Fail, check whether it is neither a MMC card nor a SD card\n"));\r
771 }\r
772 goto Exit;\r
773 }\r
774 //\r
775 //Avoid waiting if sucess. Busy bit 0 means not ready\r
776 //\r
777 if (CardData->OCRRegister.Busy == 1) {\r
778 break;\r
779 }\r
780\r
781 gBS->Stall (50 * 1000);\r
782 Count--;\r
783 if (Count == 0) {\r
784 DEBUG((EFI_D_ERROR, "Card is always in busy state\n"));\r
785 Status = EFI_TIMEOUT;\r
786 goto Exit;\r
787 }\r
788 } while (1);\r
789\r
790 //\r
791 //Check supported voltage\r
792 //\r
793 Argument = 0;\r
794 if (SDHostIo->HostCapability.V30Support == TRUE) {\r
795 if ((CardData->OCRRegister.V270_V360 & BIT2) == BIT2) {\r
796 Argument |= BIT17;\r
797 } else if ((CardData->OCRRegister.V270_V360 & BIT3) == BIT3) {\r
798 Argument |= BIT18;\r
799 }\r
800 } else if (SDHostIo->HostCapability.V33Support == TRUE) {\r
801 if ((CardData->OCRRegister.V270_V360 & BIT5) == BIT5) {\r
802 Argument |= BIT20;\r
803 } else if ((CardData->OCRRegister.V270_V360 & BIT6) == BIT6) {\r
804 Argument |= BIT21;\r
805 }\r
806 }\r
807\r
808 if (Argument == 0) {\r
809 //\r
810 //No matched support voltage\r
811 //\r
812 PutCardInactive (CardData);\r
813 DEBUG((EFI_D_ERROR, "No matched voltage for this card\n"));\r
814 Status = EFI_UNSUPPORTED;\r
815 goto Exit;\r
816 }\r
817\r
818 CardData->CardType = SDMemoryCard;\r
819 if (SDCommand8Support == TRUE) {\r
820 CardData->CardType = SDMemoryCard2;\r
821 DEBUG((EFI_D_INFO, "SD_SEND_OP_COND, SD 2.0 or above standard card was identified\n"));\r
822 }\r
823\r
824 if ((CardData->OCRRegister.AccessMode & BIT1) == BIT1) {\r
825 CardData->CardType = SDMemoryCard2High;\r
826 DEBUG((EFI_D_INFO, "SD_SEND_OP_COND, SD 2.0 or above high capacity card was identified\n"));\r
827 }\r
828\r
829\r
830\r
831Exit:\r
832 return Status;\r
833}\r
834\r
835/**\r
836 MMC card high/low voltage selection function\r
837\r
838 @param CardData Pointer to CARD_DATA.\r
839\r
840 @retval EFI_SUCCESS\r
841 @retval EFI_INVALID_PARAMETER\r
842 @retval EFI_UNSUPPORTED\r
843 @retval EFI_BAD_BUFFER_SIZE\r
844\r
845**/\r
846EFI_STATUS\r
847MMCCardVoltageSelection (\r
848 IN CARD_DATA *CardData\r
849 )\r
850{\r
851 EFI_STATUS Status;\r
852 EFI_SD_HOST_IO_PROTOCOL *SDHostIo;\r
853 UINT8 Retry;\r
854 UINT32 TimeOut;\r
855\r
856 Status = EFI_SUCCESS;\r
857 SDHostIo = CardData->SDHostIo;\r
858 //\r
859 //First try the high voltage, then if supported choose the low voltage\r
860 //\r
861\r
862 for (Retry = 0; Retry < 3; Retry++) {\r
863 //\r
864 // To bring back the normal MMC card to work\r
865 // after sending the SD command. Otherwise some\r
866 // card could not work\r
867\r
868 Status = SendCommand (\r
869 CardData,\r
870 GO_IDLE_STATE,\r
871 0,\r
872 NoData,\r
873 NULL,\r
874 0,\r
875 ResponseNo,\r
876 TIMEOUT_COMMAND,\r
877 NULL\r
878 );\r
879 if (EFI_ERROR (Status)) {\r
880 DEBUG((EFI_D_ERROR, "GO_IDLE_STATE Fail Status = 0x%x\n", Status));\r
881 continue;\r
882 }\r
883 //\r
884 //CE-ATA device needs long delay\r
885 //\r
886 gBS->Stall ((Retry + 1) * 50 * 1000);\r
887\r
888 //\r
889 //Get OCR register to check voltage support, first time the OCR is 0\r
890 //\r
891 Status = SendCommand (\r
892 CardData,\r
893 SEND_OP_COND,\r
894 0,\r
895 NoData,\r
896 NULL,\r
897 0,\r
898 ResponseR3,\r
899 TIMEOUT_COMMAND,\r
900 (UINT32*)&(CardData->OCRRegister)\r
901 );\r
902 if (!EFI_ERROR (Status)) {\r
903 break;\r
904 }\r
905 }\r
906\r
907 if (Retry == 3) {\r
908 DEBUG((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status));\r
909 Status = EFI_DEVICE_ERROR;\r
910 goto Exit;\r
911 }\r
912\r
913 //\r
914 //TimeOut Value, 5000 * 100 * 1000 = 5 s\r
915 //\r
916 TimeOut = 5000;\r
917\r
918 do {\r
919 Status = SendCommand (\r
920 CardData,\r
921 SEND_OP_COND,\r
922 0x40300000,\r
923 NoData,\r
924 NULL,\r
925 0,\r
926 ResponseR3,\r
927 TIMEOUT_COMMAND,\r
928 (UINT32*)&(CardData->OCRRegister)\r
929 );\r
930 if (EFI_ERROR (Status)) {\r
931 DEBUG((EFI_D_ERROR, "SEND_OP_COND Fail Status = 0x%x\n", Status));\r
932 goto Exit;\r
933 }\r
934\r
935 gBS->Stall (1 * 1000);\r
936 TimeOut--;\r
937 if (TimeOut == 0) {\r
938 Status = EFI_TIMEOUT;\r
939 DEBUG((EFI_D_ERROR, "Card is always in busy state\n"));\r
940 goto Exit;\r
941 }\r
942 } while (CardData->OCRRegister.Busy != 1);\r
943\r
944 if (CardData->OCRRegister.AccessMode == 2) // eMMC Card uses Sector Addressing - High Capacity\r
945 {\r
946 DEBUG((EFI_D_INFO, "eMMC Card is High Capacity\n"));\r
947 CardData->CardType = MMCCardHighCap;\r
948 }\r
949\r
950Exit:\r
951 return Status;\r
952\r
953}\r
954\r
955/**\r
956 This function set the bus and device width for MMC card\r
957\r
958 @param CardData Pointer to CARD_DATA.\r
959 @param Width 1, 4, 8 bits.\r
960\r
961 @retval EFI_SUCCESS\r
962 @retval EFI_UNSUPPORTED\r
963 @retval EFI_INVALID_PARAMETER\r
964\r
965**/\r
966EFI_STATUS\r
967MMCCardSetBusWidth (\r
968 IN CARD_DATA *CardData,\r
969 IN UINT8 BusWidth,\r
970 IN BOOLEAN EnableDDRMode\r
971 )\r
972{\r
973 EFI_STATUS Status;\r
974 EFI_SD_HOST_IO_PROTOCOL *SDHostIo;\r
975 SWITCH_ARGUMENT SwitchArgument;\r
976 UINT8 Value;\r
977\r
978 SDHostIo = CardData->SDHostIo;\r
979 Value = 0;\r
980 switch (BusWidth) {\r
981 case 8:\r
982 if (EnableDDRMode)\r
983 Value = 6;\r
984 else\r
985 Value = 2;\r
986 break;\r
987\r
988 case 4:\r
989 if (EnableDDRMode)\r
990 Value = 5;\r
991 else\r
992 Value = 1;\r
993 break;\r
994\r
995 case 1:\r
996 if (EnableDDRMode) // Bus width 1 is not supported in ddr mode\r
997 return EFI_UNSUPPORTED;\r
998 Value = 0;\r
999 break;\r
1000\r
1001 default:\r
1002 ASSERT(0);\r
1003 }\r
1004\r
1005\r
1006 ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT));\r
1007 SwitchArgument.CmdSet = 0;\r
1008 SwitchArgument.Value = Value;\r
1009 SwitchArgument.Index = (UINT32)((UINTN)\r
1010 (&(CardData->ExtCSDRegister.BUS_WIDTH)) - (UINTN)(&(CardData->ExtCSDRegister)));\r
1011 SwitchArgument.Access = WriteByte_Mode;\r
1012 Status = SendCommand (\r
1013 CardData,\r
1014 SWITCH,\r
1015 *(UINT32*)&SwitchArgument,\r
1016 NoData,\r
1017 NULL,\r
1018 0,\r
1019 ResponseR1b,\r
1020 TIMEOUT_COMMAND,\r
1021 (UINT32*)&(CardData->CardStatus)\r
1022 );\r
1023 if (!EFI_ERROR (Status)) {\r
1024 Status = SendCommand (\r
1025 CardData,\r
1026 SEND_STATUS,\r
1027 (CardData->Address << 16),\r
1028 NoData,\r
1029 NULL,\r
1030 0,\r
1031 ResponseR1,\r
1032 TIMEOUT_COMMAND,\r
1033 (UINT32*)&(CardData->CardStatus)\r
1034 );\r
1035 if (EFI_ERROR (Status)) {\r
1036 DEBUG((EFI_D_ERROR, "SWITCH %d bits Fail\n", BusWidth));\r
1037 goto Exit;\r
1038 } else {\r
1039 DEBUG((EFI_D_ERROR, "MMCCardSetBusWidth:SWITCH Card Status:0x%x\n", *(UINT32*)&(CardData->CardStatus)));\r
1040 Status = SDHostIo->SetBusWidth (SDHostIo, BusWidth);\r
1041 if (EFI_ERROR (Status)) {\r
1042 DEBUG((EFI_D_ERROR, "SWITCH set %d bits Fail\n", BusWidth));\r
1043 goto Exit;\r
1044 }\r
1045 gBS->Stall (5 * 1000);\r
1046 }\r
1047 }\r
1048\r
1049 if (!EnableDDRMode) { // CMD19 and CMD14 are illegal commands in ddr mode\r
1050 //if (EFI_ERROR (Status)) {\r
1051 // DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest: Fail to enable high speed mode\n"));\r
1052 // goto Exit;\r
1053 //}\r
1054\r
1055 Status = MMCCardBusWidthTest (CardData, BusWidth);\r
1056 if (EFI_ERROR (Status)) {\r
1057 DEBUG((EFI_D_ERROR, "MMCCardBusWidthTest %d bit Fail\n", BusWidth));\r
1058 goto Exit;\r
1059 }\r
1060 }\r
1061\r
1062 CardData->CurrentBusWidth = BusWidth;\r
1063\r
1064Exit:\r
1065 return Status;\r
1066}\r
1067\r
1068\r
1069/**\r
1070 MMC/SD card init function\r
1071\r
1072 @param CardData Pointer to CARD_DATA.\r
1073\r
1074 @return EFI_SUCCESS\r
1075 @return others\r
1076\r
1077**/\r
1078EFI_STATUS\r
1079MMCSDCardInit (\r
1080 IN CARD_DATA *CardData\r
1081 )\r
1082{\r
1083 EFI_STATUS Status;\r
1084 EFI_SD_HOST_IO_PROTOCOL *SDHostIo;\r
1085 SWITCH_ARGUMENT SwitchArgument;\r
1086 UINT32 Data;\r
1087 UINT32 Argument;\r
1088 UINT32 nIndex;\r
1089 UINT8 PowerValue;\r
1090 BOOLEAN EnableDDRMode;\r
1091\r
1092 ASSERT(CardData != NULL);\r
1093 SDHostIo = CardData->SDHostIo;\r
1094 EnableDDRMode = FALSE;\r
1095\r
1096 CardData->CardType = UnknownCard;\r
1097 Status = GetCardType (CardData);\r
1098 if (EFI_ERROR (Status)) {\r
1099 goto Exit;\r
1100 }\r
1101 DEBUG((DEBUG_INFO, "CardData->CardType 0x%x\n", CardData->CardType));\r
1102\r
1103 ASSERT (CardData->CardType != UnknownCard);\r
1104 //\r
1105 //MMC, SD card need host auto stop command support\r
1106 //\r
1107 SDHostIo->EnableAutoStopCmd (SDHostIo, TRUE);\r
1108\r
1109 if (CardData->CardType == MMCCard) {\r
1110 Status = MMCCardVoltageSelection (CardData);\r
1111 if (EFI_ERROR(Status)) {\r
1112 goto Exit;\r
1113 }\r
1114 }\r
1115\r
1116 //\r
1117 // Get CID Register\r
1118 //\r
1119 Status = SendCommand (\r
1120 CardData,\r
1121 ALL_SEND_CID,\r
1122 0,\r
1123 NoData,\r
1124 NULL,\r
1125 0,\r
1126 ResponseR2,\r
1127 TIMEOUT_COMMAND,\r
1128 (UINT32*)&(CardData->CIDRegister)\r
1129 );\r
1130 if (EFI_ERROR (Status)) {\r
1131 DEBUG((EFI_D_ERROR, "ALL_SEND_CID Fail Status = 0x%x\n", Status));\r
1132 goto Exit;\r
1133 } else {\r
1134 // Dump out the Card ID data\r
1135 DEBUG((EFI_D_INFO, "Product Name: "));\r
1136 for ( nIndex=0; nIndex<6; nIndex++ ) {\r
1137 DEBUG((EFI_D_INFO, "%c", CardData->CIDRegister.PNM[nIndex]));\r
1138 }\r
1139 DEBUG((EFI_D_INFO, "\nApplication ID : %d\n", CardData->CIDRegister.OID));\r
1140 DEBUG((EFI_D_INFO, "Manufacturer ID: %d\n", CardData->CIDRegister.MID));\r
1141 DEBUG((EFI_D_INFO, "Revision ID : %d\n", CardData->CIDRegister.PRV));\r
1142 DEBUG((EFI_D_INFO, "Serial Number : %d\n", CardData->CIDRegister.PSN));\r
1143 }\r
1144\r
1145 //\r
1146 //SET_RELATIVE_ADDR\r
1147 //\r
1148 if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {\r
1149 //\r
1150 //Hard code the RCA address\r
1151 //\r
1152 CardData->Address = 1;\r
1153\r
1154 //\r
1155 // Set RCA Register\r
1156 //\r
1157 Status = SendCommand (\r
1158 CardData,\r
1159 SET_RELATIVE_ADDR,\r
1160 (CardData->Address << 16),\r
1161 NoData,\r
1162 NULL,\r
1163 0,\r
1164 ResponseR1,\r
1165 TIMEOUT_COMMAND,\r
1166 (UINT32*)&(CardData->CardStatus)\r
1167 );\r
1168 if (EFI_ERROR (Status)) {\r
1169 DEBUG((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status));\r
1170 goto Exit;\r
1171 }\r
1172 } else {\r
1173 Data = 0;\r
1174 Status = SendCommand (\r
1175 CardData,\r
1176 SET_RELATIVE_ADDR,\r
1177 0,\r
1178 NoData,\r
1179 NULL,\r
1180 0,\r
1181 ResponseR6,\r
1182 TIMEOUT_COMMAND,\r
1183 &Data\r
1184 );\r
1185 if (EFI_ERROR (Status)) {\r
1186 DEBUG((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status));\r
1187 goto Exit;\r
1188 }\r
1189\r
1190 CardData->Address = (UINT16)(Data >> 16);\r
1191 *(UINT32*)&CardData->CardStatus = Data & 0x1FFF;\r
1192 CardData->CardStatus.ERROR = (Data >> 13) & 0x1;\r
1193 CardData->CardStatus.ILLEGAL_COMMAND = (Data >> 14) & 0x1;\r
1194 CardData->CardStatus.COM_CRC_ERROR = (Data >> 15) & 0x1;\r
1195 Status = CheckCardStatus (*(UINT32*)&CardData->CardStatus);\r
1196 if (EFI_ERROR (Status)) {\r
1197 DEBUG((EFI_D_ERROR, "SET_RELATIVE_ADDR Fail Status = 0x%x\n", Status));\r
1198 goto Exit;\r
1199 }\r
1200 }\r
1201\r
1202 //\r
1203 // Get CSD Register\r
1204 //\r
1205 Status = SendCommand (\r
1206 CardData,\r
1207 SEND_CSD,\r
1208 (CardData->Address << 16),\r
1209 NoData,\r
1210 NULL,\r
1211 0,\r
1212 ResponseR2,\r
1213 TIMEOUT_COMMAND,\r
1214 (UINT32*)&(CardData->CSDRegister)\r
1215 );\r
1216 if (EFI_ERROR (Status)) {\r
1217 DEBUG((EFI_D_ERROR, "SEND_CSD Fail Status = 0x%x\n", Status));\r
1218 goto Exit;\r
1219 }\r
1220\r
1221 DEBUG((EFI_D_INFO, "CardData->CSDRegister.SPEC_VERS = 0x%x\n", CardData->CSDRegister.SPEC_VERS));\r
1222 DEBUG((EFI_D_INFO, "CardData->CSDRegister.CSD_STRUCTURE = 0x%x\n", CardData->CSDRegister.CSD_STRUCTURE));\r
1223\r
1224 Status = CaculateCardParameter (CardData);\r
1225 if (EFI_ERROR (Status)) {\r
1226 goto Exit;\r
1227 }\r
1228\r
1229\r
1230 //\r
1231 // It is platform and hardware specific, need hadrware engineer input\r
1232 //\r
1233 if (CardData->CSDRegister.DSR_IMP == 1) {\r
1234 //\r
1235 // Default is 0x404\r
1236 //\r
1237 Status = SendCommand (\r
1238 CardData,\r
1239 SET_DSR,\r
1240 (DEFAULT_DSR_VALUE << 16),\r
1241 NoData,\r
1242 NULL,\r
1243 0,\r
1244 ResponseNo,\r
1245 TIMEOUT_COMMAND,\r
1246 NULL\r
1247 );\r
1248 if (EFI_ERROR (Status)) {\r
1249 DEBUG((EFI_D_ERROR, "SET_DSR Fail Status = 0x%x\n", Status));\r
1250 //\r
1251 // Assume can operate even fail\r
1252 //\r
1253 }\r
1254 }\r
1255 //\r
1256 //Change clock frequency from 400KHz to max supported when not in high speed mode\r
1257 //\r
1258 Status = SDHostIo->SetClockFrequency (SDHostIo, CardData->MaxFrequency);\r
1259 if (EFI_ERROR (Status)) {\r
1260 DEBUG((EFI_D_ERROR, "MMCSDCardInit:Fail to SetClockFrequency \n"));\r
1261 goto Exit;\r
1262 }\r
1263\r
1264 //\r
1265 //Put the card into tran state\r
1266 //\r
1267 Status = SendCommand (\r
1268 CardData,\r
1269 SELECT_DESELECT_CARD,\r
1270 (CardData->Address << 16),\r
1271 NoData,\r
1272 NULL,\r
1273 0,\r
1274 ResponseR1,\r
1275 TIMEOUT_COMMAND,\r
1276 (UINT32*)&(CardData->CardStatus)\r
1277 );\r
1278 if (EFI_ERROR (Status)) {\r
1279 DEBUG((EFI_D_ERROR, "SELECT_DESELECT_CARD Fail Status = 0x%x\n", Status));\r
1280 goto Exit;\r
1281 }\r
1282\r
1283 //\r
1284 // No spec requirment, can be adjusted\r
1285 //\r
1286 gBS->Stall (5 * 1000);\r
1287 //\r
1288 // No need to do so\r
1289 //\r
1290 //\r
1291 Status = SendCommand (\r
1292 CardData,\r
1293 SEND_STATUS,\r
1294 (CardData->Address << 16),\r
1295 NoData,\r
1296 NULL,\r
1297 0,\r
1298 ResponseR1,\r
1299 TIMEOUT_COMMAND,\r
1300 (UINT32*)&(CardData->CardStatus)\r
1301 );\r
1302 if (EFI_ERROR (Status)) {\r
1303 DEBUG((EFI_D_ERROR, "SELECT_DESELECT_CARD SEND_STATUS Fail Status = 0x%x\n", Status));\r
1304 goto Exit;\r
1305 }\r
1306 //\r
1307 //if the SPEC_VERS indicates a version 4.0 or higher\r
1308 //The card is a high speed card and support Switch\r
1309 //and Send_ext_csd command\r
1310 //otherwise it is an old card\r
1311 //\r
1312\r
1313 if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {\r
1314 //\r
1315 //Only V4.0 and above supports more than 1 bits and high speed\r
1316 //\r
1317 if (CardData->CSDRegister.SPEC_VERS >= 4) {\r
1318 //\r
1319 //Get ExtCSDRegister\r
1320 //\r
1321 Status = SendCommand (\r
1322 CardData,\r
1323 SEND_EXT_CSD,\r
1324 0x0,\r
1325 InData,\r
1326 CardData->AlignedBuffer,\r
1327 sizeof (EXT_CSD),\r
1328 ResponseR1,\r
1329 TIMEOUT_DATA,\r
1330 (UINT32*)&(CardData->CardStatus)\r
1331 );\r
1332 if (EFI_ERROR (Status)) {\r
1333 DEBUG((EFI_D_ERROR, "SEND_EXT_CSD Fail Status = 0x%x\n", Status));\r
1334 goto Exit;\r
1335 }\r
1336\r
1337 CopyMem (&(CardData->ExtCSDRegister), CardData->AlignedBuffer, sizeof (EXT_CSD));\r
1338\r
1339 //\r
1340 // Recaculate the block number for >2G MMC card\r
1341 //\r
1342 Data = (CardData->ExtCSDRegister.SEC_COUNT[0]) |\r
1343 (CardData->ExtCSDRegister.SEC_COUNT[1] << 8) |\r
1344 (CardData->ExtCSDRegister.SEC_COUNT[2] << 16) |\r
1345 (CardData->ExtCSDRegister.SEC_COUNT[3] << 24);\r
1346\r
1347 if (Data != 0) {\r
1348 CardData->BlockNumber = Data;\r
1349 }\r
1350 DEBUG((DEBUG_INFO, "CardData->BlockNumber %d\n", Data));\r
1351 DEBUG((EFI_D_ERROR, "CardData->ExtCSDRegister.CARD_TYPE -> %d\n", (UINTN)CardData->ExtCSDRegister.CARD_TYPE));\r
1352 if ((CardData->ExtCSDRegister.CARD_TYPE & BIT2)||\r
1353 (CardData->ExtCSDRegister.CARD_TYPE & BIT3)) {\r
1354 //DEBUG((DEBUG_INFO, "To enable DDR mode\n"));\r
1355 //EnableDDRMode = TRUE;\r
1356 }\r
1357 //\r
1358 // Check current chipset capability and the plugged-in card\r
1359 // whether supports HighSpeed\r
1360 //\r
1361 if (SDHostIo->HostCapability.HighSpeedSupport) {\r
1362\r
1363 //\r
1364 //Change card timing to high speed interface timing\r
1365 //\r
1366 ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT));\r
1367 SwitchArgument.CmdSet = 0;\r
1368 SwitchArgument.Value = 1;\r
1369 SwitchArgument.Index = (UINT32)((UINTN)\r
1370 (&(CardData->ExtCSDRegister.HS_TIMING)) - (UINTN)(&(CardData->ExtCSDRegister)));\r
1371 SwitchArgument.Access = WriteByte_Mode;\r
1372 Status = SendCommand (\r
1373 CardData,\r
1374 SWITCH,\r
1375 *(UINT32*)&SwitchArgument,\r
1376 NoData,\r
1377 NULL,\r
1378 0,\r
1379 ResponseR1b,\r
1380 TIMEOUT_COMMAND,\r
1381 (UINT32*)&(CardData->CardStatus)\r
1382 );\r
1383 if (EFI_ERROR (Status)) {\r
1384 DEBUG((EFI_D_ERROR, "MMCSDCardInit:SWITCH frequency Fail Status = 0x%x\n", Status));\r
1385 }\r
1386\r
1387 gBS->Stall (5 * 1000);\r
1388\r
1389\r
1390 if (!EFI_ERROR (Status)) {\r
1391 Status = SendCommand (\r
1392 CardData,\r
1393 SEND_STATUS,\r
1394 (CardData->Address << 16),\r
1395 NoData,\r
1396 NULL,\r
1397 0,\r
1398 ResponseR1,\r
1399 TIMEOUT_COMMAND,\r
1400 (UINT32*)&(CardData->CardStatus)\r
1401 );\r
1402 if (!EFI_ERROR (Status)) {\r
1403 if (EnableDDRMode) {\r
1404 DEBUG((EFI_D_ERROR, "Enable ddr mode on host controller\n"));\r
1405 SDHostIo->SetDDRMode (SDHostIo, TRUE);\r
1406 } else {\r
1407 DEBUG((EFI_D_ERROR, "Enable high speed mode on host controller\n"));\r
1408 SDHostIo->SetHighSpeedMode (SDHostIo, TRUE);\r
1409 }\r
1410 //\r
1411 // Change host clock to support high speed and enable chispet to\r
1412 // support speed\r
1413 //\r
1414 if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {\r
1415 Status = SDHostIo->SetClockFrequency (SDHostIo, FREQUENCY_MMC_PP_HIGH);\r
1416 } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {\r
1417 Status = SDHostIo->SetClockFrequency (SDHostIo, FREQUENCY_MMC_PP);\r
1418 } else {\r
1419 Status = EFI_UNSUPPORTED;\r
1420 }\r
1421 if (EFI_ERROR (Status)) {\r
1422 DEBUG((EFI_D_ERROR, "MMCSDCardInit:Fail to SetClockFrequency \n"));\r
1423 goto Exit;\r
1424 }\r
1425 //\r
1426 // It seems no need to stall after changing bus freqeuncy.\r
1427 // It is said that the freqeuncy can be changed at any time. Just appends 8 clocks after command.\r
1428 // But SetClock alreay has delay.\r
1429 //\r
1430 }\r
1431 }\r
1432\r
1433 }\r
1434\r
1435\r
1436\r
1437 //\r
1438 // Prefer wide bus width for performance\r
1439 //\r
1440 //\r
1441 // Set to BusWidth bits mode, only version 4.0 or above support more than 1 bits\r
1442 //\r
1443 if (SDHostIo->HostCapability.BusWidth8 == TRUE) {\r
1444 Status = MMCCardSetBusWidth (CardData, 8, EnableDDRMode);\r
1445 if (EFI_ERROR (Status)) {\r
1446 //\r
1447 // CE-ATA may support 8 bits and 4 bits, but has no software method for detection\r
1448 //\r
1449 Status = MMCCardSetBusWidth (CardData, 4, EnableDDRMode);\r
1450 if (EFI_ERROR (Status)) {\r
1451 goto Exit;\r
1452 }\r
1453 }\r
1454 } else if (SDHostIo->HostCapability.BusWidth4 == TRUE) {\r
1455 Status = MMCCardSetBusWidth (CardData, 4, EnableDDRMode);\r
1456 if (EFI_ERROR (Status)) {\r
1457 goto Exit;\r
1458 }\r
1459 }\r
1460\r
1461 PowerValue = 0;\r
1462\r
1463 if (CardData->CurrentBusWidth == 8) {\r
1464 if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {\r
1465 PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360;\r
1466 PowerValue = PowerValue >> 4;\r
1467 } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {\r
1468 PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360;\r
1469 PowerValue = PowerValue >> 4;\r
1470 }\r
1471 } else if (CardData->CurrentBusWidth == 4) {\r
1472 if ((CardData->ExtCSDRegister.CARD_TYPE & BIT1) != 0) {\r
1473 PowerValue = CardData->ExtCSDRegister.PWR_CL_52_360;\r
1474 PowerValue = PowerValue & 0xF;\r
1475 } else if ((CardData->ExtCSDRegister.CARD_TYPE & BIT0) != 0) {\r
1476 PowerValue = CardData->ExtCSDRegister.PWR_CL_26_360;\r
1477 PowerValue = PowerValue & 0xF;\r
1478 }\r
1479 }\r
1480\r
1481 if (PowerValue != 0) {\r
1482 //\r
1483 //Update Power Class\r
1484 //\r
1485 ZeroMem(&SwitchArgument, sizeof (SWITCH_ARGUMENT));\r
1486 SwitchArgument.CmdSet = 0;\r
1487 SwitchArgument.Value = PowerValue;\r
1488 SwitchArgument.Index = (UINT32)((UINTN)\r
1489 (&(CardData->ExtCSDRegister.POWER_CLASS)) - (UINTN)(&(CardData->ExtCSDRegister)));\r
1490 SwitchArgument.Access = WriteByte_Mode;\r
1491 Status = SendCommand (\r
1492 CardData,\r
1493 SWITCH,\r
1494 *(UINT32*)&SwitchArgument,\r
1495 NoData,\r
1496 NULL,\r
1497 0,\r
1498 ResponseR1b,\r
1499 TIMEOUT_COMMAND,\r
1500 (UINT32*)&(CardData->CardStatus)\r
1501 );\r
1502 if (!EFI_ERROR (Status)) {\r
1503 Status = SendCommand (\r
1504 CardData,\r
1505 SEND_STATUS,\r
1506 (CardData->Address << 16),\r
1507 NoData,\r
1508 NULL,\r
1509 0,\r
1510 ResponseR1,\r
1511 TIMEOUT_COMMAND,\r
1512 (UINT32*)&(CardData->CardStatus)\r
1513 );\r
1514 if (EFI_ERROR (Status)) {\r
1515 DEBUG((EFI_D_ERROR, "SWITCH Power Class Fail Status = 0x%x\n", Status));\r
1516 }\r
1517 //gBS->Stall (10 * 1000);\r
1518 }\r
1519 }\r
1520\r
1521\r
1522\r
1523 } else {\r
1524\r
1525\r
1526 DEBUG((EFI_D_ERROR, "MMC Card version %d only supportes 1 bits at lower transfer speed\n",CardData->CSDRegister.SPEC_VERS));\r
1527 }\r
1528 } else {\r
1529 //\r
1530 // Pin 1, at power up this line has a 50KOhm pull up enabled in the card.\r
1531 // This pull-up should be disconnected by the user, during regular data transfer,\r
1532 // with SET_CLR_CARD_DETECT (ACMD42) command\r
1533 //\r
1534 Status = SendAppCommand (\r
1535 CardData,\r
1536 SET_CLR_CARD_DETECT,\r
1537 0,\r
1538 NoData,\r
1539 NULL,\r
1540 0,\r
1541 ResponseR1,\r
1542 TIMEOUT_COMMAND,\r
1543 (UINT32*)&(CardData->CardStatus)\r
1544 );\r
1545 if (EFI_ERROR (Status)) {\r
1546 DEBUG((EFI_D_ERROR, "SET_CLR_CARD_DETECT Fail Status = 0x%x\n", Status));\r
1547 goto Exit;\r
1548 }\r
1549\r
1550 /*\r
1551 //\r
1552 // Don't rely on SCR and SD status, some cards have unexpected SCR.\r
1553 // It only sets private section, the other bits are 0\r
1554 // such as Sandisk Ultra II 4.0G, KinSton mini SD 128M, Toshiba 2.0GB\r
1555 // Some card even fail this command, KinSton SD 4GB\r
1556 //\r
1557 Status = SendAppCommand (\r
1558 CardData,\r
1559 SEND_SCR,\r
1560 0,\r
1561 InData,\r
1562 (UINT8*)&(CardData->SCRRegister),\r
1563 sizeof(SCR),\r
1564 ResponseR1,\r
1565 TIMEOUT_COMMAND,\r
1566 (UINT32*)&(CardData->CardStatus)\r
1567 );\r
1568 if (EFI_ERROR (Status)) {\r
1569 goto Exit;\r
1570 }\r
1571\r
1572 //\r
1573 // SD memory card at least supports 1 and 4 bits.\r
1574 //\r
1575 // ASSERT ((CardData->SCRRegister.SD_BUS_WIDTH & (BIT0 | BIT2)) == (BIT0 | BIT2));\r
1576 */\r
1577\r
1578 //\r
1579 // Set Bus Width to 4\r
1580 //\r
1581 Status = SendAppCommand (\r
1582 CardData,\r
1583 SET_BUS_WIDTH,\r
1584 SD_BUS_WIDTH_4,\r
1585 NoData,\r
1586 NULL,\r
1587 0,\r
1588 ResponseR1,\r
1589 TIMEOUT_COMMAND,\r
1590 (UINT32*)&(CardData->CardStatus)\r
1591 );\r
1592 if (EFI_ERROR (Status)) {\r
1593 DEBUG((EFI_D_ERROR, "SET_BUS_WIDTH 4 bits Fail Status = 0x%x\n", Status));\r
1594 goto Exit;\r
1595 }\r
1596\r
1597 Status = SDHostIo->SetBusWidth (SDHostIo, 4);\r
1598 if (EFI_ERROR (Status)) {\r
1599 goto Exit;\r
1600 }\r
1601 CardData->CurrentBusWidth = 4;\r
1602\r
1603\r
1604 if ((SDHostIo->HostCapability.HighSpeedSupport == FALSE) ||\r
1605 ((CardData->CSDRegister.CCC & BIT10) != BIT10)) {\r
1606 //\r
1607 // Host must support high speed\r
1608 // Card must support Switch function\r
1609 //\r
1610 goto Exit;\r
1611 }\r
1612\r
1613 //\r
1614 //Mode = 0, group 1, function 1, check operation\r
1615 //\r
1616 Argument = 0xFFFF01;\r
1617 ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS));\r
1618\r
1619 Status = SendCommand (\r
1620 CardData,\r
1621 SWITCH_FUNC,\r
1622 Argument,\r
1623 InData,\r
1624 CardData->AlignedBuffer,\r
1625 sizeof (SWITCH_STATUS),\r
1626 ResponseR1,\r
1627 TIMEOUT_COMMAND,\r
1628 (UINT32*)&(CardData->CardStatus)\r
1629 );\r
1630 if (EFI_ERROR (Status)) {\r
1631 goto Exit;\r
1632 }\r
1633 CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS));\r
1634\r
1635 if ((CardData->SwitchStatus.DataStructureVersion == 0x0) ||\r
1636 ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) {\r
1637 //\r
1638 // 1. SD 1.1 card does not suppport busy bit\r
1639 // 2. Ready state\r
1640 //\r
1641 //\r
1642\r
1643 //\r
1644 //Mode = 1, group 1, function 1, BIT31 set means set mode\r
1645 //\r
1646 Argument = 0xFFFF01 | BIT31;\r
1647 ZeroMem (&CardData->SwitchStatus, sizeof (SWITCH_STATUS));\r
1648\r
1649 Status = SendCommand (\r
1650 CardData,\r
1651 SWITCH_FUNC,\r
1652 Argument,\r
1653 InData,\r
1654 CardData->AlignedBuffer,\r
1655 sizeof (SWITCH_STATUS),\r
1656 ResponseR1,\r
1657 TIMEOUT_COMMAND,\r
1658 (UINT32*)&(CardData->CardStatus)\r
1659 );\r
1660 if (EFI_ERROR (Status)) {\r
1661 goto Exit;\r
1662 }\r
1663 CopyMem (&(CardData->SwitchStatus), CardData->AlignedBuffer, sizeof (SWITCH_STATUS));\r
1664\r
1665 if ((CardData->SwitchStatus.DataStructureVersion == 0x0) ||\r
1666 ((CardData->SwitchStatus.Group1BusyStatus & BIT1) != BIT1)) {\r
1667 //\r
1668 // 1. SD 1.1 card does not suppport busy bit\r
1669 // 2. Ready state\r
1670 //\r
1671\r
1672 //\r
1673 // 8 clocks, (1/ 25M) * 8 ==> 320 us, so 1ms > 0.32 ms\r
1674 //\r
1675 gBS->Stall (1000);\r
1676\r
1677 //\r
1678 //Change host clock\r
1679 //\r
1680 Status = SDHostIo->SetClockFrequency (SDHostIo, FREQUENCY_SD_PP_HIGH);\r
1681 if (EFI_ERROR (Status)) {\r
1682 goto Exit;\r
1683 }\r
1684\r
1685 }\r
1686 }\r
1687 }\r
1688 if (!((CardData->ExtCSDRegister.CARD_TYPE & BIT2) ||\r
1689 (CardData->ExtCSDRegister.CARD_TYPE & BIT3))) {\r
1690\r
1691 //\r
1692 // Set Block Length, to improve compatibility in case of some cards\r
1693 //\r
1694 Status = SendCommand (\r
1695 CardData,\r
1696 SET_BLOCKLEN,\r
1697 512,\r
1698 NoData,\r
1699 NULL,\r
1700 0,\r
1701 ResponseR1,\r
1702 TIMEOUT_COMMAND,\r
1703 (UINT32*)&(CardData->CardStatus)\r
1704 );\r
1705 if (EFI_ERROR (Status)) {\r
1706 DEBUG((EFI_D_ERROR, "SET_BLOCKLEN Fail Status = 0x%x\n", Status));\r
1707 goto Exit;\r
1708 }\r
1709 }\r
1710 SDHostIo->SetBlockLength (SDHostIo, 512);\r
1711\r
1712\r
1713Exit:\r
1714 return Status;\r
1715}\r
1716\r