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