]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
EmbeddedPkg: MmcDxe: declare ECSD structure
[mirror_edk2.git] / EmbeddedPkg / Universal / MmcDxe / MmcIdentification.c
1 /** @file
2 *
3 * Copyright (c) 2011-2015, ARM Limited. All rights reserved.
4 *
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
9 *
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 *
13 **/
14
15 #include "Mmc.h"
16
17 typedef union {
18 UINT32 Raw;
19 OCR Ocr;
20 } OCR_RESPONSE;
21
22 #define MAX_RETRY_COUNT 1000
23 #define CMD_RETRY_COUNT 20
24 #define RCA_SHIFT_OFFSET 16
25 #define EMMC_CARD_SIZE 512
26 #define EMMC_ECSD_SIZE_OFFSET 53
27
28 UINT32 mEmmcRcaCount = 0;
29
30 STATIC
31 EFI_STATUS
32 EFIAPI
33 EmmcIdentificationMode (
34 IN MMC_HOST_INSTANCE *MmcHostInstance,
35 IN OCR_RESPONSE Response
36 )
37 {
38 EFI_MMC_HOST_PROTOCOL *Host;
39 EFI_BLOCK_IO_MEDIA *Media;
40 EFI_STATUS Status;
41 UINT32 RCA;
42
43 Host = MmcHostInstance->MmcHost;
44 Media = MmcHostInstance->BlockIo.Media;
45
46 // Fetch card identity register
47 Status = Host->SendCommand (Host, MMC_CMD2, 0);
48 if (EFI_ERROR (Status)) {
49 DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to send CMD2, Status=%r.\n", Status));
50 return Status;
51 }
52
53 Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R2, (UINT32 *)&(MmcHostInstance->CardInfo.CIDData));
54 if (EFI_ERROR (Status)) {
55 DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): CID retrieval error, Status=%r.\n", Status));
56 return Status;
57 }
58
59 // Assign a relative address value to the card
60 MmcHostInstance->CardInfo.RCA = ++mEmmcRcaCount; // TODO: might need a more sophisticated way of doing this
61 RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;
62 Status = Host->SendCommand (Host, MMC_CMD3, RCA);
63 if (EFI_ERROR (Status)) {
64 DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): RCA set error, Status=%r.\n", Status));
65 return Status;
66 }
67
68 // Fetch card specific data
69 Status = Host->SendCommand (Host, MMC_CMD9, RCA);
70 if (EFI_ERROR (Status)) {
71 DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to send CMD9, Status=%r.\n", Status));
72 return Status;
73 }
74
75 Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R2, (UINT32 *)&(MmcHostInstance->CardInfo.CSDData));
76 if (EFI_ERROR (Status)) {
77 DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): CSD retrieval error, Status=%r.\n", Status));
78 return Status;
79 }
80
81 // Select the card
82 Status = Host->SendCommand (Host, MMC_CMD7, RCA);
83 if (EFI_ERROR (Status)) {
84 DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Card selection error, Status=%r.\n", Status));
85 }
86
87 // Fetch ECSD
88 Status = Host->SendCommand (Host, MMC_CMD8, RCA);
89 if (EFI_ERROR (Status)) {
90 DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));
91 }
92
93 Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)&(MmcHostInstance->CardInfo.ECSDData));
94 if (EFI_ERROR (Status)) {
95 DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));
96 return Status;
97 }
98
99 // Set up media
100 Media->BlockSize = EMMC_CARD_SIZE; // 512-byte support is mandatory for eMMC cards
101 Media->MediaId = MmcHostInstance->CardInfo.CIDData.PSN;
102 Media->ReadOnly = MmcHostInstance->CardInfo.CSDData.PERM_WRITE_PROTECT;
103 Media->LogicalBlocksPerPhysicalBlock = 1;
104 Media->IoAlign = 4;
105 // Compute last block using bits [215:212] of the ECSD
106 Media->LastBlock = MmcHostInstance->CardInfo.ECSDData.SECTOR_COUNT - 1; // eMMC isn't supposed to report this for
107 // Cards <2GB in size, but the model does.
108
109 // Setup card type
110 MmcHostInstance->CardInfo.CardType = EMMC_CARD;
111 return EFI_SUCCESS;
112 }
113
114 STATIC
115 EFI_STATUS
116 InitializeSdMmcDevice (
117 IN MMC_HOST_INSTANCE *MmcHostInstance
118 )
119 {
120 UINT32 CmdArg;
121 UINT32 Response[4];
122 UINTN BlockSize;
123 UINTN CardSize;
124 UINTN NumBlocks;
125 EFI_STATUS Status;
126 EFI_MMC_HOST_PROTOCOL *MmcHost;
127
128 MmcHost = MmcHostInstance->MmcHost;
129
130 // Send a command to get Card specific data
131 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
132 Status = MmcHost->SendCommand (MmcHost, MMC_CMD9, CmdArg);
133 if (EFI_ERROR (Status)) {
134 DEBUG((EFI_D_ERROR, "InitializeSdMmcDevice(MMC_CMD9): Error, Status=%r\n", Status));
135 return Status;
136 }
137
138 // Read Response
139 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CSD, Response);
140 if (EFI_ERROR (Status)) {
141 DEBUG((EFI_D_ERROR, "InitializeSdMmcDevice(): Failed to receive CSD, Status=%r\n", Status));
142 return Status;
143 }
144 PrintCSD (Response);
145
146 if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {
147 CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response);
148 NumBlocks = ((CardSize + 1) * 1024);
149 BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response);
150 } else {
151 CardSize = MMC_CSD_GET_DEVICESIZE (Response);
152 NumBlocks = (CardSize + 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT (Response) + 2));
153 BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response);
154 }
155
156 // For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.
157 if (BlockSize > 512) {
158 NumBlocks = MultU64x32 (NumBlocks, BlockSize / 512);
159 BlockSize = 512;
160 }
161
162 MmcHostInstance->BlockIo.Media->LastBlock = (NumBlocks - 1);
163 MmcHostInstance->BlockIo.Media->BlockSize = BlockSize;
164 MmcHostInstance->BlockIo.Media->ReadOnly = MmcHost->IsReadOnly (MmcHost);
165 MmcHostInstance->BlockIo.Media->MediaPresent = TRUE;
166 MmcHostInstance->BlockIo.Media->MediaId++;
167
168 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
169 Status = MmcHost->SendCommand (MmcHost, MMC_CMD7, CmdArg);
170 if (EFI_ERROR (Status)) {
171 DEBUG((EFI_D_ERROR, "InitializeSdMmcDevice(MMC_CMD7): Error and Status = %r\n", Status));
172 return Status;
173 }
174
175 return EFI_SUCCESS;
176 }
177
178 STATIC
179 EFI_STATUS
180 EFIAPI
181 MmcIdentificationMode (
182 IN MMC_HOST_INSTANCE *MmcHostInstance
183 )
184 {
185 EFI_STATUS Status;
186 UINT32 Response[4];
187 UINTN Timeout;
188 UINTN CmdArg;
189 BOOLEAN IsHCS;
190 EFI_MMC_HOST_PROTOCOL *MmcHost;
191 OCR_RESPONSE OcrResponse;
192
193 MmcHost = MmcHostInstance->MmcHost;
194 CmdArg = 0;
195 IsHCS = FALSE;
196
197 if (MmcHost == NULL) {
198 return EFI_INVALID_PARAMETER;
199 }
200
201 // We can get into this function if we restart the identification mode
202 if (MmcHostInstance->State == MmcHwInitializationState) {
203 // Initialize the MMC Host HW
204 Status = MmcNotifyState (MmcHostInstance, MmcHwInitializationState);
205 if (EFI_ERROR (Status)) {
206 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcHwInitializationState, Status=%r.\n", Status));
207 return Status;
208 }
209 }
210
211 Status = MmcHost->SendCommand (MmcHost, MMC_CMD0, 0);
212 if (EFI_ERROR (Status)) {
213 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD0): Error, Status=%r.\n", Status));
214 return Status;
215 }
216 Status = MmcNotifyState (MmcHostInstance, MmcIdleState);
217 if (EFI_ERROR (Status)) {
218 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdleState, Status=%r.\n", Status));
219 return Status;
220 }
221
222 // Send CMD1 to get OCR (MMC)
223 // This command only valid for MMC and eMMC
224 Timeout = MAX_RETRY_COUNT;
225 do {
226 Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, EMMC_CMD1_CAPACITY_GREATER_THAN_2GB);
227 if (EFI_ERROR (Status))
228 break;
229 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, (UINT32 *)&OcrResponse);
230 if (EFI_ERROR (Status)) {
231 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));
232 return Status;
233 }
234 Timeout--;
235 } while (!OcrResponse.Ocr.PowerUp && (Timeout > 0));
236 if (Status == EFI_SUCCESS) {
237 if (!OcrResponse.Ocr.PowerUp) {
238 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD1): Card initialisation failure, Status=%r.\n", Status));
239 return EFI_DEVICE_ERROR;
240 }
241 OcrResponse.Ocr.PowerUp = 0;
242 if (OcrResponse.Raw == EMMC_CMD1_CAPACITY_GREATER_THAN_2GB) {
243 MmcHostInstance->CardInfo.OCRData.AccessMode = BIT1;
244 }
245 else {
246 MmcHostInstance->CardInfo.OCRData.AccessMode = 0x0;
247 }
248 // Check whether MMC or eMMC
249 if (OcrResponse.Raw == EMMC_CMD1_CAPACITY_GREATER_THAN_2GB ||
250 OcrResponse.Raw == EMMC_CMD1_CAPACITY_LESS_THAN_2GB) {
251 return EmmcIdentificationMode (MmcHostInstance, OcrResponse);
252 }
253 }
254
255 // Are we using SDIO ?
256 Status = MmcHost->SendCommand (MmcHost, MMC_CMD5, 0);
257 if (Status == EFI_SUCCESS) {
258 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported, Status=%r.\n", Status));
259 return EFI_UNSUPPORTED;
260 }
261
262 // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1)
263 CmdArg = (0x0UL << 12 | BIT8 | 0xCEUL << 0);
264 Status = MmcHost->SendCommand (MmcHost, MMC_CMD8, CmdArg);
265 if (Status == EFI_SUCCESS) {
266 DEBUG ((EFI_D_ERROR, "Card is SD2.0 => Supports high capacity\n"));
267 IsHCS = TRUE;
268 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R7, Response);
269 if (EFI_ERROR (Status)) {
270 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive response to CMD8, Status=%r.\n", Status));
271 return Status;
272 }
273 PrintResponseR1 (Response[0]);
274 // Check if it is valid response
275 if (Response[0] != CmdArg) {
276 DEBUG ((EFI_D_ERROR, "The Card is not usable\n"));
277 return EFI_UNSUPPORTED;
278 }
279 } else {
280 DEBUG ((EFI_D_ERROR, "Not a SD2.0 Card\n"));
281 }
282
283 // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.PowerUp == 1)
284 Timeout = MAX_RETRY_COUNT;
285 while (Timeout > 0) {
286 // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command
287 Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, 0);
288 if (Status == EFI_SUCCESS) {
289 DEBUG ((EFI_D_INFO, "Card should be SD\n"));
290 if (IsHCS) {
291 MmcHostInstance->CardInfo.CardType = SD_CARD_2;
292 } else {
293 MmcHostInstance->CardInfo.CardType = SD_CARD;
294 }
295
296 // Note: The first time CmdArg will be zero
297 CmdArg = ((UINTN *) &(MmcHostInstance->CardInfo.OCRData))[0];
298 if (IsHCS) {
299 CmdArg |= BIT30;
300 }
301 Status = MmcHost->SendCommand (MmcHost, MMC_ACMD41, CmdArg);
302 if (!EFI_ERROR (Status)) {
303 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);
304 if (EFI_ERROR (Status)) {
305 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));
306 return Status;
307 }
308 ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
309 }
310 } else {
311 DEBUG ((EFI_D_INFO, "Card should be MMC\n"));
312 MmcHostInstance->CardInfo.CardType = MMC_CARD;
313
314 Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, 0x800000);
315 if (!EFI_ERROR (Status)) {
316 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);
317 if (EFI_ERROR (Status)) {
318 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));
319 return Status;
320 }
321 ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
322 }
323 }
324
325 if (!EFI_ERROR (Status)) {
326 if (!MmcHostInstance->CardInfo.OCRData.PowerUp) {
327 gBS->Stall (1);
328 Timeout--;
329 } else {
330 if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) {
331 MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH;
332 DEBUG ((EFI_D_ERROR, "High capacity card.\n"));
333 }
334 break; // The MMC/SD card is ready. Continue the Identification Mode
335 }
336 } else {
337 gBS->Stall (1);
338 Timeout--;
339 }
340 }
341
342 if (Timeout == 0) {
343 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n"));
344 return EFI_NO_MEDIA;
345 } else {
346 PrintOCR (Response[0]);
347 }
348
349 Status = MmcNotifyState (MmcHostInstance, MmcReadyState);
350 if (EFI_ERROR (Status)) {
351 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcReadyState\n"));
352 return Status;
353 }
354
355 Status = MmcHost->SendCommand (MmcHost, MMC_CMD2, 0);
356 if (EFI_ERROR (Status)) {
357 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n"));
358 return Status;
359 }
360 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CID, Response);
361 if (EFI_ERROR (Status)) {
362 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive CID, Status=%r.\n", Status));
363 return Status;
364 }
365
366 PrintCID (Response);
367
368 Status = MmcHost->NotifyState (MmcHost, MmcIdentificationState);
369 if (EFI_ERROR (Status)) {
370 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdentificationState\n"));
371 return Status;
372 }
373
374 //
375 // Note, SD specifications say that "if the command execution causes a state change, it
376 // will be visible to the host in the response to the next command"
377 // The status returned for this CMD3 will be 2 - identification
378 //
379 CmdArg = 1;
380 Status = MmcHost->SendCommand (MmcHost, MMC_CMD3, CmdArg);
381 if (EFI_ERROR (Status)) {
382 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n"));
383 return Status;
384 }
385
386 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_RCA, Response);
387 if (EFI_ERROR (Status)) {
388 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive RCA, Status=%r.\n", Status));
389 return Status;
390 }
391 PrintRCA (Response[0]);
392
393 // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card
394 if (MmcHostInstance->CardInfo.CardType != MMC_CARD) {
395 MmcHostInstance->CardInfo.RCA = Response[0] >> 16;
396 } else {
397 MmcHostInstance->CardInfo.RCA = CmdArg;
398 }
399 Status = MmcNotifyState (MmcHostInstance, MmcStandByState);
400 if (EFI_ERROR (Status)) {
401 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcStandByState\n"));
402 return Status;
403 }
404
405 return EFI_SUCCESS;
406 }
407
408 EFI_STATUS
409 InitializeMmcDevice (
410 IN MMC_HOST_INSTANCE *MmcHostInstance
411 )
412 {
413 EFI_STATUS Status;
414 EFI_MMC_HOST_PROTOCOL *MmcHost;
415 UINTN BlockCount;
416
417 BlockCount = 1;
418 MmcHost = MmcHostInstance->MmcHost;
419
420 Status = MmcIdentificationMode (MmcHostInstance);
421 if (EFI_ERROR (Status)) {
422 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(): Error in Identification Mode, Status=%r\n", Status));
423 return Status;
424 }
425
426 Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
427 if (EFI_ERROR (Status)) {
428 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(): Error MmcTransferState, Status=%r\n", Status));
429 return Status;
430 }
431
432 if (MmcHostInstance->CardInfo.CardType != EMMC_CARD) {
433 Status = InitializeSdMmcDevice (MmcHostInstance);
434 if (EFI_ERROR (Status)) {
435 return Status;
436 }
437 }
438
439 // Set Block Length
440 Status = MmcHost->SendCommand (MmcHost, MMC_CMD16, MmcHostInstance->BlockIo.Media->BlockSize);
441 if (EFI_ERROR (Status)) {
442 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD16): Error MmcHostInstance->BlockIo.Media->BlockSize: %d and Error = %r\n",
443 MmcHostInstance->BlockIo.Media->BlockSize, Status));
444 return Status;
445 }
446
447 // Block Count (not used). Could return an error for SD card
448 if (MmcHostInstance->CardInfo.CardType == MMC_CARD) {
449 Status = MmcHost->SendCommand (MmcHost, MMC_CMD23, BlockCount);
450 if (EFI_ERROR (Status)) {
451 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD23): Error, Status=%r\n", Status));
452 return Status;
453 }
454 }
455
456 return EFI_SUCCESS;
457 }