2 This file provides some helper functions which are specific for EMMC device.
4 Copyright (c) 2015, 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
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.
15 #include "SdMmcPciHcDxe.h"
18 Send command GO_IDLE_STATE (CMD0 with argument of 0x00000000) to the device to
19 make it go to Idle State.
21 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
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.
26 @retval EFI_SUCCESS The EMMC device is reset correctly.
27 @retval Others The device reset fails.
32 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
36 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
37 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
38 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
41 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
42 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
43 ZeroMem (&Packet
, sizeof (Packet
));
45 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
46 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
47 Packet
.Timeout
= SD_MMC_HC_GENERIC_TIMEOUT
;
49 SdMmcCmdBlk
.CommandIndex
= EMMC_GO_IDLE_STATE
;
50 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeBc
;
51 SdMmcCmdBlk
.ResponseType
= 0;
52 SdMmcCmdBlk
.CommandArgument
= 0;
54 Status
= SdMmcPassThruPassThru (PassThru
, Slot
, &Packet
, NULL
);
60 Send command SEND_OP_COND to the EMMC device to get the data of the OCR register.
62 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
64 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
65 @param[in] Slot The slot number of the SD card to send the command to.
66 @param[in, out] Argument On input, the argument of SEND_OP_COND is to send to the device.
67 On output, the argument is the value of OCR register.
69 @retval EFI_SUCCESS The operation is done correctly.
70 @retval Others The operation fails.
75 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
77 IN OUT UINT32
*Argument
80 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
81 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
82 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
85 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
86 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
87 ZeroMem (&Packet
, sizeof (Packet
));
89 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
90 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
91 Packet
.Timeout
= SD_MMC_HC_GENERIC_TIMEOUT
;
93 SdMmcCmdBlk
.CommandIndex
= EMMC_SEND_OP_COND
;
94 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeBcr
;
95 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR3
;
96 SdMmcCmdBlk
.CommandArgument
= *Argument
;
98 Status
= SdMmcPassThruPassThru (PassThru
, Slot
, &Packet
, NULL
);
99 if (!EFI_ERROR (Status
)) {
101 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
103 *Argument
= SdMmcStatusBlk
.Resp0
;
110 Broadcast command ALL_SEND_CID to the bus to ask all the EMMC devices to send the
111 data of their CID registers.
113 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
115 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
116 @param[in] Slot The slot number of the SD card to send the command to.
118 @retval EFI_SUCCESS The operation is done correctly.
119 @retval Others The operation fails.
124 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
128 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
129 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
130 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
133 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
134 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
135 ZeroMem (&Packet
, sizeof (Packet
));
137 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
138 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
139 Packet
.Timeout
= SD_MMC_HC_GENERIC_TIMEOUT
;
141 SdMmcCmdBlk
.CommandIndex
= EMMC_ALL_SEND_CID
;
142 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeBcr
;
143 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR2
;
144 SdMmcCmdBlk
.CommandArgument
= 0;
146 Status
= SdMmcPassThruPassThru (PassThru
, Slot
, &Packet
, NULL
);
152 Send command SET_RELATIVE_ADDR to the EMMC device to assign a Relative device
155 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
157 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
158 @param[in] Slot The slot number of the SD card to send the command to.
159 @param[in] Rca The relative device address to be assigned.
161 @retval EFI_SUCCESS The operation is done correctly.
162 @retval Others The operation fails.
167 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
172 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
173 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
174 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
177 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
178 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
179 ZeroMem (&Packet
, sizeof (Packet
));
181 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
182 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
183 Packet
.Timeout
= SD_MMC_HC_GENERIC_TIMEOUT
;
185 SdMmcCmdBlk
.CommandIndex
= EMMC_SET_RELATIVE_ADDR
;
186 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
187 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
188 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
190 Status
= SdMmcPassThruPassThru (PassThru
, Slot
, &Packet
, NULL
);
196 Send command SEND_CSD to the EMMC device to get the data of the CSD register.
198 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
200 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
201 @param[in] Slot The slot number of the SD card to send the command to.
202 @param[in] Rca The relative device address of selected device.
203 @param[out] Csd The buffer to store the content of the CSD register.
204 Note the caller should ignore the lowest byte of this
205 buffer as the content of this byte is meaningless even
206 if the operation succeeds.
208 @retval EFI_SUCCESS The operation is done correctly.
209 @retval Others The operation fails.
214 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
220 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
221 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
222 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
225 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
226 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
227 ZeroMem (&Packet
, sizeof (Packet
));
229 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
230 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
231 Packet
.Timeout
= SD_MMC_HC_GENERIC_TIMEOUT
;
233 SdMmcCmdBlk
.CommandIndex
= EMMC_SEND_CSD
;
234 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
235 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR2
;
236 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
238 Status
= SdMmcPassThruPassThru (PassThru
, Slot
, &Packet
, NULL
);
239 if (!EFI_ERROR (Status
)) {
241 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
243 CopyMem (((UINT8
*)Csd
) + 1, &SdMmcStatusBlk
.Resp0
, sizeof (EMMC_CSD
) - 1);
250 Send command SELECT_DESELECT_CARD to the EMMC device to select/deselect it.
252 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
254 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
255 @param[in] Slot The slot number of the SD card to send the command to.
256 @param[in] Rca The relative device address of selected device.
258 @retval EFI_SUCCESS The operation is done correctly.
259 @retval Others The operation fails.
264 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
269 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
270 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
271 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
274 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
275 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
276 ZeroMem (&Packet
, sizeof (Packet
));
278 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
279 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
280 Packet
.Timeout
= SD_MMC_HC_GENERIC_TIMEOUT
;
282 SdMmcCmdBlk
.CommandIndex
= EMMC_SELECT_DESELECT_CARD
;
283 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
284 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
285 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
287 Status
= SdMmcPassThruPassThru (PassThru
, Slot
, &Packet
, NULL
);
293 Send command SEND_EXT_CSD to the EMMC device to get the data of the EXT_CSD register.
295 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
297 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
298 @param[in] Slot The slot number of the SD card to send the command to.
299 @param[out] ExtCsd The buffer to store the content of the EXT_CSD register.
301 @retval EFI_SUCCESS The operation is done correctly.
302 @retval Others The operation fails.
307 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
309 OUT EMMC_EXT_CSD
*ExtCsd
312 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
313 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
314 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
317 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
318 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
319 ZeroMem (&Packet
, sizeof (Packet
));
321 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
322 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
323 Packet
.Timeout
= SD_MMC_HC_GENERIC_TIMEOUT
;
325 SdMmcCmdBlk
.CommandIndex
= EMMC_SEND_EXT_CSD
;
326 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
327 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
328 SdMmcCmdBlk
.CommandArgument
= 0x00000000;
330 Packet
.InDataBuffer
= ExtCsd
;
331 Packet
.InTransferLength
= sizeof (EMMC_EXT_CSD
);
333 Status
= SdMmcPassThruPassThru (PassThru
, Slot
, &Packet
, NULL
);
338 Send command SWITCH to the EMMC device to switch the mode of operation of the
339 selected Device or modifies the EXT_CSD registers.
341 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
343 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
344 @param[in] Slot The slot number of the SD card to send the command to.
345 @param[in] Access The access mode of SWTICH command.
346 @param[in] Index The offset of the field to be access.
347 @param[in] Value The value to be set to the specified field of EXT_CSD register.
348 @param[in] CmdSet The value of CmdSet field of EXT_CSD register.
350 @retval EFI_SUCCESS The operation is done correctly.
351 @retval Others The operation fails.
356 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
364 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
365 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
366 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
369 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
370 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
371 ZeroMem (&Packet
, sizeof (Packet
));
373 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
374 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
375 Packet
.Timeout
= SD_MMC_HC_GENERIC_TIMEOUT
;
377 SdMmcCmdBlk
.CommandIndex
= EMMC_SWITCH
;
378 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
379 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1b
;
380 SdMmcCmdBlk
.CommandArgument
= (Access
<< 24) | (Index
<< 16) | (Value
<< 8) | CmdSet
;
382 Status
= SdMmcPassThruPassThru (PassThru
, Slot
, &Packet
, NULL
);
388 Send command SEND_STATUS to the addressed EMMC device to get its status register.
390 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
392 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
393 @param[in] Slot The slot number of the SD card to send the command to.
394 @param[in] Rca The relative device address of addressed device.
395 @param[out] DevStatus The returned device status.
397 @retval EFI_SUCCESS The operation is done correctly.
398 @retval Others The operation fails.
403 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
406 OUT UINT32
*DevStatus
409 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
410 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
411 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
414 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
415 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
416 ZeroMem (&Packet
, sizeof (Packet
));
418 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
419 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
420 Packet
.Timeout
= SD_MMC_HC_GENERIC_TIMEOUT
;
422 SdMmcCmdBlk
.CommandIndex
= EMMC_SEND_STATUS
;
423 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAc
;
424 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
425 SdMmcCmdBlk
.CommandArgument
= (UINT32
)Rca
<< 16;
427 Status
= SdMmcPassThruPassThru (PassThru
, Slot
, &Packet
, NULL
);
428 if (!EFI_ERROR (Status
)) {
429 *DevStatus
= SdMmcStatusBlk
.Resp0
;
436 Send command SEND_TUNING_BLOCK to the EMMC device for HS200 optimal sampling point
439 It may be sent up to 40 times until the host finishes the tuning procedure.
441 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 for details.
443 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
444 @param[in] Slot The slot number of the SD card to send the command to.
445 @param[in] BusWidth The bus width to work.
447 @retval EFI_SUCCESS The operation is done correctly.
448 @retval Others The operation fails.
453 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
458 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk
;
459 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk
;
460 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet
;
462 UINT8 TuningBlock
[128];
464 ZeroMem (&SdMmcCmdBlk
, sizeof (SdMmcCmdBlk
));
465 ZeroMem (&SdMmcStatusBlk
, sizeof (SdMmcStatusBlk
));
466 ZeroMem (&Packet
, sizeof (Packet
));
468 Packet
.SdMmcCmdBlk
= &SdMmcCmdBlk
;
469 Packet
.SdMmcStatusBlk
= &SdMmcStatusBlk
;
470 Packet
.Timeout
= SD_MMC_HC_GENERIC_TIMEOUT
;
472 SdMmcCmdBlk
.CommandIndex
= EMMC_SEND_TUNING_BLOCK
;
473 SdMmcCmdBlk
.CommandType
= SdMmcCommandTypeAdtc
;
474 SdMmcCmdBlk
.ResponseType
= SdMmcResponseTypeR1
;
475 SdMmcCmdBlk
.CommandArgument
= 0;
477 Packet
.InDataBuffer
= TuningBlock
;
479 Packet
.InTransferLength
= sizeof (TuningBlock
);
481 Packet
.InTransferLength
= 64;
484 Status
= SdMmcPassThruPassThru (PassThru
, Slot
, &Packet
, NULL
);
490 Tunning the clock to get HS200 optimal sampling point.
492 Command SEND_TUNING_BLOCK may be sent up to 40 times until the host finishes the
495 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
496 Simplified Spec 3.0 Figure 2-29 for details.
498 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
499 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
500 @param[in] Slot The slot number of the SD card to send the command to.
501 @param[in] BusWidth The bus width to work.
503 @retval EFI_SUCCESS The operation is done correctly.
504 @retval Others The operation fails.
508 EmmcTuningClkForHs200 (
509 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
510 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
520 // Notify the host that the sampling clock tuning procedure starts.
523 Status
= SdMmcHcOrMmio (PciIo
, Slot
, SD_MMC_HC_HOST_CTRL2
, sizeof (HostCtrl2
), &HostCtrl2
);
524 if (EFI_ERROR (Status
)) {
528 // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.
532 Status
= EmmcSendTuningBlk (PassThru
, Slot
, BusWidth
);
533 if (EFI_ERROR (Status
)) {
534 DEBUG ((EFI_D_ERROR
, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status
));
538 Status
= SdMmcHcRwMmio (PciIo
, Slot
, SD_MMC_HC_HOST_CTRL2
, TRUE
, sizeof (HostCtrl2
), &HostCtrl2
);
539 if (EFI_ERROR (Status
)) {
543 if ((HostCtrl2
& (BIT6
| BIT7
)) == BIT7
) {
546 } while (++Retry
< 40);
549 Status
= EFI_TIMEOUT
;
550 DEBUG ((EFI_D_ERROR
, "EmmcTuningClkForHs200: Send tuning block exceeds 40 times\n"));
557 Switch the bus width to specified width.
559 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.9 and SD Host Controller
560 Simplified Spec 3.0 Figure 3-7 for details.
562 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
563 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
564 @param[in] Slot The slot number of the SD card to send the command to.
565 @param[in] Rca The relative device address to be assigned.
566 @param[in] IsDdr If TRUE, use dual data rate data simpling method. Otherwise
567 use single data rate data simpling method.
568 @param[in] BusWidth The bus width to be set, it could be 4 or 8.
570 @retval EFI_SUCCESS The operation is done correctly.
571 @retval Others The operation fails.
576 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
577 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
592 // Write Byte, the Value field is written into the byte pointed by Index.
595 Index
= OFFSET_OF (EMMC_EXT_CSD
, BusWidth
);
598 } else if (BusWidth
== 8) {
601 return EFI_INVALID_PARAMETER
;
609 Status
= EmmcSwitch (PassThru
, Slot
, Access
, Index
, Value
, CmdSet
);
610 if (EFI_ERROR (Status
)) {
611 DEBUG ((EFI_D_ERROR
, "EmmcSwitchBusWidth: Switch to bus width %d fails with %r\n", BusWidth
, Status
));
615 Status
= EmmcSendStatus (PassThru
, Slot
, Rca
, &DevStatus
);
616 if (EFI_ERROR (Status
)) {
617 DEBUG ((EFI_D_ERROR
, "EmmcSwitchBusWidth: Send status fails with %r\n", Status
));
621 // Check the switch operation is really successful or not.
623 if ((DevStatus
& BIT7
) != 0) {
624 DEBUG ((EFI_D_ERROR
, "EmmcSwitchBusWidth: The switch operation fails as DevStatus is 0x%08x\n", DevStatus
));
625 return EFI_DEVICE_ERROR
;
628 Status
= SdMmcHcSetBusWidth (PciIo
, Slot
, BusWidth
);
634 Switch the clock frequency to the specified value.
636 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6 and SD Host Controller
637 Simplified Spec 3.0 Figure 3-3 for details.
639 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
640 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
641 @param[in] Slot The slot number of the SD card to send the command to.
642 @param[in] Rca The relative device address to be assigned.
643 @param[in] HsTiming The value to be written to HS_TIMING field of EXT_CSD register.
644 @param[in] ClockFreq The max clock frequency to be set, the unit is MHz.
646 @retval EFI_SUCCESS The operation is done correctly.
647 @retval Others The operation fails.
651 EmmcSwitchClockFreq (
652 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
653 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
666 SD_MMC_HC_PRIVATE_DATA
*Private
;
668 Private
= SD_MMC_HC_PRIVATE_FROM_THIS (PassThru
);
670 // Write Byte, the Value field is written into the byte pointed by Index.
673 Index
= OFFSET_OF (EMMC_EXT_CSD
, HsTiming
);
677 Status
= EmmcSwitch (PassThru
, Slot
, Access
, Index
, Value
, CmdSet
);
678 if (EFI_ERROR (Status
)) {
679 DEBUG ((EFI_D_ERROR
, "EmmcSwitchClockFreq: Switch to hstiming %d fails with %r\n", HsTiming
, Status
));
683 Status
= EmmcSendStatus (PassThru
, Slot
, Rca
, &DevStatus
);
684 if (EFI_ERROR (Status
)) {
685 DEBUG ((EFI_D_ERROR
, "EmmcSwitchClockFreq: Send status fails with %r\n", Status
));
689 // Check the switch operation is really successful or not.
691 if ((DevStatus
& BIT7
) != 0) {
692 DEBUG ((EFI_D_ERROR
, "EmmcSwitchClockFreq: The switch operation fails as DevStatus is 0x%08x\n", DevStatus
));
693 return EFI_DEVICE_ERROR
;
696 // Convert the clock freq unit from MHz to KHz.
698 Status
= SdMmcHcClockSupply (PciIo
, Slot
, ClockFreq
* 1000, Private
->Capability
[Slot
]);
704 Switch to the High Speed timing according to request.
706 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
707 Simplified Spec 3.0 Figure 2-29 for details.
709 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
710 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
711 @param[in] Slot The slot number of the SD card to send the command to.
712 @param[in] Rca The relative device address to be assigned.
713 @param[in] ClockFreq The max clock frequency to be set.
714 @param[in] IsDdr If TRUE, use dual data rate data simpling method. Otherwise
715 use single data rate data simpling method.
716 @param[in] BusWidth The bus width to be set, it could be 4 or 8.
718 @retval EFI_SUCCESS The operation is done correctly.
719 @retval Others The operation fails.
723 EmmcSwitchToHighSpeed (
724 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
725 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
738 Status
= EmmcSwitchBusWidth (PciIo
, PassThru
, Slot
, Rca
, IsDdr
, BusWidth
);
739 if (EFI_ERROR (Status
)) {
743 // Set to Hight Speed timing
746 Status
= SdMmcHcOrMmio (PciIo
, Slot
, SD_MMC_HC_HOST_CTRL1
, sizeof (HostCtrl1
), &HostCtrl1
);
747 if (EFI_ERROR (Status
)) {
752 // Clean UHS Mode Select field of Host Control 2 reigster before update
754 HostCtrl2
= (UINT8
)~0x7;
755 Status
= SdMmcHcAndMmio (PciIo
, Slot
, SD_MMC_HC_HOST_CTRL2
, sizeof (HostCtrl2
), &HostCtrl2
);
756 if (EFI_ERROR (Status
)) {
760 // Set UHS Mode Select field of Host Control 2 reigster to SDR12/25/50
764 } else if (ClockFreq
== 52) {
769 Status
= SdMmcHcOrMmio (PciIo
, Slot
, SD_MMC_HC_HOST_CTRL2
, sizeof (HostCtrl2
), &HostCtrl2
);
770 if (EFI_ERROR (Status
)) {
775 Status
= EmmcSwitchClockFreq (PciIo
, PassThru
, Slot
, Rca
, HsTiming
, ClockFreq
);
776 if (EFI_ERROR (Status
)) {
784 Switch to the HS200 timing according to request.
786 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
787 Simplified Spec 3.0 Figure 2-29 for details.
789 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
790 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
791 @param[in] Slot The slot number of the SD card to send the command to.
792 @param[in] Rca The relative device address to be assigned.
793 @param[in] ClockFreq The max clock frequency to be set.
794 @param[in] BusWidth The bus width to be set, it could be 4 or 8.
796 @retval EFI_SUCCESS The operation is done correctly.
797 @retval Others The operation fails.
802 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
803 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
815 if ((BusWidth
!= 4) && (BusWidth
!= 8)) {
816 return EFI_INVALID_PARAMETER
;
819 Status
= EmmcSwitchBusWidth (PciIo
, PassThru
, Slot
, Rca
, FALSE
, BusWidth
);
820 if (EFI_ERROR (Status
)) {
824 // Set to HS200/SDR104 timing
827 // Stop bus clock at first
829 Status
= SdMmcHcStopClock (PciIo
, Slot
);
830 if (EFI_ERROR (Status
)) {
834 // Clean UHS Mode Select field of Host Control 2 reigster before update
836 HostCtrl2
= (UINT8
)~0x7;
837 Status
= SdMmcHcAndMmio (PciIo
, Slot
, SD_MMC_HC_HOST_CTRL2
, sizeof (HostCtrl2
), &HostCtrl2
);
838 if (EFI_ERROR (Status
)) {
842 // Set UHS Mode Select field of Host Control 2 reigster to SDR104
844 HostCtrl2
= BIT0
| BIT1
;
845 Status
= SdMmcHcOrMmio (PciIo
, Slot
, SD_MMC_HC_HOST_CTRL2
, sizeof (HostCtrl2
), &HostCtrl2
);
846 if (EFI_ERROR (Status
)) {
850 // Wait Internal Clock Stable in the Clock Control register to be 1 before set SD Clock Enable bit
852 Status
= SdMmcHcWaitMmioSet (
855 SD_MMC_HC_CLOCK_CTRL
,
859 SD_MMC_HC_GENERIC_TIMEOUT
861 if (EFI_ERROR (Status
)) {
865 // Set SD Clock Enable in the Clock Control register to 1
868 Status
= SdMmcHcOrMmio (PciIo
, Slot
, SD_MMC_HC_CLOCK_CTRL
, sizeof (ClockCtrl
), &ClockCtrl
);
871 Status
= EmmcSwitchClockFreq (PciIo
, PassThru
, Slot
, Rca
, HsTiming
, ClockFreq
);
872 if (EFI_ERROR (Status
)) {
876 Status
= EmmcTuningClkForHs200 (PciIo
, PassThru
, Slot
, BusWidth
);
882 Switch to the HS400 timing according to request.
884 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
885 Simplified Spec 3.0 Figure 2-29 for details.
887 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
888 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
889 @param[in] Slot The slot number of the SD card to send the command to.
890 @param[in] Rca The relative device address to be assigned.
891 @param[in] ClockFreq The max clock frequency to be set.
893 @retval EFI_SUCCESS The operation is done correctly.
894 @retval Others The operation fails.
899 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
900 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
910 Status
= EmmcSwitchToHS200 (PciIo
, PassThru
, Slot
, Rca
, ClockFreq
, 8);
911 if (EFI_ERROR (Status
)) {
915 // Set to Hight Speed timing and set the clock frequency to a value less than 52MHz.
918 Status
= EmmcSwitchClockFreq (PciIo
, PassThru
, Slot
, Rca
, HsTiming
, 52);
919 if (EFI_ERROR (Status
)) {
923 // HS400 mode must use 8 data lines.
925 Status
= EmmcSwitchBusWidth (PciIo
, PassThru
, Slot
, Rca
, TRUE
, 8);
926 if (EFI_ERROR (Status
)) {
930 // Clean UHS Mode Select field of Host Control 2 reigster before update
932 HostCtrl2
= (UINT8
)~0x7;
933 Status
= SdMmcHcAndMmio (PciIo
, Slot
, SD_MMC_HC_HOST_CTRL2
, sizeof (HostCtrl2
), &HostCtrl2
);
934 if (EFI_ERROR (Status
)) {
938 // Set UHS Mode Select field of Host Control 2 reigster to HS400
940 HostCtrl2
= BIT0
| BIT2
;
941 Status
= SdMmcHcOrMmio (PciIo
, Slot
, SD_MMC_HC_HOST_CTRL2
, sizeof (HostCtrl2
), &HostCtrl2
);
942 if (EFI_ERROR (Status
)) {
947 Status
= EmmcSwitchClockFreq (PciIo
, PassThru
, Slot
, Rca
, HsTiming
, ClockFreq
);
953 Switch the high speed timing according to request.
955 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
956 Simplified Spec 3.0 Figure 2-29 for details.
958 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
959 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
960 @param[in] Slot The slot number of the SD card to send the command to.
961 @param[in] Rca The relative device address to be assigned.
963 @retval EFI_SUCCESS The operation is done correctly.
964 @retval Others The operation fails.
969 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
970 IN EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
,
982 SD_MMC_HC_PRIVATE_DATA
*Private
;
984 Private
= SD_MMC_HC_PRIVATE_FROM_THIS (PassThru
);
986 Status
= EmmcGetCsd (PassThru
, Slot
, Rca
, &Csd
);
987 if (EFI_ERROR (Status
)) {
988 DEBUG ((EFI_D_ERROR
, "EmmcSetBusMode: GetCsd fails with %r\n", Status
));
992 Status
= EmmcSelect (PassThru
, Slot
, Rca
);
993 if (EFI_ERROR (Status
)) {
994 DEBUG ((EFI_D_ERROR
, "EmmcSetBusMode: Select fails with %r\n", Status
));
998 ASSERT (Private
->Capability
[Slot
].BaseClkFreq
!= 0);
1000 // Check if the Host Controller support 8bits bus width.
1002 if (Private
->Capability
[Slot
].BusWidth8
!= 0) {
1008 // Get Deivce_Type from EXT_CSD register.
1010 Status
= EmmcGetExtCsd (PassThru
, Slot
, &ExtCsd
);
1011 if (EFI_ERROR (Status
)) {
1012 DEBUG ((EFI_D_ERROR
, "EmmcSetBusMode: GetExtCsd fails with %r\n", Status
));
1016 // Calculate supported bus speed/bus width/clock frequency.
1021 if (((ExtCsd
.DeviceType
& (BIT4
| BIT5
)) != 0) && (Private
->Capability
[Slot
].Sdr104
!= 0)) {
1025 } else if (((ExtCsd
.DeviceType
& (BIT2
| BIT3
)) != 0) && (Private
->Capability
[Slot
].Ddr50
!= 0)) {
1029 } else if (((ExtCsd
.DeviceType
& BIT1
) != 0) && (Private
->Capability
[Slot
].HighSpeed
!= 0)) {
1033 } else if (((ExtCsd
.DeviceType
& BIT0
) != 0) && (Private
->Capability
[Slot
].HighSpeed
!= 0)) {
1039 // Check if both of the device and the host controller support HS400 DDR mode.
1041 if (((ExtCsd
.DeviceType
& (BIT6
| BIT7
)) != 0) && (Private
->Capability
[Slot
].Hs400
!= 0)) {
1043 // The host controller supports 8bits bus.
1045 ASSERT (BusWidth
== 8);
1051 if ((ClockFreq
== 0) || (HsTiming
== 0)) {
1053 // Continue using default setting.
1058 DEBUG ((EFI_D_INFO
, "EmmcSetBusMode: HsTiming %d ClockFreq %d BusWidth %d Ddr %a\n", HsTiming
, ClockFreq
, BusWidth
, IsDdr
? "TRUE":"FALSE"));
1060 if (HsTiming
== 3) {
1062 // Execute HS400 timing switch procedure
1064 Status
= EmmcSwitchToHS400 (PciIo
, PassThru
, Slot
, Rca
, ClockFreq
);
1065 } else if (HsTiming
== 2) {
1067 // Execute HS200 timing switch procedure
1069 Status
= EmmcSwitchToHS200 (PciIo
, PassThru
, Slot
, Rca
, ClockFreq
, BusWidth
);
1072 // Execute High Speed timing switch procedure
1074 Status
= EmmcSwitchToHighSpeed (PciIo
, PassThru
, Slot
, Rca
, ClockFreq
, BusWidth
, IsDdr
);
1077 DEBUG ((EFI_D_INFO
, "EmmcSetBusMode: Switch to %a %r\n", (HsTiming
== 3) ? "HS400" : ((HsTiming
== 2) ? "HS200" : "HighSpeed"), Status
));
1083 Execute EMMC device identification procedure.
1085 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
1087 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
1088 @param[in] Slot The slot number of the SD card to send the command to.
1090 @retval EFI_SUCCESS There is a EMMC card.
1091 @retval Others There is not a EMMC card.
1095 EmmcIdentification (
1096 IN SD_MMC_HC_PRIVATE_DATA
*Private
,
1101 EFI_PCI_IO_PROTOCOL
*PciIo
;
1102 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
1106 PciIo
= Private
->PciIo
;
1107 PassThru
= &Private
->PassThru
;
1109 Status
= EmmcReset (PassThru
, Slot
);
1110 if (EFI_ERROR (Status
)) {
1111 DEBUG ((EFI_D_VERBOSE
, "EmmcIdentification: Executing Cmd0 fails with %r\n", Status
));
1117 Status
= EmmcGetOcr (PassThru
, Slot
, &Ocr
);
1118 if (EFI_ERROR (Status
)) {
1119 DEBUG ((EFI_D_VERBOSE
, "EmmcIdentification: Executing Cmd1 fails with %r\n", Status
));
1123 } while ((Ocr
& BIT31
) == 0);
1125 Status
= EmmcGetAllCid (PassThru
, Slot
);
1126 if (EFI_ERROR (Status
)) {
1127 DEBUG ((EFI_D_VERBOSE
, "EmmcIdentification: Executing Cmd2 fails with %r\n", Status
));
1131 // Slot starts from 0 and valid RCA starts from 1.
1132 // Here we takes a simple formula to calculate the RCA.
1133 // Don't support multiple devices on the slot, that is
1134 // shared bus slot feature.
1137 Status
= EmmcSetRca (PassThru
, Slot
, Rca
);
1138 if (EFI_ERROR (Status
)) {
1139 DEBUG ((EFI_D_ERROR
, "EmmcIdentification: Executing Cmd3 fails with %r\n", Status
));
1143 // Enter Data Tranfer Mode.
1145 DEBUG ((EFI_D_INFO
, "EmmcIdentification: Found a EMMC device at slot [%d], RCA [%d]\n", Slot
, Rca
));
1146 Private
->Slot
[Slot
].CardType
= EmmcCardType
;
1148 Status
= EmmcSetBusMode (PciIo
, PassThru
, Slot
, Rca
);