• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   This file provides some helper functions which are specific for EMMC 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 #define EMMC_GET_STATE(x)                   (((x) >> 9) & 0xf)
18 #define EMMC_STATE_IDLE                     0
19 #define EMMC_STATE_READY                    1
20 #define EMMC_STATE_IDENT                    2
21 #define EMMC_STATE_STBY                     3
22 #define EMMC_STATE_TRAN                     4
23 #define EMMC_STATE_DATA                     5
24 #define EMMC_STATE_RCV                      6
25 #define EMMC_STATE_PRG                      7
26 #define EMMC_STATE_DIS                      8
27 #define EMMC_STATE_BTST                     9
28 #define EMMC_STATE_SLP                      10
29 
30 #define EMMC_CMD1_CAPACITY_LESS_THAN_2GB    0x00FF8080 // Capacity <= 2GB, byte addressing used
31 #define EMMC_CMD1_CAPACITY_GREATER_THAN_2GB 0x40FF8080 // Capacity > 2GB, 512-byte sector addressing used
32 
33 /**
34   Send command GO_IDLE_STATE (CMD0 with argument of 0x00000000) to the device to
35   make it go to Idle State.
36 
37   Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
38 
39   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
40   @param[in] Slot           The slot number of the SD card to send the command to.
41 
42   @retval EFI_SUCCESS       The EMMC device is reset correctly.
43   @retval Others            The device reset fails.
44 
45 **/
46 EFI_STATUS
EmmcReset(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)47 EmmcReset (
48   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
49   IN UINT8                              Slot
50   )
51 {
52   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
53   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
54   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
55   EFI_STATUS                            Status;
56 
57   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
58   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
59   ZeroMem (&Packet, sizeof (Packet));
60 
61   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
62   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
63   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
64 
65   SdMmcCmdBlk.CommandIndex = EMMC_GO_IDLE_STATE;
66   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBc;
67   SdMmcCmdBlk.ResponseType = 0;
68   SdMmcCmdBlk.CommandArgument = 0;
69 
70   gBS->Stall (1000);
71 
72   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
73 
74   return Status;
75 }
76 
77 /**
78   Send command SEND_OP_COND to the EMMC device to get the data of the OCR register.
79 
80   Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
81 
82   @param[in]      PassThru  A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
83   @param[in]      Slot      The slot number of the SD card to send the command to.
84   @param[in, out] Argument  On input, the argument of SEND_OP_COND is to send to the device.
85                             On output, the argument is the value of OCR register.
86 
87   @retval EFI_SUCCESS       The operation is done correctly.
88   @retval Others            The operation fails.
89 
90 **/
91 EFI_STATUS
EmmcGetOcr(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN OUT UINT32 * Argument)92 EmmcGetOcr (
93   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
94   IN     UINT8                          Slot,
95   IN OUT UINT32                         *Argument
96   )
97 {
98   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
99   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
100   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
101   EFI_STATUS                            Status;
102 
103   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
104   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
105   ZeroMem (&Packet, sizeof (Packet));
106 
107   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
108   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
109   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
110 
111   SdMmcCmdBlk.CommandIndex = EMMC_SEND_OP_COND;
112   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
113   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR3;
114   SdMmcCmdBlk.CommandArgument = *Argument;
115 
116   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
117   if (!EFI_ERROR (Status)) {
118     //
119     // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
120     //
121     *Argument = SdMmcStatusBlk.Resp0;
122   }
123 
124   return Status;
125 }
126 
127 /**
128   Broadcast command ALL_SEND_CID to the bus to ask all the EMMC devices to send the
129   data of their CID registers.
130 
131   Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
132 
133   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
134   @param[in] Slot           The slot number of the SD card to send the command to.
135 
136   @retval EFI_SUCCESS       The operation is done correctly.
137   @retval Others            The operation fails.
138 
139 **/
140 EFI_STATUS
EmmcGetAllCid(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)141 EmmcGetAllCid (
142   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
143   IN UINT8                              Slot
144   )
145 {
146   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
147   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
148   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
149   EFI_STATUS                            Status;
150 
151   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
152   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
153   ZeroMem (&Packet, sizeof (Packet));
154 
155   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
156   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
157   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
158 
159   SdMmcCmdBlk.CommandIndex = EMMC_ALL_SEND_CID;
160   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
161   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
162   SdMmcCmdBlk.CommandArgument = 0;
163 
164   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
165 
166   return Status;
167 }
168 
169 /**
170   Send command SET_RELATIVE_ADDR to the EMMC device to assign a Relative device
171   Address (RCA).
172 
173   Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
174 
175   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
176   @param[in] Slot           The slot number of the SD card to send the command to.
177   @param[in] Rca            The relative device address to be assigned.
178 
179   @retval EFI_SUCCESS       The operation is done correctly.
180   @retval Others            The operation fails.
181 
182 **/
183 EFI_STATUS
EmmcSetRca(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca)184 EmmcSetRca (
185   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
186   IN UINT8                              Slot,
187   IN UINT16                             Rca
188   )
189 {
190   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
191   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
192   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
193   EFI_STATUS                            Status;
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 = EMMC_SET_RELATIVE_ADDR;
204   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
205   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
206   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
207 
208   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
209 
210   return Status;
211 }
212 
213 /**
214   Send command SEND_CSD to the EMMC device to get the data of the CSD register.
215 
216   Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
217 
218   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
219   @param[in]  Slot          The slot number of the SD card to send the command to.
220   @param[in]  Rca           The relative device address of selected device.
221   @param[out] Csd           The buffer to store the content of the CSD register.
222                             Note the caller should ignore the lowest byte of this
223                             buffer as the content of this byte is meaningless even
224                             if the operation succeeds.
225 
226   @retval EFI_SUCCESS       The operation is done correctly.
227   @retval Others            The operation fails.
228 
229 **/
230 EFI_STATUS
EmmcGetCsd(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,OUT EMMC_CSD * Csd)231 EmmcGetCsd (
232   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
233   IN     UINT8                          Slot,
234   IN     UINT16                         Rca,
235      OUT EMMC_CSD                       *Csd
236   )
237 {
238   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
239   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
240   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
241   EFI_STATUS                            Status;
242 
243   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
244   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
245   ZeroMem (&Packet, sizeof (Packet));
246 
247   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
248   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
249   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
250 
251   SdMmcCmdBlk.CommandIndex = EMMC_SEND_CSD;
252   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
253   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
254   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
255 
256   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
257   if (!EFI_ERROR (Status)) {
258     //
259     // Copy 128bit data for CSD structure.
260     //
261     CopyMem ((VOID *)Csd + 1, &SdMmcStatusBlk.Resp0, sizeof (EMMC_CSD) - 1);
262   }
263 
264   return Status;
265 }
266 
267 /**
268   Send command SELECT_DESELECT_CARD to the EMMC device to select/deselect it.
269 
270   Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
271 
272   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
273   @param[in]  Slot          The slot number of the SD card to send the command to.
274   @param[in]  Rca           The relative device address of selected device.
275 
276   @retval EFI_SUCCESS       The operation is done correctly.
277   @retval Others            The operation fails.
278 
279 **/
280 EFI_STATUS
EmmcSelect(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca)281 EmmcSelect (
282   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
283   IN UINT8                              Slot,
284   IN UINT16                             Rca
285   )
286 {
287   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
288   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
289   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
290   EFI_STATUS                            Status;
291 
292   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
293   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
294   ZeroMem (&Packet, sizeof (Packet));
295 
296   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
297   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
298   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
299 
300   SdMmcCmdBlk.CommandIndex = EMMC_SELECT_DESELECT_CARD;
301   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
302   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
303   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
304 
305   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
306 
307   return Status;
308 }
309 
310 /**
311   Send command SEND_EXT_CSD to the EMMC device to get the data of the EXT_CSD register.
312 
313   Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
314 
315   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
316   @param[in]  Slot          The slot number of the SD card to send the command to.
317   @param[out] ExtCsd        The buffer to store the content of the EXT_CSD register.
318 
319   @retval EFI_SUCCESS       The operation is done correctly.
320   @retval Others            The operation fails.
321 
322 **/
323 EFI_STATUS
EmmcGetExtCsd(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,OUT EMMC_EXT_CSD * ExtCsd)324 EmmcGetExtCsd (
325   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
326   IN     UINT8                          Slot,
327      OUT EMMC_EXT_CSD                   *ExtCsd
328   )
329 {
330   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
331   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
332   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
333   EFI_STATUS                            Status;
334 
335   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
336   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
337   ZeroMem (&Packet, sizeof (Packet));
338 
339   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
340   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
341   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
342 
343   SdMmcCmdBlk.CommandIndex = EMMC_SEND_EXT_CSD;
344   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAdtc;
345   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
346   SdMmcCmdBlk.CommandArgument = 0x00000000;
347 
348   Packet.InDataBuffer     = ExtCsd;
349   Packet.InTransferLength = sizeof (EMMC_EXT_CSD);
350 
351   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
352   return Status;
353 }
354 
355 /**
356   Send command SWITCH to the EMMC device to switch the mode of operation of the
357   selected Device or modifies the EXT_CSD registers.
358 
359   Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
360 
361   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
362   @param[in]  Slot          The slot number of the SD card to send the command to.
363   @param[in]  Access        The access mode of SWTICH command.
364   @param[in]  Index         The offset of the field to be access.
365   @param[in]  Value         The value to be set to the specified field of EXT_CSD register.
366   @param[in]  CmdSet        The value of CmdSet field of EXT_CSD register.
367 
368   @retval EFI_SUCCESS       The operation is done correctly.
369   @retval Others            The operation fails.
370 
371 **/
372 EFI_STATUS
EmmcSwitch(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT8 Access,IN UINT8 Index,IN UINT8 Value,IN UINT8 CmdSet)373 EmmcSwitch (
374   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
375   IN UINT8                              Slot,
376   IN UINT8                              Access,
377   IN UINT8                              Index,
378   IN UINT8                              Value,
379   IN UINT8                              CmdSet
380   )
381 {
382   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
383   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
384   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
385   EFI_STATUS                            Status;
386 
387   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
388   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
389   ZeroMem (&Packet, sizeof (Packet));
390 
391   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
392   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
393   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
394 
395   SdMmcCmdBlk.CommandIndex = EMMC_SWITCH;
396   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
397   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;
398   SdMmcCmdBlk.CommandArgument = (Access << 24) | (Index << 16) | (Value << 8) | CmdSet;
399 
400   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
401 
402   return Status;
403 }
404 
405 /**
406   Send command SEND_STATUS to the addressed EMMC device to get its status register.
407 
408   Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
409 
410   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
411   @param[in]  Slot          The slot number of the SD card to send the command to.
412   @param[in]  Rca           The relative device address of addressed device.
413   @param[out] DevStatus     The returned device status.
414 
415   @retval EFI_SUCCESS       The operation is done correctly.
416   @retval Others            The operation fails.
417 
418 **/
419 EFI_STATUS
EmmcSendStatus(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,OUT UINT32 * DevStatus)420 EmmcSendStatus (
421   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
422   IN     UINT8                          Slot,
423   IN     UINT16                         Rca,
424      OUT UINT32                         *DevStatus
425   )
426 {
427   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
428   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
429   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
430   EFI_STATUS                            Status;
431 
432   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
433   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
434   ZeroMem (&Packet, sizeof (Packet));
435 
436   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
437   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
438   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
439 
440   SdMmcCmdBlk.CommandIndex = EMMC_SEND_STATUS;
441   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
442   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
443   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
444 
445   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
446   if (!EFI_ERROR (Status)) {
447     *DevStatus = SdMmcStatusBlk.Resp0;
448   }
449 
450   return Status;
451 }
452 
453 /**
454   Send command SEND_TUNING_BLOCK to the EMMC device for HS200 optimal sampling point
455   detection.
456 
457   It may be sent up to 40 times until the host finishes the tuning procedure.
458 
459   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 for details.
460 
461   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
462   @param[in] Slot           The slot number of the SD card to send the command to.
463   @param[in] BusWidth       The bus width to work.
464 
465   @retval EFI_SUCCESS       The operation is done correctly.
466   @retval Others            The operation fails.
467 
468 **/
469 EFI_STATUS
EmmcSendTuningBlk(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT8 BusWidth)470 EmmcSendTuningBlk (
471   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
472   IN UINT8                              Slot,
473   IN UINT8                              BusWidth
474   )
475 {
476   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
477   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
478   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
479   EFI_STATUS                            Status;
480   UINT8                                 TuningBlock[128];
481 
482   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
483   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
484   ZeroMem (&Packet, sizeof (Packet));
485 
486   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
487   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
488   Packet.Timeout        = DW_MMC_HC_GENERIC_TIMEOUT;
489 
490   SdMmcCmdBlk.CommandIndex = EMMC_SEND_TUNING_BLOCK;
491   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAdtc;
492   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
493   SdMmcCmdBlk.CommandArgument = 0;
494 
495   Packet.InDataBuffer = TuningBlock;
496   if (BusWidth == 8) {
497     Packet.InTransferLength = sizeof (TuningBlock);
498   } else {
499     Packet.InTransferLength = 64;
500   }
501 
502   Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
503 
504   return Status;
505 }
506 
507 /**
508   Tunning the clock to get HS200 optimal sampling point.
509 
510   Command SEND_TUNING_BLOCK may be sent up to 40 times until the host finishes the
511   tuning procedure.
512 
513   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
514   Simplified Spec 3.0 Figure 2-29 for details.
515 
516   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
517   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
518   @param[in] Slot           The slot number of the SD card to send the command to.
519   @param[in] BusWidth       The bus width to work.
520 
521   @retval EFI_SUCCESS       The operation is done correctly.
522   @retval Others            The operation fails.
523 
524 **/
525 EFI_STATUS
EmmcTuningClkForHs200(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT8 BusWidth)526 EmmcTuningClkForHs200 (
527   IN EFI_PCI_IO_PROTOCOL                *PciIo,
528   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
529   IN UINT8                              Slot,
530   IN UINT8                              BusWidth
531   )
532 {
533 #if 0
534   EFI_STATUS          Status;
535   UINT8               HostCtrl2;
536   UINT8               Retry;
537 
538   //
539   // Notify the host that the sampling clock tuning procedure starts.
540   //
541   HostCtrl2 = BIT6;
542   Status = DwMmcHcOrMmio (PciIo, Slot, DW_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
543   if (EFI_ERROR (Status)) {
544     return Status;
545   }
546   //
547   // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.
548   //
549   Retry = 0;
550   do {
551     Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth);
552     if (EFI_ERROR (Status)) {
553       DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
554       return Status;
555     }
556 
557     Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
558     if (EFI_ERROR (Status)) {
559       return Status;
560     }
561 
562     if ((HostCtrl2 & (BIT6 | BIT7)) == 0) {
563       break;
564     }
565 
566     if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {
567       return EFI_SUCCESS;
568     }
569   } while (++Retry < 40);
570 
571   DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails at %d times with HostCtrl2 %02x\n", Retry, HostCtrl2));
572   //
573   // Abort the tuning procedure and reset the tuning circuit.
574   //
575   HostCtrl2 = (UINT8)~(BIT6 | BIT7);
576   Status = DwMmcHcAndMmio (PciIo, Slot, DW_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
577   if (EFI_ERROR (Status)) {
578     return Status;
579   }
580   return EFI_DEVICE_ERROR;
581 #else
582   return EFI_SUCCESS;
583 #endif
584 }
585 
586 /**
587   Switch the bus width to specified width.
588 
589   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.9 and SD Host Controller
590   Simplified Spec 3.0 Figure 3-7 for details.
591 
592   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
593   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
594   @param[in] Slot           The slot number of the SD card to send the command to.
595   @param[in] Rca            The relative device address to be assigned.
596   @param[in] IsDdr          If TRUE, use dual data rate data simpling method. Otherwise
597                             use single data rate data simpling method.
598   @param[in] BusWidth       The bus width to be set, it could be 4 or 8.
599 
600   @retval EFI_SUCCESS       The operation is done correctly.
601   @retval Others            The operation fails.
602 
603 **/
604 EFI_STATUS
EmmcSwitchBusWidth(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)605 EmmcSwitchBusWidth (
606   IN EFI_PCI_IO_PROTOCOL                *PciIo,
607   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
608   IN UINT8                              Slot,
609   IN UINT16                             Rca,
610   IN BOOLEAN                            IsDdr,
611   IN UINT8                              BusWidth
612   )
613 {
614   EFI_STATUS          Status;
615   UINT8               Access;
616   UINT8               Index;
617   UINT8               Value;
618   UINT8               CmdSet;
619   UINT32              DevStatus;
620 
621   //
622   // Write Byte, the Value field is written into the byte pointed by Index.
623   //
624   Access = 0x03;
625   Index  = OFFSET_OF (EMMC_EXT_CSD, BusWidth);
626   if (BusWidth == 1) {
627     Value = 0;
628   } else {
629     if (BusWidth == 4) {
630       Value = 1;
631     } else if (BusWidth == 8) {
632       Value = 2;
633     } else {
634       return EFI_INVALID_PARAMETER;
635     }
636 
637     if (IsDdr) {
638       Value += 4;
639     }
640   }
641 
642   CmdSet = 0;
643   Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);
644   if (EFI_ERROR (Status)) {
645     DEBUG ((DEBUG_ERROR, "EmmcSwitchBusWidth: Switch to bus width %d fails with %r\n", BusWidth, Status));
646     return Status;
647   }
648 
649   do {
650     Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);
651     if (EFI_ERROR (Status)) {
652       DEBUG ((DEBUG_ERROR, "EmmcSwitchBusWidth: Send status fails with %r\n", Status));
653       return Status;
654     }
655     //
656     // Check the switch operation is really successful or not.
657     //
658   } while ((DevStatus & 0xf) == EMMC_STATE_PRG);
659 
660   Status = DwMmcHcSetBusWidth (PciIo, Slot, IsDdr, BusWidth);
661   if (EFI_ERROR (Status)) {
662     return Status;
663   }
664 
665   return Status;
666 }
667 
668 /**
669   Switch the clock frequency to the specified value.
670 
671   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6 and SD Host Controller
672   Simplified Spec 3.0 Figure 3-3 for details.
673 
674   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
675   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
676   @param[in] Slot           The slot number of the SD card to send the command to.
677   @param[in] Rca            The relative device address to be assigned.
678   @param[in] HsTiming       The value to be written to HS_TIMING field of EXT_CSD register.
679   @param[in] ClockFreq      The max clock frequency to be set, the unit is MHz.
680 
681   @retval EFI_SUCCESS       The operation is done correctly.
682   @retval Others            The operation fails.
683 
684 **/
685 EFI_STATUS
EmmcSwitchClockFreq(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN UINT8 HsTiming,IN UINT32 ClockFreq)686 EmmcSwitchClockFreq (
687   IN EFI_PCI_IO_PROTOCOL                *PciIo,
688   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
689   IN UINT8                              Slot,
690   IN UINT16                             Rca,
691   IN UINT8                              HsTiming,
692   IN UINT32                             ClockFreq
693   )
694 {
695   EFI_STATUS                Status;
696   UINT8                     Access;
697   UINT8                     Index;
698   UINT8                     Value;
699   UINT8                     CmdSet;
700   UINT32                    DevStatus;
701   DW_MMC_HC_PRIVATE_DATA    *Private;
702 
703   Private = DW_MMC_HC_PRIVATE_FROM_THIS (PassThru);
704   //
705   // Write Byte, the Value field is written into the byte pointed by Index.
706   //
707   Access = 0x03;
708   Index  = OFFSET_OF (EMMC_EXT_CSD, HsTiming);
709   Value  = HsTiming;
710   CmdSet = 0;
711 
712   Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);
713   if (EFI_ERROR (Status)) {
714     DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: Switch to hstiming %d fails with %r\n", HsTiming, Status));
715     return Status;
716   }
717 
718   Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);
719   if (EFI_ERROR (Status)) {
720     DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: Send status fails with %r\n", Status));
721     return Status;
722   }
723   //
724   // Check the switch operation is really successful or not.
725   //
726   if ((DevStatus & BIT7) != 0) {
727     DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));
728     return EFI_DEVICE_ERROR;
729   }
730   //
731   // Convert the clock freq unit from MHz to KHz.
732   //
733   Status = DwMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->Capability[Slot]);
734 
735   return Status;
736 }
737 
738 /**
739   Switch to the High Speed timing according to request.
740 
741   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
742   Simplified Spec 3.0 Figure 2-29 for details.
743 
744   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
745   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
746   @param[in] Slot           The slot number of the SD card to send the command to.
747   @param[in] Rca            The relative device address to be assigned.
748   @param[in] ClockFreq      The max clock frequency to be set.
749   @param[in] IsDdr          If TRUE, use dual data rate data simpling method. Otherwise
750                             use single data rate data simpling method.
751   @param[in] BusWidth       The bus width to be set, it could be 4 or 8.
752 
753   @retval EFI_SUCCESS       The operation is done correctly.
754   @retval Others            The operation fails.
755 
756 **/
757 EFI_STATUS
EmmcSwitchToHighSpeed(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN UINT32 ClockFreq,IN BOOLEAN IsDdr,IN UINT8 BusWidth)758 EmmcSwitchToHighSpeed (
759   IN EFI_PCI_IO_PROTOCOL                *PciIo,
760   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
761   IN UINT8                              Slot,
762   IN UINT16                             Rca,
763   IN UINT32                             ClockFreq,
764   IN BOOLEAN                            IsDdr,
765   IN UINT8                              BusWidth
766   )
767 {
768   EFI_STATUS          Status;
769   UINT8               HsTiming;
770 
771   HsTiming = 1;
772   Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);
773   if (EFI_ERROR (Status)) {
774     return Status;
775   }
776   Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth);
777   if (EFI_ERROR (Status)) {
778     return Status;
779   }
780   return EFI_SUCCESS;
781 }
782 
783 /**
784   Switch to the HS200 timing according to request.
785 
786   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
787   Simplified Spec 3.0 Figure 2-29 for details.
788 
789   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
790   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
791   @param[in] Slot           The slot number of the SD card to send the command to.
792   @param[in] Rca            The relative device address to be assigned.
793   @param[in] ClockFreq      The max clock frequency to be set.
794   @param[in] BusWidth       The bus width to be set, it could be 4 or 8.
795 
796   @retval EFI_SUCCESS       The operation is done correctly.
797   @retval Others            The operation fails.
798 
799 **/
800 EFI_STATUS
EmmcSwitchToHS200(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN UINT32 ClockFreq,IN UINT8 BusWidth)801 EmmcSwitchToHS200 (
802   IN EFI_PCI_IO_PROTOCOL                *PciIo,
803   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
804   IN UINT8                              Slot,
805   IN UINT16                             Rca,
806   IN UINT32                             ClockFreq,
807   IN UINT8                              BusWidth
808   )
809 {
810   return EFI_SUCCESS;
811 }
812 
813 /**
814   Switch the high speed timing according to request.
815 
816   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
817   Simplified Spec 3.0 Figure 2-29 for details.
818 
819   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
820   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
821   @param[in] Slot           The slot number of the SD card to send the command to.
822   @param[in] Rca            The relative device address to be assigned.
823 
824   @retval EFI_SUCCESS       The operation is done correctly.
825   @retval Others            The operation fails.
826 
827 **/
828 EFI_STATUS
EmmcSetBusMode(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca)829 EmmcSetBusMode (
830   IN EFI_PCI_IO_PROTOCOL                *PciIo,
831   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
832   IN UINT8                              Slot,
833   IN UINT16                             Rca
834   )
835 {
836   EFI_STATUS                    Status;
837   EMMC_CSD                      Csd;
838   EMMC_EXT_CSD                  ExtCsd;
839   UINT8                         HsTiming;
840   BOOLEAN                       IsDdr;
841   UINT32                        DevStatus;
842   UINT32                        ClockFreq;
843   UINT8                         BusWidth;
844   DW_MMC_HC_PRIVATE_DATA        *Private;
845 
846   Private = DW_MMC_HC_PRIVATE_FROM_THIS (PassThru);
847   ASSERT (Private->Capability[Slot].BaseClkFreq != 0);
848 
849   Status = EmmcGetCsd (PassThru, Slot, Rca, &Csd);
850   if (EFI_ERROR (Status)) {
851     DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetCsd fails with %r\n", Status));
852     return Status;
853   }
854 
855   Status = EmmcSelect (PassThru, Slot, Rca);
856   if (EFI_ERROR (Status)) {
857     DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: Select fails with %r\n", Status));
858     return Status;
859   }
860 
861   do {
862     Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);
863     if (EFI_ERROR (Status)) {
864       DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: Get Status fails with %r\n", Status));
865       return Status;
866     }
867   } while (EMMC_GET_STATE (DevStatus) != EMMC_STATE_TRAN);
868 
869   BusWidth = 1;
870   Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE, BusWidth);
871   if (EFI_ERROR (Status)) {
872     return Status;
873   }
874 
875   BusWidth = Private->Capability[Slot].BusWidth;
876   //
877   // Get Deivce_Type from EXT_CSD register.
878   //
879   Status = EmmcGetExtCsd (PassThru, Slot, &ExtCsd);
880   if (EFI_ERROR (Status)) {
881     DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetExtCsd fails with %r\n", Status));
882     return Status;
883   }
884 
885   //
886   // Calculate supported bus speed/bus width/clock frequency.
887   //
888   HsTiming  = 0;
889   IsDdr     = FALSE;
890   ClockFreq = 0;
891   if (((ExtCsd.DeviceType & (BIT4 | BIT5))  != 0) && (Private->Capability[Slot].Sdr104 != 0)) {
892     HsTiming  = 2;
893     IsDdr     = FALSE;
894     ClockFreq = 200;
895   } else if (((ExtCsd.DeviceType & (BIT2 | BIT3))  != 0) && (Private->Capability[Slot].Ddr50 != 0)) {
896     HsTiming  = 1;
897     IsDdr     = TRUE;
898     ClockFreq = 52;
899   } else if (((ExtCsd.DeviceType & BIT1)  != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
900     HsTiming  = 1;
901     IsDdr     = FALSE;
902     ClockFreq = 52;
903   } else if (((ExtCsd.DeviceType & BIT0)  != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
904     HsTiming  = 1;
905     IsDdr     = FALSE;
906     ClockFreq = 26;
907   }
908 
909   if ((ClockFreq == 0) || (HsTiming == 0)) {
910     //
911     // Continue using default setting.
912     //
913     return EFI_SUCCESS;
914   }
915 
916   DEBUG ((DEBUG_INFO, "EmmcSetBusMode: HsTiming %d ClockFreq %d BusWidth %d Ddr %a\n", HsTiming, ClockFreq, BusWidth, IsDdr ? "TRUE":"FALSE"));
917 
918   if (HsTiming == 2) {
919     //
920     // Execute HS200 timing switch procedure
921     //
922     Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);
923   } else {
924     //
925     // Execute High Speed timing switch procedure
926     //
927     Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth);
928   }
929 
930   DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n", (HsTiming == 3) ? "HS400" : ((HsTiming == 2) ? "HS200" : "HighSpeed"), Status));
931 
932   return Status;
933 }
934 
935 /**
936   Execute EMMC device identification procedure.
937 
938   Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
939 
940   @param[in] Private        A pointer to the DW_MMC_HC_PRIVATE_DATA instance.
941   @param[in] Slot           The slot number of the SD card to send the command to.
942 
943   @retval EFI_SUCCESS       There is a EMMC card.
944   @retval Others            There is not a EMMC card.
945 
946 **/
947 EFI_STATUS
EmmcIdentification(IN DW_MMC_HC_PRIVATE_DATA * Private,IN UINT8 Slot)948 EmmcIdentification (
949   IN DW_MMC_HC_PRIVATE_DATA             *Private,
950   IN UINT8                              Slot
951   )
952 {
953   EFI_STATUS                     Status;
954   EFI_PCI_IO_PROTOCOL            *PciIo;
955   EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru;
956   UINT32                         Ocr;
957   UINT16                         Rca;
958   UINT32                         DevStatus;
959   UINT32                         Timeout;
960 
961   PciIo    = Private->PciIo;
962   PassThru = &Private->PassThru;
963 
964   Status = EmmcReset (PassThru, Slot);
965   if (EFI_ERROR (Status)) {
966     DEBUG ((DEBUG_INFO, "EmmcIdentification: Executing Cmd0 fails with %r\n", Status));
967     return Status;
968   }
969 
970   Timeout = 100;
971   do {
972     Ocr = EMMC_CMD1_CAPACITY_GREATER_THAN_2GB;
973     Status = EmmcGetOcr (PassThru, Slot, &Ocr);
974     if (EFI_ERROR (Status)) {
975       DEBUG ((DEBUG_INFO, "EmmcIdentification: Executing Cmd1 fails with %r\n", Status));
976       return Status;
977     }
978     if (--Timeout <= 0) {
979       return EFI_DEVICE_ERROR;
980     }
981     MicroSecondDelay (100);
982   } while ((Ocr & BIT31) == 0);
983 
984   Status = EmmcGetAllCid (PassThru, Slot);
985   if (EFI_ERROR (Status)) {
986     DEBUG ((DEBUG_INFO, "EmmcIdentification: Executing Cmd2 fails with %r\n", Status));
987     return Status;
988   }
989   //
990   // Slot starts from 0 and valid RCA starts from 1.
991   // Here we takes a simple formula to calculate the RCA.
992   // Don't support multiple devices on the slot, that is
993   // shared bus slot feature.
994   //
995   Rca    = Slot + 1;
996   Status = EmmcSetRca (PassThru, Slot, Rca);
997   if (EFI_ERROR (Status)) {
998     DEBUG ((DEBUG_INFO, "EmmcIdentification: Executing Cmd3 fails with %r\n", Status));
999     return Status;
1000   }
1001   //
1002   // Enter Data Tranfer Mode.
1003   //
1004   DEBUG ((DEBUG_INFO, "EmmcIdentification: Found a EMMC device at slot [%d], RCA [%d]\n", Slot, Rca));
1005   Private->Slot[Slot].CardType = EmmcCardType;
1006 
1007   Status = EmmcSetBusMode (PciIo, PassThru, Slot, Rca);
1008   if (EFI_ERROR (Status)) {
1009     return Status;
1010   }
1011 
1012   //
1013   // Exit DATA Mode.
1014   //
1015   do {
1016     Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);
1017     if (EFI_ERROR (Status)) {
1018       DEBUG ((DEBUG_INFO, "EmmcSwitchBusWidth: Send status fails with %r\n", Status));
1019       return Status;
1020     }
1021   } while ((DevStatus & 0xf) == EMMC_STATE_DATA);
1022 
1023   return Status;
1024 }
1025