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