]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
MdeModulePkg/SdMmc: Add break to avoid dead loop when polling OCR Reg
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / SdMmcPciHcDxe / SdDevice.c
CommitLineData
48555339
FT
1/** @file\r
2 This file provides some helper functions which are specific for SD card device.\r
3\r
ac30e4c1 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 to the device to make it go to Idle State.\r
19\r
20 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
21\r
22 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
23 @param[in] Slot The slot number of the SD card to send the command to.\r
24\r
25 @retval EFI_SUCCESS The SD device is reset correctly.\r
26 @retval Others The device reset fails.\r
27\r
28**/\r
29EFI_STATUS\r
30SdCardReset (\r
31 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
32 IN UINT8 Slot\r
33 )\r
34{\r
35 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
36 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
37 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
38 EFI_STATUS Status;\r
39\r
40 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
41 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
42 ZeroMem (&Packet, sizeof (Packet));\r
43\r
44 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
45 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
46 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
47\r
48 SdMmcCmdBlk.CommandIndex = SD_GO_IDLE_STATE;\r
49 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBc;\r
50\r
51 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
52\r
53 return Status;\r
54}\r
55\r
56/**\r
57 Send command SEND_IF_COND to the device to inquiry the SD Memory Card interface\r
58 condition.\r
59\r
60 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
61\r
62 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
63 @param[in] Slot The slot number of the SD card to send the command to.\r
64 @param[in] SupplyVoltage The supplied voltage by the host.\r
65 @param[in] CheckPattern The check pattern to be sent to the device.\r
66\r
67 @retval EFI_SUCCESS The operation is done correctly.\r
68 @retval Others The operation fails.\r
69\r
70**/\r
71EFI_STATUS\r
72SdCardVoltageCheck (\r
73 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
74 IN UINT8 Slot,\r
75 IN UINT8 SupplyVoltage,\r
76 IN UINT8 CheckPattern\r
77 )\r
78{\r
79 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
80 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
81 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
82 EFI_STATUS Status;\r
83\r
84 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
85 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
86 ZeroMem (&Packet, sizeof (Packet));\r
87\r
88 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
89 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
90 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
91\r
92 SdMmcCmdBlk.CommandIndex = SD_SEND_IF_COND;\r
93 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr;\r
94 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR7;\r
95 SdMmcCmdBlk.CommandArgument = (SupplyVoltage << 8) | CheckPattern;\r
96\r
97 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
98\r
99 if (!EFI_ERROR (Status)) {\r
100 if (SdMmcStatusBlk.Resp0 != SdMmcCmdBlk.CommandArgument) {\r
101 return EFI_DEVICE_ERROR;\r
102 }\r
103 }\r
104\r
105 return Status;\r
106}\r
107\r
108/**\r
109 Send command SDIO_SEND_OP_COND to the device to see whether it is SDIO device.\r
110\r
111 Refer to SDIO Simplified Spec 3 Section 3.2 for details.\r
112\r
113 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
114 @param[in] Slot The slot number of the SD card to send the command to.\r
115 @param[in] VoltageWindow The supply voltage window.\r
116 @param[in] S18R The boolean to show if it should switch to 1.8v.\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
123SdioSendOpCond (\r
124 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
125 IN UINT8 Slot,\r
126 IN UINT32 VoltageWindow,\r
127 IN BOOLEAN S18R\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 UINT32 Switch;\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 = SDIO_SEND_OP_COND;\r
145 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr;\r
146 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR4;\r
147\r
148 Switch = S18R ? BIT24 : 0;\r
149\r
150 SdMmcCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch;\r
151\r
152 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
153\r
154 return Status;\r
155}\r
156\r
157/**\r
158 Send command SD_SEND_OP_COND to the device to see whether it is SDIO device.\r
159\r
160 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
161\r
162 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
163 @param[in] Slot The slot number of the SD card to send the command to.\r
164 @param[in] Rca The relative device address of addressed device.\r
165 @param[in] VoltageWindow The supply voltage window.\r
166 @param[in] S18R The boolean to show if it should switch to 1.8v.\r
167 @param[in] Xpc The boolean to show if it should provide 0.36w power control.\r
168 @param[in] Hcs The boolean to show if it support host capacity info.\r
169 @param[out] Ocr The buffer to store returned OCR register value.\r
170\r
171 @retval EFI_SUCCESS The operation is done correctly.\r
172 @retval Others The operation fails.\r
173\r
174**/\r
175EFI_STATUS\r
176SdCardSendOpCond (\r
177 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
178 IN UINT8 Slot,\r
179 IN UINT16 Rca,\r
180 IN UINT32 VoltageWindow,\r
181 IN BOOLEAN S18R,\r
182 IN BOOLEAN Xpc,\r
183 IN BOOLEAN Hcs,\r
184 OUT UINT32 *Ocr\r
185 )\r
186{\r
187 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
188 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
189 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
190 EFI_STATUS Status;\r
191 UINT32 Switch;\r
192 UINT32 MaxPower;\r
193 UINT32 HostCapacity;\r
194\r
195 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
196 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
197 ZeroMem (&Packet, sizeof (Packet));\r
198\r
199 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
200 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
201 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
202\r
203 SdMmcCmdBlk.CommandIndex = SD_APP_CMD;\r
204 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
205 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
206 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
207\r
208 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
209 if (EFI_ERROR (Status)) {\r
210 return Status;\r
211 }\r
212\r
213 SdMmcCmdBlk.CommandIndex = SD_SEND_OP_COND;\r
214 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr;\r
215 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR3;\r
216\r
217 Switch = S18R ? BIT24 : 0;\r
218 MaxPower = Xpc ? BIT28 : 0;\r
219 HostCapacity = Hcs ? BIT30 : 0;\r
220\r
221 SdMmcCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch | MaxPower | HostCapacity;\r
222\r
223 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
224 if (!EFI_ERROR (Status)) {\r
225 //\r
226 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.\r
227 //\r
228 *Ocr = SdMmcStatusBlk.Resp0;\r
229 }\r
230\r
231 return Status;\r
232}\r
233\r
234/**\r
235 Broadcast command ALL_SEND_CID to the bus to ask all the SD devices to send the\r
236 data of their CID registers.\r
237\r
238 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
239\r
240 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
241 @param[in] Slot The slot number of the SD card to send the command to.\r
242\r
243 @retval EFI_SUCCESS The operation is done correctly.\r
244 @retval Others The operation fails.\r
245\r
246**/\r
247EFI_STATUS\r
248SdCardAllSendCid (\r
249 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
250 IN UINT8 Slot\r
251 )\r
252{\r
253 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
254 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
255 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
256 EFI_STATUS Status;\r
257\r
258 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
259 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
260 ZeroMem (&Packet, sizeof (Packet));\r
261\r
262 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
263 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
264 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
265\r
266 SdMmcCmdBlk.CommandIndex = SD_ALL_SEND_CID;\r
267 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr;\r
268 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;\r
269\r
270 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
271\r
272 return Status;\r
273}\r
274\r
275/**\r
276 Send command SET_RELATIVE_ADDR to the SD device to assign a Relative device\r
277 Address (RCA).\r
278\r
279 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
280\r
281 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
282 @param[in] Slot The slot number of the SD card to send the command to.\r
283 @param[out] Rca The relative device address to assign.\r
284\r
285 @retval EFI_SUCCESS The operation is done correctly.\r
286 @retval Others The operation fails.\r
287\r
288**/\r
289EFI_STATUS\r
290SdCardSetRca (\r
291 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
292 IN UINT8 Slot,\r
293 OUT UINT16 *Rca\r
294 )\r
295{\r
296 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
297 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
298 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
299 EFI_STATUS Status;\r
300\r
301 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
302 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
303 ZeroMem (&Packet, sizeof (Packet));\r
304\r
305 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
306 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
307 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
308\r
309 SdMmcCmdBlk.CommandIndex = SD_SET_RELATIVE_ADDR;\r
310 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr;\r
311 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR6;\r
312\r
313 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
314 if (!EFI_ERROR (Status)) {\r
315 *Rca = (UINT16)(SdMmcStatusBlk.Resp0 >> 16);\r
316 }\r
317\r
318 return Status;\r
319}\r
320\r
321/**\r
322 Send command SEND_CSD to the SD device to get the data of the CSD register.\r
323\r
324 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
325\r
326 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
327 @param[in] Slot The slot number of the SD card to send the command to.\r
328 @param[in] Rca The relative device address of selected device.\r
329 @param[out] Csd The buffer to store the content of the CSD register.\r
330 Note the caller should ignore the lowest byte of this\r
331 buffer as the content of this byte is meaningless even\r
332 if the operation succeeds.\r
333\r
334 @retval EFI_SUCCESS The operation is done correctly.\r
335 @retval Others The operation fails.\r
336\r
337**/\r
338EFI_STATUS\r
339SdCardGetCsd (\r
340 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
341 IN UINT8 Slot,\r
342 IN UINT16 Rca,\r
343 OUT SD_CSD *Csd\r
344 )\r
345{\r
346 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
347 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
348 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
349 EFI_STATUS Status;\r
350\r
351 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
352 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
353 ZeroMem (&Packet, sizeof (Packet));\r
354\r
355 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
356 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
357 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
358\r
359 SdMmcCmdBlk.CommandIndex = SD_SEND_CSD;\r
360 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
361 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;\r
362 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
363\r
364 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
365 if (!EFI_ERROR (Status)) {\r
366 //\r
367 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.\r
368 //\r
369 CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CSD) - 1);\r
370 }\r
371\r
372 return Status;\r
373}\r
374\r
375/**\r
376 Send command SEND_CSD to the SD device to get the data of the CSD register.\r
377\r
378 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
379\r
380 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
381 @param[in] Slot The slot number of the SD card to send the command to.\r
382 @param[in] Rca The relative device address of selected device.\r
383 @param[out] Scr The buffer to store the content of the SCR register.\r
384\r
385 @retval EFI_SUCCESS The operation is done correctly.\r
386 @retval Others The operation fails.\r
387\r
388**/\r
389EFI_STATUS\r
390SdCardGetScr (\r
391 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
392 IN UINT8 Slot,\r
393 IN UINT16 Rca,\r
394 OUT SD_SCR *Scr\r
395 )\r
396{\r
397 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
398 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
399 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
400 EFI_STATUS Status;\r
401\r
402 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
403 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
404 ZeroMem (&Packet, sizeof (Packet));\r
405\r
406 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
407 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
408 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
409\r
410 SdMmcCmdBlk.CommandIndex = SD_APP_CMD;\r
411 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
412 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
413 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
414\r
415 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
416 if (EFI_ERROR (Status)) {\r
417 return Status;\r
418 }\r
419\r
420 SdMmcCmdBlk.CommandIndex = SD_SEND_SCR;\r
421 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;\r
422 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
423\r
424 Packet.InDataBuffer = Scr;\r
425 Packet.InTransferLength = sizeof (SD_SCR);\r
426\r
427 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
428\r
429 return Status;\r
430}\r
431\r
432/**\r
433 Send command SELECT_DESELECT_CARD to the SD device to select/deselect it.\r
434\r
435 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
436\r
437 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
438 @param[in] Slot The slot number of the SD card to send the command to.\r
439 @param[in] Rca The relative device address of selected device.\r
440\r
441 @retval EFI_SUCCESS The operation is done correctly.\r
442 @retval Others The operation fails.\r
443\r
444**/\r
445EFI_STATUS\r
446SdCardSelect (\r
447 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
448 IN UINT8 Slot,\r
449 IN UINT16 Rca\r
450 )\r
451{\r
452 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
453 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
454 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
455 EFI_STATUS Status;\r
456\r
457 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
458 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
459 ZeroMem (&Packet, sizeof (Packet));\r
460\r
461 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
462 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
463 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
464\r
465 SdMmcCmdBlk.CommandIndex = SD_SELECT_DESELECT_CARD;\r
466 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
ac30e4c1
FT
467 if (Rca != 0) {\r
468 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;\r
469 }\r
48555339
FT
470 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
471\r
472 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
473\r
474 return Status;\r
475}\r
476\r
477/**\r
478 Send command VOLTAGE_SWITCH to the SD device to switch the voltage of the device.\r
479\r
480 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
481\r
482 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
483 @param[in] Slot The slot number of the SD card to send the command to.\r
484\r
485 @retval EFI_SUCCESS The operation is done correctly.\r
486 @retval Others The operation fails.\r
487\r
488**/\r
489EFI_STATUS\r
490SdCardVoltageSwitch (\r
491 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
492 IN UINT8 Slot\r
493 )\r
494{\r
495 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
496 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
497 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
498 EFI_STATUS Status;\r
499\r
500 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
501 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
502 ZeroMem (&Packet, sizeof (Packet));\r
503\r
504 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
505 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
506 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
507\r
508 SdMmcCmdBlk.CommandIndex = SD_VOLTAGE_SWITCH;\r
509 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
510 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
511 SdMmcCmdBlk.CommandArgument = 0;\r
512\r
513 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
514\r
515 return Status;\r
516}\r
517\r
518/**\r
519 Send command SET_BUS_WIDTH to the SD device to set the bus width.\r
520\r
521 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
522\r
523 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
524 @param[in] Slot The slot number of the SD card to send the command to.\r
525 @param[in] Rca The relative device address of addressed device.\r
526 @param[in] BusWidth The bus width to be set, it could be 1 or 4.\r
527\r
528 @retval EFI_SUCCESS The operation is done correctly.\r
529 @retval Others The operation fails.\r
530\r
531**/\r
532EFI_STATUS\r
533SdCardSetBusWidth (\r
534 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
535 IN UINT8 Slot,\r
536 IN UINT16 Rca,\r
537 IN UINT8 BusWidth\r
538 )\r
539{\r
540 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
541 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
542 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
543 EFI_STATUS Status;\r
544 UINT8 Value;\r
545\r
546 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
547 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
548 ZeroMem (&Packet, sizeof (Packet));\r
549\r
550 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
551 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
552 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
553\r
554 SdMmcCmdBlk.CommandIndex = SD_APP_CMD;\r
555 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
556 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
557 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
558\r
559 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
560 if (EFI_ERROR (Status)) {\r
561 return Status;\r
562 }\r
563\r
564 SdMmcCmdBlk.CommandIndex = SD_SET_BUS_WIDTH;\r
565 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
566 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
567\r
568 if (BusWidth == 1) {\r
569 Value = 0;\r
570 } else if (BusWidth == 4) {\r
571 Value = 2;\r
572 } else {\r
573 return EFI_INVALID_PARAMETER;\r
574 }\r
575\r
576 SdMmcCmdBlk.CommandArgument = Value & 0x3;\r
577\r
578 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
579 return Status;\r
580}\r
581\r
582/**\r
583 Send command SWITCH_FUNC to the SD device to check switchable function or switch card function.\r
584\r
585 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
586\r
587 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
588 @param[in] Slot The slot number of the SD card to send the command to.\r
589 @param[in] AccessMode The value for access mode group.\r
590 @param[in] CommandSystem The value for command set group.\r
591 @param[in] DriveStrength The value for drive length group.\r
592 @param[in] PowerLimit The value for power limit group.\r
593 @param[in] Mode Switch or check function.\r
6263ae93 594 @param[out] SwitchResp The return switch function status.\r
48555339
FT
595\r
596 @retval EFI_SUCCESS The operation is done correctly.\r
597 @retval Others The operation fails.\r
598\r
599**/\r
600EFI_STATUS\r
601SdCardSwitch (\r
6263ae93
FT
602 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
603 IN UINT8 Slot,\r
604 IN UINT8 AccessMode,\r
605 IN UINT8 CommandSystem,\r
606 IN UINT8 DriveStrength,\r
607 IN UINT8 PowerLimit,\r
608 IN BOOLEAN Mode,\r
609 OUT UINT8 *SwitchResp\r
48555339
FT
610 )\r
611{\r
612 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
613 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
614 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
615 EFI_STATUS Status;\r
616 UINT32 ModeValue;\r
48555339
FT
617\r
618 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
619 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
620 ZeroMem (&Packet, sizeof (Packet));\r
621\r
622 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
623 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
624 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
625\r
626 SdMmcCmdBlk.CommandIndex = SD_SWITCH_FUNC;\r
627 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;\r
628 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
629\r
630 ModeValue = Mode ? BIT31 : 0;\r
631 SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \\r
632 ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \\r
633 ModeValue;\r
634\r
6263ae93
FT
635 Packet.InDataBuffer = SwitchResp;\r
636 Packet.InTransferLength = 64;\r
48555339
FT
637\r
638 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
639\r
640 return Status;\r
641}\r
642\r
643/**\r
644 Send command SEND_STATUS to the addressed SD device to get its status register.\r
645\r
646 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
647\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 of addressed device.\r
651 @param[out] DevStatus The returned device status.\r
652\r
653 @retval EFI_SUCCESS The operation is done correctly.\r
654 @retval Others The operation fails.\r
655\r
656**/\r
657EFI_STATUS\r
658SdCardSendStatus (\r
659 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
660 IN UINT8 Slot,\r
661 IN UINT16 Rca,\r
662 OUT UINT32 *DevStatus\r
663 )\r
664{\r
665 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
666 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
667 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
668 EFI_STATUS Status;\r
669\r
670 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
671 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
672 ZeroMem (&Packet, sizeof (Packet));\r
673\r
674 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
675 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
676 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
677\r
678 SdMmcCmdBlk.CommandIndex = SD_SEND_STATUS;\r
679 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
680 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
681 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
682\r
683 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
684 if (!EFI_ERROR (Status)) {\r
685 *DevStatus = SdMmcStatusBlk.Resp0;\r
686 }\r
687\r
688 return Status;\r
689}\r
690\r
691/**\r
692 Send command SEND_TUNING_BLOCK to the SD device for HS200 optimal sampling point\r
693 detection.\r
694\r
695 It may be sent up to 40 times until the host finishes the tuning procedure.\r
696\r
697 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
698\r
699 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
700 @param[in] Slot The slot number of the SD card to send the command to.\r
701\r
702 @retval EFI_SUCCESS The operation is done correctly.\r
703 @retval Others The operation fails.\r
704\r
705**/\r
706EFI_STATUS\r
707SdCardSendTuningBlk (\r
708 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
709 IN UINT8 Slot\r
710 )\r
711{\r
712 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
713 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
714 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
715 EFI_STATUS Status;\r
716 UINT8 TuningBlock[64];\r
717\r
718 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
719 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
720 ZeroMem (&Packet, sizeof (Packet));\r
721\r
722 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
723 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
724 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
725\r
726 SdMmcCmdBlk.CommandIndex = SD_SEND_TUNING_BLOCK;\r
727 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;\r
728 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
729 SdMmcCmdBlk.CommandArgument = 0;\r
730\r
731 Packet.InDataBuffer = TuningBlock;\r
732 Packet.InTransferLength = sizeof (TuningBlock);\r
733\r
734 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
735\r
736 return Status;\r
737}\r
738\r
739/**\r
740 Tunning the sampling point of SDR104 or SDR50 bus speed mode.\r
741\r
742 Command SD_SEND_TUNING_BLOCK may be sent up to 40 times until the host finishes the\r
743 tuning procedure.\r
744\r
745 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and\r
746 SD Host Controller Simplified Spec 3.0 section Figure 3-7 for details.\r
747\r
748 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
749 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
750 @param[in] Slot The slot number of the SD card to send the command to.\r
751\r
752 @retval EFI_SUCCESS The operation is done correctly.\r
753 @retval Others The operation fails.\r
754\r
755**/\r
756EFI_STATUS\r
757SdCardTuningClock (\r
758 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
759 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
760 IN UINT8 Slot\r
761 )\r
762{\r
763 EFI_STATUS Status;\r
764 UINT8 HostCtrl2;\r
765 UINT8 Retry;\r
766\r
767 //\r
768 // Notify the host that the sampling clock tuning procedure starts.\r
769 //\r
770 HostCtrl2 = BIT6;\r
771 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
772 if (EFI_ERROR (Status)) {\r
773 return Status;\r
774 }\r
775 //\r
776 // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.\r
777 //\r
778 Retry = 0;\r
779 do {\r
780 Status = SdCardSendTuningBlk (PassThru, Slot);\r
781 if (EFI_ERROR (Status)) {\r
e27ccaba 782 DEBUG ((DEBUG_ERROR, "SdCardSendTuningBlk: Send tuning block fails with %r\n", Status));\r
48555339
FT
783 return Status;\r
784 }\r
785\r
786 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);\r
787 if (EFI_ERROR (Status)) {\r
788 return Status;\r
789 }\r
790\r
8c983d3e 791 if ((HostCtrl2 & (BIT6 | BIT7)) == 0) {\r
48555339
FT
792 break;\r
793 }\r
8c983d3e
FT
794 if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {\r
795 return EFI_SUCCESS;\r
796 }\r
48555339
FT
797 } while (++Retry < 40);\r
798\r
e27ccaba 799 DEBUG ((DEBUG_ERROR, "SdCardTuningClock: Send tuning block fails at %d times with HostCtrl2 %02x\n", Retry, HostCtrl2));\r
8c983d3e
FT
800 //\r
801 // Abort the tuning procedure and reset the tuning circuit.\r
802 //\r
803 HostCtrl2 = (UINT8)~(BIT6 | BIT7);\r
804 Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
805 if (EFI_ERROR (Status)) {\r
806 return Status;\r
48555339 807 }\r
8c983d3e 808 return EFI_DEVICE_ERROR;\r
48555339
FT
809}\r
810\r
811/**\r
812 Switch the bus width to specified width.\r
813\r
814 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and\r
815 SD Host Controller Simplified Spec 3.0 section Figure 3-7 for details.\r
816\r
817 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
818 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
819 @param[in] Slot The slot number of the SD card to send the command to.\r
820 @param[in] Rca The relative device address to be assigned.\r
821 @param[in] BusWidth The bus width to be set, it could be 4 or 8.\r
822\r
823 @retval EFI_SUCCESS The operation is done correctly.\r
824 @retval Others The operation fails.\r
825\r
826**/\r
827EFI_STATUS\r
828SdCardSwitchBusWidth (\r
829 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
830 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
831 IN UINT8 Slot,\r
832 IN UINT16 Rca,\r
833 IN UINT8 BusWidth\r
834 )\r
835{\r
836 EFI_STATUS Status;\r
837 UINT32 DevStatus;\r
838\r
839 Status = SdCardSetBusWidth (PassThru, Slot, Rca, BusWidth);\r
840 if (EFI_ERROR (Status)) {\r
e27ccaba 841 DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: Switch to bus width %d fails with %r\n", BusWidth, Status));\r
48555339
FT
842 return Status;\r
843 }\r
844\r
845 Status = SdCardSendStatus (PassThru, Slot, Rca, &DevStatus);\r
846 if (EFI_ERROR (Status)) {\r
e27ccaba 847 DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: Send status fails with %r\n", Status));\r
48555339
FT
848 return Status;\r
849 }\r
850 //\r
851 // Check the switch operation is really successful or not.\r
852 //\r
853 if ((DevStatus >> 16) != 0) {\r
e27ccaba 854 DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));\r
48555339
FT
855 return EFI_DEVICE_ERROR;\r
856 }\r
857\r
858 Status = SdMmcHcSetBusWidth (PciIo, Slot, BusWidth);\r
859\r
860 return Status;\r
861}\r
862\r
863/**\r
864 Switch the high speed timing according to request.\r
865\r
866 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and\r
867 SD Host Controller Simplified Spec 3.0 section Figure 2-29 for details.\r
868\r
869 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
870 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
871 @param[in] Slot The slot number of the SD card to send the command to.\r
872 @param[in] Rca The relative device address to be assigned.\r
873 @param[in] S18A The boolean to show if it's a UHS-I SD card.\r
874\r
875 @retval EFI_SUCCESS The operation is done correctly.\r
876 @retval Others The operation fails.\r
877\r
878**/\r
879EFI_STATUS\r
880SdCardSetBusMode (\r
881 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
882 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
883 IN UINT8 Slot,\r
884 IN UINT16 Rca,\r
885 IN BOOLEAN S18A\r
886 )\r
887{\r
888 EFI_STATUS Status;\r
889 SD_MMC_HC_SLOT_CAP *Capability;\r
890 UINT32 ClockFreq;\r
891 UINT8 BusWidth;\r
892 UINT8 AccessMode;\r
893 UINT8 HostCtrl1;\r
894 UINT8 HostCtrl2;\r
6263ae93 895 UINT8 SwitchResp[64];\r
48555339
FT
896 SD_MMC_HC_PRIVATE_DATA *Private;\r
897\r
898 Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
899\r
900 Capability = &Private->Capability[Slot];\r
901\r
902 Status = SdCardSelect (PassThru, Slot, Rca);\r
903 if (EFI_ERROR (Status)) {\r
904 return Status;\r
905 }\r
906\r
907 BusWidth = 4;\r
908\r
909 Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, BusWidth);\r
910 if (EFI_ERROR (Status)) {\r
911 return Status;\r
912 }\r
48555339 913 //\r
6263ae93
FT
914 // Get the supported bus speed from SWITCH cmd return data group #1.\r
915 //\r
916 Status = SdCardSwitch (PassThru, Slot, 0xF, 0xF, 0xF, 0xF, FALSE, SwitchResp);\r
917 if (EFI_ERROR (Status)) {\r
918 return Status;\r
919 }\r
920 //\r
921 // Calculate supported bus speed/bus width/clock frequency by host and device capability.\r
48555339
FT
922 //\r
923 ClockFreq = 0;\r
6263ae93 924 if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {\r
48555339
FT
925 ClockFreq = 208;\r
926 AccessMode = 3;\r
6263ae93 927 } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {\r
48555339
FT
928 ClockFreq = 100;\r
929 AccessMode = 2;\r
6263ae93 930 } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {\r
48555339
FT
931 ClockFreq = 50;\r
932 AccessMode = 4;\r
6263ae93 933 } else if ((SwitchResp[13] & BIT1) != 0) {\r
48555339
FT
934 ClockFreq = 50;\r
935 AccessMode = 1;\r
6263ae93
FT
936 } else {\r
937 ClockFreq = 25;\r
938 AccessMode = 0;\r
48555339
FT
939 }\r
940\r
6263ae93 941 Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);\r
48555339
FT
942 if (EFI_ERROR (Status)) {\r
943 return Status;\r
944 }\r
945\r
6263ae93 946 if ((SwitchResp[16] & 0xF) != AccessMode) {\r
e27ccaba 947 DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d BusWidth %d fails! The Switch response is 0x%1x\n", AccessMode, ClockFreq, BusWidth, SwitchResp[16] & 0xF));\r
6263ae93
FT
948 return EFI_DEVICE_ERROR;\r
949 }\r
950\r
e27ccaba 951 DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));\r
6263ae93 952\r
48555339
FT
953 //\r
954 // Set to Hight Speed timing\r
955 //\r
956 if (AccessMode == 1) {\r
957 HostCtrl1 = BIT2;\r
958 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
959 if (EFI_ERROR (Status)) {\r
960 return Status;\r
961 }\r
962 }\r
963\r
964 HostCtrl2 = (UINT8)~0x7;\r
965 Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
966 if (EFI_ERROR (Status)) {\r
967 return Status;\r
968 }\r
969 HostCtrl2 = AccessMode;\r
970 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
971 if (EFI_ERROR (Status)) {\r
972 return Status;\r
973 }\r
974\r
975 Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, *Capability);\r
976 if (EFI_ERROR (Status)) {\r
977 return Status;\r
978 }\r
979\r
980 if ((AccessMode == 3) || ((AccessMode == 2) && (Capability->TuningSDR50 != 0))) {\r
981 Status = SdCardTuningClock (PciIo, PassThru, Slot);\r
982 if (EFI_ERROR (Status)) {\r
983 return Status;\r
984 }\r
985 }\r
986\r
987 return Status;\r
988}\r
989\r
990/**\r
991 Execute SD device identification procedure.\r
992\r
993 Refer to SD Physical Layer Simplified Spec 4.1 Section 3.6 for details.\r
994\r
995 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
996 @param[in] Slot The slot number of the SD card to send the command to.\r
997\r
998 @retval EFI_SUCCESS There is a SD card.\r
999 @retval Others There is not a SD card.\r
1000\r
1001**/\r
1002EFI_STATUS\r
1003SdCardIdentification (\r
1004 IN SD_MMC_HC_PRIVATE_DATA *Private,\r
1005 IN UINT8 Slot\r
1006 )\r
1007{\r
1008 EFI_STATUS Status;\r
1009 EFI_PCI_IO_PROTOCOL *PciIo;\r
1010 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
1011 UINT32 Ocr;\r
1012 UINT16 Rca;\r
1013 BOOLEAN Xpc;\r
1014 BOOLEAN S18r;\r
1015 UINT64 MaxCurrent;\r
1016 UINT16 ControllerVer;\r
1017 UINT8 PowerCtrl;\r
1018 UINT32 PresentState;\r
1019 UINT8 HostCtrl2;\r
ec86d285 1020 UINTN Retry;\r
48555339
FT
1021\r
1022 PciIo = Private->PciIo;\r
1023 PassThru = &Private->PassThru;\r
1024 //\r
1025 // 1. Send Cmd0 to the device\r
1026 //\r
1027 Status = SdCardReset (PassThru, Slot);\r
1028 if (EFI_ERROR (Status)) {\r
e27ccaba 1029 DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd0 fails with %r\n", Status));\r
48555339
FT
1030 return Status;\r
1031 }\r
1032 //\r
1033 // 2. Send Cmd8 to the device\r
1034 //\r
1035 Status = SdCardVoltageCheck (PassThru, Slot, 0x1, 0xFF);\r
1036 if (EFI_ERROR (Status)) {\r
e27ccaba 1037 DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd8 fails with %r\n", Status));\r
48555339
FT
1038 return Status;\r
1039 }\r
1040 //\r
1041 // 3. Send SDIO Cmd5 to the device to the SDIO device OCR register.\r
1042 //\r
1043 Status = SdioSendOpCond (PassThru, Slot, 0, FALSE);\r
1044 if (!EFI_ERROR (Status)) {\r
e27ccaba 1045 DEBUG ((DEBUG_INFO, "SdCardIdentification: Found SDIO device, ignore it as we don't support\n"));\r
48555339
FT
1046 return EFI_DEVICE_ERROR;\r
1047 }\r
1048 //\r
1049 // 4. Send Acmd41 with voltage window 0 to the device\r
1050 //\r
1051 Status = SdCardSendOpCond (PassThru, Slot, 0, 0, FALSE, FALSE, FALSE, &Ocr);\r
1052 if (EFI_ERROR (Status)) {\r
e27ccaba 1053 DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing SdCardSendOpCond fails with %r\n", Status));\r
48555339
FT
1054 return EFI_DEVICE_ERROR;\r
1055 }\r
1056\r
1057 if (Private->Capability[Slot].Voltage33 != 0) {\r
1058 //\r
1059 // Support 3.3V\r
1060 //\r
1061 MaxCurrent = ((UINT32)Private->MaxCurrent[Slot] & 0xFF) * 4;\r
1062 } else if (Private->Capability[Slot].Voltage30 != 0) {\r
1063 //\r
1064 // Support 3.0V\r
1065 //\r
1066 MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 8) & 0xFF) * 4;\r
1067 } else if (Private->Capability[Slot].Voltage18 != 0) {\r
1068 //\r
1069 // Support 1.8V\r
1070 //\r
1071 MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 16) & 0xFF) * 4;\r
1072 } else {\r
1073 ASSERT (FALSE);\r
1074 return EFI_DEVICE_ERROR;\r
1075 }\r
1076\r
1077 if (MaxCurrent >= 150) {\r
1078 Xpc = TRUE;\r
1079 } else {\r
1080 Xpc = FALSE;\r
1081 }\r
1082\r
1083 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);\r
1084 if (EFI_ERROR (Status)) {\r
1085 return Status;\r
1086 }\r
1087\r
1088 if ((ControllerVer & 0xFF) == 2) {\r
1089 S18r = TRUE;\r
1090 } else if (((ControllerVer & 0xFF) == 0) || ((ControllerVer & 0xFF) == 1)) {\r
1091 S18r = FALSE;\r
1092 } else {\r
1093 ASSERT (FALSE);\r
1094 return EFI_UNSUPPORTED;\r
1095 }\r
1096 //\r
1097 // 5. Repeatly send Acmd41 with supply voltage window to the device.\r
1098 // Note here we only support the cards complied with SD physical\r
1099 // layer simplified spec version 2.0 and version 3.0 and above.\r
1100 //\r
ec86d285
FT
1101 Ocr = 0;\r
1102 Retry = 0;\r
48555339
FT
1103 do {\r
1104 Status = SdCardSendOpCond (PassThru, Slot, 0, Ocr, S18r, Xpc, TRUE, &Ocr);\r
1105 if (EFI_ERROR (Status)) {\r
e27ccaba 1106 DEBUG ((DEBUG_ERROR, "SdCardIdentification: SdCardSendOpCond fails with %r Ocr %x, S18r %x, Xpc %x\n", Status, Ocr, S18r, Xpc));\r
48555339
FT
1107 return EFI_DEVICE_ERROR;\r
1108 }\r
ec86d285
FT
1109\r
1110 if (Retry++ == 100) {\r
1111 DEBUG ((DEBUG_ERROR, "SdCardIdentification: SdCardSendOpCond fails too many times\n"));\r
1112 return EFI_DEVICE_ERROR;\r
1113 }\r
1114 gBS->Stall(10 * 1000);\r
48555339
FT
1115 } while ((Ocr & BIT31) == 0);\r
1116\r
1117 //\r
1118 // 6. If the S18A bit is set and the Host Controller supports 1.8V signaling\r
1119 // (One of support bits is set to 1: SDR50, SDR104 or DDR50 in the\r
1120 // Capabilities register), switch its voltage to 1.8V.\r
1121 //\r
1122 if ((Private->Capability[Slot].Sdr50 != 0 ||\r
1123 Private->Capability[Slot].Sdr104 != 0 ||\r
1124 Private->Capability[Slot].Ddr50 != 0) &&\r
1125 ((Ocr & BIT24) != 0)) {\r
1126 Status = SdCardVoltageSwitch (PassThru, Slot);\r
1127 if (EFI_ERROR (Status)) {\r
e27ccaba 1128 DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardVoltageSwitch fails with %r\n", Status));\r
48555339
FT
1129 Status = EFI_DEVICE_ERROR;\r
1130 goto Error;\r
1131 } else {\r
1132 Status = SdMmcHcStopClock (PciIo, Slot);\r
1133 if (EFI_ERROR (Status)) {\r
1134 Status = EFI_DEVICE_ERROR;\r
1135 goto Error;\r
1136 }\r
1137\r
1138 SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);\r
1139 if (((PresentState >> 20) & 0xF) != 0) {\r
e27ccaba 1140 DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with PresentState = 0x%x\n", PresentState));\r
48555339
FT
1141 Status = EFI_DEVICE_ERROR;\r
1142 goto Error;\r
1143 }\r
1144 HostCtrl2 = BIT3;\r
1145 SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
1146\r
1147 gBS->Stall (5000);\r
1148\r
1149 SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);\r
1150 if ((HostCtrl2 & BIT3) == 0) {\r
e27ccaba 1151 DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with HostCtrl2 = 0x%x\n", HostCtrl2));\r
48555339
FT
1152 Status = EFI_DEVICE_ERROR;\r
1153 goto Error;\r
1154 }\r
1155\r
1156 SdMmcHcInitClockFreq (PciIo, Slot, Private->Capability[Slot]);\r
1157\r
2a8b78cf 1158 gBS->Stall (1000);\r
48555339
FT
1159\r
1160 SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);\r
1161 if (((PresentState >> 20) & 0xF) != 0xF) {\r
e27ccaba 1162 DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with PresentState = 0x%x, It should be 0xF\n", PresentState));\r
48555339
FT
1163 Status = EFI_DEVICE_ERROR;\r
1164 goto Error;\r
1165 }\r
1166 }\r
e27ccaba 1167 DEBUG ((DEBUG_INFO, "SdCardIdentification: Switch to 1.8v signal voltage success\n"));\r
48555339
FT
1168 }\r
1169\r
1170 Status = SdCardAllSendCid (PassThru, Slot);\r
1171 if (EFI_ERROR (Status)) {\r
e27ccaba 1172 DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardAllSendCid fails with %r\n", Status));\r
48555339
FT
1173 return Status;\r
1174 }\r
1175\r
1176 Status = SdCardSetRca (PassThru, Slot, &Rca);\r
1177 if (EFI_ERROR (Status)) {\r
e27ccaba 1178 DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardSetRca fails with %r\n", Status));\r
48555339
FT
1179 return Status;\r
1180 }\r
1181 //\r
1182 // Enter Data Tranfer Mode.\r
1183 //\r
e27ccaba 1184 DEBUG ((DEBUG_INFO, "SdCardIdentification: Found a SD device at slot [%d]\n", Slot));\r
48555339
FT
1185 Private->Slot[Slot].CardType = SdCardType;\r
1186\r
1187 Status = SdCardSetBusMode (PciIo, PassThru, Slot, Rca, ((Ocr & BIT24) != 0));\r
1188\r
1189 return Status;\r
1190\r
1191Error:\r
1192 //\r
1193 // Set SD Bus Power = 0\r
1194 //\r
1195 PowerCtrl = (UINT8)~BIT0;\r
1196 Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_POWER_CTRL, sizeof (PowerCtrl), &PowerCtrl);\r
1197 return EFI_DEVICE_ERROR;\r
1198}\r
1199\r