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