]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
MdeModulePkg/SdMmcPciHcDxe: Allow overriding base clock frequency
[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
48555339 321\r
48555339 322\r
48555339 323\r
48555339
FT
324\r
325/**\r
326 Send command SELECT_DESELECT_CARD to the SD device to select/deselect it.\r
327\r
328 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
329\r
330 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
331 @param[in] Slot The slot number of the SD card to send the command to.\r
332 @param[in] Rca The relative device address of selected device.\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
339SdCardSelect (\r
340 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
341 IN UINT8 Slot,\r
342 IN UINT16 Rca\r
343 )\r
344{\r
345 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
346 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
347 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
348 EFI_STATUS Status;\r
349\r
350 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
351 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
352 ZeroMem (&Packet, sizeof (Packet));\r
353\r
354 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
355 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
356 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
357\r
358 SdMmcCmdBlk.CommandIndex = SD_SELECT_DESELECT_CARD;\r
359 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
ac30e4c1
FT
360 if (Rca != 0) {\r
361 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;\r
362 }\r
48555339
FT
363 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
364\r
365 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
366\r
367 return Status;\r
368}\r
369\r
370/**\r
371 Send command VOLTAGE_SWITCH to the SD device to switch the voltage of the device.\r
372\r
373 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
374\r
375 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
376 @param[in] Slot The slot number of the SD card to send the command to.\r
377\r
378 @retval EFI_SUCCESS The operation is done correctly.\r
379 @retval Others The operation fails.\r
380\r
381**/\r
382EFI_STATUS\r
383SdCardVoltageSwitch (\r
384 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
385 IN UINT8 Slot\r
386 )\r
387{\r
388 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
389 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
390 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
391 EFI_STATUS Status;\r
392\r
393 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
394 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
395 ZeroMem (&Packet, sizeof (Packet));\r
396\r
397 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
398 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
399 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
400\r
401 SdMmcCmdBlk.CommandIndex = SD_VOLTAGE_SWITCH;\r
402 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
403 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
404 SdMmcCmdBlk.CommandArgument = 0;\r
405\r
406 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
407\r
408 return Status;\r
409}\r
410\r
411/**\r
412 Send command SET_BUS_WIDTH to the SD device to set the bus width.\r
413\r
414 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
415\r
416 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
417 @param[in] Slot The slot number of the SD card to send the command to.\r
418 @param[in] Rca The relative device address of addressed device.\r
419 @param[in] BusWidth The bus width to be set, it could be 1 or 4.\r
420\r
421 @retval EFI_SUCCESS The operation is done correctly.\r
422 @retval Others The operation fails.\r
423\r
424**/\r
425EFI_STATUS\r
426SdCardSetBusWidth (\r
427 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
428 IN UINT8 Slot,\r
429 IN UINT16 Rca,\r
430 IN UINT8 BusWidth\r
431 )\r
432{\r
433 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
434 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
435 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
436 EFI_STATUS Status;\r
437 UINT8 Value;\r
438\r
439 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
440 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
441 ZeroMem (&Packet, sizeof (Packet));\r
442\r
443 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
444 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
445 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
446\r
447 SdMmcCmdBlk.CommandIndex = SD_APP_CMD;\r
448 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
449 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
450 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
451\r
452 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
453 if (EFI_ERROR (Status)) {\r
454 return Status;\r
455 }\r
456\r
457 SdMmcCmdBlk.CommandIndex = SD_SET_BUS_WIDTH;\r
458 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
459 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
460\r
461 if (BusWidth == 1) {\r
462 Value = 0;\r
463 } else if (BusWidth == 4) {\r
464 Value = 2;\r
465 } else {\r
466 return EFI_INVALID_PARAMETER;\r
467 }\r
468\r
469 SdMmcCmdBlk.CommandArgument = Value & 0x3;\r
470\r
471 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
472 return Status;\r
473}\r
474\r
475/**\r
476 Send command SWITCH_FUNC to the SD device to check switchable function or switch card function.\r
477\r
478 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
479\r
480 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
481 @param[in] Slot The slot number of the SD card to send the command to.\r
482 @param[in] AccessMode The value for access mode group.\r
483 @param[in] CommandSystem The value for command set group.\r
484 @param[in] DriveStrength The value for drive length group.\r
485 @param[in] PowerLimit The value for power limit group.\r
486 @param[in] Mode Switch or check function.\r
6263ae93 487 @param[out] SwitchResp The return switch function status.\r
48555339
FT
488\r
489 @retval EFI_SUCCESS The operation is done correctly.\r
490 @retval Others The operation fails.\r
491\r
492**/\r
493EFI_STATUS\r
494SdCardSwitch (\r
6263ae93
FT
495 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
496 IN UINT8 Slot,\r
497 IN UINT8 AccessMode,\r
498 IN UINT8 CommandSystem,\r
499 IN UINT8 DriveStrength,\r
500 IN UINT8 PowerLimit,\r
501 IN BOOLEAN Mode,\r
502 OUT UINT8 *SwitchResp\r
48555339
FT
503 )\r
504{\r
505 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
506 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
507 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
508 EFI_STATUS Status;\r
509 UINT32 ModeValue;\r
48555339
FT
510\r
511 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
512 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
513 ZeroMem (&Packet, sizeof (Packet));\r
514\r
515 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
516 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
517 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
518\r
519 SdMmcCmdBlk.CommandIndex = SD_SWITCH_FUNC;\r
520 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;\r
521 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
522\r
523 ModeValue = Mode ? BIT31 : 0;\r
524 SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \\r
525 ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \\r
526 ModeValue;\r
527\r
6263ae93
FT
528 Packet.InDataBuffer = SwitchResp;\r
529 Packet.InTransferLength = 64;\r
48555339
FT
530\r
531 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
532\r
533 return Status;\r
534}\r
535\r
536/**\r
537 Send command SEND_STATUS to the addressed SD device to get its status register.\r
538\r
539 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
540\r
541 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
542 @param[in] Slot The slot number of the SD card to send the command to.\r
543 @param[in] Rca The relative device address of addressed device.\r
544 @param[out] DevStatus The returned device status.\r
545\r
546 @retval EFI_SUCCESS The operation is done correctly.\r
547 @retval Others The operation fails.\r
548\r
549**/\r
550EFI_STATUS\r
551SdCardSendStatus (\r
552 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
553 IN UINT8 Slot,\r
554 IN UINT16 Rca,\r
555 OUT UINT32 *DevStatus\r
556 )\r
557{\r
558 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
559 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
560 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
561 EFI_STATUS Status;\r
562\r
563 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
564 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
565 ZeroMem (&Packet, sizeof (Packet));\r
566\r
567 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
568 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
569 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
570\r
571 SdMmcCmdBlk.CommandIndex = SD_SEND_STATUS;\r
572 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;\r
573 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
574 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;\r
575\r
576 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
577 if (!EFI_ERROR (Status)) {\r
578 *DevStatus = SdMmcStatusBlk.Resp0;\r
579 }\r
580\r
581 return Status;\r
582}\r
583\r
584/**\r
585 Send command SEND_TUNING_BLOCK to the SD device for HS200 optimal sampling point\r
586 detection.\r
587\r
588 It may be sent up to 40 times until the host finishes the tuning procedure.\r
589\r
590 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.\r
591\r
592 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
593 @param[in] Slot The slot number of the SD card to send the command to.\r
594\r
595 @retval EFI_SUCCESS The operation is done correctly.\r
596 @retval Others The operation fails.\r
597\r
598**/\r
599EFI_STATUS\r
600SdCardSendTuningBlk (\r
601 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
602 IN UINT8 Slot\r
603 )\r
604{\r
605 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;\r
606 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;\r
607 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;\r
608 EFI_STATUS Status;\r
609 UINT8 TuningBlock[64];\r
610\r
611 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));\r
612 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));\r
613 ZeroMem (&Packet, sizeof (Packet));\r
614\r
615 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;\r
616 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;\r
617 Packet.Timeout = SD_MMC_HC_GENERIC_TIMEOUT;\r
618\r
619 SdMmcCmdBlk.CommandIndex = SD_SEND_TUNING_BLOCK;\r
620 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;\r
621 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;\r
622 SdMmcCmdBlk.CommandArgument = 0;\r
623\r
624 Packet.InDataBuffer = TuningBlock;\r
625 Packet.InTransferLength = sizeof (TuningBlock);\r
626\r
627 Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);\r
628\r
629 return Status;\r
630}\r
631\r
632/**\r
633 Tunning the sampling point of SDR104 or SDR50 bus speed mode.\r
634\r
635 Command SD_SEND_TUNING_BLOCK may be sent up to 40 times until the host finishes the\r
636 tuning procedure.\r
637\r
638 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and\r
639 SD Host Controller Simplified Spec 3.0 section Figure 3-7 for details.\r
640\r
641 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
642 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
643 @param[in] Slot The slot number of the SD card to send the command to.\r
644\r
645 @retval EFI_SUCCESS The operation is done correctly.\r
646 @retval Others The operation fails.\r
647\r
648**/\r
649EFI_STATUS\r
650SdCardTuningClock (\r
651 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
652 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
653 IN UINT8 Slot\r
654 )\r
655{\r
656 EFI_STATUS Status;\r
657 UINT8 HostCtrl2;\r
658 UINT8 Retry;\r
659\r
660 //\r
661 // Notify the host that the sampling clock tuning procedure starts.\r
662 //\r
663 HostCtrl2 = BIT6;\r
664 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
665 if (EFI_ERROR (Status)) {\r
666 return Status;\r
667 }\r
668 //\r
669 // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.\r
670 //\r
671 Retry = 0;\r
672 do {\r
673 Status = SdCardSendTuningBlk (PassThru, Slot);\r
674 if (EFI_ERROR (Status)) {\r
e27ccaba 675 DEBUG ((DEBUG_ERROR, "SdCardSendTuningBlk: Send tuning block fails with %r\n", Status));\r
48555339
FT
676 return Status;\r
677 }\r
678\r
679 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);\r
680 if (EFI_ERROR (Status)) {\r
681 return Status;\r
682 }\r
683\r
8c983d3e 684 if ((HostCtrl2 & (BIT6 | BIT7)) == 0) {\r
48555339
FT
685 break;\r
686 }\r
8c983d3e
FT
687 if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {\r
688 return EFI_SUCCESS;\r
689 }\r
48555339
FT
690 } while (++Retry < 40);\r
691\r
e27ccaba 692 DEBUG ((DEBUG_ERROR, "SdCardTuningClock: Send tuning block fails at %d times with HostCtrl2 %02x\n", Retry, HostCtrl2));\r
8c983d3e
FT
693 //\r
694 // Abort the tuning procedure and reset the tuning circuit.\r
695 //\r
696 HostCtrl2 = (UINT8)~(BIT6 | BIT7);\r
697 Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
698 if (EFI_ERROR (Status)) {\r
699 return Status;\r
48555339 700 }\r
8c983d3e 701 return EFI_DEVICE_ERROR;\r
48555339
FT
702}\r
703\r
704/**\r
705 Switch the bus width to specified width.\r
706\r
707 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and\r
708 SD Host Controller Simplified Spec 3.0 section Figure 3-7 for details.\r
709\r
710 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
711 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
712 @param[in] Slot The slot number of the SD card to send the command to.\r
713 @param[in] Rca The relative device address to be assigned.\r
714 @param[in] BusWidth The bus width to be set, it could be 4 or 8.\r
715\r
716 @retval EFI_SUCCESS The operation is done correctly.\r
717 @retval Others The operation fails.\r
718\r
719**/\r
720EFI_STATUS\r
721SdCardSwitchBusWidth (\r
722 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
723 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
724 IN UINT8 Slot,\r
725 IN UINT16 Rca,\r
726 IN UINT8 BusWidth\r
727 )\r
728{\r
729 EFI_STATUS Status;\r
730 UINT32 DevStatus;\r
731\r
732 Status = SdCardSetBusWidth (PassThru, Slot, Rca, BusWidth);\r
733 if (EFI_ERROR (Status)) {\r
e27ccaba 734 DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: Switch to bus width %d fails with %r\n", BusWidth, Status));\r
48555339
FT
735 return Status;\r
736 }\r
737\r
738 Status = SdCardSendStatus (PassThru, Slot, Rca, &DevStatus);\r
739 if (EFI_ERROR (Status)) {\r
e27ccaba 740 DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: Send status fails with %r\n", Status));\r
48555339
FT
741 return Status;\r
742 }\r
743 //\r
744 // Check the switch operation is really successful or not.\r
745 //\r
746 if ((DevStatus >> 16) != 0) {\r
e27ccaba 747 DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));\r
48555339
FT
748 return EFI_DEVICE_ERROR;\r
749 }\r
750\r
751 Status = SdMmcHcSetBusWidth (PciIo, Slot, BusWidth);\r
752\r
753 return Status;\r
754}\r
755\r
756/**\r
757 Switch the high speed timing according to request.\r
758\r
759 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and\r
760 SD Host Controller Simplified Spec 3.0 section Figure 2-29 for details.\r
761\r
762 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
763 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.\r
764 @param[in] Slot The slot number of the SD card to send the command to.\r
765 @param[in] Rca The relative device address to be assigned.\r
766 @param[in] S18A The boolean to show if it's a UHS-I SD card.\r
767\r
768 @retval EFI_SUCCESS The operation is done correctly.\r
769 @retval Others The operation fails.\r
770\r
771**/\r
772EFI_STATUS\r
773SdCardSetBusMode (\r
774 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
775 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,\r
776 IN UINT8 Slot,\r
777 IN UINT16 Rca,\r
778 IN BOOLEAN S18A\r
779 )\r
780{\r
781 EFI_STATUS Status;\r
782 SD_MMC_HC_SLOT_CAP *Capability;\r
783 UINT32 ClockFreq;\r
784 UINT8 BusWidth;\r
785 UINT8 AccessMode;\r
786 UINT8 HostCtrl1;\r
6263ae93 787 UINT8 SwitchResp[64];\r
a4708009 788 SD_MMC_BUS_MODE Timing;\r
48555339
FT
789 SD_MMC_HC_PRIVATE_DATA *Private;\r
790\r
791 Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);\r
792\r
793 Capability = &Private->Capability[Slot];\r
794\r
795 Status = SdCardSelect (PassThru, Slot, Rca);\r
796 if (EFI_ERROR (Status)) {\r
797 return Status;\r
798 }\r
799\r
800 BusWidth = 4;\r
801\r
802 Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, BusWidth);\r
803 if (EFI_ERROR (Status)) {\r
804 return Status;\r
805 }\r
48555339 806 //\r
6263ae93
FT
807 // Get the supported bus speed from SWITCH cmd return data group #1.\r
808 //\r
809 Status = SdCardSwitch (PassThru, Slot, 0xF, 0xF, 0xF, 0xF, FALSE, SwitchResp);\r
810 if (EFI_ERROR (Status)) {\r
811 return Status;\r
812 }\r
813 //\r
814 // Calculate supported bus speed/bus width/clock frequency by host and device capability.\r
48555339
FT
815 //\r
816 ClockFreq = 0;\r
6263ae93 817 if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) {\r
48555339
FT
818 ClockFreq = 208;\r
819 AccessMode = 3;\r
a4708009 820 Timing = SdMmcUhsSdr104;\r
6263ae93 821 } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) {\r
48555339
FT
822 ClockFreq = 100;\r
823 AccessMode = 2;\r
a4708009 824 Timing = SdMmcUhsSdr50;\r
6263ae93 825 } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) {\r
48555339
FT
826 ClockFreq = 50;\r
827 AccessMode = 4;\r
a4708009 828 Timing = SdMmcUhsDdr50;\r
6263ae93 829 } else if ((SwitchResp[13] & BIT1) != 0) {\r
48555339
FT
830 ClockFreq = 50;\r
831 AccessMode = 1;\r
a4708009 832 Timing = SdMmcUhsSdr25;\r
6263ae93
FT
833 } else {\r
834 ClockFreq = 25;\r
835 AccessMode = 0;\r
a4708009 836 Timing = SdMmcUhsSdr12;\r
48555339
FT
837 }\r
838\r
6263ae93 839 Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp);\r
48555339
FT
840 if (EFI_ERROR (Status)) {\r
841 return Status;\r
842 }\r
843\r
6263ae93 844 if ((SwitchResp[16] & 0xF) != AccessMode) {\r
e27ccaba 845 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
846 return EFI_DEVICE_ERROR;\r
847 }\r
848\r
e27ccaba 849 DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d BusWidth %d\n", AccessMode, ClockFreq, BusWidth));\r
6263ae93 850\r
48555339
FT
851 //\r
852 // Set to Hight Speed timing\r
853 //\r
854 if (AccessMode == 1) {\r
855 HostCtrl1 = BIT2;\r
856 Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);\r
857 if (EFI_ERROR (Status)) {\r
858 return Status;\r
859 }\r
860 }\r
861\r
a4708009 862 Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, Timing);\r
48555339
FT
863 if (EFI_ERROR (Status)) {\r
864 return Status;\r
865 }\r
866\r
7f3b0bad 867 Status = SdMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->BaseClkFreq[Slot]);\r
48555339
FT
868 if (EFI_ERROR (Status)) {\r
869 return Status;\r
870 }\r
871\r
b7b803a6
TM
872 if (mOverride != NULL && mOverride->NotifyPhase != NULL) {\r
873 Status = mOverride->NotifyPhase (\r
874 Private->ControllerHandle,\r
875 Slot,\r
876 EdkiiSdMmcSwitchClockFreqPost,\r
877 &Timing\r
878 );\r
879 if (EFI_ERROR (Status)) {\r
880 DEBUG ((\r
881 DEBUG_ERROR,\r
882 "%a: SD/MMC switch clock freq post notifier callback failed - %r\n",\r
883 __FUNCTION__,\r
884 Status\r
885 ));\r
886 return Status;\r
887 }\r
888 }\r
889\r
48555339
FT
890 if ((AccessMode == 3) || ((AccessMode == 2) && (Capability->TuningSDR50 != 0))) {\r
891 Status = SdCardTuningClock (PciIo, PassThru, Slot);\r
892 if (EFI_ERROR (Status)) {\r
893 return Status;\r
894 }\r
895 }\r
896\r
897 return Status;\r
898}\r
899\r
900/**\r
901 Execute SD device identification procedure.\r
902\r
903 Refer to SD Physical Layer Simplified Spec 4.1 Section 3.6 for details.\r
904\r
905 @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
906 @param[in] Slot The slot number of the SD card to send the command to.\r
907\r
908 @retval EFI_SUCCESS There is a SD card.\r
909 @retval Others There is not a SD card.\r
910\r
911**/\r
912EFI_STATUS\r
913SdCardIdentification (\r
914 IN SD_MMC_HC_PRIVATE_DATA *Private,\r
915 IN UINT8 Slot\r
916 )\r
917{\r
918 EFI_STATUS Status;\r
919 EFI_PCI_IO_PROTOCOL *PciIo;\r
920 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
921 UINT32 Ocr;\r
922 UINT16 Rca;\r
923 BOOLEAN Xpc;\r
924 BOOLEAN S18r;\r
925 UINT64 MaxCurrent;\r
926 UINT16 ControllerVer;\r
927 UINT8 PowerCtrl;\r
928 UINT32 PresentState;\r
929 UINT8 HostCtrl2;\r
ec86d285 930 UINTN Retry;\r
48555339
FT
931\r
932 PciIo = Private->PciIo;\r
933 PassThru = &Private->PassThru;\r
934 //\r
935 // 1. Send Cmd0 to the device\r
936 //\r
937 Status = SdCardReset (PassThru, Slot);\r
938 if (EFI_ERROR (Status)) {\r
e27ccaba 939 DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd0 fails with %r\n", Status));\r
48555339
FT
940 return Status;\r
941 }\r
942 //\r
943 // 2. Send Cmd8 to the device\r
944 //\r
945 Status = SdCardVoltageCheck (PassThru, Slot, 0x1, 0xFF);\r
946 if (EFI_ERROR (Status)) {\r
e27ccaba 947 DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd8 fails with %r\n", Status));\r
48555339
FT
948 return Status;\r
949 }\r
950 //\r
951 // 3. Send SDIO Cmd5 to the device to the SDIO device OCR register.\r
952 //\r
953 Status = SdioSendOpCond (PassThru, Slot, 0, FALSE);\r
954 if (!EFI_ERROR (Status)) {\r
e27ccaba 955 DEBUG ((DEBUG_INFO, "SdCardIdentification: Found SDIO device, ignore it as we don't support\n"));\r
48555339
FT
956 return EFI_DEVICE_ERROR;\r
957 }\r
958 //\r
959 // 4. Send Acmd41 with voltage window 0 to the device\r
960 //\r
961 Status = SdCardSendOpCond (PassThru, Slot, 0, 0, FALSE, FALSE, FALSE, &Ocr);\r
962 if (EFI_ERROR (Status)) {\r
e27ccaba 963 DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing SdCardSendOpCond fails with %r\n", Status));\r
48555339
FT
964 return EFI_DEVICE_ERROR;\r
965 }\r
966\r
967 if (Private->Capability[Slot].Voltage33 != 0) {\r
968 //\r
969 // Support 3.3V\r
970 //\r
971 MaxCurrent = ((UINT32)Private->MaxCurrent[Slot] & 0xFF) * 4;\r
972 } else if (Private->Capability[Slot].Voltage30 != 0) {\r
973 //\r
974 // Support 3.0V\r
975 //\r
976 MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 8) & 0xFF) * 4;\r
977 } else if (Private->Capability[Slot].Voltage18 != 0) {\r
978 //\r
979 // Support 1.8V\r
980 //\r
981 MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 16) & 0xFF) * 4;\r
982 } else {\r
983 ASSERT (FALSE);\r
984 return EFI_DEVICE_ERROR;\r
985 }\r
986\r
987 if (MaxCurrent >= 150) {\r
988 Xpc = TRUE;\r
989 } else {\r
990 Xpc = FALSE;\r
991 }\r
992\r
993 Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);\r
994 if (EFI_ERROR (Status)) {\r
995 return Status;\r
996 }\r
997\r
bbce0015
JB
998 if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&\r
999 ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {\r
48555339 1000 S18r = TRUE;\r
bdf038cc 1001 } else if (((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_100) || ((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_200)) {\r
48555339
FT
1002 S18r = FALSE;\r
1003 } else {\r
1004 ASSERT (FALSE);\r
1005 return EFI_UNSUPPORTED;\r
1006 }\r
1007 //\r
1008 // 5. Repeatly send Acmd41 with supply voltage window to the device.\r
1009 // Note here we only support the cards complied with SD physical\r
1010 // layer simplified spec version 2.0 and version 3.0 and above.\r
1011 //\r
ec86d285
FT
1012 Ocr = 0;\r
1013 Retry = 0;\r
48555339
FT
1014 do {\r
1015 Status = SdCardSendOpCond (PassThru, Slot, 0, Ocr, S18r, Xpc, TRUE, &Ocr);\r
1016 if (EFI_ERROR (Status)) {\r
e27ccaba 1017 DEBUG ((DEBUG_ERROR, "SdCardIdentification: SdCardSendOpCond fails with %r Ocr %x, S18r %x, Xpc %x\n", Status, Ocr, S18r, Xpc));\r
48555339
FT
1018 return EFI_DEVICE_ERROR;\r
1019 }\r
ec86d285
FT
1020\r
1021 if (Retry++ == 100) {\r
1022 DEBUG ((DEBUG_ERROR, "SdCardIdentification: SdCardSendOpCond fails too many times\n"));\r
1023 return EFI_DEVICE_ERROR;\r
1024 }\r
1025 gBS->Stall(10 * 1000);\r
48555339
FT
1026 } while ((Ocr & BIT31) == 0);\r
1027\r
1028 //\r
1029 // 6. If the S18A bit is set and the Host Controller supports 1.8V signaling\r
1030 // (One of support bits is set to 1: SDR50, SDR104 or DDR50 in the\r
1031 // Capabilities register), switch its voltage to 1.8V.\r
1032 //\r
1033 if ((Private->Capability[Slot].Sdr50 != 0 ||\r
1034 Private->Capability[Slot].Sdr104 != 0 ||\r
1035 Private->Capability[Slot].Ddr50 != 0) &&\r
1036 ((Ocr & BIT24) != 0)) {\r
1037 Status = SdCardVoltageSwitch (PassThru, Slot);\r
1038 if (EFI_ERROR (Status)) {\r
e27ccaba 1039 DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardVoltageSwitch fails with %r\n", Status));\r
48555339
FT
1040 Status = EFI_DEVICE_ERROR;\r
1041 goto Error;\r
1042 } else {\r
1043 Status = SdMmcHcStopClock (PciIo, Slot);\r
1044 if (EFI_ERROR (Status)) {\r
1045 Status = EFI_DEVICE_ERROR;\r
1046 goto Error;\r
1047 }\r
1048\r
1049 SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);\r
1050 if (((PresentState >> 20) & 0xF) != 0) {\r
e27ccaba 1051 DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with PresentState = 0x%x\n", PresentState));\r
48555339
FT
1052 Status = EFI_DEVICE_ERROR;\r
1053 goto Error;\r
1054 }\r
1055 HostCtrl2 = BIT3;\r
1056 SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);\r
1057\r
1058 gBS->Stall (5000);\r
1059\r
1060 SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);\r
1061 if ((HostCtrl2 & BIT3) == 0) {\r
e27ccaba 1062 DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with HostCtrl2 = 0x%x\n", HostCtrl2));\r
48555339
FT
1063 Status = EFI_DEVICE_ERROR;\r
1064 goto Error;\r
1065 }\r
1066\r
7f3b0bad 1067 SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);\r
48555339 1068\r
2a8b78cf 1069 gBS->Stall (1000);\r
48555339
FT
1070\r
1071 SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);\r
1072 if (((PresentState >> 20) & 0xF) != 0xF) {\r
e27ccaba 1073 DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with PresentState = 0x%x, It should be 0xF\n", PresentState));\r
48555339
FT
1074 Status = EFI_DEVICE_ERROR;\r
1075 goto Error;\r
1076 }\r
1077 }\r
e27ccaba 1078 DEBUG ((DEBUG_INFO, "SdCardIdentification: Switch to 1.8v signal voltage success\n"));\r
48555339
FT
1079 }\r
1080\r
1081 Status = SdCardAllSendCid (PassThru, Slot);\r
1082 if (EFI_ERROR (Status)) {\r
e27ccaba 1083 DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardAllSendCid fails with %r\n", Status));\r
48555339
FT
1084 return Status;\r
1085 }\r
1086\r
1087 Status = SdCardSetRca (PassThru, Slot, &Rca);\r
1088 if (EFI_ERROR (Status)) {\r
e27ccaba 1089 DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardSetRca fails with %r\n", Status));\r
48555339
FT
1090 return Status;\r
1091 }\r
1092 //\r
1093 // Enter Data Tranfer Mode.\r
1094 //\r
e27ccaba 1095 DEBUG ((DEBUG_INFO, "SdCardIdentification: Found a SD device at slot [%d]\n", Slot));\r
48555339
FT
1096 Private->Slot[Slot].CardType = SdCardType;\r
1097\r
1098 Status = SdCardSetBusMode (PciIo, PassThru, Slot, Rca, ((Ocr & BIT24) != 0));\r
1099\r
1100 return Status;\r
1101\r
1102Error:\r
1103 //\r
1104 // Set SD Bus Power = 0\r
1105 //\r
1106 PowerCtrl = (UINT8)~BIT0;\r
1107 Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_POWER_CTRL, sizeof (PowerCtrl), &PowerCtrl);\r
1108 return EFI_DEVICE_ERROR;\r
1109}\r
1110\r