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