]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - Omap35xxPkg/MmcHostDxe/MmcHostDxe.c
Omap35xxPkg/Library/RealTimeClockLib: Add RTC Support
[mirror_edk2.git] / Omap35xxPkg / MmcHostDxe / MmcHostDxe.c
... / ...
CommitLineData
1/** @file
2*
3* Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
4* Copyright (c) 2011, ARM Limited. All rights reserved.
5*
6* This program and the accompanying materials
7* are licensed and made available under the terms and conditions of the BSD License
8* which accompanies this distribution. The full text of the license may be found at
9* http://opensource.org/licenses/bsd-license.php
10*
11* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13*
14**/
15
16#include "MmcHostDxe.h"
17
18EMBEDDED_EXTERNAL_DEVICE *gTPS65950;
19UINT8 MaxDataTransferRate = 0;
20UINT32 Rca = 0;
21BOOLEAN BitModeSet = FALSE;
22
23
24typedef struct {
25 VENDOR_DEVICE_PATH Mmc;
26 EFI_DEVICE_PATH End;
27} MMCHS_DEVICE_PATH;
28
29MMCHS_DEVICE_PATH gMMCDevicePath = {
30 {
31 HARDWARE_DEVICE_PATH,
32 HW_VENDOR_DP,
33 (UINT8)(sizeof(VENDOR_DEVICE_PATH)),
34 (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8),
35 0xb615f1f5, 0x5088, 0x43cd, 0x80, 0x9c, 0xa1, 0x6e, 0x52, 0x48, 0x7d, 0x00
36 },
37 {
38 END_DEVICE_PATH_TYPE,
39 END_ENTIRE_DEVICE_PATH_SUBTYPE,
40 sizeof (EFI_DEVICE_PATH_PROTOCOL),
41 0
42 }
43};
44
45BOOLEAN
46IgnoreCommand (
47 UINT32 Command
48 )
49{
50 switch(Command) {
51 case MMC_CMD12:
52 return TRUE;
53 case MMC_CMD13:
54 return TRUE;
55 default:
56 return FALSE;
57 }
58}
59
60UINT32
61TranslateCommand (
62 UINT32 Command
63 )
64{
65 UINT32 Translation;
66
67 switch(Command) {
68 case MMC_CMD2:
69 Translation = CMD2;
70 break;
71 case MMC_CMD3:
72 Translation = CMD3;
73 break;
74 /*case MMC_CMD6:
75 Translation = CMD6;
76 break;*/
77 case MMC_CMD7:
78 Translation = CMD7;
79 break;
80 case MMC_CMD8:
81 Translation = CMD8;
82 break;
83 case MMC_CMD9:
84 Translation = CMD9;
85 break;
86 /*case MMC_CMD12:
87 Translation = CMD12;
88 break;
89 case MMC_CMD13:
90 Translation = CMD13;
91 break;*/
92 case MMC_CMD16:
93 Translation = CMD16;
94 break;
95 case MMC_CMD17:
96 Translation = 0x113A0014;//CMD17;
97 break;
98 case MMC_CMD24:
99 Translation = CMD24 | 4;
100 break;
101 case MMC_CMD55:
102 Translation = CMD55;
103 break;
104 case MMC_ACMD41:
105 Translation = ACMD41;
106 break;
107 default:
108 Translation = Command;
109 }
110
111 return Translation;
112}
113
114VOID
115CalculateCardCLKD (
116 UINTN *ClockFrequencySelect
117 )
118{
119 DEBUG((EFI_D_ERROR, "CalculateCardCLKD()\n"));
120 UINTN TransferRateValue = 0;
121 UINTN TimeValue = 0 ;
122 UINTN Frequency = 0;
123
124 // For SD Cards we would need to send CMD6 to set
125 // speeds abouve 25MHz. High Speed mode 50 MHz and up
126
127 //Calculate Transfer rate unit (Bits 2:0 of TRAN_SPEED)
128 switch (MaxDataTransferRate & 0x7) { // 2
129 case 0:
130 TransferRateValue = 100 * 1000;
131 break;
132
133 case 1:
134 TransferRateValue = 1 * 1000 * 1000;
135 break;
136
137 case 2:
138 TransferRateValue = 10 * 1000 * 1000;
139 break;
140
141 case 3:
142 TransferRateValue = 100 * 1000 * 1000;
143 break;
144
145 default:
146 DEBUG((EFI_D_ERROR, "Invalid parameter.\n"));
147 ASSERT(FALSE);
148 }
149
150 //Calculate Time value (Bits 6:3 of TRAN_SPEED)
151 switch ((MaxDataTransferRate >> 3) & 0xF) { // 6
152 case 1:
153 TimeValue = 10;
154 break;
155
156 case 2:
157 TimeValue = 12;
158 break;
159
160 case 3:
161 TimeValue = 13;
162 break;
163
164 case 4:
165 TimeValue = 15;
166 break;
167
168 case 5:
169 TimeValue = 20;
170 break;
171
172 case 6:
173 TimeValue = 25;
174 break;
175
176 case 7:
177 TimeValue = 30;
178 break;
179
180 case 8:
181 TimeValue = 35;
182 break;
183
184 case 9:
185 TimeValue = 40;
186 break;
187
188 case 10:
189 TimeValue = 45;
190 break;
191
192 case 11:
193 TimeValue = 50;
194 break;
195
196 case 12:
197 TimeValue = 55;
198 break;
199
200 case 13:
201 TimeValue = 60;
202 break;
203
204 case 14:
205 TimeValue = 70;
206 break;
207
208 case 15:
209 TimeValue = 80;
210 break;
211
212 default:
213 DEBUG((EFI_D_ERROR, "Invalid parameter.\n"));
214 ASSERT(FALSE);
215 }
216
217 Frequency = TransferRateValue * TimeValue/10;
218
219 //Calculate Clock divider value to program in MMCHS_SYSCTL[CLKD] field.
220 *ClockFrequencySelect = ((MMC_REFERENCE_CLK/Frequency) + 1);
221
222 DEBUG ((EFI_D_INFO, "MaxDataTransferRate: 0x%x, Frequency: %d KHz, ClockFrequencySelect: %x\n", MaxDataTransferRate, Frequency/1000, *ClockFrequencySelect));
223}
224
225VOID
226UpdateMMCHSClkFrequency (
227 UINTN NewCLKD
228 )
229{
230 DEBUG((EFI_D_ERROR, "UpdateMMCHSClkFrequency()\n"));
231 //Set Clock enable to 0x0 to not provide the clock to the card
232 MmioAnd32 (MMCHS_SYSCTL, ~CEN);
233
234 //Set new clock frequency.
235 MmioAndThenOr32 (MMCHS_SYSCTL, ~CLKD_MASK, NewCLKD << 6);
236
237 //Poll till Internal Clock Stable
238 while ((MmioRead32 (MMCHS_SYSCTL) & ICS_MASK) != ICS);
239
240 //Set Clock enable to 0x1 to provide the clock to the card
241 MmioOr32 (MMCHS_SYSCTL, CEN);
242}
243
244EFI_STATUS
245InitializeMMCHS (
246 VOID
247 )
248{
249 DEBUG((EFI_D_ERROR, "InitializeMMCHS()\n"));
250 UINT8 Data = 0;
251 EFI_STATUS Status;
252
253 //Select Device group to belong to P1 device group in Power IC.
254 Data = DEV_GRP_P1;
255 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEV_GRP), 1, &Data);
256 ASSERT_EFI_ERROR(Status);
257
258 //Configure voltage regulator for MMC1 in Power IC to output 3.0 voltage.
259 Data = VSEL_3_00V;
260 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEDICATED_REG), 1, &Data);
261 ASSERT_EFI_ERROR(Status);
262
263 //After ramping up voltage, set VDDS stable bit to indicate that voltage level is stable.
264 MmioOr32 (CONTROL_PBIAS_LITE, (PBIASLITEVMODE0 | PBIASLITEPWRDNZ0 | PBIASSPEEDCTRL0 | PBIASLITEVMODE1 | PBIASLITEWRDNZ1));
265
266 // Enable WP GPIO
267 MmioAndThenOr32 (GPIO1_BASE + GPIO_OE, ~BIT23, BIT23);
268
269 // Enable Card Detect
270 Data = CARD_DETECT_ENABLE;
271 gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, TPS65950_GPIO_CTRL), 1, &Data);
272
273
274 return Status;
275}
276
277BOOLEAN
278MMCIsCardPresent (
279 VOID
280 )
281{
282 //DEBUG((EFI_D_ERROR, "MMCIsCardPresent()\n"));
283 EFI_STATUS Status;
284 UINT8 Data;
285
286 //
287 // Card detect is a GPIO0 on the TPS65950
288 //
289 Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID2, GPIODATAIN1), 1, &Data);
290 if (EFI_ERROR (Status)) {
291 return FALSE;
292 }
293
294 return !(Data & CARD_DETECT_BIT);
295}
296
297BOOLEAN
298MMCIsReadOnly (
299 VOID
300 )
301{
302 /* Note:
303 * On our BeagleBoard the SD card WP pin is always read as TRUE.
304 * Probably something wrong with GPIO configuration.
305 * BeagleBoard-xM uses microSD cards so there is no write protect at all.
306 * Hence commenting out SD card WP pin read status.
307 */
308 //return (MmioRead32 (GPIO1_BASE + GPIO_DATAIN) & BIT23) == BIT23;
309 return 0;
310
311}
312
313// TODO
314EFI_GUID mPL180MciDevicePathGuid = EFI_CALLER_ID_GUID;
315
316EFI_STATUS
317MMCBuildDevicePath (
318 IN EFI_DEVICE_PATH_PROTOCOL **DevicePath
319 )
320{
321 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
322
323 NewDevicePathNode = CreateDeviceNode(HARDWARE_DEVICE_PATH,HW_VENDOR_DP,sizeof(VENDOR_DEVICE_PATH));
324 CopyGuid(&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid,&mPL180MciDevicePathGuid);
325 *DevicePath = NewDevicePathNode;
326 return EFI_SUCCESS;
327}
328
329EFI_STATUS
330MMCSendCommand (
331 IN MMC_CMD MmcCmd,
332 IN UINT32 Argument
333 )
334{
335 if (IgnoreCommand(MmcCmd))
336 return EFI_SUCCESS;
337
338 MmcCmd = TranslateCommand(MmcCmd);
339
340 //DEBUG((EFI_D_ERROR, "MMCSendCommand(%d)\n", MmcCmd));
341 UINTN MmcStatus;
342 UINTN RetryCount = 0;
343
344 //Check if command line is in use or not. Poll till command line is available.
345 while ((MmioRead32 (MMCHS_PSTATE) & DATI_MASK) == DATI_NOT_ALLOWED);
346
347 //Provide the block size.
348 MmioWrite32 (MMCHS_BLK, BLEN_512BYTES);
349
350 //Setting Data timeout counter value to max value.
351 MmioAndThenOr32 (MMCHS_SYSCTL, ~DTO_MASK, DTO_VAL);
352
353 //Clear Status register.
354 MmioWrite32 (MMCHS_STAT, 0xFFFFFFFF);
355
356 //Set command argument register
357 MmioWrite32 (MMCHS_ARG, Argument);
358
359 //TODO: fix this
360 //Enable interrupt enable events to occur
361 //MmioWrite32 (MMCHS_IE, CmdInterruptEnableVal);
362
363 //Send a command
364 MmioWrite32 (MMCHS_CMD, MmcCmd);
365
366 //Check for the command status.
367 while (RetryCount < MAX_RETRY_COUNT) {
368 do {
369 MmcStatus = MmioRead32 (MMCHS_STAT);
370 } while (MmcStatus == 0);
371
372 //Read status of command response
373 if ((MmcStatus & ERRI) != 0) {
374
375 //Perform soft-reset for mmci_cmd line.
376 MmioOr32 (MMCHS_SYSCTL, SRC);
377 while ((MmioRead32 (MMCHS_SYSCTL) & SRC));
378
379 //DEBUG ((EFI_D_INFO, "MmcStatus: 0x%x\n", MmcStatus));
380 return EFI_DEVICE_ERROR;
381 }
382
383 //Check if command is completed.
384 if ((MmcStatus & CC) == CC) {
385 MmioWrite32 (MMCHS_STAT, CC);
386 break;
387 }
388
389 RetryCount++;
390 }
391
392 if (RetryCount == MAX_RETRY_COUNT) {
393 DEBUG((EFI_D_ERROR, "MMCSendCommand: Timeout\n"));
394 return EFI_TIMEOUT;
395 }
396
397 return EFI_SUCCESS;
398}
399
400EFI_STATUS
401MMCNotifyState (
402 IN MMC_STATE State
403 )
404{
405 EFI_STATUS Status;
406 UINTN freqSel;
407 switch(State) {
408 case MmcInvalidState:
409 ASSERT(0);
410 break;
411 case MmcHwInitializationState:
412 BitModeSet = FALSE;
413
414 DEBUG((EFI_D_ERROR, "MMCHwInitializationState()\n"));
415 Status = InitializeMMCHS ();
416 if (EFI_ERROR(Status)) {
417 DEBUG ((EFI_D_ERROR, "Initialize MMC host controller fails. Status: %x\n", Status));
418 return Status;
419 }
420
421 //Software reset of the MMCHS host controller.
422 MmioWrite32 (MMCHS_SYSCONFIG, SOFTRESET);
423 gBS->Stall(1000);
424 while ((MmioRead32 (MMCHS_SYSSTATUS) & RESETDONE_MASK) != RESETDONE);
425
426 //Soft reset for all.
427 MmioWrite32 (MMCHS_SYSCTL, SRA);
428 gBS->Stall(1000);
429 while ((MmioRead32 (MMCHS_SYSCTL) & SRA) != 0x0);
430
431 //Voltage capabilities initialization. Activate VS18 and VS30.
432 MmioOr32 (MMCHS_CAPA, (VS30 | VS18));
433
434 //Wakeup configuration
435 MmioOr32 (MMCHS_SYSCONFIG, ENAWAKEUP);
436 MmioOr32 (MMCHS_HCTL, IWE);
437
438 //MMCHS Controller default initialization
439 MmioOr32 (MMCHS_CON, (OD | DW8_1_4_BIT | CEATA_OFF));
440
441 MmioWrite32 (MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_OFF));
442
443 //Enable internal clock
444 MmioOr32 (MMCHS_SYSCTL, ICE);
445
446 //Set the clock frequency to 80KHz.
447 UpdateMMCHSClkFrequency (CLKD_80KHZ);
448
449 //Enable SD bus power.
450 MmioOr32 (MMCHS_HCTL, (SDBP_ON));
451
452 //Poll till SD bus power bit is set.
453 while ((MmioRead32 (MMCHS_HCTL) & SDBP_MASK) != SDBP_ON);
454
455 //Enable interrupts.
456 MmioWrite32 (MMCHS_IE, (BADA_EN | CERR_EN | DEB_EN | DCRC_EN | DTO_EN | CIE_EN |
457 CEB_EN | CCRC_EN | CTO_EN | BRR_EN | BWR_EN | TC_EN | CC_EN));
458
459 //Controller INIT procedure start.
460 MmioOr32 (MMCHS_CON, INIT);
461 MmioWrite32 (MMCHS_CMD, 0x00000000);
462 while (!(MmioRead32 (MMCHS_STAT) & CC));
463
464 //Wait for 1 ms
465 gBS->Stall(1000);
466
467 //Set CC bit to 0x1 to clear the flag
468 MmioOr32 (MMCHS_STAT, CC);
469
470 //Retry INIT procedure.
471 MmioWrite32 (MMCHS_CMD, 0x00000000);
472 while (!(MmioRead32 (MMCHS_STAT) & CC));
473
474 //End initialization sequence
475 MmioAnd32 (MMCHS_CON, ~INIT);
476
477 MmioOr32 (MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_ON));
478
479 //Change clock frequency to 400KHz to fit protocol
480 UpdateMMCHSClkFrequency(CLKD_400KHZ);
481
482 MmioOr32 (MMCHS_CON, OD);
483 break;
484 case MmcIdleState:
485 break;
486 case MmcReadyState:
487 break;
488 case MmcIdentificationState:
489 break;
490 case MmcStandByState:
491 CalculateCardCLKD(&freqSel);
492 UpdateMMCHSClkFrequency(freqSel);
493 break;
494 case MmcTransferState:
495 if (!BitModeSet) {
496 Status = MMCSendCommand (CMD55, Rca << 16);
497 if (!EFI_ERROR (Status)) {
498 // set device into 4-bit data bus mode
499 Status = MMCSendCommand (ACMD6, 0x2);
500 if (!EFI_ERROR (Status)) {
501 // Set host controler into 4-bit mode
502 MmioOr32 (MMCHS_HCTL, DTW_4_BIT);
503 DEBUG ((EFI_D_INFO, "SD Memory Card set to 4-bit mode\n"));
504 BitModeSet = TRUE;
505 }
506 }
507 }
508 break;
509 case MmcSendingDataState:
510 break;
511 case MmcReceiveDataState:
512 break;
513 case MmcProgrammingState:
514 break;
515 case MmcDisconnectState:
516 default:
517 ASSERT(0);
518 }
519 return EFI_SUCCESS;
520}
521
522EFI_STATUS
523MMCReceiveResponse (
524 IN MMC_RESPONSE_TYPE Type,
525 IN UINT32* Buffer
526 )
527{
528 //DEBUG((EFI_D_ERROR, "MMCReceiveResponse()\n"));
529 if (Buffer == NULL) {
530 DEBUG((EFI_D_ERROR, "Buffer was NULL\n"));
531 return EFI_INVALID_PARAMETER;
532 }
533
534 if (Type == MMC_RESPONSE_TYPE_R2) {
535 Buffer[0] = MmioRead32 (MMCHS_RSP10);
536 Buffer[1] = MmioRead32 (MMCHS_RSP32);
537 Buffer[2] = MmioRead32 (MMCHS_RSP54);
538 Buffer[3] = MmioRead32 (MMCHS_RSP76);
539 } else {
540 Buffer[0] = MmioRead32 (MMCHS_RSP10);
541 }
542
543 if (Type == MMC_RESPONSE_TYPE_CSD) {
544 MaxDataTransferRate = Buffer[3] & 0xFF;
545 } else if (Type == MMC_RESPONSE_TYPE_RCA) {
546 Rca = Buffer[0] >> 16;
547 }
548
549 return EFI_SUCCESS;
550}
551
552EFI_STATUS
553MMCReadBlockData (
554 IN EFI_LBA Lba,
555 IN UINTN Length,
556 IN UINT32* Buffer
557 )
558{
559 //DEBUG((EFI_D_ERROR, "MMCReadBlockData(LBA: 0x%x, ", Lba));
560 //DEBUG((EFI_D_ERROR, "Length: 0x%x, ", Length));
561 //DEBUG((EFI_D_ERROR, "Buffer: 0x%x)\n", Buffer));
562 UINTN MmcStatus;
563 UINTN Count;
564 UINTN RetryCount = 0;
565
566 //Check controller status to make sure there is no error.
567 while (RetryCount < MAX_RETRY_COUNT) {
568 do {
569 //Read Status.
570 MmcStatus = MmioRead32 (MMCHS_STAT);
571 } while(MmcStatus == 0);
572
573 //Check if Buffer read ready (BRR) bit is set?
574 if (MmcStatus & BRR) {
575
576 //Clear BRR bit
577 MmioOr32 (MMCHS_STAT, BRR);
578
579 for (Count = 0; Count < Length / 4; Count++) {
580 *Buffer++ = MmioRead32(MMCHS_DATA);
581 }
582 break;
583 }
584 RetryCount++;
585 }
586
587 if (RetryCount == MAX_RETRY_COUNT) {
588 return EFI_TIMEOUT;
589 }
590
591 return EFI_SUCCESS;
592}
593
594EFI_STATUS
595MMCWriteBlockData (
596 IN EFI_LBA Lba,
597 IN UINTN Length,
598 IN UINT32* Buffer
599 )
600{
601 UINTN MmcStatus;
602 UINTN Count;
603 UINTN RetryCount = 0;
604
605 //Check controller status to make sure there is no error.
606 while (RetryCount < MAX_RETRY_COUNT) {
607 do {
608 //Read Status.
609 MmcStatus = MmioRead32 (MMCHS_STAT);
610 } while(MmcStatus == 0);
611
612 //Check if Buffer write ready (BWR) bit is set?
613 if (MmcStatus & BWR) {
614
615 //Clear BWR bit
616 MmioOr32 (MMCHS_STAT, BWR);
617
618 //Write block worth of data.
619 for (Count = 0; Count < Length / 4; Count++) {
620 MmioWrite32 (MMCHS_DATA, *Buffer++);
621 }
622
623 break;
624 }
625 RetryCount++;
626 }
627
628 if (RetryCount == MAX_RETRY_COUNT) {
629 return EFI_TIMEOUT;
630 }
631
632 return EFI_SUCCESS;
633}
634
635EFI_MMC_HOST_PROTOCOL gMMCHost = {
636 MMCIsCardPresent,
637 MMCIsReadOnly,
638 MMCBuildDevicePath,
639 MMCNotifyState,
640 MMCSendCommand,
641 MMCReceiveResponse,
642 MMCReadBlockData,
643 MMCWriteBlockData
644};
645
646EFI_STATUS
647MMCInitialize (
648 IN EFI_HANDLE ImageHandle,
649 IN EFI_SYSTEM_TABLE *SystemTable
650 )
651{
652 DEBUG((EFI_D_ERROR, "MMCInitialize()\n"));
653 EFI_STATUS Status;
654 EFI_HANDLE Handle = NULL;
655
656 Status = gBS->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);
657 ASSERT_EFI_ERROR(Status);
658
659 Status = gBS->InstallMultipleProtocolInterfaces (
660 &Handle,
661 &gEfiMmcHostProtocolGuid, &gMMCHost,
662 NULL
663 );
664 ASSERT_EFI_ERROR (Status);
665
666 return Status;
667}