1 /** @file
2   This file provides some helper functions which are specific for EMMC device.
3 
4   Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
5   Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "SdMmcPciHcDxe.h"
11 
12 /**
13   Send command GO_IDLE_STATE (CMD0 with argument of 0x00000000) to the device to
14   make it go to Idle State.
15 
16   Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
17 
18   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
19   @param[in] Slot           The slot number of the SD card to send the command to.
20 
21   @retval EFI_SUCCESS       The EMMC device is reset correctly.
22   @retval Others            The device reset fails.
23 
24 **/
25 EFI_STATUS
EmmcReset(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)26 EmmcReset (
27   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
28   IN UINT8                              Slot
29   )
30 {
31   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
32   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
33   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
34   EFI_STATUS                            Status;
35 
36   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
37   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
38   ZeroMem (&Packet, sizeof (Packet));
39 
40   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
41   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
42   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
43 
44   SdMmcCmdBlk.CommandIndex = EMMC_GO_IDLE_STATE;
45   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBc;
46   SdMmcCmdBlk.ResponseType = 0;
47   SdMmcCmdBlk.CommandArgument = 0;
48 
49   gBS->Stall (1000);
50 
51   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
52 
53   return Status;
54 }
55 
56 /**
57   Send command SEND_OP_COND to the EMMC device to get the data of the OCR register.
58 
59   Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
60 
61   @param[in]      PassThru  A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
62   @param[in]      Slot      The slot number of the SD card to send the command to.
63   @param[in, out] Argument  On input, the argument of SEND_OP_COND is to send to the device.
64                             On output, the argument is the value of OCR register.
65 
66   @retval EFI_SUCCESS       The operation is done correctly.
67   @retval Others            The operation fails.
68 
69 **/
70 EFI_STATUS
EmmcGetOcr(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN OUT UINT32 * Argument)71 EmmcGetOcr (
72   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
73   IN     UINT8                          Slot,
74   IN OUT UINT32                         *Argument
75   )
76 {
77   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
78   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
79   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
80   EFI_STATUS                            Status;
81 
82   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
83   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
84   ZeroMem (&Packet, sizeof (Packet));
85 
86   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
87   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
88   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
89 
90   SdMmcCmdBlk.CommandIndex = EMMC_SEND_OP_COND;
91   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
92   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR3;
93   SdMmcCmdBlk.CommandArgument = *Argument;
94 
95   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
96   if (!EFI_ERROR (Status)) {
97     //
98     // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
99     //
100     *Argument = SdMmcStatusBlk.Resp0;
101   }
102 
103   return Status;
104 }
105 
106 /**
107   Broadcast command ALL_SEND_CID to the bus to ask all the EMMC devices to send the
108   data of their CID registers.
109 
110   Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
111 
112   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
113   @param[in] Slot           The slot number of the SD card to send the command to.
114 
115   @retval EFI_SUCCESS       The operation is done correctly.
116   @retval Others            The operation fails.
117 
118 **/
119 EFI_STATUS
EmmcGetAllCid(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)120 EmmcGetAllCid (
121   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
122   IN UINT8                              Slot
123   )
124 {
125   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
126   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
127   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
128   EFI_STATUS                            Status;
129 
130   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
131   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
132   ZeroMem (&Packet, sizeof (Packet));
133 
134   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
135   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
136   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
137 
138   SdMmcCmdBlk.CommandIndex = EMMC_ALL_SEND_CID;
139   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
140   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
141   SdMmcCmdBlk.CommandArgument = 0;
142 
143   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
144 
145   return Status;
146 }
147 
148 /**
149   Send command SET_RELATIVE_ADDR to the EMMC device to assign a Relative device
150   Address (RCA).
151 
152   Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
153 
154   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
155   @param[in] Slot           The slot number of the SD card to send the command to.
156   @param[in] Rca            The relative device address to be assigned.
157 
158   @retval EFI_SUCCESS       The operation is done correctly.
159   @retval Others            The operation fails.
160 
161 **/
162 EFI_STATUS
EmmcSetRca(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca)163 EmmcSetRca (
164   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
165   IN UINT8                              Slot,
166   IN UINT16                             Rca
167   )
168 {
169   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
170   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
171   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
172   EFI_STATUS                            Status;
173 
174   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
175   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
176   ZeroMem (&Packet, sizeof (Packet));
177 
178   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
179   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
180   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
181 
182   SdMmcCmdBlk.CommandIndex = EMMC_SET_RELATIVE_ADDR;
183   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
184   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
185   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
186 
187   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
188 
189   return Status;
190 }
191 
192 /**
193   Send command SEND_CSD to the EMMC device to get the data of the CSD register.
194 
195   Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
196 
197   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
198   @param[in]  Slot          The slot number of the SD card to send the command to.
199   @param[in]  Rca           The relative device address of selected device.
200   @param[out] Csd           The buffer to store the content of the CSD register.
201                             Note the caller should ignore the lowest byte of this
202                             buffer as the content of this byte is meaningless even
203                             if the operation succeeds.
204 
205   @retval EFI_SUCCESS       The operation is done correctly.
206   @retval Others            The operation fails.
207 
208 **/
209 EFI_STATUS
EmmcGetCsd(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,OUT EMMC_CSD * Csd)210 EmmcGetCsd (
211   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
212   IN     UINT8                          Slot,
213   IN     UINT16                         Rca,
214      OUT EMMC_CSD                       *Csd
215   )
216 {
217   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
218   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
219   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
220   EFI_STATUS                            Status;
221 
222   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
223   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
224   ZeroMem (&Packet, sizeof (Packet));
225 
226   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
227   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
228   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
229 
230   SdMmcCmdBlk.CommandIndex = EMMC_SEND_CSD;
231   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
232   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
233   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
234 
235   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
236   if (!EFI_ERROR (Status)) {
237     //
238     // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
239     //
240     CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (EMMC_CSD) - 1);
241   }
242 
243   return Status;
244 }
245 
246 /**
247   Send command SELECT_DESELECT_CARD to the EMMC device to select/deselect it.
248 
249   Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
250 
251   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
252   @param[in]  Slot          The slot number of the SD card to send the command to.
253   @param[in]  Rca           The relative device address of selected device.
254 
255   @retval EFI_SUCCESS       The operation is done correctly.
256   @retval Others            The operation fails.
257 
258 **/
259 EFI_STATUS
EmmcSelect(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca)260 EmmcSelect (
261   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
262   IN UINT8                              Slot,
263   IN UINT16                             Rca
264   )
265 {
266   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
267   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
268   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
269   EFI_STATUS                            Status;
270 
271   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
272   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
273   ZeroMem (&Packet, sizeof (Packet));
274 
275   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
276   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
277   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
278 
279   SdMmcCmdBlk.CommandIndex = EMMC_SELECT_DESELECT_CARD;
280   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
281   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
282   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
283 
284   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
285 
286   return Status;
287 }
288 
289 /**
290   Send command SEND_EXT_CSD to the EMMC device to get the data of the EXT_CSD register.
291 
292   Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
293 
294   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
295   @param[in]  Slot          The slot number of the SD card to send the command to.
296   @param[out] ExtCsd        The buffer to store the content of the EXT_CSD register.
297 
298   @retval EFI_SUCCESS       The operation is done correctly.
299   @retval Others            The operation fails.
300 
301 **/
302 EFI_STATUS
EmmcGetExtCsd(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,OUT EMMC_EXT_CSD * ExtCsd)303 EmmcGetExtCsd (
304   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
305   IN     UINT8                          Slot,
306      OUT EMMC_EXT_CSD                   *ExtCsd
307   )
308 {
309   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
310   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
311   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
312   EFI_STATUS                            Status;
313 
314   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
315   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
316   ZeroMem (&Packet, sizeof (Packet));
317 
318   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
319   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
320   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
321 
322   SdMmcCmdBlk.CommandIndex = EMMC_SEND_EXT_CSD;
323   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAdtc;
324   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
325   SdMmcCmdBlk.CommandArgument = 0x00000000;
326 
327   Packet.InDataBuffer     = ExtCsd;
328   Packet.InTransferLength = sizeof (EMMC_EXT_CSD);
329 
330   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
331   return Status;
332 }
333 
334 /**
335   Send command SWITCH to the EMMC device to switch the mode of operation of the
336   selected Device or modifies the EXT_CSD registers.
337 
338   Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
339 
340   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
341   @param[in]  Slot          The slot number of the SD card to send the command to.
342   @param[in]  Access        The access mode of SWTICH command.
343   @param[in]  Index         The offset of the field to be access.
344   @param[in]  Value         The value to be set to the specified field of EXT_CSD register.
345   @param[in]  CmdSet        The value of CmdSet field of EXT_CSD register.
346 
347   @retval EFI_SUCCESS       The operation is done correctly.
348   @retval Others            The operation fails.
349 
350 **/
351 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)352 EmmcSwitch (
353   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
354   IN UINT8                              Slot,
355   IN UINT8                              Access,
356   IN UINT8                              Index,
357   IN UINT8                              Value,
358   IN UINT8                              CmdSet
359   )
360 {
361   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
362   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
363   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
364   EFI_STATUS                            Status;
365 
366   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
367   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
368   ZeroMem (&Packet, sizeof (Packet));
369 
370   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
371   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
372   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
373 
374   SdMmcCmdBlk.CommandIndex = EMMC_SWITCH;
375   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
376   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;
377   SdMmcCmdBlk.CommandArgument = (Access << 24) | (Index << 16) | (Value << 8) | CmdSet;
378 
379   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
380 
381   return Status;
382 }
383 
384 /**
385   Send command SEND_STATUS to the addressed EMMC device to get its status register.
386 
387   Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
388 
389   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
390   @param[in]  Slot          The slot number of the SD card to send the command to.
391   @param[in]  Rca           The relative device address of addressed device.
392   @param[out] DevStatus     The returned device status.
393 
394   @retval EFI_SUCCESS       The operation is done correctly.
395   @retval Others            The operation fails.
396 
397 **/
398 EFI_STATUS
EmmcSendStatus(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,OUT UINT32 * DevStatus)399 EmmcSendStatus (
400   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
401   IN     UINT8                          Slot,
402   IN     UINT16                         Rca,
403      OUT UINT32                         *DevStatus
404   )
405 {
406   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
407   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
408   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
409   EFI_STATUS                            Status;
410 
411   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
412   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
413   ZeroMem (&Packet, sizeof (Packet));
414 
415   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
416   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
417   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
418 
419   SdMmcCmdBlk.CommandIndex = EMMC_SEND_STATUS;
420   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
421   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
422   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
423 
424   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
425   if (!EFI_ERROR (Status)) {
426     *DevStatus = SdMmcStatusBlk.Resp0;
427   }
428 
429   return Status;
430 }
431 
432 /**
433   Send command SEND_TUNING_BLOCK to the EMMC device for HS200 optimal sampling point
434   detection.
435 
436   It may be sent up to 40 times until the host finishes the tuning procedure.
437 
438   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 for details.
439 
440   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
441   @param[in] Slot           The slot number of the SD card to send the command to.
442   @param[in] BusWidth       The bus width to work.
443 
444   @retval EFI_SUCCESS       The operation is done correctly.
445   @retval Others            The operation fails.
446 
447 **/
448 EFI_STATUS
EmmcSendTuningBlk(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT8 BusWidth)449 EmmcSendTuningBlk (
450   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
451   IN UINT8                              Slot,
452   IN UINT8                              BusWidth
453   )
454 {
455   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
456   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
457   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
458   EFI_STATUS                            Status;
459   UINT8                                 TuningBlock[128];
460 
461   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
462   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
463   ZeroMem (&Packet, sizeof (Packet));
464 
465   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
466   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
467   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
468 
469   SdMmcCmdBlk.CommandIndex = EMMC_SEND_TUNING_BLOCK;
470   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAdtc;
471   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
472   SdMmcCmdBlk.CommandArgument = 0;
473 
474   Packet.InDataBuffer = TuningBlock;
475   if (BusWidth == 8) {
476     Packet.InTransferLength = sizeof (TuningBlock);
477   } else {
478     Packet.InTransferLength = 64;
479   }
480 
481   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
482 
483   return Status;
484 }
485 
486 /**
487   Tunning the clock to get HS200 optimal sampling point.
488 
489   Command SEND_TUNING_BLOCK may be sent up to 40 times until the host finishes the
490   tuning procedure.
491 
492   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
493   Simplified Spec 3.0 Figure 2-29 for details.
494 
495   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
496   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
497   @param[in] Slot           The slot number of the SD card to send the command to.
498   @param[in] BusWidth       The bus width to work.
499 
500   @retval EFI_SUCCESS       The operation is done correctly.
501   @retval Others            The operation fails.
502 
503 **/
504 EFI_STATUS
EmmcTuningClkForHs200(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT8 BusWidth)505 EmmcTuningClkForHs200 (
506   IN EFI_PCI_IO_PROTOCOL                *PciIo,
507   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
508   IN UINT8                              Slot,
509   IN UINT8                              BusWidth
510   )
511 {
512   EFI_STATUS          Status;
513   UINT8               HostCtrl2;
514   UINT8               Retry;
515 
516   //
517   // Notify the host that the sampling clock tuning procedure starts.
518   //
519   HostCtrl2 = BIT6;
520   Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
521   if (EFI_ERROR (Status)) {
522     return Status;
523   }
524   //
525   // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.
526   //
527   Retry = 0;
528   do {
529     Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth);
530     if (EFI_ERROR (Status)) {
531       DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
532       return Status;
533     }
534 
535     Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
536     if (EFI_ERROR (Status)) {
537       return Status;
538     }
539 
540     if ((HostCtrl2 & (BIT6 | BIT7)) == 0) {
541       break;
542     }
543 
544     if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {
545       return EFI_SUCCESS;
546     }
547   } while (++Retry < 40);
548 
549   DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails at %d times with HostCtrl2 %02x\n", Retry, HostCtrl2));
550   //
551   // Abort the tuning procedure and reset the tuning circuit.
552   //
553   HostCtrl2 = (UINT8)~(BIT6 | BIT7);
554   Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
555   if (EFI_ERROR (Status)) {
556     return Status;
557   }
558   return EFI_DEVICE_ERROR;
559 }
560 
561 /**
562   Check the SWITCH operation status.
563 
564   @param[in] PassThru  A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
565   @param[in] Slot      The slot number on which command should be sent.
566   @param[in] Rca       The relative device address.
567 
568   @retval EFI_SUCCESS  The SWITCH finished siccessfully.
569   @retval others       The SWITCH failed.
570 **/
571 EFI_STATUS
EmmcCheckSwitchStatus(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca)572 EmmcCheckSwitchStatus (
573   IN EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
574   IN UINT8                          Slot,
575   IN UINT16                         Rca
576   )
577 {
578   EFI_STATUS  Status;
579   UINT32      DevStatus;
580 
581   Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);
582   if (EFI_ERROR (Status)) {
583     DEBUG ((DEBUG_ERROR, "EmmcCheckSwitchStatus: Send status fails with %r\n", Status));
584     return Status;
585   }
586 
587   //
588   // Check the switch operation is really successful or not.
589   //
590   if ((DevStatus & BIT7) != 0) {
591     DEBUG ((DEBUG_ERROR, "EmmcCheckSwitchStatus: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));
592     return EFI_DEVICE_ERROR;
593   }
594 
595   return EFI_SUCCESS;
596 }
597 
598 /**
599   Switch the bus width to specified width.
600 
601   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.9 and SD Host Controller
602   Simplified Spec 3.0 Figure 3-7 for details.
603 
604   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
605   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
606   @param[in] Slot           The slot number of the SD card to send the command to.
607   @param[in] Rca            The relative device address to be assigned.
608   @param[in] IsDdr          If TRUE, use dual data rate data simpling method. Otherwise
609                             use single data rate data simpling method.
610   @param[in] BusWidth       The bus width to be set, it could be 4 or 8.
611 
612   @retval EFI_SUCCESS       The operation is done correctly.
613   @retval Others            The operation fails.
614 
615 **/
616 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)617 EmmcSwitchBusWidth (
618   IN EFI_PCI_IO_PROTOCOL                *PciIo,
619   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
620   IN UINT8                              Slot,
621   IN UINT16                             Rca,
622   IN BOOLEAN                            IsDdr,
623   IN UINT8                              BusWidth
624   )
625 {
626   EFI_STATUS          Status;
627   UINT8               Access;
628   UINT8               Index;
629   UINT8               Value;
630   UINT8               CmdSet;
631 
632   //
633   // Write Byte, the Value field is written into the byte pointed by Index.
634   //
635   Access = 0x03;
636   Index  = OFFSET_OF (EMMC_EXT_CSD, BusWidth);
637   if (BusWidth == 4) {
638     Value = 1;
639   } else if (BusWidth == 8) {
640     Value = 2;
641   } else {
642     return EFI_INVALID_PARAMETER;
643   }
644 
645   if (IsDdr) {
646     Value += 4;
647   }
648 
649   CmdSet = 0;
650   Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);
651   if (EFI_ERROR (Status)) {
652     DEBUG ((DEBUG_ERROR, "EmmcSwitchBusWidth: Switch to bus width %d fails with %r\n", BusWidth, Status));
653     return Status;
654   }
655 
656   Status = EmmcCheckSwitchStatus (PassThru, Slot, Rca);
657   if (EFI_ERROR (Status)) {
658     return Status;
659   }
660 
661   Status = SdMmcHcSetBusWidth (PciIo, Slot, BusWidth);
662 
663   return Status;
664 }
665 
666 /**
667   Switch the bus timing and clock frequency.
668 
669   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6 and SD Host Controller
670   Simplified Spec 3.0 Figure 3-3 for details.
671 
672   @param[in] PciIo           A pointer to the EFI_PCI_IO_PROTOCOL instance.
673   @param[in] PassThru        A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
674   @param[in] Slot            The slot number of the SD card to send the command to.
675   @param[in] Rca             The relative device address to be assigned.
676   @param[in] DriverStrength  Driver strength to set for speed modes that support it.
677   @param[in] BusTiming       The bus mode timing indicator.
678   @param[in] ClockFreq       The max clock frequency to be set, the unit is MHz.
679 
680   @retval EFI_SUCCESS       The operation is done correctly.
681   @retval Others            The operation fails.
682 
683 **/
684 EFI_STATUS
EmmcSwitchBusTiming(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN EDKII_SD_MMC_DRIVER_STRENGTH DriverStrength,IN SD_MMC_BUS_MODE BusTiming,IN UINT32 ClockFreq)685 EmmcSwitchBusTiming (
686   IN EFI_PCI_IO_PROTOCOL                *PciIo,
687   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
688   IN UINT8                              Slot,
689   IN UINT16                             Rca,
690   IN EDKII_SD_MMC_DRIVER_STRENGTH       DriverStrength,
691   IN SD_MMC_BUS_MODE                    BusTiming,
692   IN UINT32                             ClockFreq
693   )
694 {
695   EFI_STATUS                Status;
696   UINT8                     Access;
697   UINT8                     Index;
698   UINT8                     Value;
699   UINT8                     CmdSet;
700   SD_MMC_HC_PRIVATE_DATA    *Private;
701   UINT8                     HostCtrl1;
702   BOOLEAN                   DelaySendStatus;
703 
704   Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
705   //
706   // Write Byte, the Value field is written into the byte pointed by Index.
707   //
708   Access = 0x03;
709   Index  = OFFSET_OF (EMMC_EXT_CSD, HsTiming);
710   CmdSet = 0;
711   switch (BusTiming) {
712     case SdMmcMmcHs400:
713       Value = (UINT8)((DriverStrength.Emmc << 4) | 3);
714       break;
715     case SdMmcMmcHs200:
716       Value = (UINT8)((DriverStrength.Emmc << 4) | 2);
717       break;
718     case SdMmcMmcHsSdr:
719     case SdMmcMmcHsDdr:
720       Value = 1;
721       break;
722     case SdMmcMmcLegacy:
723       Value = 0;
724       break;
725     default:
726       DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Unsupported BusTiming(%d)\n", BusTiming));
727       return EFI_INVALID_PARAMETER;
728   }
729 
730   Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);
731   if (EFI_ERROR (Status)) {
732     DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to bus timing %d fails with %r\n", BusTiming, Status));
733     return Status;
734   }
735 
736   if (BusTiming == SdMmcMmcHsSdr || BusTiming == SdMmcMmcHsDdr) {
737     HostCtrl1 = BIT2;
738     Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
739     if (EFI_ERROR (Status)) {
740       return Status;
741     }
742   } else {
743     HostCtrl1 = (UINT8)~BIT2;
744     Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
745     if (EFI_ERROR (Status)) {
746       return Status;
747     }
748   }
749 
750   Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, BusTiming);
751   if (EFI_ERROR (Status)) {
752     return Status;
753   }
754 
755   //
756   // For cases when we switch bus timing to higher mode from current we want to
757   // send SEND_STATUS at current, lower, frequency then the target frequency to avoid
758   // stability issues. It has been observed that some designs are unable to process the
759   // SEND_STATUS at higher frequency during switch to HS200 @200MHz irrespective of the number of retries
760   // and only running the clock tuning is able to make them work at target frequency.
761   //
762   // For cases when we are downgrading the frequency and current high frequency is invalid
763   // we have to first change the frequency to target frequency and then send the SEND_STATUS.
764   //
765   if (Private->Slot[Slot].CurrentFreq < (ClockFreq * 1000)) {
766     Status = EmmcCheckSwitchStatus (PassThru, Slot, Rca);
767     if (EFI_ERROR (Status)) {
768       return Status;
769     }
770     DelaySendStatus = FALSE;
771   } else {
772     DelaySendStatus = TRUE;
773   }
774 
775   //
776   // Convert the clock freq unit from MHz to KHz.
777   //
778   Status = SdMmcHcClockSupply (Private, Slot, BusTiming, FALSE, ClockFreq * 1000);
779   if (EFI_ERROR (Status)) {
780     return Status;
781   }
782 
783   if (DelaySendStatus) {
784     Status = EmmcCheckSwitchStatus (PassThru, Slot, Rca);
785     if (EFI_ERROR (Status)) {
786       return Status;
787     }
788   }
789 
790   return Status;
791 }
792 
793 /**
794   Switch to the High Speed 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] BusMode        Pointer to SD_MMC_BUS_SETTINGS structure containing bus settings.
804 
805   @retval EFI_SUCCESS       The operation is done correctly.
806   @retval Others            The operation fails.
807 
808 **/
809 EFI_STATUS
EmmcSwitchToHighSpeed(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN SD_MMC_BUS_SETTINGS * BusMode)810 EmmcSwitchToHighSpeed (
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 SD_MMC_BUS_SETTINGS                *BusMode
816   )
817 {
818   EFI_STATUS  Status;
819   BOOLEAN     IsDdr;
820 
821   if ((BusMode->BusTiming != SdMmcMmcHsSdr && BusMode->BusTiming != SdMmcMmcHsDdr && BusMode->BusTiming != SdMmcMmcLegacy) ||
822       BusMode->ClockFreq > 52) {
823     return EFI_INVALID_PARAMETER;
824   }
825 
826   if (BusMode->BusTiming == SdMmcMmcHsDdr) {
827     IsDdr = TRUE;
828   } else {
829     IsDdr = FALSE;
830   }
831 
832   Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusMode->BusWidth);
833   if (EFI_ERROR (Status)) {
834     return Status;
835   }
836 
837   return EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode->DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
838 }
839 
840 /**
841   Switch to the HS200 timing. This function assumes that eMMC bus is still in legacy mode.
842 
843   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
844   Simplified Spec 3.0 Figure 2-29 for details.
845 
846   @param[in] PciIo           A pointer to the EFI_PCI_IO_PROTOCOL instance.
847   @param[in] PassThru        A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
848   @param[in] Slot            The slot number of the SD card to send the command to.
849   @param[in] Rca             The relative device address to be assigned.
850   @param[in] BusMode         Pointer to SD_MMC_BUS_SETTINGS structure containing bus settings.
851 
852   @retval EFI_SUCCESS       The operation is done correctly.
853   @retval Others            The operation fails.
854 
855 **/
856 EFI_STATUS
EmmcSwitchToHS200(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN SD_MMC_BUS_SETTINGS * BusMode)857 EmmcSwitchToHS200 (
858   IN EFI_PCI_IO_PROTOCOL                *PciIo,
859   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
860   IN UINT8                              Slot,
861   IN UINT16                             Rca,
862   IN SD_MMC_BUS_SETTINGS                *BusMode
863   )
864 {
865   EFI_STATUS  Status;
866 
867   if (BusMode->BusTiming != SdMmcMmcHs200 ||
868       (BusMode->BusWidth != 4 && BusMode->BusWidth != 8)) {
869     return EFI_INVALID_PARAMETER;
870   }
871 
872   Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE, BusMode->BusWidth);
873   if (EFI_ERROR (Status)) {
874     return Status;
875   }
876 
877   Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode->DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
878   if (EFI_ERROR (Status)) {
879     return Status;
880   }
881 
882   Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusMode->BusWidth);
883 
884   return Status;
885 }
886 
887 /**
888   Switch to the HS400 timing. This function assumes that eMMC bus is still in legacy mode.
889 
890   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
891   Simplified Spec 3.0 Figure 2-29 for details.
892 
893   @param[in] PciIo           A pointer to the EFI_PCI_IO_PROTOCOL instance.
894   @param[in] PassThru        A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
895   @param[in] Slot            The slot number of the SD card to send the command to.
896   @param[in] Rca             The relative device address to be assigned.
897   @param[in] BusMode         Pointer to SD_MMC_BUS_SETTINGS structure containing bus settings.
898 
899   @retval EFI_SUCCESS       The operation is done correctly.
900   @retval Others            The operation fails.
901 
902 **/
903 EFI_STATUS
EmmcSwitchToHS400(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN SD_MMC_BUS_SETTINGS * BusMode)904 EmmcSwitchToHS400 (
905   IN EFI_PCI_IO_PROTOCOL                *PciIo,
906   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
907   IN UINT8                              Slot,
908   IN UINT16                             Rca,
909   IN SD_MMC_BUS_SETTINGS                *BusMode
910   )
911 {
912   EFI_STATUS           Status;
913   SD_MMC_BUS_SETTINGS  Hs200BusMode;
914   UINT32               HsFreq;
915 
916   if (BusMode->BusTiming != SdMmcMmcHs400 ||
917       BusMode->BusWidth != 8) {
918     return EFI_INVALID_PARAMETER;
919   }
920 
921   Hs200BusMode.BusTiming = SdMmcMmcHs200;
922   Hs200BusMode.BusWidth = BusMode->BusWidth;
923   Hs200BusMode.ClockFreq = BusMode->ClockFreq;
924   Hs200BusMode.DriverStrength = BusMode->DriverStrength;
925 
926   Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, &Hs200BusMode);
927   if (EFI_ERROR (Status)) {
928     return Status;
929   }
930 
931   //
932   // Set to High Speed timing and set the clock frequency to a value less than or equal to 52MHz.
933   // This step is necessary to be able to switch Bus into 8 bit DDR mode which is unsupported in HS200.
934   //
935   HsFreq = BusMode->ClockFreq < 52 ? BusMode->ClockFreq : 52;
936   Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode->DriverStrength, SdMmcMmcHsSdr, HsFreq);
937   if (EFI_ERROR (Status)) {
938     return Status;
939   }
940 
941   Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, TRUE, BusMode->BusWidth);
942   if (EFI_ERROR (Status)) {
943     return Status;
944   }
945 
946   return EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, BusMode->DriverStrength, BusMode->BusTiming, BusMode->ClockFreq);
947 }
948 
949 /**
950   Check if passed BusTiming is supported in both controller and card.
951 
952   @param[in] Private    Pointer to controller private data
953   @param[in] SlotIndex  Index of the slot in the controller
954   @param[in] ExtCsd     Pointer to the card's extended CSD
955   @param[in] BusTiming  Bus timing to check
956 
957   @retval TRUE  Both card and controller support given BusTiming
958   @retval FALSE Card or controller doesn't support given BusTiming
959 **/
960 BOOLEAN
EmmcIsBusTimingSupported(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 SlotIndex,IN EMMC_EXT_CSD * ExtCsd,IN SD_MMC_BUS_MODE BusTiming)961 EmmcIsBusTimingSupported (
962   IN SD_MMC_HC_PRIVATE_DATA  *Private,
963   IN UINT8                   SlotIndex,
964   IN EMMC_EXT_CSD            *ExtCsd,
965   IN SD_MMC_BUS_MODE         BusTiming
966   )
967 {
968   BOOLEAN             Supported;
969   SD_MMC_HC_SLOT_CAP  *Capabilities;
970 
971   Capabilities = &Private->Capability[SlotIndex];
972 
973   Supported = FALSE;
974   switch (BusTiming) {
975     case SdMmcMmcHs400:
976       if ((((ExtCsd->DeviceType & (BIT6 | BIT7))  != 0) && (Capabilities->Hs400 != 0)) && Capabilities->BusWidth8 != 0) {
977         Supported = TRUE;
978       }
979       break;
980     case SdMmcMmcHs200:
981       if ((((ExtCsd->DeviceType & (BIT4 | BIT5))  != 0) && (Capabilities->Sdr104 != 0))) {
982         Supported = TRUE;
983       }
984       break;
985     case SdMmcMmcHsDdr:
986       if ((((ExtCsd->DeviceType & (BIT2 | BIT3))  != 0) && (Capabilities->Ddr50 != 0))) {
987         Supported = TRUE;
988       }
989       break;
990     case SdMmcMmcHsSdr:
991       if ((((ExtCsd->DeviceType & BIT1)  != 0) && (Capabilities->HighSpeed != 0))) {
992         Supported = TRUE;
993       }
994       break;
995     case SdMmcMmcLegacy:
996       if ((ExtCsd->DeviceType & BIT0) != 0) {
997         Supported = TRUE;
998       }
999       break;
1000     default:
1001       ASSERT (FALSE);
1002   }
1003 
1004   return Supported;
1005 }
1006 
1007 /**
1008   Get the target bus timing to set on the link. This function
1009   will try to select highest bus timing supported by card, controller
1010   and the driver.
1011 
1012   @param[in] Private    Pointer to controller private data
1013   @param[in] SlotIndex  Index of the slot in the controller
1014   @param[in] ExtCsd     Pointer to the card's extended CSD
1015 
1016   @return  Bus timing value that should be set on link
1017 **/
1018 SD_MMC_BUS_MODE
EmmcGetTargetBusTiming(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 SlotIndex,IN EMMC_EXT_CSD * ExtCsd)1019 EmmcGetTargetBusTiming (
1020   IN SD_MMC_HC_PRIVATE_DATA  *Private,
1021   IN UINT8                    SlotIndex,
1022   IN EMMC_EXT_CSD             *ExtCsd
1023   )
1024 {
1025   SD_MMC_BUS_MODE  BusTiming;
1026 
1027   //
1028   // We start with highest bus timing that this driver currently supports and
1029   // return as soon as we find supported timing.
1030   //
1031   BusTiming = SdMmcMmcHs400;
1032   while (BusTiming > SdMmcMmcLegacy) {
1033     if (EmmcIsBusTimingSupported (Private, SlotIndex, ExtCsd, BusTiming)) {
1034       break;
1035     }
1036     BusTiming--;
1037   }
1038 
1039   return BusTiming;
1040 }
1041 
1042 /**
1043   Check if the passed bus width is supported by controller and card.
1044 
1045   @param[in] Private    Pointer to controller private data
1046   @param[in] SlotIndex  Index of the slot in the controller
1047   @param[in] BusTiming  Bus timing set on the link
1048   @param[in] BusWidth   Bus width to check
1049 
1050   @retval TRUE   Passed bus width is supported in current bus configuration
1051   @retval FALSE  Passed bus width is not supported in current bus configuration
1052 **/
1053 BOOLEAN
EmmcIsBusWidthSupported(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 SlotIndex,IN SD_MMC_BUS_MODE BusTiming,IN UINT16 BusWidth)1054 EmmcIsBusWidthSupported (
1055   IN SD_MMC_HC_PRIVATE_DATA   *Private,
1056   IN UINT8                    SlotIndex,
1057   IN SD_MMC_BUS_MODE          BusTiming,
1058   IN UINT16                   BusWidth
1059   )
1060 {
1061   if (BusWidth == 8 && Private->Capability[SlotIndex].BusWidth8 != 0) {
1062     return TRUE;
1063   } else if (BusWidth == 4 && BusTiming != SdMmcMmcHs400) {
1064     return TRUE;
1065   } else if (BusWidth == 1 && (BusTiming == SdMmcMmcHsSdr || BusTiming == SdMmcMmcLegacy)) {
1066     return TRUE;
1067   }
1068 
1069   return FALSE;
1070 }
1071 
1072 /**
1073   Get the target bus width to be set on the bus.
1074 
1075   @param[in] Private    Pointer to controller private data
1076   @param[in] SlotIndex  Index of the slot in the controller
1077   @param[in] ExtCsd     Pointer to card's extended CSD
1078   @param[in] BusTiming  Bus timing set on the bus
1079 
1080   @return Bus width to be set on the bus
1081 **/
1082 UINT8
EmmcGetTargetBusWidth(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 SlotIndex,IN EMMC_EXT_CSD * ExtCsd,IN SD_MMC_BUS_MODE BusTiming)1083 EmmcGetTargetBusWidth (
1084   IN SD_MMC_HC_PRIVATE_DATA   *Private,
1085   IN UINT8                    SlotIndex,
1086   IN EMMC_EXT_CSD             *ExtCsd,
1087   IN SD_MMC_BUS_MODE          BusTiming
1088   )
1089 {
1090   UINT8  BusWidth;
1091   UINT8  PreferredBusWidth;
1092 
1093   PreferredBusWidth = Private->Slot[SlotIndex].OperatingParameters.BusWidth;
1094 
1095   if (PreferredBusWidth != EDKII_SD_MMC_BUS_WIDTH_IGNORE &&
1096       EmmcIsBusWidthSupported (Private, SlotIndex, BusTiming, PreferredBusWidth)) {
1097     BusWidth = PreferredBusWidth;
1098   } else if (EmmcIsBusWidthSupported (Private, SlotIndex, BusTiming, 8)) {
1099     BusWidth = 8;
1100   } else if (EmmcIsBusWidthSupported (Private, SlotIndex, BusTiming, 4)) {
1101     BusWidth = 4;
1102   } else {
1103     BusWidth = 1;
1104   }
1105 
1106   return BusWidth;
1107 }
1108 
1109 /**
1110   Get the target clock frequency to be set on the bus.
1111 
1112   @param[in] Private    Pointer to controller private data
1113   @param[in] SlotIndex  Index of the slot in the controller
1114   @param[in] ExtCsd     Pointer to card's extended CSD
1115   @param[in] BusTiming  Bus timing to be set on the bus
1116 
1117   @return Value of the clock frequency to be set on bus in MHz
1118 **/
1119 UINT32
EmmcGetTargetClockFreq(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 SlotIndex,IN EMMC_EXT_CSD * ExtCsd,IN SD_MMC_BUS_MODE BusTiming)1120 EmmcGetTargetClockFreq (
1121   IN SD_MMC_HC_PRIVATE_DATA   *Private,
1122   IN UINT8                    SlotIndex,
1123   IN EMMC_EXT_CSD             *ExtCsd,
1124   IN SD_MMC_BUS_MODE          BusTiming
1125   )
1126 {
1127   UINT32 PreferredClockFreq;
1128   UINT32 MaxClockFreq;
1129 
1130   PreferredClockFreq = Private->Slot[SlotIndex].OperatingParameters.ClockFreq;
1131 
1132   switch (BusTiming) {
1133     case SdMmcMmcHs400:
1134     case SdMmcMmcHs200:
1135       MaxClockFreq = 200;
1136       break;
1137     case SdMmcMmcHsSdr:
1138     case SdMmcMmcHsDdr:
1139       MaxClockFreq = 52;
1140       break;
1141     default:
1142       MaxClockFreq = 26;
1143       break;
1144   }
1145 
1146   if (PreferredClockFreq != EDKII_SD_MMC_CLOCK_FREQ_IGNORE && PreferredClockFreq < MaxClockFreq) {
1147     return PreferredClockFreq;
1148   } else {
1149     return MaxClockFreq;
1150   }
1151 }
1152 
1153 /**
1154   Get the driver strength to be set on bus.
1155 
1156   @param[in] Private    Pointer to controller private data
1157   @param[in] SlotIndex  Index of the slot in the controller
1158   @param[in] ExtCsd     Pointer to card's extended CSD
1159   @param[in] BusTiming  Bus timing set on the bus
1160 
1161   @return Value of the driver strength to be set on the bus
1162 **/
1163 EDKII_SD_MMC_DRIVER_STRENGTH
EmmcGetTargetDriverStrength(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 SlotIndex,IN EMMC_EXT_CSD * ExtCsd,IN SD_MMC_BUS_MODE BusTiming)1164 EmmcGetTargetDriverStrength (
1165   IN SD_MMC_HC_PRIVATE_DATA   *Private,
1166   IN UINT8                    SlotIndex,
1167   IN EMMC_EXT_CSD             *ExtCsd,
1168   IN SD_MMC_BUS_MODE          BusTiming
1169   )
1170 {
1171   EDKII_SD_MMC_DRIVER_STRENGTH  PreferredDriverStrength;
1172   EDKII_SD_MMC_DRIVER_STRENGTH  DriverStrength;
1173 
1174   PreferredDriverStrength = Private->Slot[SlotIndex].OperatingParameters.DriverStrength;
1175   DriverStrength.Emmc = EmmcDriverStrengthType0;
1176 
1177   if (PreferredDriverStrength.Emmc != EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE &&
1178       (ExtCsd->DriverStrength & (BIT0 << PreferredDriverStrength.Emmc))) {
1179     DriverStrength.Emmc = PreferredDriverStrength.Emmc;
1180   }
1181 
1182   return DriverStrength;
1183 }
1184 
1185 /**
1186   Get the target settings for the bus mode.
1187 
1188   @param[in]  Private    Pointer to controller private data
1189   @param[in]  SlotIndex  Index of the slot in the controller
1190   @param[in]  ExtCsd     Pointer to card's extended CSD
1191   @param[out] BusMode    Target configuration of the bus
1192 **/
1193 VOID
EmmcGetTargetBusMode(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 SlotIndex,IN EMMC_EXT_CSD * ExtCsd,OUT SD_MMC_BUS_SETTINGS * BusMode)1194 EmmcGetTargetBusMode (
1195   IN SD_MMC_HC_PRIVATE_DATA  *Private,
1196   IN UINT8                   SlotIndex,
1197   IN EMMC_EXT_CSD            *ExtCsd,
1198   OUT SD_MMC_BUS_SETTINGS    *BusMode
1199   )
1200 {
1201   BusMode->BusTiming = EmmcGetTargetBusTiming (Private, SlotIndex, ExtCsd);
1202   BusMode->BusWidth = EmmcGetTargetBusWidth (Private, SlotIndex, ExtCsd, BusMode->BusTiming);
1203   BusMode->ClockFreq = EmmcGetTargetClockFreq (Private, SlotIndex, ExtCsd, BusMode->BusTiming);
1204   BusMode->DriverStrength = EmmcGetTargetDriverStrength (Private, SlotIndex, ExtCsd, BusMode->BusTiming);
1205 }
1206 
1207 /**
1208   Switch the high speed timing according to request.
1209 
1210   Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
1211   Simplified Spec 3.0 Figure 2-29 for details.
1212 
1213   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
1214   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
1215   @param[in] Slot           The slot number of the SD card to send the command to.
1216   @param[in] Rca            The relative device address to be assigned.
1217 
1218   @retval EFI_SUCCESS       The operation is done correctly.
1219   @retval Others            The operation fails.
1220 
1221 **/
1222 EFI_STATUS
EmmcSetBusMode(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca)1223 EmmcSetBusMode (
1224   IN EFI_PCI_IO_PROTOCOL                *PciIo,
1225   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
1226   IN UINT8                              Slot,
1227   IN UINT16                             Rca
1228   )
1229 {
1230   EFI_STATUS                    Status;
1231   EMMC_CSD                      Csd;
1232   EMMC_EXT_CSD                  ExtCsd;
1233   SD_MMC_BUS_SETTINGS           BusMode;
1234   SD_MMC_HC_PRIVATE_DATA        *Private;
1235 
1236   Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
1237 
1238   Status = EmmcGetCsd (PassThru, Slot, Rca, &Csd);
1239   if (EFI_ERROR (Status)) {
1240     DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetCsd fails with %r\n", Status));
1241     return Status;
1242   }
1243 
1244   Status = EmmcSelect (PassThru, Slot, Rca);
1245   if (EFI_ERROR (Status)) {
1246     DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: Select fails with %r\n", Status));
1247     return Status;
1248   }
1249 
1250   ASSERT (Private->BaseClkFreq[Slot] != 0);
1251 
1252   //
1253   // Get Device_Type from EXT_CSD register.
1254   //
1255   Status = EmmcGetExtCsd (PassThru, Slot, &ExtCsd);
1256   if (EFI_ERROR (Status)) {
1257     DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetExtCsd fails with %r\n", Status));
1258     return Status;
1259   }
1260 
1261   EmmcGetTargetBusMode (Private, Slot, &ExtCsd, &BusMode);
1262 
1263   DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Target bus mode: timing = %d, width = %d, clock freq = %d, driver strength = %d\n",
1264                           BusMode.BusTiming, BusMode.BusWidth, BusMode.ClockFreq, BusMode.DriverStrength.Emmc));
1265 
1266   if (BusMode.BusTiming == SdMmcMmcHs400) {
1267     Status = EmmcSwitchToHS400 (PciIo, PassThru, Slot, Rca, &BusMode);
1268   } else if (BusMode.BusTiming == SdMmcMmcHs200) {
1269     Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, &BusMode);
1270   } else {
1271     //
1272     // Note that EmmcSwitchToHighSpeed is also called for SdMmcMmcLegacy
1273     // bus timing. This is because even though we might not want to
1274     // change the timing itself we still want to allow customization of
1275     // bus parameters such as clock frequency and bus width.
1276     //
1277     Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, &BusMode);
1278   }
1279 
1280   DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n", (BusMode.BusTiming == SdMmcMmcHs400) ? "HS400" : ((BusMode.BusTiming == SdMmcMmcHs200) ? "HS200" : "HighSpeed"), Status));
1281 
1282   return Status;
1283 }
1284 
1285 /**
1286   Execute EMMC device identification procedure.
1287 
1288   Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
1289 
1290   @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
1291   @param[in] Slot           The slot number of the SD card to send the command to.
1292 
1293   @retval EFI_SUCCESS       There is a EMMC card.
1294   @retval Others            There is not a EMMC card.
1295 
1296 **/
1297 EFI_STATUS
EmmcIdentification(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 Slot)1298 EmmcIdentification (
1299   IN SD_MMC_HC_PRIVATE_DATA             *Private,
1300   IN UINT8                              Slot
1301   )
1302 {
1303   EFI_STATUS                     Status;
1304   EFI_PCI_IO_PROTOCOL            *PciIo;
1305   EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru;
1306   UINT32                         Ocr;
1307   UINT16                         Rca;
1308   UINTN                          Retry;
1309 
1310   PciIo    = Private->PciIo;
1311   PassThru = &Private->PassThru;
1312 
1313   Status = EmmcReset (PassThru, Slot);
1314   if (EFI_ERROR (Status)) {
1315     DEBUG ((DEBUG_VERBOSE, "EmmcIdentification: Executing Cmd0 fails with %r\n", Status));
1316     return Status;
1317   }
1318 
1319   Ocr   = 0;
1320   Retry = 0;
1321   do {
1322     Status = EmmcGetOcr (PassThru, Slot, &Ocr);
1323     if (EFI_ERROR (Status)) {
1324       DEBUG ((DEBUG_VERBOSE, "EmmcIdentification: Executing Cmd1 fails with %r\n", Status));
1325       return Status;
1326     }
1327     Ocr |= BIT30;
1328 
1329     if (Retry++ == 100) {
1330       DEBUG ((DEBUG_VERBOSE, "EmmcIdentification: Executing Cmd1 fails too many times\n"));
1331       return EFI_DEVICE_ERROR;
1332     }
1333     gBS->Stall(10 * 1000);
1334   } while ((Ocr & BIT31) == 0);
1335 
1336   Status = EmmcGetAllCid (PassThru, Slot);
1337   if (EFI_ERROR (Status)) {
1338     DEBUG ((DEBUG_VERBOSE, "EmmcIdentification: Executing Cmd2 fails with %r\n", Status));
1339     return Status;
1340   }
1341   //
1342   // Slot starts from 0 and valid RCA starts from 1.
1343   // Here we takes a simple formula to calculate the RCA.
1344   // Don't support multiple devices on the slot, that is
1345   // shared bus slot feature.
1346   //
1347   Rca    = Slot + 1;
1348   Status = EmmcSetRca (PassThru, Slot, Rca);
1349   if (EFI_ERROR (Status)) {
1350     DEBUG ((DEBUG_ERROR, "EmmcIdentification: Executing Cmd3 fails with %r\n", Status));
1351     return Status;
1352   }
1353   //
1354   // Enter Data Tranfer Mode.
1355   //
1356   DEBUG ((DEBUG_INFO, "EmmcIdentification: Found a EMMC device at slot [%d], RCA [%d]\n", Slot, Rca));
1357   Private->Slot[Slot].CardType = EmmcCardType;
1358 
1359   Status = EmmcSetBusMode (PciIo, PassThru, Slot, Rca);
1360 
1361   return Status;
1362 }
1363 
1364