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