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