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