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