]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
MdeModulePkg/SdMmcPciHcDxe: Add V3 64b DMA Support
[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
195f673f 645 Switch the bus timing and clock frequency.\r
48555339
FT
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
195f673f 663EmmcSwitchBusTiming (\r
48555339
FT
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
195f673f
AM
692 DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Switch to hstiming %d fails with %r\n", HsTiming, Status));\r
693 return Status;\r
694 }\r
695\r
696 //\r
697 // Convert the clock freq unit from MHz to KHz.\r
698 //\r
699 Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);\r
700 if (EFI_ERROR (Status)) {\r
48555339
FT
701 return Status;\r
702 }\r
703\r
704 Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);\r
705 if (EFI_ERROR (Status)) {\r
195f673f 706 DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: Send status fails with %r\n", Status));\r
48555339
FT
707 return Status;\r
708 }\r
709 //\r
710 // Check the switch operation is really successful or not.\r
711 //\r
712 if ((DevStatus & BIT7) != 0) {\r
195f673f 713 DEBUG ((DEBUG_ERROR, "EmmcSwitchBusTiming: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));\r
48555339
FT
714 return EFI_DEVICE_ERROR;\r
715 }\r
b7b803a6
TM
716\r
717 if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
718 Status = mOverride->NotifyPhase (\r
719 Private->ControllerHandle,\r
720 Slot,\r
721 EdkiiSdMmcSwitchClockFreqPost,\r
722 &Timing\r
723 );\r
724 if (EFI_ERROR (Status)) {\r
725 DEBUG ((\r
726 DEBUG_ERROR,\r
727 "%a: SD/MMC switch clock freq post notifier callback failed - %r\n",\r
728 __FUNCTION__,\r
729 Status\r
730 ));\r
731 return Status;\r
732 }\r
733 }\r
48555339
FT
734\r
735 return Status;\r
736}\r
737\r
738/**\r
739 Switch to the High Speed timing according to request.\r
740\r
741 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller\r
742 Simplified Spec 3.0 Figure 2-29 for details.\r
743\r
744 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
745 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
746 @param[in] Slot The slot number of the SD card to send the command to.\r
747 @param[in] Rca The relative device address to be assigned.\r
748 @param[in] ClockFreq The max clock frequency to be set.\r
749 @param[in] IsDdr If TRUE, use dual data rate data simpling method. Otherwise\r
750 use single data rate data simpling method.\r
751 @param[in] BusWidth The bus width to be set, it could be 4 or 8.\r
752\r
753 @retval EFI_SUCCESS The operation is done correctly.\r
754 @retval Others The operation fails.\r
755\r
756**/\r
757EFI_STATUS\r
758EmmcSwitchToHighSpeed (\r
759 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
760 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
761 IN UINT8 Slot,\r
762 IN UINT16 Rca,\r
763 IN UINT32 ClockFreq,\r
764 IN BOOLEAN IsDdr,\r
765 IN UINT8 BusWidth\r
766 )\r
767{\r
a4708009
TM
768 EFI_STATUS Status;\r
769 UINT8 HsTiming;\r
770 UINT8 HostCtrl1;\r
771 SD_MMC_BUS_MODE Timing;\r
772 SD_MMC_HC_PRIVATE_DATA *Private;\r
773\r
774 Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
48555339
FT
775\r
776 Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth);\r
777 if (EFI_ERROR (Status)) {\r
778 return Status;\r
779 }\r
780 //\r
781 // Set to Hight Speed timing\r
782 //\r
783 HostCtrl1 = BIT2;\r
784 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
785 if (EFI_ERROR (Status)) {\r
786 return Status;\r
787 }\r
788\r
48555339 789 if (IsDdr) {\r
a4708009 790 Timing = SdMmcMmcHsDdr;\r
48555339 791 } else if (ClockFreq == 52) {\r
a4708009 792 Timing = SdMmcMmcHsSdr;\r
48555339 793 } else {\r
a4708009 794 Timing = SdMmcMmcLegacy;\r
48555339 795 }\r
a4708009
TM
796\r
797 Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);\r
48555339
FT
798 if (EFI_ERROR (Status)) {\r
799 return Status;\r
800 }\r
801\r
802 HsTiming = 1;\r
195f673f 803 Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);\r
48555339
FT
804\r
805 return Status;\r
806}\r
807\r
808/**\r
809 Switch to the HS200 timing according to request.\r
810\r
811 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller\r
812 Simplified Spec 3.0 Figure 2-29 for details.\r
813\r
814 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
815 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
816 @param[in] Slot The slot number of the SD card to send the command to.\r
817 @param[in] Rca The relative device address to be assigned.\r
818 @param[in] ClockFreq The max clock frequency to be set.\r
819 @param[in] BusWidth The bus width to be set, it could be 4 or 8.\r
820\r
821 @retval EFI_SUCCESS The operation is done correctly.\r
822 @retval Others The operation fails.\r
823\r
824**/\r
825EFI_STATUS\r
826EmmcSwitchToHS200 (\r
827 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
828 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
829 IN UINT8 Slot,\r
830 IN UINT16 Rca,\r
831 IN UINT32 ClockFreq,\r
832 IN UINT8 BusWidth\r
833 )\r
834{\r
a4708009
TM
835 EFI_STATUS Status;\r
836 UINT8 HsTiming;\r
837 UINT16 ClockCtrl;\r
838 SD_MMC_BUS_MODE Timing;\r
839 SD_MMC_HC_PRIVATE_DATA *Private;\r
840\r
841 Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
48555339
FT
842\r
843 if ((BusWidth != 4) && (BusWidth != 8)) {\r
844 return EFI_INVALID_PARAMETER;\r
845 }\r
846\r
847 Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE, BusWidth);\r
848 if (EFI_ERROR (Status)) {\r
849 return Status;\r
850 }\r
851 //\r
852 // Set to HS200/SDR104 timing\r
853 //\r
854 //\r
855 // Stop bus clock at first\r
856 //\r
857 Status = SdMmcHcStopClock (PciIo, Slot);\r
858 if (EFI_ERROR (Status)) {\r
859 return Status;\r
860 }\r
a4708009
TM
861\r
862 Timing = SdMmcMmcHs200;\r
863\r
864 Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);\r
48555339
FT
865 if (EFI_ERROR (Status)) {\r
866 return Status;\r
867 }\r
a4708009 868\r
48555339
FT
869 //\r
870 // Wait Internal Clock Stable in the Clock Control register to be 1 before set SD Clock Enable bit\r
871 //\r
872 Status = SdMmcHcWaitMmioSet (\r
873 PciIo,\r
874 Slot,\r
875 SD_MMC_HC_CLOCK_CTRL,\r
876 sizeof (ClockCtrl),\r
877 BIT1,\r
878 BIT1,\r
879 SD_MMC_HC_GENERIC_TIMEOUT\r
880 );\r
881 if (EFI_ERROR (Status)) {\r
882 return Status;\r
883 }\r
884 //\r
885 // Set SD Clock Enable in the Clock Control register to 1\r
886 //\r
887 ClockCtrl = BIT2;\r
888 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);\r
889\r
890 HsTiming = 2;\r
195f673f 891 Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);\r
48555339
FT
892 if (EFI_ERROR (Status)) {\r
893 return Status;\r
894 }\r
895\r
896 Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth);\r
897\r
898 return Status;\r
899}\r
900\r
901/**\r
902 Switch to the HS400 timing according to request.\r
903\r
904 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller\r
905 Simplified Spec 3.0 Figure 2-29 for details.\r
906\r
907 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
908 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
909 @param[in] Slot The slot number of the SD card to send the command to.\r
910 @param[in] Rca The relative device address to be assigned.\r
911 @param[in] ClockFreq The max clock frequency to be set.\r
912\r
913 @retval EFI_SUCCESS The operation is done correctly.\r
914 @retval Others The operation fails.\r
915\r
916**/\r
917EFI_STATUS\r
918EmmcSwitchToHS400 (\r
919 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
920 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
921 IN UINT8 Slot,\r
922 IN UINT16 Rca,\r
923 IN UINT32 ClockFreq\r
924 )\r
925{\r
a4708009
TM
926 EFI_STATUS Status;\r
927 UINT8 HsTiming;\r
928 SD_MMC_BUS_MODE Timing;\r
929 SD_MMC_HC_PRIVATE_DATA *Private;\r
930\r
931 Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
48555339
FT
932\r
933 Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, 8);\r
934 if (EFI_ERROR (Status)) {\r
935 return Status;\r
936 }\r
937 //\r
938 // Set to Hight Speed timing and set the clock frequency to a value less than 52MHz.\r
939 //\r
940 HsTiming = 1;\r
195f673f 941 Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, SdMmcMmcHsSdr, 52);\r
48555339
FT
942 if (EFI_ERROR (Status)) {\r
943 return Status;\r
944 }\r
945 //\r
946 // HS400 mode must use 8 data lines.\r
947 //\r
948 Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, TRUE, 8);\r
949 if (EFI_ERROR (Status)) {\r
950 return Status;\r
951 }\r
a4708009
TM
952\r
953 Timing = SdMmcMmcHs400;\r
954\r
955 Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);\r
48555339
FT
956 if (EFI_ERROR (Status)) {\r
957 return Status;\r
958 }\r
959\r
960 HsTiming = 3;\r
195f673f 961 Status = EmmcSwitchBusTiming (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);\r
48555339
FT
962\r
963 return Status;\r
964}\r
965\r
966/**\r
967 Switch the high speed timing according to request.\r
968\r
969 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller\r
970 Simplified Spec 3.0 Figure 2-29 for details.\r
971\r
972 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
973 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
974 @param[in] Slot The slot number of the SD card to send the command to.\r
975 @param[in] Rca The relative device address to be assigned.\r
976\r
977 @retval EFI_SUCCESS The operation is done correctly.\r
978 @retval Others The operation fails.\r
979\r
980**/\r
981EFI_STATUS\r
982EmmcSetBusMode (\r
983 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
984 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
985 IN UINT8 Slot,\r
986 IN UINT16 Rca\r
987 )\r
988{\r
989 EFI_STATUS Status;\r
990 EMMC_CSD Csd;\r
991 EMMC_EXT_CSD ExtCsd;\r
992 UINT8 HsTiming;\r
993 BOOLEAN IsDdr;\r
994 UINT32 ClockFreq;\r
995 UINT8 BusWidth;\r
996 SD_MMC_HC_PRIVATE_DATA *Private;\r
997\r
998 Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
999\r
1000 Status = EmmcGetCsd (PassThru, Slot, Rca, &Csd);\r
1001 if (EFI_ERROR (Status)) {\r
e27ccaba 1002 DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetCsd fails with %r\n", Status));\r
48555339
FT
1003 return Status;\r
1004 }\r
1005\r
1006 Status = EmmcSelect (PassThru, Slot, Rca);\r
1007 if (EFI_ERROR (Status)) {\r
e27ccaba 1008 DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: Select fails with %r\n", Status));\r
48555339
FT
1009 return Status;\r
1010 }\r
1011\r
7f3b0bad 1012 ASSERT (Private->BaseClkFreq[Slot] != 0);\r
48555339
FT
1013 //\r
1014 // Check if the Host Controller support 8bits bus width.\r
1015 //\r
1016 if (Private->Capability[Slot].BusWidth8 != 0) {\r
1017 BusWidth = 8;\r
1018 } else {\r
1019 BusWidth = 4;\r
1020 }\r
1021 //\r
1022 // Get Deivce_Type from EXT_CSD register.\r
1023 //\r
1024 Status = EmmcGetExtCsd (PassThru, Slot, &ExtCsd);\r
1025 if (EFI_ERROR (Status)) {\r
e27ccaba 1026 DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetExtCsd fails with %r\n", Status));\r
48555339
FT
1027 return Status;\r
1028 }\r
1029 //\r
1030 // Calculate supported bus speed/bus width/clock frequency.\r
1031 //\r
1032 HsTiming = 0;\r
1033 IsDdr = FALSE;\r
1034 ClockFreq = 0;\r
1035 if (((ExtCsd.DeviceType & (BIT4 | BIT5)) != 0) && (Private->Capability[Slot].Sdr104 != 0)) {\r
1036 HsTiming = 2;\r
1037 IsDdr = FALSE;\r
1038 ClockFreq = 200;\r
1039 } else if (((ExtCsd.DeviceType & (BIT2 | BIT3)) != 0) && (Private->Capability[Slot].Ddr50 != 0)) {\r
1040 HsTiming = 1;\r
1041 IsDdr = TRUE;\r
1042 ClockFreq = 52;\r
1043 } else if (((ExtCsd.DeviceType & BIT1) != 0) && (Private->Capability[Slot].HighSpeed != 0)) {\r
1044 HsTiming = 1;\r
1045 IsDdr = FALSE;\r
1046 ClockFreq = 52;\r
1047 } else if (((ExtCsd.DeviceType & BIT0) != 0) && (Private->Capability[Slot].HighSpeed != 0)) {\r
1048 HsTiming = 1;\r
1049 IsDdr = FALSE;\r
1050 ClockFreq = 26;\r
1051 }\r
1052 //\r
1053 // Check if both of the device and the host controller support HS400 DDR mode.\r
1054 //\r
1055 if (((ExtCsd.DeviceType & (BIT6 | BIT7)) != 0) && (Private->Capability[Slot].Hs400 != 0)) {\r
1056 //\r
1057 // The host controller supports 8bits bus.\r
1058 //\r
1059 ASSERT (BusWidth == 8);\r
1060 HsTiming = 3;\r
1061 IsDdr = TRUE;\r
1062 ClockFreq = 200;\r
1063 }\r
1064\r
1065 if ((ClockFreq == 0) || (HsTiming == 0)) {\r
1066 //\r
1067 // Continue using default setting.\r
1068 //\r
1069 return EFI_SUCCESS;\r
1070 }\r
1071\r
e27ccaba 1072 DEBUG ((DEBUG_INFO, "EmmcSetBusMode: HsTiming %d ClockFreq %d BusWidth %d Ddr %a\n", HsTiming, ClockFreq, BusWidth, IsDdr ? "TRUE":"FALSE"));\r
48555339
FT
1073\r
1074 if (HsTiming == 3) {\r
1075 //\r
1076 // Execute HS400 timing switch procedure\r
1077 //\r
1078 Status = EmmcSwitchToHS400 (PciIo, PassThru, Slot, Rca, ClockFreq);\r
1079 } else if (HsTiming == 2) {\r
1080 //\r
1081 // Execute HS200 timing switch procedure\r
1082 //\r
1083 Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);\r
1084 } else {\r
1085 //\r
1086 // Execute High Speed timing switch procedure\r
1087 //\r
91ff0f05 1088 Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth);\r
48555339
FT
1089 }\r
1090\r
e27ccaba 1091 DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n", (HsTiming == 3) ? "HS400" : ((HsTiming == 2) ? "HS200" : "HighSpeed"), Status));\r
48555339
FT
1092\r
1093 return Status;\r
1094}\r
1095\r
1096/**\r
1097 Execute EMMC device identification procedure.\r
1098\r
1099 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.\r
1100\r
1101 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
1102 @param[in] Slot The slot number of the SD card to send the command to.\r
1103\r
1104 @retval EFI_SUCCESS There is a EMMC card.\r
1105 @retval Others There is not a EMMC card.\r
1106\r
1107**/\r
1108EFI_STATUS\r
1109EmmcIdentification (\r
1110 IN SD_MMC_HC_PRIVATE_DATA *Private,\r
1111 IN UINT8 Slot\r
1112 )\r
1113{\r
1114 EFI_STATUS Status;\r
1115 EFI_PCI_IO_PROTOCOL *PciIo;\r
1116 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
1117 UINT32 Ocr;\r
1118 UINT16 Rca;\r
ec86d285 1119 UINTN Retry;\r
48555339
FT
1120\r
1121 PciIo = Private->PciIo;\r
1122 PassThru = &Private->PassThru;\r
1123\r
1124 Status = EmmcReset (PassThru, Slot);\r
1125 if (EFI_ERROR (Status)) {\r
e27ccaba 1126 DEBUG ((DEBUG_VERBOSE, "EmmcIdentification: Executing Cmd0 fails with %r\n", Status));\r
48555339
FT
1127 return Status;\r
1128 }\r
1129\r
ec86d285
FT
1130 Ocr = 0;\r
1131 Retry = 0;\r
48555339
FT
1132 do {\r
1133 Status = EmmcGetOcr (PassThru, Slot, &Ocr);\r
1134 if (EFI_ERROR (Status)) {\r
e27ccaba 1135 DEBUG ((DEBUG_VERBOSE, "EmmcIdentification: Executing Cmd1 fails with %r\n", Status));\r
48555339
FT
1136 return Status;\r
1137 }\r
1138 Ocr |= BIT30;\r
ec86d285
FT
1139\r
1140 if (Retry++ == 100) {\r
1141 DEBUG ((DEBUG_VERBOSE, "EmmcIdentification: Executing Cmd1 fails too many times\n"));\r
1142 return EFI_DEVICE_ERROR;\r
1143 }\r
1144 gBS->Stall(10 * 1000);\r
48555339
FT
1145 } while ((Ocr & BIT31) == 0);\r
1146\r
1147 Status = EmmcGetAllCid (PassThru, Slot);\r
1148 if (EFI_ERROR (Status)) {\r
e27ccaba 1149 DEBUG ((DEBUG_VERBOSE, "EmmcIdentification: Executing Cmd2 fails with %r\n", Status));\r
48555339
FT
1150 return Status;\r
1151 }\r
1152 //\r
1153 // Slot starts from 0 and valid RCA starts from 1.\r
1154 // Here we takes a simple formula to calculate the RCA.\r
1155 // Don't support multiple devices on the slot, that is\r
1156 // shared bus slot feature.\r
1157 //\r
1158 Rca = Slot + 1;\r
1159 Status = EmmcSetRca (PassThru, Slot, Rca);\r
1160 if (EFI_ERROR (Status)) {\r
e27ccaba 1161 DEBUG ((DEBUG_ERROR, "EmmcIdentification: Executing Cmd3 fails with %r\n", Status));\r
48555339
FT
1162 return Status;\r
1163 }\r
1164 //\r
1165 // Enter Data Tranfer Mode.\r
1166 //\r
e27ccaba 1167 DEBUG ((DEBUG_INFO, "EmmcIdentification: Found a EMMC device at slot [%d], RCA [%d]\n", Slot, Rca));\r
48555339
FT
1168 Private->Slot[Slot].CardType = EmmcCardType;\r
1169\r
1170 Status = EmmcSetBusMode (PciIo, PassThru, Slot, Rca);\r
1171\r
1172 return Status;\r
1173}\r
1174\r