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