]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
EmbeddedPkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / EmbeddedPkg / Universal / MmcDxe / MmcIdentification.c
CommitLineData
b4fdedc2
OM
1/** @file\r
2*\r
eff98cf9 3* Copyright (c) 2011-2015, ARM Limited. All rights reserved.\r
b4fdedc2 4*\r
878b807a 5* SPDX-License-Identifier: BSD-2-Clause-Patent\r
b4fdedc2
OM
6*\r
7**/\r
8\r
e06253ba 9#include <Library/BaseMemoryLib.h>\r
7bb5fad5 10#include <Library/MemoryAllocationLib.h>\r
e06253ba
HZ
11#include <Library/TimerLib.h>\r
12\r
b4fdedc2
OM
13#include "Mmc.h"\r
14\r
15typedef union {\r
16 UINT32 Raw;\r
17 OCR Ocr;\r
18} OCR_RESPONSE;\r
19\r
20#define MAX_RETRY_COUNT 1000\r
21#define CMD_RETRY_COUNT 20\r
22#define RCA_SHIFT_OFFSET 16\r
23#define EMMC_CARD_SIZE 512\r
24#define EMMC_ECSD_SIZE_OFFSET 53\r
25\r
752ae805
HZ
26#define EXTCSD_BUS_WIDTH 183\r
27#define EXTCSD_HS_TIMING 185\r
28\r
29#define EMMC_TIMING_BACKWARD 0\r
30#define EMMC_TIMING_HS 1\r
31#define EMMC_TIMING_HS200 2\r
32#define EMMC_TIMING_HS400 3\r
33\r
34#define EMMC_BUS_WIDTH_1BIT 0\r
35#define EMMC_BUS_WIDTH_4BIT 1\r
36#define EMMC_BUS_WIDTH_8BIT 2\r
37#define EMMC_BUS_WIDTH_DDR_4BIT 5\r
38#define EMMC_BUS_WIDTH_DDR_8BIT 6\r
39\r
40#define EMMC_SWITCH_ERROR (1 << 7)\r
41\r
e06253ba
HZ
42#define SD_BUS_WIDTH_1BIT (1 << 0)\r
43#define SD_BUS_WIDTH_4BIT (1 << 2)\r
44\r
45#define SD_CCC_SWITCH (1 << 10)\r
46\r
752ae805
HZ
47#define DEVICE_STATE(x) (((x) >> 9) & 0xf)\r
48typedef enum _EMMC_DEVICE_STATE {\r
49 EMMC_IDLE_STATE = 0,\r
50 EMMC_READY_STATE,\r
51 EMMC_IDENT_STATE,\r
52 EMMC_STBY_STATE,\r
53 EMMC_TRAN_STATE,\r
54 EMMC_DATA_STATE,\r
55 EMMC_RCV_STATE,\r
56 EMMC_PRG_STATE,\r
57 EMMC_DIS_STATE,\r
58 EMMC_BTST_STATE,\r
59 EMMC_SLP_STATE\r
60} EMMC_DEVICE_STATE;\r
61\r
b4fdedc2
OM
62UINT32 mEmmcRcaCount = 0;\r
63\r
752ae805
HZ
64STATIC\r
65EFI_STATUS\r
66EFIAPI\r
67EmmcGetDeviceState (\r
68 IN MMC_HOST_INSTANCE *MmcHostInstance,\r
69 OUT EMMC_DEVICE_STATE *State\r
70 )\r
71{\r
72 EFI_MMC_HOST_PROTOCOL *Host;\r
73 EFI_STATUS Status;\r
74 UINT32 Data, RCA;\r
75\r
76 if (State == NULL) {\r
77 return EFI_INVALID_PARAMETER;\r
78 }\r
79\r
80 Host = MmcHostInstance->MmcHost;\r
81 RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;\r
82 Status = Host->SendCommand (Host, MMC_CMD13, RCA);\r
83 if (EFI_ERROR (Status)) {\r
a1878955 84 DEBUG ((DEBUG_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status));\r
752ae805
HZ
85 return Status;\r
86 }\r
87 Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, &Data);\r
88 if (EFI_ERROR (Status)) {\r
a1878955 89 DEBUG ((DEBUG_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status));\r
752ae805
HZ
90 return Status;\r
91 }\r
92 if (Data & EMMC_SWITCH_ERROR) {\r
a1878955 93 DEBUG ((DEBUG_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status));\r
752ae805
HZ
94 return EFI_DEVICE_ERROR;\r
95 }\r
96 *State = DEVICE_STATE(Data);\r
97 return EFI_SUCCESS;\r
98}\r
99\r
100STATIC\r
101EFI_STATUS\r
102EFIAPI\r
103EmmcSetEXTCSD (\r
104 IN MMC_HOST_INSTANCE *MmcHostInstance,\r
105 UINT32 ExtCmdIndex,\r
106 UINT32 Value\r
107 )\r
108{\r
109 EFI_MMC_HOST_PROTOCOL *Host;\r
110 EMMC_DEVICE_STATE State;\r
111 EFI_STATUS Status;\r
112 UINT32 Argument;\r
113\r
114 Host = MmcHostInstance->MmcHost;\r
115 Argument = EMMC_CMD6_ARG_ACCESS(3) | EMMC_CMD6_ARG_INDEX(ExtCmdIndex) |\r
116 EMMC_CMD6_ARG_VALUE(Value) | EMMC_CMD6_ARG_CMD_SET(1);\r
117 Status = Host->SendCommand (Host, MMC_CMD6, Argument);\r
118 if (EFI_ERROR (Status)) {\r
a1878955 119 DEBUG ((DEBUG_ERROR, "EmmcSetEXTCSD(): Failed to send CMD6, Status=%r.\n", Status));\r
752ae805
HZ
120 return Status;\r
121 }\r
122 // Make sure device exiting prog mode\r
123 do {\r
124 Status = EmmcGetDeviceState (MmcHostInstance, &State);\r
125 if (EFI_ERROR (Status)) {\r
a1878955 126 DEBUG ((DEBUG_ERROR, "EmmcSetEXTCSD(): Failed to get device state, Status=%r.\n", Status));\r
752ae805
HZ
127 return Status;\r
128 }\r
129 } while (State == EMMC_PRG_STATE);\r
130 return EFI_SUCCESS;\r
131}\r
132\r
b4fdedc2
OM
133STATIC\r
134EFI_STATUS\r
135EFIAPI\r
136EmmcIdentificationMode (\r
137 IN MMC_HOST_INSTANCE *MmcHostInstance,\r
138 IN OCR_RESPONSE Response\r
139 )\r
140{\r
141 EFI_MMC_HOST_PROTOCOL *Host;\r
142 EFI_BLOCK_IO_MEDIA *Media;\r
143 EFI_STATUS Status;\r
752ae805 144 EMMC_DEVICE_STATE State;\r
b4fdedc2 145 UINT32 RCA;\r
b4fdedc2
OM
146\r
147 Host = MmcHostInstance->MmcHost;\r
148 Media = MmcHostInstance->BlockIo.Media;\r
149\r
150 // Fetch card identity register\r
151 Status = Host->SendCommand (Host, MMC_CMD2, 0);\r
152 if (EFI_ERROR (Status)) {\r
a1878955 153 DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): Failed to send CMD2, Status=%r.\n", Status));\r
b4fdedc2
OM
154 return Status;\r
155 }\r
156\r
157 Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R2, (UINT32 *)&(MmcHostInstance->CardInfo.CIDData));\r
158 if (EFI_ERROR (Status)) {\r
a1878955 159 DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): CID retrieval error, Status=%r.\n", Status));\r
b4fdedc2
OM
160 return Status;\r
161 }\r
162\r
163 // Assign a relative address value to the card\r
164 MmcHostInstance->CardInfo.RCA = ++mEmmcRcaCount; // TODO: might need a more sophisticated way of doing this\r
165 RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;\r
166 Status = Host->SendCommand (Host, MMC_CMD3, RCA);\r
167 if (EFI_ERROR (Status)) {\r
a1878955 168 DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): RCA set error, Status=%r.\n", Status));\r
b4fdedc2
OM
169 return Status;\r
170 }\r
171\r
172 // Fetch card specific data\r
173 Status = Host->SendCommand (Host, MMC_CMD9, RCA);\r
174 if (EFI_ERROR (Status)) {\r
a1878955 175 DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): Failed to send CMD9, Status=%r.\n", Status));\r
b4fdedc2
OM
176 return Status;\r
177 }\r
178\r
179 Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R2, (UINT32 *)&(MmcHostInstance->CardInfo.CSDData));\r
180 if (EFI_ERROR (Status)) {\r
a1878955 181 DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): CSD retrieval error, Status=%r.\n", Status));\r
b4fdedc2
OM
182 return Status;\r
183 }\r
184\r
185 // Select the card\r
186 Status = Host->SendCommand (Host, MMC_CMD7, RCA);\r
187 if (EFI_ERROR (Status)) {\r
a1878955 188 DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): Card selection error, Status=%r.\n", Status));\r
b4fdedc2
OM
189 }\r
190\r
752ae805
HZ
191 if (MMC_HOST_HAS_SETIOS(Host)) {\r
192 // Set 1-bit bus width\r
193 Status = Host->SetIos (Host, 0, 1, EMMCBACKWARD);\r
194 if (EFI_ERROR (Status)) {\r
a1878955 195 DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): Set 1-bit bus width error, Status=%r.\n", Status));\r
752ae805
HZ
196 return Status;\r
197 }\r
198\r
199 // Set 1-bit bus width for EXTCSD\r
200 Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_1BIT);\r
201 if (EFI_ERROR (Status)) {\r
a1878955 202 DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): Set extcsd bus width error, Status=%r.\n", Status));\r
752ae805
HZ
203 return Status;\r
204 }\r
205 }\r
206\r
b4fdedc2 207 // Fetch ECSD\r
7bb5fad5
JN
208 MmcHostInstance->CardInfo.ECSDData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ECSD)));\r
209 if (MmcHostInstance->CardInfo.ECSDData == NULL) {\r
210 return EFI_OUT_OF_RESOURCES;\r
211 }\r
0ad564ff 212 Status = Host->SendCommand (Host, MMC_CMD8, 0);\r
b4fdedc2 213 if (EFI_ERROR (Status)) {\r
a1878955 214 DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));\r
b4fdedc2
OM
215 }\r
216\r
7bb5fad5 217 Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)MmcHostInstance->CardInfo.ECSDData);\r
b4fdedc2 218 if (EFI_ERROR (Status)) {\r
a1878955 219 DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));\r
7bb5fad5 220 goto FreePageExit;\r
b4fdedc2
OM
221 }\r
222\r
752ae805
HZ
223 // Make sure device exiting data mode\r
224 do {\r
225 Status = EmmcGetDeviceState (MmcHostInstance, &State);\r
226 if (EFI_ERROR (Status)) {\r
a1878955 227 DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): Failed to get device state, Status=%r.\n", Status));\r
7bb5fad5 228 goto FreePageExit;\r
752ae805
HZ
229 }\r
230 } while (State == EMMC_DATA_STATE);\r
231\r
b4fdedc2
OM
232 // Set up media\r
233 Media->BlockSize = EMMC_CARD_SIZE; // 512-byte support is mandatory for eMMC cards\r
234 Media->MediaId = MmcHostInstance->CardInfo.CIDData.PSN;\r
235 Media->ReadOnly = MmcHostInstance->CardInfo.CSDData.PERM_WRITE_PROTECT;\r
236 Media->LogicalBlocksPerPhysicalBlock = 1;\r
237 Media->IoAlign = 4;\r
238 // Compute last block using bits [215:212] of the ECSD\r
7bb5fad5 239 Media->LastBlock = MmcHostInstance->CardInfo.ECSDData->SECTOR_COUNT - 1; // eMMC isn't supposed to report this for\r
b4fdedc2
OM
240 // Cards <2GB in size, but the model does.\r
241\r
242 // Setup card type\r
243 MmcHostInstance->CardInfo.CardType = EMMC_CARD;\r
244 return EFI_SUCCESS;\r
7bb5fad5
JN
245\r
246FreePageExit:\r
247 FreePages (MmcHostInstance->CardInfo.ECSDData, EFI_SIZE_TO_PAGES (sizeof (ECSD)));\r
248 return Status;\r
b4fdedc2
OM
249}\r
250\r
752ae805
HZ
251STATIC\r
252EFI_STATUS\r
253InitializeEmmcDevice (\r
254 IN MMC_HOST_INSTANCE *MmcHostInstance\r
255 )\r
256{\r
257 EFI_MMC_HOST_PROTOCOL *Host;\r
258 EFI_STATUS Status = EFI_SUCCESS;\r
259 ECSD *ECSDData;\r
44f4ff62 260 UINT32 BusClockFreq, Idx, BusMode;\r
752ae805
HZ
261 UINT32 TimingMode[4] = {EMMCHS52DDR1V2, EMMCHS52DDR1V8, EMMCHS52, EMMCHS26};\r
262\r
263 Host = MmcHostInstance->MmcHost;\r
7bb5fad5 264 ECSDData = MmcHostInstance->CardInfo.ECSDData;\r
752ae805
HZ
265 if (ECSDData->DEVICE_TYPE == EMMCBACKWARD)\r
266 return EFI_SUCCESS;\r
267\r
268 if (!MMC_HOST_HAS_SETIOS(Host)) {\r
269 return EFI_SUCCESS;\r
270 }\r
271 Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_HS_TIMING, EMMC_TIMING_HS);\r
272 if (EFI_ERROR (Status)) {\r
273 DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to switch high speed mode, Status:%r.\n", Status));\r
274 return Status;\r
275 }\r
276\r
277 for (Idx = 0; Idx < 4; Idx++) {\r
278 switch (TimingMode[Idx]) {\r
279 case EMMCHS52DDR1V2:\r
280 case EMMCHS52DDR1V8:\r
281 case EMMCHS52:\r
282 BusClockFreq = 52000000;\r
283 break;\r
284 case EMMCHS26:\r
285 BusClockFreq = 26000000;\r
286 break;\r
287 default:\r
288 return EFI_UNSUPPORTED;\r
289 }\r
290 Status = Host->SetIos (Host, BusClockFreq, 8, TimingMode[Idx]);\r
291 if (!EFI_ERROR (Status)) {\r
44f4ff62
JN
292 switch (TimingMode[Idx]) {\r
293 case EMMCHS52DDR1V2:\r
294 case EMMCHS52DDR1V8:\r
295 BusMode = EMMC_BUS_WIDTH_DDR_8BIT;\r
296 break;\r
297 case EMMCHS52:\r
298 case EMMCHS26:\r
299 BusMode = EMMC_BUS_WIDTH_8BIT;\r
300 break;\r
301 default:\r
302 return EFI_UNSUPPORTED;\r
303 }\r
304 Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, BusMode);\r
752ae805
HZ
305 if (EFI_ERROR (Status)) {\r
306 DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to set EXTCSD bus width, Status:%r\n", Status));\r
307 }\r
308 return Status;\r
309 }\r
310 }\r
311 return Status;\r
312}\r
313\r
ea21f1d9
MA
314STATIC\r
315UINT32\r
316CreateSwitchCmdArgument (\r
317 IN UINT32 Mode,\r
318 IN UINT8 Group,\r
319 IN UINT8 Value\r
320 )\r
321{\r
322 UINT32 Argument;\r
323\r
324 Argument = Mode << 31 | 0x00FFFFFF;\r
325 Argument &= ~(0xF << (Group * 4));\r
326 Argument |= Value << (Group * 4);\r
327\r
328 return Argument;\r
329}\r
330\r
b4fdedc2
OM
331STATIC\r
332EFI_STATUS\r
333InitializeSdMmcDevice (\r
334 IN MMC_HOST_INSTANCE *MmcHostInstance\r
335 )\r
336{\r
337 UINT32 CmdArg;\r
338 UINT32 Response[4];\r
e06253ba 339 UINT32 Buffer[128];\r
ea21f1d9 340 UINT32 Speed;\r
b4fdedc2
OM
341 UINTN BlockSize;\r
342 UINTN CardSize;\r
343 UINTN NumBlocks;\r
e06253ba
HZ
344 BOOLEAN CccSwitch;\r
345 SCR Scr;\r
b4fdedc2
OM
346 EFI_STATUS Status;\r
347 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
348\r
ea21f1d9 349 Speed = SD_DEFAULT_SPEED;\r
b4fdedc2
OM
350 MmcHost = MmcHostInstance->MmcHost;\r
351\r
352 // Send a command to get Card specific data\r
353 CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
354 Status = MmcHost->SendCommand (MmcHost, MMC_CMD9, CmdArg);\r
355 if (EFI_ERROR (Status)) {\r
a1878955 356 DEBUG((DEBUG_ERROR, "InitializeSdMmcDevice(MMC_CMD9): Error, Status=%r\n", Status));\r
b4fdedc2
OM
357 return Status;\r
358 }\r
359\r
360 // Read Response\r
361 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CSD, Response);\r
362 if (EFI_ERROR (Status)) {\r
a1878955 363 DEBUG((DEBUG_ERROR, "InitializeSdMmcDevice(): Failed to receive CSD, Status=%r\n", Status));\r
b4fdedc2
OM
364 return Status;\r
365 }\r
366 PrintCSD (Response);\r
e06253ba
HZ
367 if (MMC_CSD_GET_CCC(Response) & SD_CCC_SWITCH) {\r
368 CccSwitch = TRUE;\r
369 } else {\r
370 CccSwitch = FALSE;\r
371 }\r
b4fdedc2
OM
372\r
373 if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {\r
374 CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response);\r
375 NumBlocks = ((CardSize + 1) * 1024);\r
376 BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response);\r
377 } else {\r
378 CardSize = MMC_CSD_GET_DEVICESIZE (Response);\r
379 NumBlocks = (CardSize + 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT (Response) + 2));\r
380 BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response);\r
381 }\r
382\r
383 // For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.\r
384 if (BlockSize > 512) {\r
385 NumBlocks = MultU64x32 (NumBlocks, BlockSize / 512);\r
386 BlockSize = 512;\r
387 }\r
388\r
389 MmcHostInstance->BlockIo.Media->LastBlock = (NumBlocks - 1);\r
390 MmcHostInstance->BlockIo.Media->BlockSize = BlockSize;\r
391 MmcHostInstance->BlockIo.Media->ReadOnly = MmcHost->IsReadOnly (MmcHost);\r
392 MmcHostInstance->BlockIo.Media->MediaPresent = TRUE;\r
393 MmcHostInstance->BlockIo.Media->MediaId++;\r
394\r
395 CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
396 Status = MmcHost->SendCommand (MmcHost, MMC_CMD7, CmdArg);\r
397 if (EFI_ERROR (Status)) {\r
a1878955 398 DEBUG((DEBUG_ERROR, "InitializeSdMmcDevice(MMC_CMD7): Error and Status = %r\n", Status));\r
b4fdedc2
OM
399 return Status;\r
400 }\r
401\r
e06253ba
HZ
402 Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);\r
403 if (EFI_ERROR (Status)) {\r
3d436166 404 DEBUG ((DEBUG_ERROR, "%a (MMC_CMD55): Error and Status = %r\n", __FUNCTION__, Status));\r
e06253ba
HZ
405 return Status;\r
406 }\r
407 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);\r
408 if (EFI_ERROR (Status)) {\r
3d436166 409 DEBUG ((DEBUG_ERROR, "%a (MMC_CMD55): Error and Status = %r\n", __FUNCTION__, Status));\r
e06253ba
HZ
410 return Status;\r
411 }\r
412 if ((Response[0] & MMC_STATUS_APP_CMD) == 0) {\r
413 return EFI_SUCCESS;\r
414 }\r
415\r
416 /* SCR */\r
417 Status = MmcHost->SendCommand (MmcHost, MMC_ACMD51, 0);\r
418 if (EFI_ERROR (Status)) {\r
a1878955 419 DEBUG ((DEBUG_ERROR, "%a(MMC_ACMD51): Error and Status = %r\n", __func__, Status));\r
e06253ba
HZ
420 return Status;\r
421 } else {\r
422 Status = MmcHost->ReadBlockData (MmcHost, 0, 8, Buffer);\r
423 if (EFI_ERROR (Status)) {\r
a1878955 424 DEBUG ((DEBUG_ERROR, "%a(MMC_ACMD51): ReadBlockData Error and Status = %r\n", __func__, Status));\r
e06253ba
HZ
425 return Status;\r
426 }\r
427 CopyMem (&Scr, Buffer, 8);\r
428 if (Scr.SD_SPEC == 2) {\r
429 if (Scr.SD_SPEC3 == 1) {\r
a1878955
MK
430 if (Scr.SD_SPEC4 == 1) {\r
431 DEBUG ((DEBUG_INFO, "Found SD Card for Spec Version 4.xx\n"));\r
432 } else {\r
433 DEBUG ((DEBUG_INFO, "Found SD Card for Spec Version 3.0x\n"));\r
434 }\r
e06253ba 435 } else {\r
a1878955
MK
436 if (Scr.SD_SPEC4 == 0) {\r
437 DEBUG ((DEBUG_INFO, "Found SD Card for Spec Version 2.0\n"));\r
438 } else {\r
439 DEBUG ((DEBUG_ERROR, "Found invalid SD Card\n"));\r
440 }\r
e06253ba
HZ
441 }\r
442 } else {\r
443 if ((Scr.SD_SPEC3 == 0) && (Scr.SD_SPEC4 == 0)) {\r
444 if (Scr.SD_SPEC == 1) {\r
a1878955
MK
445 DEBUG ((DEBUG_INFO, "Found SD Card for Spec Version 1.10\n"));\r
446 } else {\r
447 DEBUG ((DEBUG_INFO, "Found SD Card for Spec Version 1.0\n"));\r
448 }\r
e06253ba 449 } else {\r
a1878955 450 DEBUG ((DEBUG_ERROR, "Found invalid SD Card\n"));\r
e06253ba
HZ
451 }\r
452 }\r
453 }\r
454 if (CccSwitch) {\r
ea21f1d9
MA
455 /* SD Switch, Mode:0, Group:0, Value:0 */\r
456 CmdArg = CreateSwitchCmdArgument(0, 0, 0);\r
457 Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);\r
458 if (EFI_ERROR (Status)) {\r
459 DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): Error and Status = %r\n", __FUNCTION__, Status));\r
460 return Status;\r
461 } else {\r
462 Status = MmcHost->ReadBlockData (MmcHost, 0, SWITCH_CMD_DATA_LENGTH, Buffer);\r
463 if (EFI_ERROR (Status)) {\r
464 DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): ReadBlockData Error and Status = %r\n", __FUNCTION__, Status));\r
465 return Status;\r
466 }\r
467 }\r
468\r
469 if (!(Buffer[3] & SD_HIGH_SPEED_SUPPORTED)) {\r
c49f298d 470 DEBUG ((DEBUG_INFO, "%a : High Speed not supported by Card\n", __FUNCTION__));\r
e06253ba 471 } else {\r
c49f298d 472 Speed = SD_HIGH_SPEED;\r
ea21f1d9 473\r
c49f298d
LTH
474 /* SD Switch, Mode:1, Group:0, Value:1 */\r
475 CmdArg = CreateSwitchCmdArgument(1, 0, 1);\r
476 Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg);\r
477 if (EFI_ERROR (Status)) {\r
478 DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): Error and Status = %r\n", __FUNCTION__, Status));\r
ea21f1d9 479 return Status;\r
c49f298d
LTH
480 } else {\r
481 Status = MmcHost->ReadBlockData (MmcHost, 0, SWITCH_CMD_DATA_LENGTH, Buffer);\r
482 if (EFI_ERROR (Status)) {\r
483 DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): ReadBlockData Error and Status = %r\n", __FUNCTION__, Status));\r
484 return Status;\r
485 }\r
486\r
487 if ((Buffer[4] & SWITCH_CMD_SUCCESS_MASK) != 0x01000000) {\r
488 DEBUG((DEBUG_ERROR, "Problem switching SD card into high-speed mode\n"));\r
489 return Status;\r
490 }\r
ea21f1d9 491 }\r
e06253ba
HZ
492 }\r
493 }\r
494 if (Scr.SD_BUS_WIDTHS & SD_BUS_WIDTH_4BIT) {\r
495 CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
496 Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg);\r
497 if (EFI_ERROR (Status)) {\r
3d436166 498 DEBUG ((DEBUG_ERROR, "%a (MMC_CMD55): Error and Status = %r\n", __FUNCTION__, Status));\r
e06253ba
HZ
499 return Status;\r
500 }\r
501 /* Width: 4 */\r
502 Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, 2);\r
503 if (EFI_ERROR (Status)) {\r
3d436166 504 DEBUG ((DEBUG_ERROR, "%a (MMC_CMD6): Error and Status = %r\n", __FUNCTION__, Status));\r
e06253ba
HZ
505 return Status;\r
506 }\r
507 }\r
508 if (MMC_HOST_HAS_SETIOS(MmcHost)) {\r
ea21f1d9 509 Status = MmcHost->SetIos (MmcHost, Speed, BUSWIDTH_4, EMMCBACKWARD);\r
e06253ba 510 if (EFI_ERROR (Status)) {\r
3d436166 511 DEBUG ((DEBUG_ERROR, "%a (SetIos): Error and Status = %r\n", __FUNCTION__, Status));\r
e06253ba
HZ
512 return Status;\r
513 }\r
514 }\r
b4fdedc2
OM
515 return EFI_SUCCESS;\r
516}\r
517\r
518STATIC\r
519EFI_STATUS\r
520EFIAPI\r
521MmcIdentificationMode (\r
522 IN MMC_HOST_INSTANCE *MmcHostInstance\r
523 )\r
524{\r
525 EFI_STATUS Status;\r
526 UINT32 Response[4];\r
527 UINTN Timeout;\r
528 UINTN CmdArg;\r
529 BOOLEAN IsHCS;\r
530 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
531 OCR_RESPONSE OcrResponse;\r
532\r
533 MmcHost = MmcHostInstance->MmcHost;\r
534 CmdArg = 0;\r
535 IsHCS = FALSE;\r
536\r
537 if (MmcHost == NULL) {\r
538 return EFI_INVALID_PARAMETER;\r
539 }\r
540\r
541 // We can get into this function if we restart the identification mode\r
542 if (MmcHostInstance->State == MmcHwInitializationState) {\r
543 // Initialize the MMC Host HW\r
544 Status = MmcNotifyState (MmcHostInstance, MmcHwInitializationState);\r
545 if (EFI_ERROR (Status)) {\r
a1878955 546 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcHwInitializationState, Status=%r.\n", Status));\r
b4fdedc2
OM
547 return Status;\r
548 }\r
549 }\r
550\r
551 Status = MmcHost->SendCommand (MmcHost, MMC_CMD0, 0);\r
552 if (EFI_ERROR (Status)) {\r
a1878955 553 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode(MMC_CMD0): Error, Status=%r.\n", Status));\r
b4fdedc2
OM
554 return Status;\r
555 }\r
556 Status = MmcNotifyState (MmcHostInstance, MmcIdleState);\r
557 if (EFI_ERROR (Status)) {\r
a1878955 558 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcIdleState, Status=%r.\n", Status));\r
b4fdedc2
OM
559 return Status;\r
560 }\r
561\r
139b5773
OM
562 // Send CMD1 to get OCR (MMC)\r
563 // This command only valid for MMC and eMMC\r
32010753
HZ
564 Timeout = MAX_RETRY_COUNT;\r
565 do {\r
566 Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, EMMC_CMD1_CAPACITY_GREATER_THAN_2GB);\r
567 if (EFI_ERROR (Status))\r
568 break;\r
b4fdedc2
OM
569 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, (UINT32 *)&OcrResponse);\r
570 if (EFI_ERROR (Status)) {\r
a1878955 571 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));\r
b4fdedc2
OM
572 return Status;\r
573 }\r
32010753
HZ
574 Timeout--;\r
575 } while (!OcrResponse.Ocr.PowerUp && (Timeout > 0));\r
576 if (Status == EFI_SUCCESS) {\r
b4fdedc2 577 if (!OcrResponse.Ocr.PowerUp) {\r
a1878955 578 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode(MMC_CMD1): Card initialisation failure, Status=%r.\n", Status));\r
b4fdedc2
OM
579 return EFI_DEVICE_ERROR;\r
580 }\r
581 OcrResponse.Ocr.PowerUp = 0;\r
582 if (OcrResponse.Raw == EMMC_CMD1_CAPACITY_GREATER_THAN_2GB) {\r
583 MmcHostInstance->CardInfo.OCRData.AccessMode = BIT1;\r
584 }\r
585 else {\r
586 MmcHostInstance->CardInfo.OCRData.AccessMode = 0x0;\r
587 }\r
139b5773 588 // Check whether MMC or eMMC\r
b4fdedc2
OM
589 if (OcrResponse.Raw == EMMC_CMD1_CAPACITY_GREATER_THAN_2GB ||\r
590 OcrResponse.Raw == EMMC_CMD1_CAPACITY_LESS_THAN_2GB) {\r
591 return EmmcIdentificationMode (MmcHostInstance, OcrResponse);\r
592 }\r
b4fdedc2
OM
593 }\r
594\r
595 // Are we using SDIO ?\r
596 Status = MmcHost->SendCommand (MmcHost, MMC_CMD5, 0);\r
597 if (Status == EFI_SUCCESS) {\r
a1878955 598 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported, Status=%r.\n", Status));\r
b4fdedc2
OM
599 return EFI_UNSUPPORTED;\r
600 }\r
601\r
602 // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1)\r
603 CmdArg = (0x0UL << 12 | BIT8 | 0xCEUL << 0);\r
604 Status = MmcHost->SendCommand (MmcHost, MMC_CMD8, CmdArg);\r
605 if (Status == EFI_SUCCESS) {\r
a1878955 606 DEBUG ((DEBUG_ERROR, "Card is SD2.0 => Supports high capacity\n"));\r
b4fdedc2
OM
607 IsHCS = TRUE;\r
608 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R7, Response);\r
609 if (EFI_ERROR (Status)) {\r
a1878955 610 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Failed to receive response to CMD8, Status=%r.\n", Status));\r
b4fdedc2
OM
611 return Status;\r
612 }\r
613 PrintResponseR1 (Response[0]);\r
614 // Check if it is valid response\r
615 if (Response[0] != CmdArg) {\r
a1878955 616 DEBUG ((DEBUG_ERROR, "The Card is not usable\n"));\r
b4fdedc2
OM
617 return EFI_UNSUPPORTED;\r
618 }\r
619 } else {\r
a1878955 620 DEBUG ((DEBUG_ERROR, "Not a SD2.0 Card\n"));\r
b4fdedc2
OM
621 }\r
622\r
623 // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.PowerUp == 1)\r
624 Timeout = MAX_RETRY_COUNT;\r
625 while (Timeout > 0) {\r
626 // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command\r
627 Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, 0);\r
628 if (Status == EFI_SUCCESS) {\r
a1878955 629 DEBUG ((DEBUG_INFO, "Card should be SD\n"));\r
b4fdedc2
OM
630 if (IsHCS) {\r
631 MmcHostInstance->CardInfo.CardType = SD_CARD_2;\r
632 } else {\r
633 MmcHostInstance->CardInfo.CardType = SD_CARD;\r
634 }\r
635\r
636 // Note: The first time CmdArg will be zero\r
637 CmdArg = ((UINTN *) &(MmcHostInstance->CardInfo.OCRData))[0];\r
638 if (IsHCS) {\r
639 CmdArg |= BIT30;\r
640 }\r
641 Status = MmcHost->SendCommand (MmcHost, MMC_ACMD41, CmdArg);\r
642 if (!EFI_ERROR (Status)) {\r
643 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);\r
644 if (EFI_ERROR (Status)) {\r
a1878955 645 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));\r
b4fdedc2
OM
646 return Status;\r
647 }\r
648 ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];\r
649 }\r
650 } else {\r
a1878955 651 DEBUG ((DEBUG_INFO, "Card should be MMC\n"));\r
b4fdedc2
OM
652 MmcHostInstance->CardInfo.CardType = MMC_CARD;\r
653\r
654 Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, 0x800000);\r
655 if (!EFI_ERROR (Status)) {\r
656 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);\r
657 if (EFI_ERROR (Status)) {\r
a1878955 658 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));\r
b4fdedc2
OM
659 return Status;\r
660 }\r
661 ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];\r
662 }\r
663 }\r
664\r
665 if (!EFI_ERROR (Status)) {\r
666 if (!MmcHostInstance->CardInfo.OCRData.PowerUp) {\r
eff98cf9 667 gBS->Stall (1);\r
b4fdedc2
OM
668 Timeout--;\r
669 } else {\r
670 if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) {\r
671 MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH;\r
a1878955 672 DEBUG ((DEBUG_ERROR, "High capacity card.\n"));\r
b4fdedc2
OM
673 }\r
674 break; // The MMC/SD card is ready. Continue the Identification Mode\r
675 }\r
676 } else {\r
eff98cf9 677 gBS->Stall (1);\r
b4fdedc2
OM
678 Timeout--;\r
679 }\r
680 }\r
681\r
682 if (Timeout == 0) {\r
a1878955 683 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode(): No Card\n"));\r
b4fdedc2
OM
684 return EFI_NO_MEDIA;\r
685 } else {\r
686 PrintOCR (Response[0]);\r
687 }\r
688\r
689 Status = MmcNotifyState (MmcHostInstance, MmcReadyState);\r
690 if (EFI_ERROR (Status)) {\r
a1878955 691 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcReadyState\n"));\r
b4fdedc2
OM
692 return Status;\r
693 }\r
694\r
695 Status = MmcHost->SendCommand (MmcHost, MMC_CMD2, 0);\r
696 if (EFI_ERROR (Status)) {\r
a1878955 697 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n"));\r
b4fdedc2
OM
698 return Status;\r
699 }\r
700 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CID, Response);\r
701 if (EFI_ERROR (Status)) {\r
a1878955 702 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Failed to receive CID, Status=%r.\n", Status));\r
b4fdedc2
OM
703 return Status;\r
704 }\r
705\r
706 PrintCID (Response);\r
707\r
708 Status = MmcHost->NotifyState (MmcHost, MmcIdentificationState);\r
709 if (EFI_ERROR (Status)) {\r
a1878955 710 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcIdentificationState\n"));\r
b4fdedc2
OM
711 return Status;\r
712 }\r
713\r
714 //\r
715 // Note, SD specifications say that "if the command execution causes a state change, it\r
716 // will be visible to the host in the response to the next command"\r
717 // The status returned for this CMD3 will be 2 - identification\r
718 //\r
719 CmdArg = 1;\r
720 Status = MmcHost->SendCommand (MmcHost, MMC_CMD3, CmdArg);\r
721 if (EFI_ERROR (Status)) {\r
a1878955 722 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n"));\r
b4fdedc2
OM
723 return Status;\r
724 }\r
725\r
726 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_RCA, Response);\r
727 if (EFI_ERROR (Status)) {\r
a1878955 728 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Failed to receive RCA, Status=%r.\n", Status));\r
b4fdedc2
OM
729 return Status;\r
730 }\r
731 PrintRCA (Response[0]);\r
732\r
733 // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card\r
734 if (MmcHostInstance->CardInfo.CardType != MMC_CARD) {\r
735 MmcHostInstance->CardInfo.RCA = Response[0] >> 16;\r
736 } else {\r
737 MmcHostInstance->CardInfo.RCA = CmdArg;\r
738 }\r
739 Status = MmcNotifyState (MmcHostInstance, MmcStandByState);\r
740 if (EFI_ERROR (Status)) {\r
a1878955 741 DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcStandByState\n"));\r
b4fdedc2
OM
742 return Status;\r
743 }\r
744\r
745 return EFI_SUCCESS;\r
746}\r
747\r
748EFI_STATUS\r
749InitializeMmcDevice (\r
750 IN MMC_HOST_INSTANCE *MmcHostInstance\r
751 )\r
752{\r
753 EFI_STATUS Status;\r
754 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
755 UINTN BlockCount;\r
756\r
757 BlockCount = 1;\r
758 MmcHost = MmcHostInstance->MmcHost;\r
759\r
760 Status = MmcIdentificationMode (MmcHostInstance);\r
761 if (EFI_ERROR (Status)) {\r
a1878955 762 DEBUG((DEBUG_ERROR, "InitializeMmcDevice(): Error in Identification Mode, Status=%r\n", Status));\r
b4fdedc2
OM
763 return Status;\r
764 }\r
765\r
766 Status = MmcNotifyState (MmcHostInstance, MmcTransferState);\r
767 if (EFI_ERROR (Status)) {\r
a1878955 768 DEBUG((DEBUG_ERROR, "InitializeMmcDevice(): Error MmcTransferState, Status=%r\n", Status));\r
b4fdedc2
OM
769 return Status;\r
770 }\r
771\r
772 if (MmcHostInstance->CardInfo.CardType != EMMC_CARD) {\r
773 Status = InitializeSdMmcDevice (MmcHostInstance);\r
752ae805
HZ
774 } else {\r
775 Status = InitializeEmmcDevice (MmcHostInstance);\r
776 }\r
777 if (EFI_ERROR (Status)) {\r
778 return Status;\r
b4fdedc2
OM
779 }\r
780\r
781 // Set Block Length\r
782 Status = MmcHost->SendCommand (MmcHost, MMC_CMD16, MmcHostInstance->BlockIo.Media->BlockSize);\r
783 if (EFI_ERROR (Status)) {\r
a1878955 784 DEBUG((DEBUG_ERROR, "InitializeMmcDevice(MMC_CMD16): Error MmcHostInstance->BlockIo.Media->BlockSize: %d and Error = %r\n",\r
b4fdedc2
OM
785 MmcHostInstance->BlockIo.Media->BlockSize, Status));\r
786 return Status;\r
787 }\r
788\r
789 // Block Count (not used). Could return an error for SD card\r
790 if (MmcHostInstance->CardInfo.CardType == MMC_CARD) {\r
791 Status = MmcHost->SendCommand (MmcHost, MMC_CMD23, BlockCount);\r
792 if (EFI_ERROR (Status)) {\r
a1878955 793 DEBUG((DEBUG_ERROR, "InitializeMmcDevice(MMC_CMD23): Error, Status=%r\n", Status));\r
b4fdedc2
OM
794 return Status;\r
795 }\r
796 }\r
797\r
798 return EFI_SUCCESS;\r
799}\r