• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   This file provides some helper functions which are specific for SD card device.
3 
4   Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "DwMmcHcDxe.h"
16 
17 /**
18   Send command GO_IDLE_STATE to the device to make it go to Idle State.
19 
20   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
21 
22   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
23   @param[in] Slot           The slot number of the SD card to send the command to.
24 
25   @retval EFI_SUCCESS       The SD device is reset correctly.
26   @retval Others            The device reset fails.
27 
28 **/
29 EFI_STATUS
SdCardReset(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)30 SdCardReset (
31   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
32   IN UINT8                              Slot
33   )
34 {
35   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
36   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
37   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
38   EFI_STATUS                            Status;
39 
40   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
41   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
42   ZeroMem (&Packet, sizeof (Packet));
43 
44   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
45   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
46   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
47 
48   SdMmcCmdBlk.CommandIndex = SD_GO_IDLE_STATE;
49   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBc;
50 
51   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
52 
53   return Status;
54 }
55 
56 /**
57   Send command SEND_IF_COND to the device to inquiry the SD Memory Card interface
58   condition.
59 
60   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
61 
62   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
63   @param[in] Slot           The slot number of the SD card to send the command to.
64   @param[in] SupplyVoltage  The supplied voltage by the host.
65   @param[in] CheckPattern   The check pattern to be sent to the device.
66 
67   @retval EFI_SUCCESS       The operation is done correctly.
68   @retval Others            The operation fails.
69 
70 **/
71 EFI_STATUS
SdCardVoltageCheck(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT8 SupplyVoltage,IN UINT8 CheckPattern)72 SdCardVoltageCheck (
73   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
74   IN UINT8                              Slot,
75   IN UINT8                              SupplyVoltage,
76   IN UINT8                              CheckPattern
77   )
78 {
79   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
80   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
81   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
82   EFI_STATUS                            Status;
83 
84   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
85   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
86   ZeroMem (&Packet, sizeof (Packet));
87 
88   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
89   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
90   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
91 
92   SdMmcCmdBlk.CommandIndex = SD_SEND_IF_COND;
93   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
94   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR7;
95   SdMmcCmdBlk.CommandArgument = (SupplyVoltage << 8) | CheckPattern;
96 
97   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
98 
99   if (!EFI_ERROR (Status)) {
100     if (SdMmcStatusBlk.Resp0 != SdMmcCmdBlk.CommandArgument) {
101       return EFI_DEVICE_ERROR;
102     }
103   }
104 
105   return Status;
106 }
107 
108 /**
109   Send command SDIO_SEND_OP_COND to the device to see whether it is SDIO device.
110 
111   Refer to SDIO Simplified Spec 3 Section 3.2 for details.
112 
113   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
114   @param[in] Slot           The slot number of the SD card to send the command to.
115   @param[in] VoltageWindow  The supply voltage window.
116   @param[in] S18R           The boolean to show if it should switch to 1.8v.
117 
118   @retval EFI_SUCCESS       The operation is done correctly.
119   @retval Others            The operation fails.
120 
121 **/
122 EFI_STATUS
SdioSendOpCond(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT32 VoltageWindow,IN BOOLEAN S18R)123 SdioSendOpCond (
124   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
125   IN UINT8                              Slot,
126   IN UINT32                             VoltageWindow,
127   IN BOOLEAN                            S18R
128   )
129 {
130   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
131   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
132   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
133   EFI_STATUS                            Status;
134   UINT32                                Switch;
135 
136   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
137   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
138   ZeroMem (&Packet, sizeof (Packet));
139 
140   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
141   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
142   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
143 
144   SdMmcCmdBlk.CommandIndex = SDIO_SEND_OP_COND;
145   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
146   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR4;
147 
148   Switch = S18R ? BIT24 : 0;
149 
150   SdMmcCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch;
151 
152   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
153 
154   return Status;
155 }
156 
157 /**
158   Send command SD_SEND_OP_COND to the device to see whether it is SDIO device.
159 
160   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
161 
162   @param[in]  PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
163   @param[in]  Slot           The slot number of the SD card to send the command to.
164   @param[in]  Rca            The relative device address of addressed device.
165   @param[in]  VoltageWindow  The supply voltage window.
166   @param[in]  S18R           The boolean to show if it should switch to 1.8v.
167   @param[in]  Xpc            The boolean to show if it should provide 0.36w power control.
168   @param[in]  Hcs            The boolean to show if it support host capacity info.
169   @param[out] Ocr            The buffer to store returned OCR register value.
170 
171   @retval EFI_SUCCESS        The operation is done correctly.
172   @retval Others             The operation fails.
173 
174 **/
175 EFI_STATUS
SdCardSendOpCond(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN UINT32 VoltageWindow,IN BOOLEAN S18R,IN BOOLEAN Xpc,IN BOOLEAN Hcs,OUT UINT32 * Ocr)176 SdCardSendOpCond (
177   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
178   IN     UINT8                          Slot,
179   IN     UINT16                         Rca,
180   IN     UINT32                         VoltageWindow,
181   IN     BOOLEAN                        S18R,
182   IN     BOOLEAN                        Xpc,
183   IN     BOOLEAN                        Hcs,
184      OUT UINT32                         *Ocr
185   )
186 {
187   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
188   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
189   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
190   EFI_STATUS                            Status;
191   UINT32                                Switch;
192   UINT32                                MaxPower;
193   UINT32                                HostCapacity;
194 
195   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
196   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
197   ZeroMem (&Packet, sizeof (Packet));
198 
199   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
200   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
201   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
202 
203   SdMmcCmdBlk.CommandIndex = SD_APP_CMD;
204   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
205   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
206   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
207 
208   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
209   if (EFI_ERROR (Status)) {
210     return Status;
211   }
212 
213   SdMmcCmdBlk.CommandIndex = SD_SEND_OP_COND;
214   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
215   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR3;
216 
217   Switch       = S18R ? BIT24 : 0;
218   MaxPower     = Xpc ? BIT28 : 0;
219   HostCapacity = Hcs ? BIT30 : 0;
220 
221   SdMmcCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch | MaxPower | HostCapacity;
222 
223   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
224   if (!EFI_ERROR (Status)) {
225     //
226     // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
227     //
228     *Ocr = SdMmcStatusBlk.Resp0;
229   }
230 
231   return Status;
232 }
233 
234 /**
235   Broadcast command ALL_SEND_CID to the bus to ask all the SD devices to send the
236   data of their CID registers.
237 
238   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
239 
240   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
241   @param[in] Slot           The slot number of the SD card to send the command to.
242 
243   @retval EFI_SUCCESS       The operation is done correctly.
244   @retval Others            The operation fails.
245 
246 **/
247 EFI_STATUS
SdCardAllSendCid(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)248 SdCardAllSendCid (
249   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
250   IN UINT8                              Slot
251   )
252 {
253   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
254   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
255   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
256   EFI_STATUS                            Status;
257 
258   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
259   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
260   ZeroMem (&Packet, sizeof (Packet));
261 
262   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
263   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
264   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
265 
266   SdMmcCmdBlk.CommandIndex = SD_ALL_SEND_CID;
267   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
268   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
269 
270   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
271 
272   return Status;
273 }
274 
275 /**
276   Send command SET_RELATIVE_ADDR to the SD device to assign a Relative device
277   Address (RCA).
278 
279   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
280 
281   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
282   @param[in]  Slot          The slot number of the SD card to send the command to.
283   @param[out] Rca           The relative device address to assign.
284 
285   @retval EFI_SUCCESS       The operation is done correctly.
286   @retval Others            The operation fails.
287 
288 **/
289 EFI_STATUS
SdCardSetRca(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,OUT UINT16 * Rca)290 SdCardSetRca (
291   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
292   IN     UINT8                          Slot,
293      OUT UINT16                         *Rca
294   )
295 {
296   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
297   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
298   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
299   EFI_STATUS                            Status;
300 
301   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
302   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
303   ZeroMem (&Packet, sizeof (Packet));
304 
305   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
306   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
307   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
308 
309   SdMmcCmdBlk.CommandIndex = SD_SET_RELATIVE_ADDR;
310   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
311   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR6;
312 
313   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
314   if (!EFI_ERROR (Status)) {
315     *Rca = (UINT16)(SdMmcStatusBlk.Resp0 >> 16);
316   }
317 
318   return Status;
319 }
320 
321 /**
322   Send command SEND_CSD to the SD device to get the data of the CSD register.
323 
324   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
325 
326   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
327   @param[in]  Slot          The slot number of the SD card to send the command to.
328   @param[in]  Rca           The relative device address of selected device.
329   @param[out] Csd           The buffer to store the content of the CSD register.
330                             Note the caller should ignore the lowest byte of this
331                             buffer as the content of this byte is meaningless even
332                             if the operation succeeds.
333 
334   @retval EFI_SUCCESS       The operation is done correctly.
335   @retval Others            The operation fails.
336 
337 **/
338 EFI_STATUS
SdCardGetCsd(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,OUT SD_CSD * Csd)339 SdCardGetCsd (
340   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
341   IN     UINT8                          Slot,
342   IN     UINT16                         Rca,
343      OUT SD_CSD                         *Csd
344   )
345 {
346   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
347   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
348   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
349   EFI_STATUS                            Status;
350 
351   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
352   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
353   ZeroMem (&Packet, sizeof (Packet));
354 
355   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
356   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
357   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
358 
359   SdMmcCmdBlk.CommandIndex = SD_SEND_CSD;
360   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
361   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
362   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
363 
364   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
365   if (!EFI_ERROR (Status)) {
366     //
367     // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
368     //
369     CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CSD) - 1);
370   }
371 
372   return Status;
373 }
374 
375 /**
376   Send command SEND_CSD to the SD device to get the data of the CSD register.
377 
378   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
379 
380   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
381   @param[in]  Slot          The slot number of the SD card to send the command to.
382   @param[in]  Rca           The relative device address of selected device.
383   @param[out] Scr           The buffer to store the content of the SCR register.
384 
385   @retval EFI_SUCCESS       The operation is done correctly.
386   @retval Others            The operation fails.
387 
388 **/
389 EFI_STATUS
SdCardGetScr(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,OUT SD_SCR * Scr)390 SdCardGetScr (
391   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
392   IN     UINT8                          Slot,
393   IN     UINT16                         Rca,
394      OUT SD_SCR                         *Scr
395   )
396 {
397   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
398   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
399   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
400   EFI_STATUS                            Status;
401 
402   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
403   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
404   ZeroMem (&Packet, sizeof (Packet));
405 
406   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
407   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
408   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
409 
410   SdMmcCmdBlk.CommandIndex = SD_APP_CMD;
411   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
412   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
413   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
414 
415   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
416   if (EFI_ERROR (Status)) {
417     return Status;
418   }
419 
420   SdMmcCmdBlk.CommandIndex = SD_SEND_SCR;
421   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAdtc;
422   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
423 
424   Packet.InDataBuffer     = Scr;
425   Packet.InTransferLength = sizeof (SD_SCR);
426 
427   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
428 
429   return Status;
430 }
431 
432 /**
433   Send command SELECT_DESELECT_CARD to the SD device to select/deselect it.
434 
435   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
436 
437   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
438   @param[in]  Slot          The slot number of the SD card to send the command to.
439   @param[in]  Rca           The relative device address of selected device.
440 
441   @retval EFI_SUCCESS       The operation is done correctly.
442   @retval Others            The operation fails.
443 
444 **/
445 EFI_STATUS
SdCardSelect(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca)446 SdCardSelect (
447   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
448   IN UINT8                              Slot,
449   IN UINT16                             Rca
450   )
451 {
452   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
453   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
454   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
455   EFI_STATUS                            Status;
456 
457   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
458   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
459   ZeroMem (&Packet, sizeof (Packet));
460 
461   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
462   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
463   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
464 
465   SdMmcCmdBlk.CommandIndex = SD_SELECT_DESELECT_CARD;
466   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
467   if (Rca != 0) {
468     SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;
469   }
470   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
471 
472   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
473 
474   return Status;
475 }
476 
477 /**
478   Send command VOLTAGE_SWITCH to the SD device to switch the voltage of the device.
479 
480   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
481 
482   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
483   @param[in]  Slot          The slot number of the SD card to send the command to.
484 
485   @retval EFI_SUCCESS       The operation is done correctly.
486   @retval Others            The operation fails.
487 
488 **/
489 EFI_STATUS
SdCardVoltageSwitch(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)490 SdCardVoltageSwitch (
491   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
492   IN UINT8                              Slot
493   )
494 {
495   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
496   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
497   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
498   EFI_STATUS                            Status;
499 
500   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
501   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
502   ZeroMem (&Packet, sizeof (Packet));
503 
504   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
505   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
506   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
507 
508   SdMmcCmdBlk.CommandIndex = SD_VOLTAGE_SWITCH;
509   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
510   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
511   SdMmcCmdBlk.CommandArgument = 0;
512 
513   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
514 
515   return Status;
516 }
517 
518 /**
519   Send command SET_BUS_WIDTH to the SD device to set the bus width.
520 
521   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
522 
523   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
524   @param[in] Slot           The slot number of the SD card to send the command to.
525   @param[in] Rca            The relative device address of addressed device.
526   @param[in] BusWidth       The bus width to be set, it could be 1 or 4.
527 
528   @retval EFI_SUCCESS       The operation is done correctly.
529   @retval Others            The operation fails.
530 
531 **/
532 EFI_STATUS
SdCardSetBusWidth(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN UINT8 BusWidth)533 SdCardSetBusWidth (
534   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
535   IN UINT8                              Slot,
536   IN UINT16                             Rca,
537   IN UINT8                              BusWidth
538   )
539 {
540   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
541   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
542   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
543   EFI_STATUS                            Status;
544   UINT8                                 Value;
545 
546   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
547   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
548   ZeroMem (&Packet, sizeof (Packet));
549 
550   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
551   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
552   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
553 
554   SdMmcCmdBlk.CommandIndex = SD_APP_CMD;
555   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
556   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
557   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
558 
559   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
560   if (EFI_ERROR (Status)) {
561     return Status;
562   }
563 
564   SdMmcCmdBlk.CommandIndex = SD_SET_BUS_WIDTH;
565   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
566   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
567 
568   if (BusWidth == 1) {
569     Value = 0;
570   } else if (BusWidth == 4) {
571     Value = 2;
572   } else {
573     return EFI_INVALID_PARAMETER;
574   }
575 
576   SdMmcCmdBlk.CommandArgument = Value & 0x3;
577 
578   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
579   return Status;
580 }
581 
582 /**
583   Send command SWITCH_FUNC to the SD device to check switchable function or switch card function.
584 
585   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
586 
587   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
588   @param[in]  Slot          The slot number of the SD card to send the command to.
589   @param[in]  AccessMode    The value for access mode group.
590   @param[in]  CommandSystem The value for command set group.
591   @param[in]  DriveStrength The value for drive length group.
592   @param[in]  PowerLimit    The value for power limit group.
593   @param[in]  Mode          Switch or check function.
594   @param[out] SwitchResp    The return switch function status.
595 
596   @retval EFI_SUCCESS       The operation is done correctly.
597   @retval Others            The operation fails.
598 
599 **/
600 EFI_STATUS
SdCardSwitch(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT8 AccessMode,IN UINT8 CommandSystem,IN UINT8 DriveStrength,IN UINT8 PowerLimit,IN BOOLEAN Mode,OUT UINT8 * SwitchResp)601 SdCardSwitch (
602   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
603   IN     UINT8                          Slot,
604   IN     UINT8                          AccessMode,
605   IN     UINT8                          CommandSystem,
606   IN     UINT8                          DriveStrength,
607   IN     UINT8                          PowerLimit,
608   IN     BOOLEAN                        Mode,
609      OUT UINT8                          *SwitchResp
610   )
611 {
612   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
613   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
614   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
615   EFI_STATUS                            Status;
616   UINT32                                ModeValue;
617 
618   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
619   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
620   ZeroMem (&Packet, sizeof (Packet));
621 
622   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
623   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
624   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
625 
626   SdMmcCmdBlk.CommandIndex = SD_SWITCH_FUNC;
627   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAdtc;
628   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
629 
630   ModeValue = Mode ? BIT31 : 0;
631   SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \
632                                 ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \
633                                 ModeValue;
634 
635   Packet.InDataBuffer     = SwitchResp;
636   Packet.InTransferLength = 64;
637 
638   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
639 
640   return Status;
641 }
642 
643 /**
644   Send command SEND_STATUS to the addressed SD device to get its status register.
645 
646   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
647 
648   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
649   @param[in]  Slot          The slot number of the SD card to send the command to.
650   @param[in]  Rca           The relative device address of addressed device.
651   @param[out] DevStatus     The returned device status.
652 
653   @retval EFI_SUCCESS       The operation is done correctly.
654   @retval Others            The operation fails.
655 
656 **/
657 EFI_STATUS
SdCardSendStatus(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,OUT UINT32 * DevStatus)658 SdCardSendStatus (
659   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
660   IN     UINT8                          Slot,
661   IN     UINT16                         Rca,
662      OUT UINT32                         *DevStatus
663   )
664 {
665   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
666   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
667   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
668   EFI_STATUS                            Status;
669 
670   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
671   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
672   ZeroMem (&Packet, sizeof (Packet));
673 
674   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
675   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
676   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
677 
678   SdMmcCmdBlk.CommandIndex = SD_SEND_STATUS;
679   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
680   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
681   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
682 
683   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
684   if (!EFI_ERROR (Status)) {
685     *DevStatus = SdMmcStatusBlk.Resp0;
686   }
687 
688   return Status;
689 }
690 
691 /**
692   Send command SEND_TUNING_BLOCK to the SD device for HS200 optimal sampling point
693   detection.
694 
695   It may be sent up to 40 times until the host finishes the tuning procedure.
696 
697   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
698 
699   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
700   @param[in] Slot           The slot number of the SD card to send the command to.
701 
702   @retval EFI_SUCCESS       The operation is done correctly.
703   @retval Others            The operation fails.
704 
705 **/
706 EFI_STATUS
SdCardSendTuningBlk(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)707 SdCardSendTuningBlk (
708   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
709   IN UINT8                              Slot
710   )
711 {
712   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
713   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
714   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
715   EFI_STATUS                            Status;
716   UINT8                                 TuningBlock[64];
717 
718   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
719   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
720   ZeroMem (&Packet, sizeof (Packet));
721 
722   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
723   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
724   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
725 
726   SdMmcCmdBlk.CommandIndex = SD_SEND_TUNING_BLOCK;
727   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAdtc;
728   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
729   SdMmcCmdBlk.CommandArgument = 0;
730 
731   Packet.InDataBuffer     = TuningBlock;
732   Packet.InTransferLength = sizeof (TuningBlock);
733 
734   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
735 
736   return Status;
737 }
738 
739 /**
740   Switch the bus width to specified width.
741 
742   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and
743   SD Host Controller Simplified Spec 3.0 section Figure 3-7 for details.
744 
745   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
746   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
747   @param[in] Slot           The slot number of the SD card to send the command to.
748   @param[in] Rca            The relative device address to be assigned.
749   @param[in] BusWidth       The bus width to be set, it could be 4 or 8.
750 
751   @retval EFI_SUCCESS       The operation is done correctly.
752   @retval Others            The operation fails.
753 
754 **/
755 EFI_STATUS
SdCardSwitchBusWidth(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN BOOLEAN IsDdr,IN UINT8 BusWidth)756 SdCardSwitchBusWidth (
757   IN EFI_PCI_IO_PROTOCOL                *PciIo,
758   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
759   IN UINT8                              Slot,
760   IN UINT16                             Rca,
761   IN BOOLEAN                            IsDdr,
762   IN UINT8                              BusWidth
763   )
764 {
765   EFI_STATUS          Status;
766   UINT32              DevStatus;
767 
768   Status = SdCardSetBusWidth (PassThru, Slot, Rca, BusWidth);
769   if (EFI_ERROR (Status)) {
770     DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: Switch to bus width %d fails with %r\n", BusWidth, Status));
771     return Status;
772   }
773 
774   Status = SdCardSendStatus (PassThru, Slot, Rca, &DevStatus);
775   if (EFI_ERROR (Status)) {
776     DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: Send status fails with %r\n", Status));
777     return Status;
778   }
779   //
780   // Check the switch operation is really successful or not.
781   //
782   if ((DevStatus >> 16) != 0) {
783     DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));
784     return EFI_DEVICE_ERROR;
785   }
786 
787   Status = DwMmcHcSetBusWidth (PciIo, Slot, IsDdr, BusWidth);
788 
789   return Status;
790 }
791 
792 /**
793   Switch the high speed timing according to request.
794 
795   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and
796   SD Host Controller Simplified Spec 3.0 section Figure 2-29 for details.
797 
798   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
799   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
800   @param[in] Slot           The slot number of the SD card to send the command to.
801   @param[in] Rca            The relative device address to be assigned.
802   @param[in] S18A           The boolean to show if it's a UHS-I SD card.
803   @param[in] BusWidths      The bus width of the SD card.
804 
805   @retval EFI_SUCCESS       The operation is done correctly.
806   @retval Others            The operation fails.
807 
808 **/
809 EFI_STATUS
SdCardSetBusMode(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN BOOLEAN S18A,IN UINT32 BusWidths)810 SdCardSetBusMode (
811   IN EFI_PCI_IO_PROTOCOL                *PciIo,
812   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
813   IN UINT8                              Slot,
814   IN UINT16                             Rca,
815   IN BOOLEAN                            S18A,
816   IN UINT32                             BusWidths
817   )
818 {
819   EFI_STATUS                   Status;
820   DW_MMC_HC_SLOT_CAP           *Capability;
821   UINT32                       ClockFreq;
822   UINT8                        AccessMode;
823   UINT8                        SwitchResp[64];
824   DW_MMC_HC_PRIVATE_DATA       *Private;
825   BOOLEAN                      IsDdr;
826 
827   Private = DW_MMC_HC_PRIVATE_FROM_THIS (PassThru);
828 
829   Capability = &Private->Capability[Slot];
830 
831   if ((Capability->BusWidth == 1) || (Capability->BusWidth == 4)) {
832     BusWidths &= Capability[Slot].BusWidth;
833   } else {
834     DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: BusWidths (%d) in capability are wrong\n", Capability->BusWidth));
835     return EFI_INVALID_PARAMETER;
836   }
837 
838   if (BusWidths == 0) {
839     DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: Get wrong BusWidths:%d\n", BusWidths));
840     return EFI_INVALID_PARAMETER;
841   }
842 
843   if (Private->Capability[Slot].Ddr50) {
844     IsDdr = TRUE;
845   } else {
846     IsDdr = FALSE;
847   }
848 
849   Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidths);
850   if (EFI_ERROR (Status)) {
851     DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: Executing SdCardSwitchBusWidth fails with %r\n", Status));
852     return Status;
853   }
854 
855   //
856   // Get the supported bus speed from SWITCH cmd return data group #1.
857   //
858   Status = SdCardSwitch (PassThru, Slot, 0xF, 0xF, 0xF, 0xF, FALSE, SwitchResp);
859   if (EFI_ERROR (Status)) {
860     return Status;
861   }
862   //
863   // Calculate supported bus speed/bus width/clock frequency by host and device capability.
864   //
865   ClockFreq = 0;
866   if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {
867     ClockFreq = 208;
868     AccessMode = 3;
869   } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {
870     ClockFreq = 100;
871     AccessMode = 2;
872   } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {
873     ClockFreq = 50;
874     AccessMode = 4;
875   } else if ((SwitchResp[13] & BIT1) != 0) {
876     ClockFreq = 50;
877     AccessMode = 1;
878   } else {
879     ClockFreq = 25;
880     AccessMode = 0;
881   }
882 
883   Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);
884   if (EFI_ERROR (Status)) {
885     return Status;
886   }
887 
888   if ((SwitchResp[16] & 0xF) != AccessMode) {
889     DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d fails! The Switch response is 0x%1x\n", AccessMode, ClockFreq, SwitchResp[16] & 0xF));
890     return EFI_DEVICE_ERROR;
891   }
892 
893   DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d \n", AccessMode, ClockFreq));
894 
895   Status = DwMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, *Capability);
896   if (EFI_ERROR (Status)) {
897     return Status;
898   }
899 
900   return Status;
901 }
902 
903 /**
904   Execute SD device identification procedure.
905 
906   Refer to SD Physical Layer Simplified Spec 4.1 Section 3.6 for details.
907 
908   @param[in] Private        A pointer to the DW_MMC_HC_PRIVATE_DATA instance.
909   @param[in] Slot           The slot number of the SD card to send the command to.
910 
911   @retval EFI_SUCCESS       There is a SD card.
912   @retval Others            There is not a SD card.
913 
914 **/
915 EFI_STATUS
SdCardIdentification(IN DW_MMC_HC_PRIVATE_DATA * Private,IN UINT8 Slot)916 SdCardIdentification (
917   IN DW_MMC_HC_PRIVATE_DATA             *Private,
918   IN UINT8                              Slot
919   )
920 {
921   EFI_STATUS                     Status;
922   EFI_PCI_IO_PROTOCOL            *PciIo;
923   EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru;
924   UINT32                         Ocr;
925   UINT16                         Rca;
926   BOOLEAN                        Xpc;
927   BOOLEAN                        S18r;
928   UINT64                         MaxCurrent;
929   SD_SCR                         Scr;
930   SD_CSD                         Csd;
931 
932   PciIo    = Private->PciIo;
933   PassThru = &Private->PassThru;
934   //
935   // 1. Send Cmd0 to the device
936   //
937   Status = SdCardReset (PassThru, Slot);
938   if (EFI_ERROR (Status)) {
939     DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd0 fails with %r\n", Status));
940     return Status;
941   }
942   MicroSecondDelay (10000);
943   //
944   // 2. Send Cmd8 to the device
945   //
946   Status = SdCardVoltageCheck (PassThru, Slot, 0x1, 0xFF);
947   if (EFI_ERROR (Status)) {
948     DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd8 fails with %r\n", Status));
949     return Status;
950   }
951   //
952   // 3. Send Acmd41 with voltage window 0 to the device
953   //
954   Status = SdCardSendOpCond (PassThru, Slot, 0, 0, FALSE, FALSE, FALSE, &Ocr);
955   if (EFI_ERROR (Status)) {
956     DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing SdCardSendOpCond fails with %r\n", Status));
957     return EFI_DEVICE_ERROR;
958   }
959 
960   if (Private->Capability[Slot].Voltage33 != 0) {
961     //
962     // Support 3.3V
963     //
964     MaxCurrent = ((UINT32)Private->MaxCurrent[Slot] & 0xFF) * 4;
965     S18r = FALSE;
966   } else if (Private->Capability[Slot].Voltage30 != 0) {
967     //
968     // Support 3.0V
969     //
970     MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 8) & 0xFF) * 4;
971     S18r = FALSE;
972   } else if (Private->Capability[Slot].Voltage18 != 0) {
973     //
974     // Support 1.8V
975     //
976     MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 16) & 0xFF) * 4;
977     S18r = TRUE;
978   } else {
979     ASSERT (FALSE);
980     return EFI_DEVICE_ERROR;
981   }
982 
983   if (MaxCurrent >= 150) {
984     Xpc = TRUE;
985   } else {
986     Xpc = FALSE;
987   }
988 
989   //
990   // 4. Repeatly send Acmd41 with supply voltage window to the device.
991   //    Note here we only support the cards complied with SD physical
992   //    layer simplified spec version 2.0 and version 3.0 and above.
993   //
994   do {
995     Status = SdCardSendOpCond (PassThru, Slot, 0, Ocr, S18r, Xpc, TRUE, &Ocr);
996     if (EFI_ERROR (Status)) {
997       DEBUG ((DEBUG_ERROR, "SdCardIdentification: SdCardSendOpCond fails with %r Ocr %x, S18r %x, Xpc %x\n", Status, Ocr, S18r, Xpc));
998       return EFI_DEVICE_ERROR;
999     }
1000   } while ((Ocr & BIT31) == 0);
1001 
1002   Status = SdCardAllSendCid (PassThru, Slot);
1003   if (EFI_ERROR (Status)) {
1004     DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardAllSendCid fails with %r\n", Status));
1005     return Status;
1006   }
1007 
1008   Status = SdCardSetRca (PassThru, Slot, &Rca);
1009   if (EFI_ERROR (Status)) {
1010     DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardSetRca fails with %r\n", Status));
1011     return Status;
1012   }
1013 
1014   Status = SdCardGetCsd (PassThru, Slot, Rca, &Csd);
1015   if (EFI_ERROR (Status)) {
1016     DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardGetCsd fails with %r\n", Status));
1017     return Status;
1018   }
1019 
1020   Status = SdCardSelect (PassThru, Slot, Rca);
1021   if (EFI_ERROR (Status)) {
1022     DEBUG ((DEBUG_ERROR, "SdCardIdentification: Selecting card fails with %r\n", Status));
1023     return Status;
1024   }
1025 
1026   Status = SdCardGetScr (PassThru, Slot, Rca, &Scr);
1027   if (EFI_ERROR (Status)) {
1028     DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardGetScr fails with %r\n", Status));
1029     return Status;
1030   }
1031 
1032   //
1033   // Enter Data Tranfer Mode.
1034   //
1035   DEBUG ((DEBUG_INFO, "SdCardIdentification: Found a SD device at slot [%d]\n", Slot));
1036   Private->Slot[Slot].CardType = SdCardType;
1037 
1038   Status = SdCardSetBusMode (PciIo, PassThru, Slot, Rca, S18r, Scr.SdBusWidths);
1039   if (EFI_ERROR (Status)) {
1040     return Status;
1041   }
1042 
1043   Private->Slot[Slot].Initialized = TRUE;
1044 
1045   return Status;
1046 }
1047