]> git.proxmox.com Git - mirror_edk2.git/blame - Omap35xxPkg/MMCHSDxe/MMCHS.c
Add a little more code for SD Card DMA, but make sure it is turned off until it...
[mirror_edk2.git] / Omap35xxPkg / MMCHSDxe / MMCHS.c
CommitLineData
a3f98646 1/** @file
8c6151f2 2 MMC/SD Card driver for OMAP 35xx (SDIO not supported)
3
4 This driver always produces a BlockIo protocol but it starts off with no Media
5 present. A TimerCallBack detects when media is inserted or removed and after
6 a media change event a call to BlockIo ReadBlocks/WriteBlocks will cause the
7 media to be detected (or removed) and the BlockIo Media structure will get
8 updated. No MMC/SD Card harward registers are updated until the first BlockIo
9 ReadBlocks/WriteBlocks after media has been insterted (booting with a card
10 plugged in counts as an insertion event).
a3f98646 11
3d70643b 12 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
a3f98646 13
3d70643b 14 This program and the accompanying materials
a3f98646 15 are licensed and made available under the terms and conditions of the BSD License
16 which accompanies this distribution. The full text of the license may be found at
17 http://opensource.org/licenses/bsd-license.php
18
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21
22**/
23
a3f98646 24#include "MMCHS.h"
25
8c6151f2 26EFI_BLOCK_IO_MEDIA gMMCHSMedia = {
a3f98646 27 SIGNATURE_32('s','d','i','o'), // MediaId
28 TRUE, // RemovableMedia
8c6151f2 29 FALSE, // MediaPresent
a3f98646 30 FALSE, // LogicalPartition
31 FALSE, // ReadOnly
32 FALSE, // WriteCaching
33 512, // BlockSize
34 4, // IoAlign
35 0, // Pad
36 0 // LastBlock
37};
38
39typedef struct {
40 VENDOR_DEVICE_PATH Mmc;
41 EFI_DEVICE_PATH End;
42} MMCHS_DEVICE_PATH;
43
8c6151f2 44MMCHS_DEVICE_PATH gMmcHsDevicePath = {
a3f98646 45 {
46 HARDWARE_DEVICE_PATH,
47 HW_VENDOR_DP,
48 (UINT8)(sizeof(VENDOR_DEVICE_PATH)),
49 (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8),
50 0xb615f1f5, 0x5088, 0x43cd, 0x80, 0x9c, 0xa1, 0x6e, 0x52, 0x48, 0x7d, 0x00
51 },
52 {
53 END_DEVICE_PATH_TYPE,
54 END_ENTIRE_DEVICE_PATH_SUBTYPE,
55 sizeof (EFI_DEVICE_PATH_PROTOCOL),
56 0
57 }
58};
59
8c6151f2 60CARD_INFO gCardInfo;
a3f98646 61EMBEDDED_EXTERNAL_DEVICE *gTPS65950;
8c6151f2 62EFI_EVENT gTimerEvent;
63BOOLEAN gMediaChange = FALSE;
a3f98646 64
65//
66// Internal Functions
67//
68
8c6151f2 69
a3f98646 70VOID
71ParseCardCIDData (
72 UINT32 Response0,
73 UINT32 Response1,
74 UINT32 Response2,
75 UINT32 Response3
76 )
77{
8c6151f2 78 gCardInfo.CIDData.MDT = ((Response0 >> 8) & 0xFFF);
79 gCardInfo.CIDData.PSN = (((Response0 >> 24) & 0xFF) | ((Response1 & 0xFFFFFF) << 8));
80 gCardInfo.CIDData.PRV = ((Response1 >> 24) & 0xFF);
81 gCardInfo.CIDData.PNM[4] = ((Response2) & 0xFF);
82 gCardInfo.CIDData.PNM[3] = ((Response2 >> 8) & 0xFF);
83 gCardInfo.CIDData.PNM[2] = ((Response2 >> 16) & 0xFF);
84 gCardInfo.CIDData.PNM[1] = ((Response2 >> 24) & 0xFF);
85 gCardInfo.CIDData.PNM[0] = ((Response3) & 0xFF);
86 gCardInfo.CIDData.OID = ((Response3 >> 8) & 0xFFFF);
87 gCardInfo.CIDData.MID = ((Response3 >> 24) & 0xFF);
a3f98646 88}
89
8c6151f2 90
a3f98646 91VOID
92UpdateMMCHSClkFrequency (
93 UINTN NewCLKD
94 )
95{
96 //Set Clock enable to 0x0 to not provide the clock to the card
8c6151f2 97 MmioAnd32 (MMCHS_SYSCTL, ~CEN);
a3f98646 98
99 //Set new clock frequency.
8c6151f2 100 MmioAndThenOr32 (MMCHS_SYSCTL, ~CLKD_MASK, NewCLKD << 6);
a3f98646 101
102 //Poll till Internal Clock Stable
43263288 103 while ((MmioRead32 (MMCHS_SYSCTL) & ICS_MASK) != ICS);
a3f98646 104
105 //Set Clock enable to 0x1 to provide the clock to the card
43263288 106 MmioOr32 (MMCHS_SYSCTL, CEN);
a3f98646 107}
108
8c6151f2 109
a3f98646 110EFI_STATUS
111SendCmd (
112 UINTN Cmd,
113 UINTN CmdInterruptEnableVal,
114 UINTN CmdArgument
115 )
116{
117 UINTN MmcStatus;
118 UINTN RetryCount = 0;
119
120 //Check if command line is in use or not. Poll till command line is available.
43263288 121 while ((MmioRead32 (MMCHS_PSTATE) & DATI_MASK) == DATI_NOT_ALLOWED);
a3f98646 122
123 //Provide the block size.
026e30c4 124 MmioWrite32 (MMCHS_BLK, BLEN_512BYTES);
a3f98646 125
126 //Setting Data timeout counter value to max value.
8c6151f2 127 MmioAndThenOr32 (MMCHS_SYSCTL, ~DTO_MASK, DTO_VAL);
a3f98646 128
129 //Clear Status register.
026e30c4 130 MmioWrite32 (MMCHS_STAT, 0xFFFFFFFF);
a3f98646 131
132 //Set command argument register
026e30c4 133 MmioWrite32 (MMCHS_ARG, CmdArgument);
a3f98646 134
135 //Enable interrupt enable events to occur
026e30c4 136 MmioWrite32 (MMCHS_IE, CmdInterruptEnableVal);
a3f98646 137
138 //Send a command
026e30c4 139 MmioWrite32 (MMCHS_CMD, Cmd);
a3f98646 140
141 //Check for the command status.
142 while (RetryCount < MAX_RETRY_COUNT) {
143 do {
43263288 144 MmcStatus = MmioRead32 (MMCHS_STAT);
a3f98646 145 } while (MmcStatus == 0);
146
147 //Read status of command response
148 if ((MmcStatus & ERRI) != 0) {
149
150 //Perform soft-reset for mmci_cmd line.
43263288 151 MmioOr32 (MMCHS_SYSCTL, SRC);
152 while ((MmioRead32 (MMCHS_SYSCTL) & SRC));
a3f98646 153
154 DEBUG ((EFI_D_INFO, "MmcStatus: %x\n", MmcStatus));
155 return EFI_DEVICE_ERROR;
156 }
157
158 //Check if command is completed.
159 if ((MmcStatus & CC) == CC) {
026e30c4 160 MmioWrite32 (MMCHS_STAT, CC);
a3f98646 161 break;
162 }
163
164 RetryCount++;
165 }
166
167 if (RetryCount == MAX_RETRY_COUNT) {
168 return EFI_TIMEOUT;
169 }
170
171 return EFI_SUCCESS;
172}
173
8c6151f2 174
a3f98646 175VOID
176GetBlockInformation (
177 UINTN *BlockSize,
178 UINTN *NumBlocks
179 )
180{
181 CSD_SDV2 *CsdSDV2Data;
182 UINTN CardSize;
183
8c6151f2 184 if (gCardInfo.CardType == SD_CARD_2_HIGH) {
185 CsdSDV2Data = (CSD_SDV2 *)&gCardInfo.CSDData;
a3f98646 186
187 //Populate BlockSize.
188 *BlockSize = (0x1UL << CsdSDV2Data->READ_BL_LEN);
189
190 //Calculate Total number of blocks.
191 CardSize = CsdSDV2Data->C_SIZELow16 | (CsdSDV2Data->C_SIZEHigh6 << 2);
192 *NumBlocks = ((CardSize + 1) * 1024);
193 } else {
194 //Populate BlockSize.
8c6151f2 195 *BlockSize = (0x1UL << gCardInfo.CSDData.READ_BL_LEN);
a3f98646 196
197 //Calculate Total number of blocks.
8c6151f2 198 CardSize = gCardInfo.CSDData.C_SIZELow2 | (gCardInfo.CSDData.C_SIZEHigh10 << 2);
199 *NumBlocks = (CardSize + 1) * (1 << (gCardInfo.CSDData.C_SIZE_MULT + 2));
a3f98646 200 }
201
202 //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.
203 if (*BlockSize > 512) {
204 *NumBlocks = MultU64x32(*NumBlocks, *BlockSize/2);
205 *BlockSize = 512;
206 }
207
8c6151f2 208 DEBUG ((EFI_D_INFO, "Card type: %x, BlockSize: %x, NumBlocks: %x\n", gCardInfo.CardType, *BlockSize, *NumBlocks));
a3f98646 209}
210
8c6151f2 211
a3f98646 212VOID
213CalculateCardCLKD (
214 UINTN *ClockFrequencySelect
215 )
216{
217 UINT8 MaxDataTransferRate;
218 UINTN TransferRateValue = 0;
219 UINTN TimeValue = 0 ;
220 UINTN Frequency = 0;
221
8c6151f2 222 MaxDataTransferRate = gCardInfo.CSDData.TRAN_SPEED;
a3f98646 223
7f814ffd 224 // For SD Cards we would need to send CMD6 to set
225 // speeds abouve 25MHz. High Speed mode 50 MHz and up
226
a3f98646 227 //Calculate Transfer rate unit (Bits 2:0 of TRAN_SPEED)
228 switch (MaxDataTransferRate & 0x7) {
229 case 0:
230 TransferRateValue = 100 * 1000;
231 break;
232
233 case 1:
234 TransferRateValue = 1 * 1000 * 1000;
235 break;
236
237 case 2:
238 TransferRateValue = 10 * 1000 * 1000;
239 break;
240
241 case 3:
242 TransferRateValue = 100 * 1000 * 1000;
243 break;
244
245 default:
246 DEBUG((EFI_D_ERROR, "Invalid parameter.\n"));
247 ASSERT(FALSE);
248 }
249
250 //Calculate Time value (Bits 6:3 of TRAN_SPEED)
251 switch ((MaxDataTransferRate >> 3) & 0xF) {
252 case 1:
253 TimeValue = 10;
254 break;
255
256 case 2:
257 TimeValue = 12;
258 break;
259
260 case 3:
261 TimeValue = 13;
262 break;
263
264 case 4:
265 TimeValue = 15;
266 break;
267
268 case 5:
269 TimeValue = 20;
270 break;
271
272 case 6:
273 TimeValue = 25;
274 break;
275
276 case 7:
277 TimeValue = 30;
278 break;
279
280 case 8:
281 TimeValue = 35;
282 break;
283
284 case 9:
285 TimeValue = 40;
286 break;
287
288 case 10:
289 TimeValue = 45;
290 break;
291
292 case 11:
293 TimeValue = 50;
294 break;
295
296 case 12:
297 TimeValue = 55;
298 break;
299
300 case 13:
301 TimeValue = 60;
302 break;
303
304 case 14:
305 TimeValue = 70;
306 break;
307
308 case 15:
309 TimeValue = 80;
310 break;
311
312 default:
313 DEBUG((EFI_D_ERROR, "Invalid parameter.\n"));
314 ASSERT(FALSE);
315 }
316
317 Frequency = TransferRateValue * TimeValue/10;
318
319 //Calculate Clock divider value to program in MMCHS_SYSCTL[CLKD] field.
320 *ClockFrequencySelect = ((MMC_REFERENCE_CLK/Frequency) + 1);
321
322 DEBUG ((EFI_D_INFO, "MaxDataTransferRate: 0x%x, Frequency: %d KHz, ClockFrequencySelect: %x\n", MaxDataTransferRate, Frequency/1000, *ClockFrequencySelect));
323}
324
8c6151f2 325
a3f98646 326VOID
327GetCardConfigurationData (
328 VOID
329 )
330{
331 UINTN BlockSize;
332 UINTN NumBlocks;
333 UINTN ClockFrequencySelect;
334
335 //Calculate BlockSize and Total number of blocks in the detected card.
336 GetBlockInformation(&BlockSize, &NumBlocks);
8c6151f2 337 gCardInfo.BlockSize = BlockSize;
338 gCardInfo.NumBlocks = NumBlocks;
a3f98646 339
340 //Calculate Card clock divider value.
341 CalculateCardCLKD(&ClockFrequencySelect);
8c6151f2 342 gCardInfo.ClockFrequencySelect = ClockFrequencySelect;
a3f98646 343}
344
8c6151f2 345
a3f98646 346EFI_STATUS
347InitializeMMCHS (
348 VOID
349 )
350{
351 UINT8 Data = 0;
352 EFI_STATUS Status;
353
354 //Select Device group to belong to P1 device group in Power IC.
355 Data = DEV_GRP_P1;
8c6151f2 356 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEV_GRP), 1, &Data);
a3f98646 357 ASSERT_EFI_ERROR(Status);
358
359 //Configure voltage regulator for MMC1 in Power IC to output 3.0 voltage.
360 Data = VSEL_3_00V;
8c6151f2 361 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEDICATED_REG), 1, &Data);
a3f98646 362 ASSERT_EFI_ERROR(Status);
363
364 //After ramping up voltage, set VDDS stable bit to indicate that voltage level is stable.
43263288 365 MmioOr32 (CONTROL_PBIAS_LITE, (PBIASLITEVMODE0 | PBIASLITEPWRDNZ0 | PBIASSPEEDCTRL0 | PBIASLITEVMODE1 | PBIASLITEWRDNZ1));
a3f98646 366
8c6151f2 367 // Enable WP GPIO
368 MmioAndThenOr32 (GPIO1_BASE + GPIO_OE, ~BIT23, BIT23);
a3f98646 369
8c6151f2 370 // Enable Card Detect
371 Data = CARD_DETECT_ENABLE;
372 gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, TPS65950_GPIO_CTRL), 1, &Data);
a3f98646 373
a3f98646 374
375 return Status;
376}
377
8c6151f2 378
a3f98646 379EFI_STATUS
380PerformCardIdenfication (
381 VOID
382 )
383{
384 EFI_STATUS Status;
385 UINTN CmdArgument = 0;
386 UINTN Response = 0;
387 UINTN RetryCount = 0;
388 BOOLEAN SDCmd8Supported = FALSE;
389
390 //Enable interrupts.
8c6151f2 391 MmioWrite32 (MMCHS_IE, (BADA_EN | CERR_EN | DEB_EN | DCRC_EN | DTO_EN | CIE_EN |
a3f98646 392 CEB_EN | CCRC_EN | CTO_EN | BRR_EN | BWR_EN | TC_EN | CC_EN));
393
394 //Controller INIT procedure start.
43263288 395 MmioOr32 (MMCHS_CON, INIT);
026e30c4 396 MmioWrite32 (MMCHS_CMD, 0x00000000);
43263288 397 while (!(MmioRead32 (MMCHS_STAT) & CC));
a3f98646 398
399 //Wait for 1 ms
400 gBS->Stall(1000);
401
402 //Set CC bit to 0x1 to clear the flag
43263288 403 MmioOr32 (MMCHS_STAT, CC);
a3f98646 404
405 //Retry INIT procedure.
026e30c4 406 MmioWrite32 (MMCHS_CMD, 0x00000000);
43263288 407 while (!(MmioRead32 (MMCHS_STAT) & CC));
a3f98646 408
409 //End initialization sequence
8c6151f2 410 MmioAnd32 (MMCHS_CON, ~INIT);
a3f98646 411
43263288 412 MmioOr32 (MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_ON));
a3f98646 413
414 //Change clock frequency to 400KHz to fit protocol
415 UpdateMMCHSClkFrequency(CLKD_400KHZ);
416
43263288 417 MmioOr32 (MMCHS_CON, OD);
a3f98646 418
419 //Send CMD0 command.
8c6151f2 420 Status = SendCmd (CMD0, CMD0_INT_EN, CmdArgument);
a3f98646 421 if (EFI_ERROR(Status)) {
422 DEBUG ((EFI_D_ERROR, "Cmd0 fails.\n"));
423 return Status;
424 }
425
43263288 426 DEBUG ((EFI_D_INFO, "CMD0 response: %x\n", MmioRead32 (MMCHS_RSP10)));
a3f98646 427
428 //Send CMD5 command.
8c6151f2 429 Status = SendCmd (CMD5, CMD5_INT_EN, CmdArgument);
a3f98646 430 if (Status == EFI_SUCCESS) {
431 DEBUG ((EFI_D_ERROR, "CMD5 Success. SDIO card. Follow SDIO card specification.\n"));
43263288 432 DEBUG ((EFI_D_INFO, "CMD5 response: %x\n", MmioRead32 (MMCHS_RSP10)));
a3f98646 433 //NOTE: Returning unsupported error for now. Need to implement SDIO specification.
434 return EFI_UNSUPPORTED;
435 } else {
436 DEBUG ((EFI_D_INFO, "CMD5 fails. Not an SDIO card.\n"));
437 }
438
43263288 439 MmioOr32 (MMCHS_SYSCTL, SRC);
a3f98646 440 gBS->Stall(1000);
43263288 441 while ((MmioRead32 (MMCHS_SYSCTL) & SRC));
a3f98646 442
443 //Send CMD8 command. (New v2.00 command for Voltage check)
444 //Only 2.7V - 3.6V is supported for SD2.0, only SD 2.0 card can pass.
445 //MMC & SD1.1 card will fail this command.
446 CmdArgument = CMD8_ARG;
8c6151f2 447 Status = SendCmd (CMD8, CMD8_INT_EN, CmdArgument);
a3f98646 448 if (Status == EFI_SUCCESS) {
43263288 449 Response = MmioRead32 (MMCHS_RSP10);
a3f98646 450 DEBUG ((EFI_D_INFO, "CMD8 success. CMD8 response: %x\n", Response));
451 if (Response != CmdArgument) {
452 return EFI_DEVICE_ERROR;
453 }
454 DEBUG ((EFI_D_INFO, "Card is SD2.0\n"));
455 SDCmd8Supported = TRUE; //Supports high capacity.
456 } else {
457 DEBUG ((EFI_D_INFO, "CMD8 fails. Not an SD2.0 card.\n"));
458 }
459
43263288 460 MmioOr32 (MMCHS_SYSCTL, SRC);
a3f98646 461 gBS->Stall(1000);
43263288 462 while ((MmioRead32 (MMCHS_SYSCTL) & SRC));
a3f98646 463
464 //Poll till card is busy
465 while (RetryCount < MAX_RETRY_COUNT) {
466 //Send CMD55 command.
467 CmdArgument = 0;
8c6151f2 468 Status = SendCmd (CMD55, CMD55_INT_EN, CmdArgument);
a3f98646 469 if (Status == EFI_SUCCESS) {
43263288 470 DEBUG ((EFI_D_INFO, "CMD55 success. CMD55 response: %x\n", MmioRead32 (MMCHS_RSP10)));
8c6151f2 471 gCardInfo.CardType = SD_CARD;
a3f98646 472 } else {
473 DEBUG ((EFI_D_INFO, "CMD55 fails.\n"));
8c6151f2 474 gCardInfo.CardType = MMC_CARD;
a3f98646 475 }
476
477 //Send appropriate command for the card type which got detected.
8c6151f2 478 if (gCardInfo.CardType == SD_CARD) {
479 CmdArgument = ((UINTN *) &(gCardInfo.OCRData))[0];
a3f98646 480
481 //Set HCS bit.
482 if (SDCmd8Supported) {
483 CmdArgument |= HCS;
484 }
485
8c6151f2 486 Status = SendCmd (ACMD41, ACMD41_INT_EN, CmdArgument);
a3f98646 487 if (EFI_ERROR(Status)) {
488 DEBUG ((EFI_D_INFO, "ACMD41 fails.\n"));
489 return Status;
490 }
8c6151f2 491 ((UINT32 *) &(gCardInfo.OCRData))[0] = MmioRead32 (MMCHS_RSP10);
492 DEBUG ((EFI_D_INFO, "SD card detected. ACMD41 OCR: %x\n", ((UINT32 *) &(gCardInfo.OCRData))[0]));
493 } else if (gCardInfo.CardType == MMC_CARD) {
a3f98646 494 CmdArgument = 0;
8c6151f2 495 Status = SendCmd (CMD1, CMD1_INT_EN, CmdArgument);
a3f98646 496 if (EFI_ERROR(Status)) {
497 DEBUG ((EFI_D_INFO, "CMD1 fails.\n"));
498 return Status;
499 }
43263288 500 Response = MmioRead32 (MMCHS_RSP10);
a3f98646 501 DEBUG ((EFI_D_INFO, "MMC card detected.. CMD1 response: %x\n", Response));
502
503 //NOTE: For now, I am skipping this since I only have an SD card.
504 //Compare card OCR and host OCR (Section 22.6.1.3.2.4)
505 return EFI_UNSUPPORTED; //For now, MMC is not supported.
506 }
507
508 //Poll the card until it is out of its power-up sequence.
8c6151f2 509 if (gCardInfo.OCRData.Busy == 1) {
a3f98646 510
511 if (SDCmd8Supported) {
8c6151f2 512 gCardInfo.CardType = SD_CARD_2;
a3f98646 513 }
514
515 //Card is ready. Check CCS (Card capacity status) bit (bit#30).
516 //SD 2.0 standard card will response with CCS 0, SD high capacity card will respond with CCS 1.
8c6151f2 517 if (gCardInfo.OCRData.AccessMode & BIT1) {
518 gCardInfo.CardType = SD_CARD_2_HIGH;
a3f98646 519 DEBUG ((EFI_D_INFO, "High capacity card.\n"));
520 } else {
521 DEBUG ((EFI_D_INFO, "Standard capacity card.\n"));
522 }
523
524 break;
525 }
526
527 gBS->Stall(1000);
528 RetryCount++;
529 }
530
531 if (RetryCount == MAX_RETRY_COUNT) {
532 DEBUG ((EFI_D_ERROR, "Timeout error. RetryCount: %d\n", RetryCount));
533 return EFI_TIMEOUT;
534 }
535
536 //Read CID data.
537 CmdArgument = 0;
8c6151f2 538 Status = SendCmd (CMD2, CMD2_INT_EN, CmdArgument);
a3f98646 539 if (EFI_ERROR(Status)) {
540 DEBUG ((EFI_D_ERROR, "CMD2 fails. Status: %x\n", Status));
541 return Status;
542 }
543
43263288 544 DEBUG ((EFI_D_INFO, "CMD2 response: %x %x %x %x\n", MmioRead32 (MMCHS_RSP10), MmioRead32 (MMCHS_RSP32), MmioRead32 (MMCHS_RSP54), MmioRead32 (MMCHS_RSP76)));
a3f98646 545
546 //Parse CID register data.
43263288 547 ParseCardCIDData(MmioRead32 (MMCHS_RSP10), MmioRead32 (MMCHS_RSP32), MmioRead32 (MMCHS_RSP54), MmioRead32 (MMCHS_RSP76));
a3f98646 548
549 //Read RCA
550 CmdArgument = 0;
8c6151f2 551 Status = SendCmd (CMD3, CMD3_INT_EN, CmdArgument);
a3f98646 552 if (EFI_ERROR(Status)) {
553 DEBUG ((EFI_D_ERROR, "CMD3 fails. Status: %x\n", Status));
554 return Status;
555 }
556
557 //Set RCA for the detected card. RCA is CMD3 response.
8c6151f2 558 gCardInfo.RCA = (MmioRead32 (MMCHS_RSP10) >> 16);
559 DEBUG ((EFI_D_INFO, "CMD3 response: RCA %x\n", gCardInfo.RCA));
a3f98646 560
561 //MMC Bus setting change after card identification.
8c6151f2 562 MmioAnd32 (MMCHS_CON, ~OD);
43263288 563 MmioOr32 (MMCHS_HCTL, SDVS_3_0_V);
a3f98646 564 UpdateMMCHSClkFrequency(CLKD_400KHZ); //Set the clock frequency to 400KHz.
565
566 return EFI_SUCCESS;
567}
568
8c6151f2 569
a3f98646 570EFI_STATUS
571GetCardSpecificData (
572 VOID
573 )
574{
575 EFI_STATUS Status;
576 UINTN CmdArgument;
577
578 //Send CMD9 to retrieve CSD.
8c6151f2 579 CmdArgument = gCardInfo.RCA << 16;
580 Status = SendCmd (CMD9, CMD9_INT_EN, CmdArgument);
a3f98646 581 if (EFI_ERROR(Status)) {
582 DEBUG ((EFI_D_ERROR, "CMD9 fails. Status: %x\n", Status));
583 return Status;
584 }
585
586 //Populate 128-bit CSD register data.
8c6151f2 587 ((UINT32 *)&(gCardInfo.CSDData))[0] = MmioRead32 (MMCHS_RSP10);
588 ((UINT32 *)&(gCardInfo.CSDData))[1] = MmioRead32 (MMCHS_RSP32);
589 ((UINT32 *)&(gCardInfo.CSDData))[2] = MmioRead32 (MMCHS_RSP54);
590 ((UINT32 *)&(gCardInfo.CSDData))[3] = MmioRead32 (MMCHS_RSP76);
a3f98646 591
43263288 592 DEBUG ((EFI_D_INFO, "CMD9 response: %x %x %x %x\n", MmioRead32 (MMCHS_RSP10), MmioRead32 (MMCHS_RSP32), MmioRead32 (MMCHS_RSP54), MmioRead32 (MMCHS_RSP76)));
a3f98646 593
594 //Calculate total number of blocks and max. data transfer rate supported by the detected card.
595 GetCardConfigurationData();
596
a3f98646 597 return Status;
598}
599
8c6151f2 600
a3f98646 601EFI_STATUS
602PerformCardConfiguration (
603 VOID
604 )
605{
606 UINTN CmdArgument = 0;
607 EFI_STATUS Status;
608
609 //Send CMD7
8c6151f2 610 CmdArgument = gCardInfo.RCA << 16;
611 Status = SendCmd (CMD7, CMD7_INT_EN, CmdArgument);
a3f98646 612 if (EFI_ERROR(Status)) {
613 DEBUG ((EFI_D_ERROR, "CMD7 fails. Status: %x\n", Status));
614 return Status;
615 }
616
2b649f74 617 if ((gCardInfo.CardType != UNKNOWN_CARD) && (gCardInfo.CardType != MMC_CARD)) {
618 // We could read SCR register, but SD Card Phys spec stats any SD Card shall
619 // set SCR.SD_BUS_WIDTHS to support 4-bit mode, so why bother?
620
621 // Send ACMD6 (application specific commands must be prefixed with CMD55)
622 Status = SendCmd (CMD55, CMD55_INT_EN, CmdArgument);
623 if (!EFI_ERROR (Status)) {
624 // set device into 4-bit data bus mode
625 Status = SendCmd (ACMD6, ACMD6_INT_EN, 0x2);
626 if (!EFI_ERROR (Status)) {
627 // Set host controler into 4-bit mode
628 MmioOr32 (MMCHS_HCTL, DTW_4_BIT);
629 DEBUG ((EFI_D_INFO, "SD Memory Card set to 4-bit mode\n"));
630 }
631 }
632 }
633
a3f98646 634 //Send CMD16 to set the block length
8c6151f2 635 CmdArgument = gCardInfo.BlockSize;
636 Status = SendCmd (CMD16, CMD16_INT_EN, CmdArgument);
a3f98646 637 if (EFI_ERROR(Status)) {
638 DEBUG ((EFI_D_ERROR, "CMD16 fails. Status: %x\n", Status));
639 return Status;
640 }
641
7f814ffd 642 //Change MMCHS clock frequency to what detected card can support.
643 UpdateMMCHSClkFrequency(gCardInfo.ClockFrequencySelect);
644
a3f98646 645 return EFI_SUCCESS;
646}
647
8c6151f2 648
a3f98646 649EFI_STATUS
8c6151f2 650ReadBlockData (
a3f98646 651 IN EFI_BLOCK_IO_PROTOCOL *This,
652 OUT VOID *Buffer
653 )
654{
655 UINTN MmcStatus;
656 UINTN *DataBuffer = Buffer;
657 UINTN DataSize = This->Media->BlockSize/4;
658 UINTN Count;
659 UINTN RetryCount = 0;
660
661 //Check controller status to make sure there is no error.
662 while (RetryCount < MAX_RETRY_COUNT) {
663 do {
664 //Read Status.
43263288 665 MmcStatus = MmioRead32 (MMCHS_STAT);
a3f98646 666 } while(MmcStatus == 0);
667
668 //Check if Buffer read ready (BRR) bit is set?
669 if (MmcStatus & BRR) {
670
671 //Clear BRR bit
43263288 672 MmioOr32 (MMCHS_STAT, BRR);
a3f98646 673
674 //Read block worth of data.
675 for (Count = 0; Count < DataSize; Count++) {
43263288 676 *DataBuffer++ = MmioRead32 (MMCHS_DATA);
a3f98646 677 }
678 break;
679 }
680 RetryCount++;
681 }
682
683 if (RetryCount == MAX_RETRY_COUNT) {
684 return EFI_TIMEOUT;
685 }
686
687 return EFI_SUCCESS;
688}
689
8c6151f2 690
a3f98646 691EFI_STATUS
8c6151f2 692WriteBlockData (
a3f98646 693 IN EFI_BLOCK_IO_PROTOCOL *This,
694 OUT VOID *Buffer
695 )
696{
697 UINTN MmcStatus;
698 UINTN *DataBuffer = Buffer;
699 UINTN DataSize = This->Media->BlockSize/4;
700 UINTN Count;
701 UINTN RetryCount = 0;
702
703 //Check controller status to make sure there is no error.
704 while (RetryCount < MAX_RETRY_COUNT) {
705 do {
706 //Read Status.
43263288 707 MmcStatus = MmioRead32 (MMCHS_STAT);
a3f98646 708 } while(MmcStatus == 0);
709
710 //Check if Buffer write ready (BWR) bit is set?
711 if (MmcStatus & BWR) {
712
713 //Clear BWR bit
43263288 714 MmioOr32 (MMCHS_STAT, BWR);
a3f98646 715
716 //Write block worth of data.
717 for (Count = 0; Count < DataSize; Count++) {
026e30c4 718 MmioWrite32 (MMCHS_DATA, *DataBuffer++);
a3f98646 719 }
720
721 break;
722 }
723 RetryCount++;
724 }
725
726 if (RetryCount == MAX_RETRY_COUNT) {
727 return EFI_TIMEOUT;
728 }
729
730 return EFI_SUCCESS;
731}
732
7f814ffd 733EFI_STATUS
734DmaBlocks (
735 IN EFI_BLOCK_IO_PROTOCOL *This,
736 IN UINTN Lba,
737 IN OUT VOID *Buffer,
738 IN UINTN BlockCount,
739 IN OPERATION_TYPE OperationType
740 )
741{
742 EFI_STATUS Status;
9f6b977f 743 UINTN DmaSize = 0;
7f814ffd 744 UINTN Cmd = 0;
745 UINTN CmdInterruptEnable;
746 UINTN CmdArgument;
747 VOID *BufferMap;
748 EFI_PHYSICAL_ADDRESS BufferAddress;
749 OMAP_DMA4 Dma4;
750 DMA_MAP_OPERATION DmaOperation;
d744b79c 751 EFI_STATUS MmcStatus;
752 UINTN RetryCount = 0;
7f814ffd 753
9f6b977f 754CpuDeadLoop ();
755 // Map passed in buffer for DMA xfer
756 DmaSize = BlockCount * This->Media->BlockSize;
757 Status = DmaMap (DmaOperation, Buffer, &DmaSize, &BufferAddress, &BufferMap);
758 if (EFI_ERROR (Status)) {
759 return Status;
760 }
761
762 ZeroMem (&DmaOperation, sizeof (DMA_MAP_OPERATION));
763 \r
764 Dma4.DataType = 2; // DMA4_CSDPi[1:0] 32-bit elements from MMCHS_DATA\r
765 Dma4.SourceEndiansim = 0; // DMA4_CSDPi[21] \r
766 Dma4.DestinationEndianism = 0; // DMA4_CSDPi[19]\r
767 Dma4.SourcePacked = 0; // DMA4_CSDPi[6]\r
768 Dma4.DestinationPacked = 0; // DMA4_CSDPi[13]\r
769 Dma4.NumberOfElementPerFrame = This->Media->BlockSize/4; // DMA4_CENi (TRM 4K is optimum value) \r
770 Dma4.NumberOfFramePerTransferBlock = BlockCount; // DMA4_CFNi \r
771 Dma4.ReadPriority = 0; // DMA4_CCRi[6] Low priority read \r
772 Dma4.WritePriority = 0; // DMA4_CCRi[23] Prefetech disabled\r
7f814ffd 773
774 //Populate the command information based on the operation type.
775 if (OperationType == READ) {
776 Cmd = CMD18; //Multiple block read
777 CmdInterruptEnable = CMD18_INT_EN;
778 DmaOperation = MapOperationBusMasterCommonBuffer;
9f6b977f 779
780 Dma4.ReadPortAccessType =0 ; // DMA4_CSDPi[8:7] Can not burst MMCHS_DATA reg\r
781 Dma4.WritePortAccessType = 3; // DMA4_CSDPi[15:14] Memory burst 16x32\r
782 Dma4.WriteMode = 1; // DMA4_CSDPi[17:16] Write posted\r
783 \r
784 Dma4.SourceStartAddress = MMCHS_DATA; // DMA4_CSSAi\r
785 Dma4.DestinationStartAddress = (UINT32)BufferAddress; // DMA4_CDSAi\r
786 Dma4.SourceElementIndex = 1; // DMA4_CSEi\r
787 Dma4.SourceFrameIndex = 0x200; // DMA4_CSFi\r
788 Dma4.DestinationElementIndex = 1; // DMA4_CDEi\r
789 Dma4.DestinationFrameIndex = 0; // DMA4_CDFi\r
790\r
791 Dma4.ReadPortAccessMode = 0; // DMA4_CCRi[13:12] Always read MMCHS_DATA\r
792 Dma4.WritePortAccessMode = 1; // DMA4_CCRi[15:14] Post increment memory address\r
793 Dma4.ReadRequestNumber = 0x1e; // DMA4_CCRi[4:0] Syncro with MMCA_DMA_RX (61) \r
794 Dma4.WriteRequestNumber = 1; // DMA4_CCRi[20:19] Syncro upper 0x3e == 62 (one based)
795
7f814ffd 796 } else if (OperationType == WRITE) {
797 Cmd = CMD25; //Multiple block write
798 CmdInterruptEnable = CMD25_INT_EN;
799 DmaOperation = MapOperationBusMasterRead;
7f814ffd 800
9f6b977f 801 Dma4.ReadPortAccessType = 3; // DMA4_CSDPi[8:7] Memory burst 16x32\r
802 Dma4.WritePortAccessType = 0; // DMA4_CSDPi[15:14] Can not burst MMCHS_DATA reg\r
803 Dma4.WriteMode = 1; // DMA4_CSDPi[17:16] Write posted ???\r
804 \r
805 Dma4.SourceStartAddress = (UINT32)BufferAddress; // DMA4_CSSAi\r
806 Dma4.DestinationStartAddress = MMCHS_DATA; // DMA4_CDSAi\r
807 Dma4.SourceElementIndex = 1; // DMA4_CSEi\r
808 Dma4.SourceFrameIndex = 0x200; // DMA4_CSFi\r
809 Dma4.DestinationElementIndex = 1; // DMA4_CDEi\r
810 Dma4.DestinationFrameIndex = 0; // DMA4_CDFi\r
811\r
812 Dma4.ReadPortAccessMode = 1; // DMA4_CCRi[13:12] Post increment memory address\r
813 Dma4.WritePortAccessMode = 0; // DMA4_CCRi[15:14] Always write MMCHS_DATA\r
814 Dma4.ReadRequestNumber = 0x1d; // DMA4_CCRi[4:0] Syncro with MMCA_DMA_TX (60) \r
815 Dma4.WriteRequestNumber = 1; // DMA4_CCRi[20:19] Syncro upper 0x3d == 61 (one based)
7f814ffd 816
7f814ffd 817 } else {
9f6b977f 818 return EFI_INVALID_PARAMETER;
7f814ffd 819 }
9f6b977f 820
7f814ffd 821
822 EnableDmaChannel (2, &Dma4);
823
824
825 //Set command argument based on the card access mode (Byte mode or Block mode)
826 if (gCardInfo.OCRData.AccessMode & BIT1) {
827 CmdArgument = Lba;
828 } else {
829 CmdArgument = Lba * This->Media->BlockSize;
830 }
831
832 //Send Command.
833 Status = SendCmd (Cmd, CmdInterruptEnable, CmdArgument);
834 if (EFI_ERROR (Status)) {
835 DEBUG ((EFI_D_ERROR, "CMD fails. Status: %x\n", Status));
836 return Status;
837 }
838
d744b79c 839 //Check for the Transfer completion.
840 while (RetryCount < MAX_RETRY_COUNT) {
841 //Read Status
842 do {
843 MmcStatus = MmioRead32 (MMCHS_STAT);
844 } while (MmcStatus == 0);
845
846 //Check if Transfer complete (TC) bit is set?
847 if (MmcStatus & TC) {
848 break;
849 } else {
850 DEBUG ((EFI_D_ERROR, "MmcStatus for TC: %x\n", MmcStatus));
851 //Check if DEB, DCRC or DTO interrupt occured.
852 if ((MmcStatus & DEB) | (MmcStatus & DCRC) | (MmcStatus & DTO)) {
853 //There was an error during the data transfer.
854
855 //Set SRD bit to 1 and wait until it return to 0x0.
856 MmioOr32 (MMCHS_SYSCTL, SRD);
857 while((MmioRead32 (MMCHS_SYSCTL) & SRD) != 0x0);
858
859 DisableDmaChannel (2, DMA4_CSR_BLOCK, DMA4_CSR_ERR);
860 DmaUnmap (BufferMap);
861 return EFI_DEVICE_ERROR;
862 }
863 }
864 RetryCount++;
865 }
866
9f6b977f 867 DisableDmaChannel (2, DMA4_CSR_BLOCK, DMA4_CSR_ERR);
7f814ffd 868 Status = DmaUnmap (BufferMap);
869
d744b79c 870 if (RetryCount == MAX_RETRY_COUNT) {
871 DEBUG ((EFI_D_ERROR, "TransferBlockData timed out.\n"));
872 return EFI_TIMEOUT;
873 }
874
7f814ffd 875 return Status;
876}
877
8c6151f2 878
a3f98646 879EFI_STATUS
7f814ffd 880TransferBlock (
881 IN EFI_BLOCK_IO_PROTOCOL *This,
882 IN UINTN Lba,
883 IN OUT VOID *Buffer,
a3f98646 884 IN OPERATION_TYPE OperationType
885 )
886{
887 EFI_STATUS Status;
888 UINTN MmcStatus;
889 UINTN RetryCount = 0;
7f814ffd 890 UINTN Cmd = 0;
891 UINTN CmdInterruptEnable = 0;
892 UINTN CmdArgument = 0;
893
894
895 //Populate the command information based on the operation type.
896 if (OperationType == READ) {
897 Cmd = CMD17; //Single block read
898 CmdInterruptEnable = CMD18_INT_EN;
899 } else if (OperationType == WRITE) {
900 Cmd = CMD24; //Single block write
901 CmdInterruptEnable = CMD24_INT_EN;
902 }
903
904 //Set command argument based on the card access mode (Byte mode or Block mode)
905 if (gCardInfo.OCRData.AccessMode & BIT1) {
906 CmdArgument = Lba;
907 } else {
908 CmdArgument = Lba * This->Media->BlockSize;
909 }
910
911 //Send Command.
912 Status = SendCmd (Cmd, CmdInterruptEnable, CmdArgument);
913 if (EFI_ERROR(Status)) {
914 DEBUG ((EFI_D_ERROR, "CMD fails. Status: %x\n", Status));
915 return Status;
916 }
a3f98646 917
918 //Read or Write data.
919 if (OperationType == READ) {
7f814ffd 920 Status = ReadBlockData (This, Buffer);
a3f98646 921 if (EFI_ERROR(Status)) {
922 DEBUG((EFI_D_ERROR, "ReadBlockData fails.\n"));
923 return Status;
924 }
925 } else if (OperationType == WRITE) {
7f814ffd 926 Status = WriteBlockData (This, Buffer);
a3f98646 927 if (EFI_ERROR(Status)) {
928 DEBUG((EFI_D_ERROR, "WriteBlockData fails.\n"));
929 return Status;
930 }
931 }
932
933 //Check for the Transfer completion.
934 while (RetryCount < MAX_RETRY_COUNT) {
935 //Read Status
936 do {
43263288 937 MmcStatus = MmioRead32 (MMCHS_STAT);
a3f98646 938 } while (MmcStatus == 0);
939
940 //Check if Transfer complete (TC) bit is set?
941 if (MmcStatus & TC) {
942 break;
943 } else {
944 DEBUG ((EFI_D_ERROR, "MmcStatus for TC: %x\n", MmcStatus));
945 //Check if DEB, DCRC or DTO interrupt occured.
946 if ((MmcStatus & DEB) | (MmcStatus & DCRC) | (MmcStatus & DTO)) {
947 //There was an error during the data transfer.
948
949 //Set SRD bit to 1 and wait until it return to 0x0.
43263288 950 MmioOr32 (MMCHS_SYSCTL, SRD);
951 while((MmioRead32 (MMCHS_SYSCTL) & SRD) != 0x0);
a3f98646 952
953 return EFI_DEVICE_ERROR;
954 }
955 }
956 RetryCount++;
957 }
958
959 if (RetryCount == MAX_RETRY_COUNT) {
960 DEBUG ((EFI_D_ERROR, "TransferBlockData timed out.\n"));
961 return EFI_TIMEOUT;
962 }
963
964 return EFI_SUCCESS;
965}
966
8c6151f2 967BOOLEAN
968CardPresent (
969 VOID
970 )
971{
972 EFI_STATUS Status;
973 UINT8 Data;
974
975 //
976 // Card detect is a GPIO0 on the TPS65950
977 //
978 Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, GPIODATAIN1), 1, &Data);
979 if (EFI_ERROR (Status)) {
980 return FALSE;
981 }
982
983 if ((Data & CARD_DETECT_BIT) == CARD_DETECT_BIT) {
984 // No Card present
985 return FALSE;
986 } else {
987 return TRUE;
988 }
989}
990
991EFI_STATUS
992DetectCard (
993 VOID
994 )
995{
996 EFI_STATUS Status;
997
998 if (!CardPresent ()) {
999 return EFI_NO_MEDIA;
1000 }
1001
1002 //Initialize MMC host controller clocks.
1003 Status = InitializeMMCHS ();
1004 if (EFI_ERROR(Status)) {
1005 DEBUG ((EFI_D_ERROR, "Initialize MMC host controller fails. Status: %x\n", Status));
1006 return Status;
1007 }
1008
1009 //Software reset of the MMCHS host controller.
1010 MmioWrite32 (MMCHS_SYSCONFIG, SOFTRESET);
1011 gBS->Stall(1000);
1012 while ((MmioRead32 (MMCHS_SYSSTATUS) & RESETDONE_MASK) != RESETDONE);
1013
1014 //Soft reset for all.
1015 MmioWrite32 (MMCHS_SYSCTL, SRA);
1016 gBS->Stall(1000);
1017 while ((MmioRead32 (MMCHS_SYSCTL) & SRA) != 0x0);
1018
1019 //Voltage capabilities initialization. Activate VS18 and VS30.
1020 MmioOr32 (MMCHS_CAPA, (VS30 | VS18));
1021
1022 //Wakeup configuration
1023 MmioOr32 (MMCHS_SYSCONFIG, ENAWAKEUP);
1024 MmioOr32 (MMCHS_HCTL, IWE);
1025
1026 //MMCHS Controller default initialization
1027 MmioOr32 (MMCHS_CON, (OD | DW8_1_4_BIT | CEATA_OFF));
1028
1029 MmioWrite32 (MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_OFF));
1030
1031 //Enable internal clock
1032 MmioOr32 (MMCHS_SYSCTL, ICE);
1033
1034 //Set the clock frequency to 80KHz.
1035 UpdateMMCHSClkFrequency (CLKD_80KHZ);
1036
1037 //Enable SD bus power.
1038 MmioOr32 (MMCHS_HCTL, (SDBP_ON));
1039
1040 //Poll till SD bus power bit is set.
1041 while ((MmioRead32 (MMCHS_HCTL) & SDBP_MASK) != SDBP_ON);
1042
1043 //Card idenfication
1044 Status = PerformCardIdenfication ();
1045 if (EFI_ERROR(Status)) {
1046 DEBUG ((EFI_D_ERROR, "No MMC/SD card detected.\n"));
1047 return Status;
1048 }
1049
1050 //Get CSD (Card specific data) for the detected card.
1051 Status = GetCardSpecificData();
1052 if (EFI_ERROR(Status)) {
1053 return Status;
1054 }
1055
1056 //Configure the card in data transfer mode.
1057 Status = PerformCardConfiguration();
1058 if (EFI_ERROR(Status)) {
1059 return Status;
1060 }
1061
1062 //Patch the Media structure.
1063 gMMCHSMedia.LastBlock = (gCardInfo.NumBlocks - 1);
1064 gMMCHSMedia.BlockSize = gCardInfo.BlockSize;
1065 gMMCHSMedia.ReadOnly = (MmioRead32 (GPIO1_BASE + GPIO_DATAIN) & BIT23) == BIT23;
1066 gMMCHSMedia.MediaPresent = TRUE;
1067 gMMCHSMedia.MediaId++;
8c6151f2 1068
7f814ffd 1069 DEBUG ((EFI_D_INFO, "SD Card Media Change on Handle 0x%08x\n", gImageHandle));
2b649f74 1070
8c6151f2 1071 return Status;
1072}
1073
9f6b977f 1074#define MAX_MMCHS_TRANSFER_SIZE 0x4000
8c6151f2 1075
a3f98646 1076EFI_STATUS
1077SdReadWrite (
1078 IN EFI_BLOCK_IO_PROTOCOL *This,
1079 IN UINTN Lba,
1080 OUT VOID *Buffer,
1081 IN UINTN BufferSize,
1082 IN OPERATION_TYPE OperationType
1083 )
1084{
8c6151f2 1085 EFI_STATUS Status = EFI_SUCCESS;
a3f98646 1086 UINTN RetryCount = 0;
7f814ffd 1087 UINTN BlockCount;
9f6b977f 1088 UINTN BytesToBeTranferedThisPass = 0;
7f814ffd 1089 UINTN BytesRemainingToBeTransfered;
8c6151f2 1090 EFI_TPL OldTpl;\r
8c6151f2 1091 BOOLEAN Update;\r
1092
8c6151f2 1093
1094 Update = FALSE;
8c6151f2 1095
1096 if (gMediaChange) {
7f814ffd 1097 Update = TRUE;
8c6151f2 1098 Status = DetectCard ();
1099 if (EFI_ERROR (Status)) {
1100 // We detected a removal
1101 gMMCHSMedia.MediaPresent = FALSE;
1102 gMMCHSMedia.LastBlock = 0;
1103 gMMCHSMedia.BlockSize = 512; // Should be zero but there is a bug in DiskIo
1104 gMMCHSMedia.ReadOnly = FALSE;
8c6151f2 1105 }
1106 gMediaChange = FALSE;
1107 } else if (!gMMCHSMedia.MediaPresent) {
1108 Status = EFI_NO_MEDIA;
1109 goto Done;
1110 }
1111
7f814ffd 1112 if (Update) {
1113 DEBUG ((EFI_D_INFO, "SD Card ReinstallProtocolInterface ()\n"));
8c6151f2 1114 gBS->ReinstallProtocolInterface (\r
1115 gImageHandle,\r
1116 &gEfiBlockIoProtocolGuid,\r
1117 &gBlockIo,\r
1118 &gBlockIo\r
1119 );\r
1120 }
1121
1122 if (EFI_ERROR (Status)) {
1123 goto Done;
1124 }
1125
7f814ffd 1126 if (Buffer == NULL) {
1127 Status = EFI_INVALID_PARAMETER;
1128 goto Done;
1129 }
1130
1131 if (Lba > This->Media->LastBlock) {
8c6151f2 1132 Status = EFI_INVALID_PARAMETER;
1133 goto Done;
1134 }
1135
1136 if ((BufferSize % This->Media->BlockSize) != 0) {
1137 Status = EFI_BAD_BUFFER_SIZE;
1138 goto Done;
1139 }
a3f98646 1140
1141 //Check if the data lines are not in use.
43263288 1142 while ((RetryCount++ < MAX_RETRY_COUNT) && ((MmioRead32 (MMCHS_PSTATE) & DATI_MASK) != DATI_ALLOWED));
a3f98646 1143 if (RetryCount == MAX_RETRY_COUNT) {
8c6151f2 1144 Status = EFI_TIMEOUT;
1145 goto Done;
a3f98646 1146 }
1147
7f814ffd 1148 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
a3f98646 1149
7f814ffd 1150 BytesRemainingToBeTransfered = BufferSize;
1151 while (BytesRemainingToBeTransfered > 0) {
a3f98646 1152
7f814ffd 1153 if (gMediaChange) {
1154 Status = EFI_NO_MEDIA;
1155 DEBUG ((EFI_D_INFO, "SdReadWrite() EFI_NO_MEDIA due to gMediaChange\n"));
1156 goto DoneRestoreTPL;
1157 }
a3f98646 1158
d744b79c 1159 // Turn OFF DMA path until it is debugged
1160 // BytesToBeTranferedThisPass = (BytesToBeTranferedThisPass >= MAX_MMCHS_TRANSFER_SIZE) ? MAX_MMCHS_TRANSFER_SIZE : BytesRemainingToBeTransfered;
7f814ffd 1161 BytesToBeTranferedThisPass = This->Media->BlockSize;
1162
1163 BlockCount = BytesToBeTranferedThisPass/This->Media->BlockSize;
1164
1165 if (BlockCount > 1) {
1166 Status = DmaBlocks (This, Lba, Buffer, BlockCount, OperationType);
1167 } else {
1168 //Transfer a block worth of data.
1169 Status = TransferBlock (This, Lba, Buffer, OperationType);
a3f98646 1170 }
1171
a3f98646 1172 if (EFI_ERROR(Status)) {
1173 DEBUG ((EFI_D_ERROR, "TransferBlockData fails. %x\n", Status));
7f814ffd 1174 goto DoneRestoreTPL;
a3f98646 1175 }
1176
7f814ffd 1177 BytesRemainingToBeTransfered -= BytesToBeTranferedThisPass;
1178 Lba += BlockCount;
a3f98646 1179 Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
a3f98646 1180 }
1181
7f814ffd 1182DoneRestoreTPL:\r
8c6151f2 1183 gBS->RestoreTPL (OldTpl);\r
7f814ffd 1184Done:\r
8c6151f2 1185 return Status;\r
a3f98646 1186}
1187
8c6151f2 1188
1189/**\r
1190 Reset the Block Device.\r
1191\r
1192 @param This Indicates a pointer to the calling context.\r
1193 @param ExtendedVerification Driver may perform diagnostics on reset.\r
1194\r
1195 @retval EFI_SUCCESS The device was reset.\r
1196 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
1197 not be reset.\r
1198\r
1199**/
a3f98646 1200EFI_STATUS
1201EFIAPI
1202MMCHSReset (
1203 IN EFI_BLOCK_IO_PROTOCOL *This,
1204 IN BOOLEAN ExtendedVerification
1205 )
1206{
8c6151f2 1207 return EFI_SUCCESS;
a3f98646 1208}
1209
8c6151f2 1210
1211/**\r
1212 Read BufferSize bytes from Lba into Buffer.\r
1213\r
1214 @param This Indicates a pointer to the calling context.\r
1215 @param MediaId Id of the media, changes every time the media is replaced.\r
1216 @param Lba The starting Logical Block Address to read from\r
1217 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
1218 @param Buffer A pointer to the destination buffer for the data. The caller is\r
1219 responsible for either having implicit or explicit ownership of the buffer.\r
1220\r
1221 @retval EFI_SUCCESS The data was read correctly from the device.\r
1222 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
1223 @retval EFI_NO_MEDIA There is no media in the device.\r
1224 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.\r
1225 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
1226 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, \r
1227 or the buffer is not on proper alignment.\r
1228EFI_STATUS
1229
1230**/
a3f98646 1231EFI_STATUS
1232EFIAPI
1233MMCHSReadBlocks (
1234 IN EFI_BLOCK_IO_PROTOCOL *This,
1235 IN UINT32 MediaId,
1236 IN EFI_LBA Lba,
1237 IN UINTN BufferSize,
1238 OUT VOID *Buffer
1239 )
1240{
1241 EFI_STATUS Status;
1242
a3f98646 1243 //Perform Read operation.
8c6151f2 1244 Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, READ);
a3f98646 1245
8c6151f2 1246 return Status;\r
a3f98646 1247}
1248
8c6151f2 1249
1250/**\r
1251 Write BufferSize bytes from Lba into Buffer.\r
1252\r
1253 @param This Indicates a pointer to the calling context.\r
1254 @param MediaId The media ID that the write request is for.\r
1255 @param Lba The starting logical block address to be written. The caller is\r
1256 responsible for writing to only legitimate locations.\r
1257 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
1258 @param Buffer A pointer to the source buffer for the data.\r
1259\r
1260 @retval EFI_SUCCESS The data was written correctly to the device.\r
1261 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
1262 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
1263 @retval EFI_NO_MEDIA There is no media in the device.\r
1264 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.\r
1265 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
1266 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, \r
1267 or the buffer is not on proper alignment.\r
1268\r
1269**/
a3f98646 1270EFI_STATUS
1271EFIAPI
1272MMCHSWriteBlocks (
1273 IN EFI_BLOCK_IO_PROTOCOL *This,
1274 IN UINT32 MediaId,
1275 IN EFI_LBA Lba,
1276 IN UINTN BufferSize,
1277 IN VOID *Buffer
1278 )
1279{
8c6151f2 1280 EFI_STATUS Status;
a3f98646 1281
1282 //Perform write operation.
8c6151f2 1283 Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, WRITE);
1284\r
1285 return Status;\r
a3f98646 1286}
1287
8c6151f2 1288
1289/**\r
1290 Flush the Block Device.\r
1291\r
1292 @param This Indicates a pointer to the calling context.\r
1293\r
1294 @retval EFI_SUCCESS All outstanding data was written to the device\r
1295 @retval EFI_DEVICE_ERROR The device reported an error while writting back the data\r
1296 @retval EFI_NO_MEDIA There is no media in the device.\r
1297\r
1298**/
a3f98646 1299EFI_STATUS
1300EFIAPI
1301MMCHSFlushBlocks (
1302 IN EFI_BLOCK_IO_PROTOCOL *This
1303 )
1304{
1305 return EFI_SUCCESS;
1306}
1307
8c6151f2 1308
1309EFI_BLOCK_IO_PROTOCOL gBlockIo = {
a3f98646 1310 EFI_BLOCK_IO_INTERFACE_REVISION, // Revision
8c6151f2 1311 &gMMCHSMedia, // *Media
a3f98646 1312 MMCHSReset, // Reset
1313 MMCHSReadBlocks, // ReadBlocks
1314 MMCHSWriteBlocks, // WriteBlocks
1315 MMCHSFlushBlocks // FlushBlocks
1316};
1317
8c6151f2 1318
1319/**\r
1320 Timer callback to convert card present hardware into a boolean that indicates\r
1321 a media change event has happened. If you just check the GPIO you could see \r
1322 card 1 and then check again after card 1 was removed and card 2 was inserted\r
1323 and you would still see media present. Thus you need the timer tick to catch\r
1324 the toggle event.\r
1325\r
1326 @param Event Event whose notification function is being invoked.\r
1327 @param Context The pointer to the notification function's context,\r
1328 which is implementation-dependent. Not used.\r
1329\r
1330**/
1331VOID
1332EFIAPI
1333TimerCallback (
1334 IN EFI_EVENT Event,
1335 IN VOID *Context
1336 )
1337{
1338 BOOLEAN Present;
1339
1340 Present = CardPresent ();
1341 if (gMMCHSMedia.MediaPresent) {
1342 if (!Present && !gMediaChange) {
1343 gMediaChange = TRUE;
1344 }
1345 } else {
1346 if (Present && !gMediaChange) {
1347 gMediaChange = TRUE;
1348 }
1349 }
1350}
1351
1352
a3f98646 1353EFI_STATUS
8c6151f2 1354EFIAPI
a3f98646 1355MMCHSInitialize (
1356 IN EFI_HANDLE ImageHandle,
1357 IN EFI_SYSTEM_TABLE *SystemTable
1358 )
1359{
1360 EFI_STATUS Status;
1361
8c6151f2 1362 Status = gBS->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);
a3f98646 1363 ASSERT_EFI_ERROR(Status);
1364
8c6151f2 1365 ZeroMem (&gCardInfo, sizeof (CARD_INFO));
7f814ffd 1366
8c6151f2 1367 Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, TimerCallback, NULL, &gTimerEvent);
1368 ASSERT_EFI_ERROR (Status);
1369
9f6b977f 1370 Status = gBS->SetTimer (gTimerEvent, TimerPeriodic, FixedPcdGet32 (PcdMmchsTimerFreq100NanoSeconds));
8c6151f2 1371 ASSERT_EFI_ERROR (Status);
a3f98646 1372
1373 //Publish BlockIO.
8c6151f2 1374 Status = gBS->InstallMultipleProtocolInterfaces (
1375 &ImageHandle,
1376 &gEfiBlockIoProtocolGuid, &gBlockIo,
1377 &gEfiDevicePathProtocolGuid, &gMmcHsDevicePath,
1378 NULL
1379 );
a3f98646 1380 return Status;
1381}