]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Universal/MmcDxe/MmcIdentification.c
EmbeddedPkg/MmcDxe: Fix mixed EOL
[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 (SD / MMC)
226 Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, EMMC_CMD1_CAPACITY_GREATER_THAN_2GB);
227 if (Status == EFI_SUCCESS) {
228 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, (UINT32 *)&OcrResponse);
229 if (EFI_ERROR (Status)) {
230 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));
231 return Status;
232 }
233
234 if (!OcrResponse.Ocr.PowerUp) {
235 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD1): Card initialisation failure, Status=%r.\n", Status));
236 return EFI_DEVICE_ERROR;
237 }
238 OcrResponse.Ocr.PowerUp = 0;
239 if (OcrResponse.Raw == EMMC_CMD1_CAPACITY_GREATER_THAN_2GB) {
240 MmcHostInstance->CardInfo.OCRData.AccessMode = BIT1;
241 }
242 else {
243 MmcHostInstance->CardInfo.OCRData.AccessMode = 0x0;
244 }
245 if (OcrResponse.Raw == EMMC_CMD1_CAPACITY_GREATER_THAN_2GB ||
246 OcrResponse.Raw == EMMC_CMD1_CAPACITY_LESS_THAN_2GB) {
247 return EmmcIdentificationMode (MmcHostInstance, OcrResponse);
248 }
249 } else {
250 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD1) : Failed to send command, Status=%r.\n", Status));
251 return Status;
252 }
253
254 // Are we using SDIO ?
255 Status = MmcHost->SendCommand (MmcHost, MMC_CMD5, 0);
256 if (Status == EFI_SUCCESS) {
257 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported, Status=%r.\n", Status));
258 return EFI_UNSUPPORTED;
259 }
260
261 // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1)
262 CmdArg = (0x0UL << 12 | BIT8 | 0xCEUL << 0);
263 Status = MmcHost->SendCommand (MmcHost, MMC_CMD8, CmdArg);
264 if (Status == EFI_SUCCESS) {
265 DEBUG ((EFI_D_ERROR, "Card is SD2.0 => Supports high capacity\n"));
266 IsHCS = TRUE;
267 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R7, Response);
268 if (EFI_ERROR (Status)) {
269 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive response to CMD8, Status=%r.\n", Status));
270 return Status;
271 }
272 PrintResponseR1 (Response[0]);
273 // Check if it is valid response
274 if (Response[0] != CmdArg) {
275 DEBUG ((EFI_D_ERROR, "The Card is not usable\n"));
276 return EFI_UNSUPPORTED;
277 }
278 } else {
279 DEBUG ((EFI_D_ERROR, "Not a SD2.0 Card\n"));
280 }
281
282 // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.PowerUp == 1)
283 Timeout = MAX_RETRY_COUNT;
284 while (Timeout > 0) {
285 // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command
286 Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, 0);
287 if (Status == EFI_SUCCESS) {
288 DEBUG ((EFI_D_INFO, "Card should be SD\n"));
289 if (IsHCS) {
290 MmcHostInstance->CardInfo.CardType = SD_CARD_2;
291 } else {
292 MmcHostInstance->CardInfo.CardType = SD_CARD;
293 }
294
295 // Note: The first time CmdArg will be zero
296 CmdArg = ((UINTN *) &(MmcHostInstance->CardInfo.OCRData))[0];
297 if (IsHCS) {
298 CmdArg |= BIT30;
299 }
300 Status = MmcHost->SendCommand (MmcHost, MMC_ACMD41, CmdArg);
301 if (!EFI_ERROR (Status)) {
302 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);
303 if (EFI_ERROR (Status)) {
304 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));
305 return Status;
306 }
307 ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
308 }
309 } else {
310 DEBUG ((EFI_D_INFO, "Card should be MMC\n"));
311 MmcHostInstance->CardInfo.CardType = MMC_CARD;
312
313 Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, 0x800000);
314 if (!EFI_ERROR (Status)) {
315 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);
316 if (EFI_ERROR (Status)) {
317 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status));
318 return Status;
319 }
320 ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
321 }
322 }
323
324 if (!EFI_ERROR (Status)) {
325 if (!MmcHostInstance->CardInfo.OCRData.PowerUp) {
326 MicroSecondDelay (1);
327 Timeout--;
328 } else {
329 if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) {
330 MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH;
331 DEBUG ((EFI_D_ERROR, "High capacity card.\n"));
332 }
333 break; // The MMC/SD card is ready. Continue the Identification Mode
334 }
335 } else {
336 MicroSecondDelay (1);
337 Timeout--;
338 }
339 }
340
341 if (Timeout == 0) {
342 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n"));
343 return EFI_NO_MEDIA;
344 } else {
345 PrintOCR (Response[0]);
346 }
347
348 Status = MmcNotifyState (MmcHostInstance, MmcReadyState);
349 if (EFI_ERROR (Status)) {
350 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcReadyState\n"));
351 return Status;
352 }
353
354 Status = MmcHost->SendCommand (MmcHost, MMC_CMD2, 0);
355 if (EFI_ERROR (Status)) {
356 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n"));
357 return Status;
358 }
359 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CID, Response);
360 if (EFI_ERROR (Status)) {
361 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive CID, Status=%r.\n", Status));
362 return Status;
363 }
364
365 PrintCID (Response);
366
367 Status = MmcHost->NotifyState (MmcHost, MmcIdentificationState);
368 if (EFI_ERROR (Status)) {
369 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdentificationState\n"));
370 return Status;
371 }
372
373 //
374 // Note, SD specifications say that "if the command execution causes a state change, it
375 // will be visible to the host in the response to the next command"
376 // The status returned for this CMD3 will be 2 - identification
377 //
378 CmdArg = 1;
379 Status = MmcHost->SendCommand (MmcHost, MMC_CMD3, CmdArg);
380 if (EFI_ERROR (Status)) {
381 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n"));
382 return Status;
383 }
384
385 Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_RCA, Response);
386 if (EFI_ERROR (Status)) {
387 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Failed to receive RCA, Status=%r.\n", Status));
388 return Status;
389 }
390 PrintRCA (Response[0]);
391
392 // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card
393 if (MmcHostInstance->CardInfo.CardType != MMC_CARD) {
394 MmcHostInstance->CardInfo.RCA = Response[0] >> 16;
395 } else {
396 MmcHostInstance->CardInfo.RCA = CmdArg;
397 }
398 Status = MmcNotifyState (MmcHostInstance, MmcStandByState);
399 if (EFI_ERROR (Status)) {
400 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcStandByState\n"));
401 return Status;
402 }
403
404 return EFI_SUCCESS;
405 }
406
407 EFI_STATUS
408 InitializeMmcDevice (
409 IN MMC_HOST_INSTANCE *MmcHostInstance
410 )
411 {
412 EFI_STATUS Status;
413 EFI_MMC_HOST_PROTOCOL *MmcHost;
414 UINTN BlockCount;
415
416 BlockCount = 1;
417 MmcHost = MmcHostInstance->MmcHost;
418
419 Status = MmcIdentificationMode (MmcHostInstance);
420 if (EFI_ERROR (Status)) {
421 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(): Error in Identification Mode, Status=%r\n", Status));
422 return Status;
423 }
424
425 Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
426 if (EFI_ERROR (Status)) {
427 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(): Error MmcTransferState, Status=%r\n", Status));
428 return Status;
429 }
430
431 if (MmcHostInstance->CardInfo.CardType != EMMC_CARD) {
432 Status = InitializeSdMmcDevice (MmcHostInstance);
433 if (EFI_ERROR (Status)) {
434 return Status;
435 }
436 }
437
438 // Set Block Length
439 Status = MmcHost->SendCommand (MmcHost, MMC_CMD16, MmcHostInstance->BlockIo.Media->BlockSize);
440 if (EFI_ERROR (Status)) {
441 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD16): Error MmcHostInstance->BlockIo.Media->BlockSize: %d and Error = %r\n",
442 MmcHostInstance->BlockIo.Media->BlockSize, Status));
443 return Status;
444 }
445
446 // Block Count (not used). Could return an error for SD card
447 if (MmcHostInstance->CardInfo.CardType == MMC_CARD) {
448 Status = MmcHost->SendCommand (MmcHost, MMC_CMD23, BlockCount);
449 if (EFI_ERROR (Status)) {
450 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD23): Error, Status=%r\n", Status));
451 return Status;
452 }
453 }
454
455 return EFI_SUCCESS;
456 }