]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDControllerDxe/SDController.c
QuarkSocPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / QuarkSocPkg / QuarkSouthCluster / Sdio / Dxe / SDControllerDxe / SDController.c
1 /** @file
2
3 The SD host controller driver model and HC protocol routines.
4
5 Copyright (c) 2013-2016 Intel Corporation.
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11
12
13 #include "SDController.h"
14
15
16 EFI_DRIVER_BINDING_PROTOCOL gSDControllerDriverBinding = {
17 SDControllerSupported,
18 SDControllerStart,
19 SDControllerStop,
20 0x20,
21 NULL,
22 NULL
23 };
24
25
26 EFI_SD_HOST_IO_PROTOCOL mSDHostIo = {
27 EFI_SD_HOST_IO_PROTOCOL_REVISION_01,
28 {
29 0, // HighSpeedSupport
30 0, // V18Support
31 0, // V30Support
32 0, // V33Support
33 0, // Reserved0
34 0, // BusWidth4
35 0, // BusWidth8
36 0, // Reserved1
37 0, // Reserved1
38 (512 * 1024) //BoundarySize
39 },
40 SendCommand,
41 SetClockFrequency,
42 SetBusWidth,
43 SetHostVoltage,
44 ResetSDHost,
45 EnableAutoStopCmd,
46 DetectCardAndInitHost,
47 SetBlockLength,
48 SetHighSpeedMode,
49 SetDDRMode
50 };
51
52 /**
53 Find sdclk_freq_sel and upr_sdclk_freq_sel bits
54 for Clock Control Register (CLK_CTL)Offset 2Ch when using 8bit or 10bit
55 divided clock mode.
56
57 @param BaseClockFreg Base Clock Frequency in Hz For SD Clock in the
58 Capabilities register.
59 @param TargetFreq Target Frequency in Hz to reach.
60 @param Is8BitMode True if 8-bit Divided Clock Mode else 10bit mode.
61 @param Bits sdclk_freq_sel and upr_sdclk_freq_sel bits for
62 TargetFreq.
63
64 @return EFI_SUCCESS // Bits setup.
65 @return EFI_UNSUPPORTED // Cannot divide base clock to reach target clock.
66 **/
67 EFI_STATUS
68 DividedClockModeBits (
69 IN CONST UINTN BaseClockFreg,
70 IN CONST UINTN TargetFreq,
71 IN CONST BOOLEAN Is8BitMode,
72 OUT UINT16 *Bits
73 )
74 {
75 UINTN N;
76 UINTN CurrFreq;
77
78 *Bits = 0;
79 CurrFreq = BaseClockFreg;
80 N = 0;
81 //
82 // N == 0 same for 8bit & 10bit mode i.e. BaseClockFreg of controller.
83 //
84 if (TargetFreq < CurrFreq) {
85 if (Is8BitMode) {
86 N = 1;
87 do {
88 //
89 // N values for 8bit mode when N > 0.
90 // Bit[15:8] SDCLK Frequency Select at offset 2Ch
91 // 80h - base clock divided by 256
92 // 40h - base clock divided by 128
93 // 20h - base clock divided by 64
94 // 10h - base clock divided by 32
95 // 08h - base clock divided by 16
96 // 04h - base clock divided by 8
97 // 02h - base clock divided by 4
98 // 01h - base clock divided by 2
99 //
100 CurrFreq = BaseClockFreg / (2 * N);
101 if (TargetFreq >= CurrFreq) {
102 break;
103 }
104 N *= 2;
105 if (N > V_MMIO_CLKCTL_MAX_8BIT_FREQ_SEL) {
106 return EFI_UNSUPPORTED;
107 }
108 } while (TRUE);
109 } else {
110 N = 1;
111 CurrFreq = BaseClockFreg / (2 * N);
112 //
113 // (try N = 0 or 1 first since don't want divide by 0).
114 //
115 if (TargetFreq < CurrFreq) {
116 //
117 // If still no match then calculate it for 10bit.
118 // N values for 10bit mode.
119 // N 1/2N Divided Clock (Duty 50%).
120 // from Spec "The length of divider is extended to 10 bits and all
121 // divider values shall be supported.
122 //
123 N = (BaseClockFreg / TargetFreq) / 2;
124
125 //
126 // Can only be N or N+1;
127 //
128 CurrFreq = BaseClockFreg / (2 * N);
129 if (TargetFreq < CurrFreq) {
130 N++;
131 CurrFreq = BaseClockFreg / (2 * N);
132 }
133
134 if (N > V_MMIO_CLKCTL_MAX_10BIT_FREQ_SEL) {
135 return EFI_UNSUPPORTED;
136 }
137
138 //
139 // Set upper bits of SDCLK Frequency Select (bits 7:6 of reg 0x2c).
140 //
141 *Bits |= ((UINT16) ((N >> 2) & B_MMIO_CLKCTL_UPR_SDCLK_FREQ_SEL_MASK));
142 }
143 }
144 }
145
146 //
147 // Set lower bits of SDCLK Frequency Select (bits 15:8 of reg 0x2c).
148 //
149 *Bits |= ((UINT16) ((UINT8) N) << 8);
150 DEBUG (
151 (EFI_D_INFO,
152 "SDIO:DividedClockModeBits: %dbit mode Want %dHz Got %dHz bits = %04x\r\n",
153 (Is8BitMode) ? 8 : 10,
154 TargetFreq,
155 CurrFreq,
156 (UINTN) *Bits
157 ));
158
159 return EFI_SUCCESS;
160 }
161
162 /**
163 Print type of error and command index
164
165 @param CommandIndex Command index to set the command index field of command register.
166 @param ErrorCode Error interrupt status read from host controller
167
168 @return EFI_DEVICE_ERROR
169 @return EFI_TIMEOUT
170 @return EFI_CRC_ERROR
171
172 **/
173 EFI_STATUS
174 GetErrorReason (
175 IN UINT16 CommandIndex,
176 IN UINT16 ErrorCode
177 )
178 {
179 EFI_STATUS Status;
180
181 Status = EFI_DEVICE_ERROR;
182
183 DEBUG((EFI_D_ERROR, "[%2d] -- ", CommandIndex));
184
185 if (ErrorCode & BIT0) {
186 Status = EFI_TIMEOUT;
187 DEBUG((EFI_D_ERROR, "Command Timeout Erro"));
188 }
189
190 if (ErrorCode & BIT1) {
191 Status = EFI_CRC_ERROR;
192 DEBUG((EFI_D_ERROR, "Command CRC Error"));
193 }
194
195 if (ErrorCode & BIT2) {
196 DEBUG((EFI_D_ERROR, "Command End Bit Error"));
197 }
198
199 if (ErrorCode & BIT3) {
200 DEBUG((EFI_D_ERROR, "Command Index Error"));
201 }
202 if (ErrorCode & BIT4) {
203 Status = EFI_TIMEOUT;
204 DEBUG((EFI_D_ERROR, "Data Timeout Error"));
205 }
206
207 if (ErrorCode & BIT5) {
208 Status = EFI_CRC_ERROR;
209 DEBUG((EFI_D_ERROR, "Data CRC Error"));
210 }
211
212 if (ErrorCode & BIT6) {
213 DEBUG((EFI_D_ERROR, "Data End Bit Error"));
214 }
215
216 if (ErrorCode & BIT7) {
217 DEBUG((EFI_D_ERROR, "Current Limit Error"));
218 }
219
220 if (ErrorCode & BIT8) {
221 DEBUG((EFI_D_ERROR, "Auto CMD12 Error"));
222 }
223
224 if (ErrorCode & BIT9) {
225 DEBUG((EFI_D_ERROR, "ADMA Error"));
226 }
227
228 DEBUG((EFI_D_ERROR, "\n"));
229
230 return Status;
231 }
232 /**
233 Enable/Disable High Speed transfer mode
234
235 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
236 @param Enable TRUE to Enable, FALSE to Disable
237
238 @return EFI_SUCCESS
239 **/
240 EFI_STATUS
241 EFIAPI
242 SetHighSpeedMode (
243 IN EFI_SD_HOST_IO_PROTOCOL *This,
244 IN BOOLEAN Enable
245 )
246 {
247 UINT32 Data;
248 SDHOST_DATA *SDHostData;
249 EFI_PCI_IO_PROTOCOL *PciIo;
250
251 SDHostData = SDHOST_DATA_FROM_THIS (This);
252 PciIo = SDHostData->PciIo;
253
254 PciIo->Mem.Read (
255 PciIo,
256 EfiPciIoWidthUint8,
257 0,
258 (UINT64)MMIO_HOSTCTL,
259 1,
260 &Data
261 );
262
263 if (Enable) {
264 if (PcdGetBool(PcdSdHciQuirkNoHiSpd)) {
265 DEBUG ((EFI_D_INFO, "SDIO: Quirk never set High Speed Enable bit\r\n"));
266 return EFI_SUCCESS;
267 }
268 DEBUG ((EFI_D_INFO, "Enable High Speed transfer mode ... \r\n"));
269 Data |= BIT2;
270 } else {
271 Data &= ~BIT2;
272 }
273 PciIo->Mem.Write (
274 PciIo,
275 EfiPciIoWidthUint8,
276 0,
277 (UINT64)MMIO_HOSTCTL,
278 1,
279 &Data
280 );
281 return EFI_SUCCESS;
282 }
283 EFI_STATUS
284 EFIAPI
285 SetDDRMode (
286 IN EFI_SD_HOST_IO_PROTOCOL *This,
287 IN BOOLEAN Enable
288 )
289 {
290 UINT16 Data;
291 SDHOST_DATA *SDHostData;
292 EFI_PCI_IO_PROTOCOL *PciIo;
293 SDHostData = SDHOST_DATA_FROM_THIS (This);
294 PciIo = SDHostData->PciIo;
295 PciIo->Mem.Read (
296 PciIo,
297 EfiPciIoWidthUint16,
298 0,
299 (UINT64)MMIO_HOSTCTL2,
300 1,
301 &Data
302 );
303 Data &= 0xFFF0;
304 if (Enable) {
305 Data |= 0x0004; // Enable DDR50 by default, later should enable other mode like HS200/400
306 Data |= BIT3; // Enable 1.8V Signaling
307 }
308 PciIo->Mem.Write (
309 PciIo,
310 EfiPciIoWidthUint16,
311 0,
312 (UINT64)MMIO_HOSTCTL2,
313 1,
314 &Data
315 );
316 return EFI_SUCCESS;
317 }
318 /**
319 Power on/off the LED associated with the slot
320
321 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
322 @param Enable TRUE to set LED on, FALSE to set LED off
323
324 @return EFI_SUCCESS
325 **/
326 EFI_STATUS
327 HostLEDEnable (
328 IN EFI_SD_HOST_IO_PROTOCOL *This,
329 IN BOOLEAN Enable
330 )
331 {
332 SDHOST_DATA *SDHostData;
333 EFI_PCI_IO_PROTOCOL *PciIo;
334 UINT32 Data;
335
336 SDHostData = SDHOST_DATA_FROM_THIS (This);
337 PciIo = SDHostData->PciIo;
338
339 PciIo->Mem.Read (
340 PciIo,
341 EfiPciIoWidthUint8,
342 0,
343 (UINT64)MMIO_HOSTCTL,
344 1,
345 &Data
346 );
347
348 if (Enable) {
349 //
350 //LED On
351 //
352 Data |= BIT0;
353 } else {
354 //
355 //LED Off
356 //
357 Data &= ~BIT0;
358 }
359
360 PciIo->Mem.Write (
361 PciIo,
362 EfiPciIoWidthUint8,
363 0,
364 (UINT64)MMIO_HOSTCTL,
365 1,
366 &Data
367 );
368
369 return EFI_SUCCESS;
370 }
371
372
373 /**
374 The main function used to send the command to the card inserted into the SD host slot.
375 It will assemble the arguments to set the command register and wait for the command
376 and transfer completed until timeout. Then it will read the response register to fill
377 the ResponseData.
378
379 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
380 @param CommandIndex The command index to set the command index field of command register.
381 @param Argument Command argument to set the argument field of command register.
382 @param DataType TRANSFER_TYPE, indicates no data, data in or data out.
383 @param Buffer Contains the data read from / write to the device.
384 @param BufferSize The size of the buffer.
385 @param ResponseType RESPONSE_TYPE.
386 @param TimeOut Time out value in 1 ms unit.
387 @param ResponseData Depending on the ResponseType, such as CSD or card status.
388
389 @retval EFI_SUCCESS
390 @retval EFI_INVALID_PARAMETER
391 @retval EFI_OUT_OF_RESOURCES
392 @retval EFI_TIMEOUT
393 @retval EFI_DEVICE_ERROR
394
395 **/
396
397 EFI_STATUS
398 EFIAPI
399 SendCommand (
400 IN EFI_SD_HOST_IO_PROTOCOL *This,
401 IN UINT16 CommandIndex,
402 IN UINT32 Argument,
403 IN TRANSFER_TYPE DataType,
404 IN UINT8 *Buffer, OPTIONAL
405 IN UINT32 BufferSize,
406 IN RESPONSE_TYPE ResponseType,
407 IN UINT32 TimeOut,
408 OUT UINT32 *ResponseData OPTIONAL
409 )
410 /*++
411
412 Routine Description:
413 The main function used to send the command to the card inserted into the SD host
414 slot.
415 It will assemble the arguments to set the command register and wait for the command
416 and transfer completed until timeout. Then it will read the response register to fill
417 the ResponseData
418
419 Arguments:
420 This - Pointer to EFI_SD_HOST_IO_PROTOCOL
421 CommandIndex - The command index to set the command index field of command register
422 Argument - Command argument to set the argument field of command register
423 DataType - TRANSFER_TYPE, indicates no data, data in or data out
424 Buffer - Contains the data read from / write to the device
425 BufferSize - The size of the buffer
426 ResponseType - RESPONSE_TYPE
427 TimeOut - Time out value in 1 ms unit
428 ResponseData - Depending on the ResponseType, such as CSD or card status
429
430 Returns:
431 EFI_SUCCESS
432 EFI_INVALID_PARAMETER
433 EFI_OUT_OF_RESOURCES
434 EFI_TIMEOUT
435 EFI_DEVICE_ERROR
436
437 --*/
438 {
439 EFI_STATUS Status;
440 SDHOST_DATA *SDHostData;
441 EFI_PCI_IO_PROTOCOL *PciIo;
442 UINT32 ResponseDataCount;
443 UINT32 Data;
444 UINT64 Data64;
445 UINT8 Index;
446 INTN TimeOut2;
447 BOOLEAN AutoCMD12Enable = FALSE;
448
449
450 Status = EFI_SUCCESS;
451 ResponseDataCount = 1;
452 SDHostData = SDHOST_DATA_FROM_THIS (This);
453 PciIo = SDHostData->PciIo;
454 AutoCMD12Enable = (CommandIndex & AUTO_CMD12_ENABLE) ? TRUE : FALSE;
455 CommandIndex = CommandIndex & CMD_INDEX_MASK;
456
457 if (Buffer != NULL && DataType == NoData) {
458 Status = EFI_INVALID_PARAMETER;
459 DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));
460 goto Exit;
461 }
462
463 if (((UINTN)Buffer & (This->HostCapability.BoundarySize - 1)) != (UINTN)NULL) {
464 Status = EFI_INVALID_PARAMETER;
465 DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));
466 goto Exit;
467 }
468
469 DEBUG ((EFI_D_INFO, "SendCommand: Command Index = %d \r\n", CommandIndex));
470 //
471 TimeOut2 = 1000; // 10 ms
472 do {
473 PciIo->Mem.Read (
474 PciIo,
475 EfiPciIoWidthUint32,
476 0,
477 (UINT64)MMIO_PSTATE,
478 1,
479 &Data
480 );
481 gBS->Stall (10);
482 }while ((TimeOut2-- > 0) && (Data & BIT0));
483 TimeOut2 = 1000; // 10 ms
484 do {
485 PciIo->Mem.Read (
486 PciIo,
487 EfiPciIoWidthUint32,
488 0,
489 (UINT64)MMIO_PSTATE,
490 1,
491 &Data
492 );
493 gBS->Stall (10);
494 }while ((TimeOut2-- > 0) && (Data & BIT1));
495 //Clear status bits
496 //
497 Data = 0xFFFF;
498 PciIo->Mem.Write (
499 PciIo,
500 EfiPciIoWidthUint16,
501 0,
502 (UINT64)MMIO_NINTSTS,
503 1,
504 &Data
505 );
506
507 Data = 0xFFFF;
508 PciIo->Mem.Write (
509 PciIo,
510 EfiPciIoWidthUint16,
511 0,
512 (UINT64)MMIO_ERINTSTS,
513 1,
514 &Data
515 );
516
517
518 if (Buffer != NULL) {
519 PciIo->Mem.Write (
520 PciIo,
521 EfiPciIoWidthUint32,
522 0,
523 (UINT64)MMIO_DMAADR,
524 1,
525 &Buffer
526 );
527
528 PciIo->Mem.Read (
529 PciIo,
530 EfiPciIoWidthUint16,
531 0,
532 (UINT64)MMIO_BLKSZ,
533 1,
534 &Data
535 );
536 Data &= ~(0xFFF);
537 if (BufferSize <= SDHostData->BlockLength) {
538 Data |= (BufferSize | 0x7000);
539 } else {
540 Data |= (SDHostData->BlockLength | 0x7000);
541 }
542
543
544 PciIo->Mem.Write (
545 PciIo,
546 EfiPciIoWidthUint16,
547 0,
548 (UINT64)MMIO_BLKSZ,
549 1,
550 &Data
551 );
552 if (BufferSize <= SDHostData->BlockLength) {
553 Data = 1;
554 } else {
555 Data = BufferSize / SDHostData->BlockLength;
556 }
557 PciIo->Mem.Write (
558 PciIo,
559 EfiPciIoWidthUint16,
560 0,
561 (UINT64)MMIO_BLKCNT,
562 1,
563 &Data
564 );
565
566 } else {
567 Data = 0;
568 PciIo->Mem.Write (
569 PciIo,
570 EfiPciIoWidthUint16,
571 0,
572 (UINT64)MMIO_BLKSZ,
573 1,
574 &Data
575 );
576 PciIo->Mem.Write (
577 PciIo,
578 EfiPciIoWidthUint16,
579 0,
580 (UINT64)MMIO_BLKCNT,
581 1,
582 &Data
583 );
584 }
585
586 //
587 //Argument
588 //
589 Data = Argument;
590 PciIo->Mem.Write (
591 PciIo,
592 EfiPciIoWidthUint32,
593 0,
594 (UINT64)MMIO_CMDARG,
595 1,
596 &Data
597 );
598
599
600 PciIo->Mem.Read (
601 PciIo,
602 EfiPciIoWidthUint16,
603 0,
604 (UINT64)MMIO_XFRMODE,
605 1,
606 &Data
607 );
608
609
610 DEBUG ((EFI_D_INFO, "Transfer mode read = 0x%x \r\n", (Data & 0xFFFF)));
611 //
612 //BIT0 - DMA Enable
613 //BIT2 - Auto Cmd12
614 //
615 if (DataType == InData) {
616 Data |= BIT4 | BIT0;
617 } else if (DataType == OutData){
618 Data &= ~BIT4;
619 Data |= BIT0;
620 } else {
621 Data &= ~(BIT4 | BIT0);
622 }
623
624 if (BufferSize <= SDHostData->BlockLength) {
625 Data &= ~ (BIT5 | BIT1 | BIT2);
626 Data |= BIT1; // Enable block count always
627 } else {
628 if (SDHostData->IsAutoStopCmd && AutoCMD12Enable) {
629 Data |= (BIT5 | BIT1 | BIT2);
630 } else {
631 Data |= (BIT5 | BIT1);
632 }
633 }
634
635 DEBUG ((EFI_D_INFO, "Transfer mode write = 0x%x \r\n", (Data & 0xffff)));
636 PciIo->Mem.Write (
637 PciIo,
638 EfiPciIoWidthUint16,
639 0,
640 (UINT64)MMIO_XFRMODE,
641 1,
642 &Data
643 );
644 //
645 //Command
646 //
647 //ResponseTypeSelect IndexCheck CRCCheck ResponseType
648 // 00 0 0 NoResponse
649 // 01 0 1 R2
650 // 10 0 0 R3, R4
651 // 10 1 1 R1, R5, R6, R7
652 // 11 1 1 R1b, R5b
653 //
654 switch (ResponseType) {
655 case ResponseNo:
656 Data = (CommandIndex << 8);
657 ResponseDataCount = 0;
658 break;
659
660 case ResponseR1:
661 case ResponseR5:
662 case ResponseR6:
663 case ResponseR7:
664 Data = (CommandIndex << 8) | BIT1 | BIT4| BIT3;
665 ResponseDataCount = 1;
666 break;
667
668 case ResponseR1b:
669 case ResponseR5b:
670 Data = (CommandIndex << 8) | BIT0 | BIT1 | BIT4| BIT3;
671 ResponseDataCount = 1;
672 break;
673
674 case ResponseR2:
675 Data = (CommandIndex << 8) | BIT0 | BIT3;
676 ResponseDataCount = 4;
677 break;
678
679 case ResponseR3:
680 case ResponseR4:
681 Data = (CommandIndex << 8) | BIT1;
682 ResponseDataCount = 1;
683 break;
684
685 default:
686 ASSERT (0);
687 Status = EFI_INVALID_PARAMETER;
688 DEBUG ((EFI_D_ERROR, "SendCommand: invalid parameter \r\n"));
689 goto Exit;
690 }
691
692 if (DataType != NoData) {
693 Data |= BIT5;
694 }
695
696 HostLEDEnable (This, TRUE);
697
698
699 PciIo->Mem.Write (
700 PciIo,
701 EfiPciIoWidthUint16,
702 0,
703 (UINT64)MMIO_SDCMD,
704 1,
705 &Data
706 );
707
708
709 Data = 0;
710 do {
711 PciIo->Mem.Read (
712 PciIo,
713 EfiPciIoWidthUint16,
714 0,
715 (UINT64)MMIO_ERINTSTS,
716 1,
717 &Data
718 );
719
720 if ((Data & 0x07FF) != 0) {
721 Status = GetErrorReason (CommandIndex, (UINT16)Data);
722 DEBUG ((EFI_D_ERROR, "SendCommand: Error happens \r\n"));
723 goto Exit;
724 }
725
726 PciIo->Mem.Read (
727 PciIo,
728 EfiPciIoWidthUint16,
729 0,
730 (UINT64)MMIO_NINTSTS,
731 1,
732 &Data
733 );
734
735 if ((Data & BIT0) == BIT0) {
736 //
737 //Command completed, can read response
738 //
739 if (DataType == NoData) {
740 break;
741 } else {
742 //
743 //Transfer completed
744 //
745 if ((Data & BIT1) == BIT1) {
746 break;
747 }
748 }
749 }
750
751 gBS->Stall (1 * 1000);
752
753 TimeOut --;
754
755 } while (TimeOut > 0);
756
757 if (TimeOut == 0) {
758 Status = EFI_TIMEOUT;
759 DEBUG ((EFI_D_ERROR, "SendCommand: Time out \r\n"));
760 goto Exit;
761 }
762
763 if (ResponseData != NULL) {
764 PciIo->Mem.Read (
765 PciIo,
766 EfiPciIoWidthUint32,
767 0,
768 (UINT64)MMIO_RESP,
769 ResponseDataCount,
770 ResponseData
771 );
772 if (ResponseType == ResponseR2) {
773 //
774 // Adjustment for R2 response
775 //
776 Data = 1;
777 for (Index = 0; Index < ResponseDataCount; Index++) {
778 Data64 = LShiftU64(*ResponseData, 8);
779 *ResponseData = (UINT32)((Data64 & 0xFFFFFFFF) | Data);
780 Data = (UINT32)RShiftU64 (Data64, 32);
781 ResponseData++;
782 }
783 }
784 }
785
786 Exit:
787 HostLEDEnable (This, FALSE);
788 return Status;
789 }
790
791 /**
792 Set max clock frequency of the host, the actual frequency may not be the same as MaxFrequency.
793 It depends on the max frequency the host can support, divider, and host speed mode.
794
795 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
796 @param MaxFrequency Max frequency in HZ.
797
798 @retval EFI_SUCCESS
799 @retval EFI_TIMEOUT
800
801 **/
802 EFI_STATUS
803 EFIAPI
804 SetClockFrequency (
805 IN EFI_SD_HOST_IO_PROTOCOL *This,
806 IN UINT32 MaxFrequency
807 )
808 {
809 UINT32 Data;
810 UINT16 FreqSelBits;
811 EFI_STATUS Status;
812 SDHOST_DATA *SDHostData;
813 EFI_PCI_IO_PROTOCOL *PciIo;
814 UINT32 TimeOutCount;
815 UINT32 Revision;
816
817 SDHostData = SDHOST_DATA_FROM_THIS (This);
818 PciIo = SDHostData->PciIo;
819 Data = 0;
820 PciIo->Mem.Write (
821 PciIo,
822 EfiPciIoWidthUint16,
823 0,
824 (UINT64)MMIO_CLKCTL,
825 1,
826 &Data
827 );
828
829 PciIo->Mem.Read (
830 PciIo,
831 EfiPciIoWidthUint8,
832 0,
833 (UINT64)MMIO_CTRLRVER,
834 1,
835 &Revision
836 );
837 Revision &= 0x000000FF;
838
839 Status = DividedClockModeBits (
840 SDHostData->BaseClockInMHz * 1000 * 1000,
841 MaxFrequency,
842 (Revision < SDHCI_SPEC_300),
843 &FreqSelBits
844 );
845
846 if (EFI_ERROR (Status)) {
847 //
848 // Cannot reach MaxFrequency with SDHostData->BaseClockInMHz.
849 //
850 ASSERT_EFI_ERROR (Status);
851 return Status;
852 }
853
854 Data = 0;
855
856 //
857 //Enable internal clock and Stop Clock Enable
858 //
859 Data = BIT0;
860 PciIo->Mem.Write (
861 PciIo,
862 EfiPciIoWidthUint16,
863 0,
864 (UINT64)MMIO_CLKCTL,
865 1,
866 &Data
867 );
868
869 TimeOutCount = TIME_OUT_1S;
870 do {
871 PciIo->Mem.Read (
872 PciIo,
873 EfiPciIoWidthUint16,
874 0,
875 (UINT64)MMIO_CLKCTL,
876 1,
877 &Data
878 );
879 gBS->Stall (1 * 1000);
880 TimeOutCount --;
881 if (TimeOutCount == 0) {
882 DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n"));
883 return EFI_TIMEOUT;
884 }
885 } while ((Data & BIT1) != BIT1);
886
887 DEBUG ((EFI_D_INFO, "Base Clock In MHz: %d\r\n", SDHostData->BaseClockInMHz));
888
889 Data = (BIT0 | ((UINT32) FreqSelBits));
890 DEBUG ((EFI_D_INFO, "Data write to MMIO_CLKCTL: 0x%04x \r\n", Data));
891 PciIo->Mem.Write (
892 PciIo,
893 EfiPciIoWidthUint16,
894 0,
895 (UINT64)MMIO_CLKCTL,
896 1,
897 &Data
898 );
899
900 TimeOutCount = TIME_OUT_1S;
901 do {
902 PciIo->Mem.Read (
903 PciIo,
904 EfiPciIoWidthUint16,
905 0,
906 (UINT64)MMIO_CLKCTL,
907 1,
908 &Data
909 );
910 gBS->Stall (1 * 1000);
911 TimeOutCount --;
912 if (TimeOutCount == 0) {
913 DEBUG ((EFI_D_ERROR, "SetClockFrequency: Time out \r\n"));
914 return EFI_TIMEOUT;
915 }
916 } while ((Data & BIT1) != BIT1);
917 gBS->Stall (20 * 1000);
918 Data |= BIT2;
919 PciIo->Mem.Write (
920 PciIo,
921 EfiPciIoWidthUint16,
922 0,
923 (UINT64)MMIO_CLKCTL,
924 1,
925 &Data
926 );
927
928 return EFI_SUCCESS;
929 }
930
931 /**
932 Set bus width of the host controller
933
934 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
935 @param BusWidth Bus width in 1, 4, 8 bits.
936
937 @retval EFI_SUCCESS
938 @retval EFI_INVALID_PARAMETER
939
940 **/
941 EFI_STATUS
942 EFIAPI
943 SetBusWidth (
944 IN EFI_SD_HOST_IO_PROTOCOL *This,
945 IN UINT32 BusWidth
946 )
947 {
948 SDHOST_DATA *SDHostData;
949 EFI_PCI_IO_PROTOCOL *PciIo;
950 UINT8 Data;
951
952 SDHostData = SDHOST_DATA_FROM_THIS (This);
953
954
955 if ((BusWidth != 1) && (BusWidth != 4) && (BusWidth != 8)) {
956 DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n"));
957 return EFI_INVALID_PARAMETER;
958 }
959
960 if ((SDHostData->SDHostIo.HostCapability.BusWidth8 == FALSE) && (BusWidth == 8)) {
961 DEBUG ((EFI_D_ERROR, "SetBusWidth: Invalid parameter \r\n"));
962 return EFI_INVALID_PARAMETER;
963 }
964
965 PciIo = SDHostData->PciIo;
966
967 PciIo->Mem.Read (
968 PciIo,
969 EfiPciIoWidthUint8,
970 0,
971 (UINT64)MMIO_HOSTCTL,
972 1,
973 &Data
974 );
975 //
976 // BIT5 8-bit MMC Support (MMC8):
977 // If set, IOH supports 8-bit MMC. When cleared, IOH does not support this feature
978 //
979 if (BusWidth == 8) {
980 DEBUG ((EFI_D_INFO, "Bus Width is 8-bit ... \r\n"));
981 Data |= BIT5;
982 } else if (BusWidth == 4) {
983 DEBUG ((EFI_D_INFO, "Bus Width is 4-bit ... \r\n"));
984 Data &= ~BIT5;
985 Data |= BIT1;
986 } else {
987 DEBUG ((EFI_D_INFO, "Bus Width is 1-bit ... \r\n"));
988 Data &= ~BIT5;
989 Data &= ~BIT1;
990 }
991
992 PciIo->Mem.Write (
993 PciIo,
994 EfiPciIoWidthUint8,
995 0,
996 (UINT64)MMIO_HOSTCTL,
997 1,
998 &Data
999 );
1000
1001 return EFI_SUCCESS;
1002 }
1003
1004
1005 /**
1006 Set voltage which could supported by the host controller.
1007 Support 0(Power off the host), 1.8V, 3.0V, 3.3V
1008
1009 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
1010 @param Voltage Units in 0.1 V.
1011
1012 @retval EFI_SUCCESS
1013 @retval EFI_INVALID_PARAMETER
1014
1015 **/
1016 EFI_STATUS
1017 EFIAPI
1018 SetHostVoltage (
1019 IN EFI_SD_HOST_IO_PROTOCOL *This,
1020 IN UINT32 Voltage
1021 )
1022 {
1023 SDHOST_DATA *SDHostData;
1024 EFI_PCI_IO_PROTOCOL *PciIo;
1025 UINT8 Data;
1026 EFI_STATUS Status;
1027
1028 SDHostData = SDHOST_DATA_FROM_THIS (This);
1029 PciIo = SDHostData->PciIo;
1030 Status = EFI_SUCCESS;
1031
1032 PciIo->Mem.Read (
1033 PciIo,
1034 EfiPciIoWidthUint8,
1035 0,
1036 (UINT64)MMIO_PWRCTL,
1037 1,
1038 &Data
1039 );
1040
1041 if (Voltage == 0) {
1042 //
1043 //Power Off the host
1044 //
1045 Data &= ~BIT0;
1046 } else if (Voltage <= 18 && This->HostCapability.V18Support) {
1047 //
1048 //1.8V
1049 //
1050 Data |= (BIT1 | BIT3 | BIT0);
1051 } else if (Voltage > 18 && Voltage <= 30 && This->HostCapability.V30Support) {
1052 //
1053 //3.0V
1054 //
1055 Data |= (BIT2 | BIT3 | BIT0);
1056 } else if (Voltage > 30 && Voltage <= 33 && This->HostCapability.V33Support) {
1057 //
1058 //3.3V
1059 //
1060 Data |= (BIT1 | BIT2 | BIT3 | BIT0);
1061 } else {
1062 Status = EFI_UNSUPPORTED;
1063 goto Exit;
1064 }
1065
1066 PciIo->Mem.Write (
1067 PciIo,
1068 EfiPciIoWidthUint8,
1069 0,
1070 (UINT64)MMIO_PWRCTL,
1071 1,
1072 &Data
1073 );
1074 gBS->Stall (10 * 1000);
1075
1076 Exit:
1077 return Status;
1078 }
1079
1080
1081
1082 /**
1083 Reset the host controller.
1084
1085 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
1086 @param ResetAll TRUE to reset all.
1087
1088 @retval EFI_SUCCESS
1089 @retval EFI_TIMEOUT
1090
1091 **/
1092 EFI_STATUS
1093 EFIAPI
1094 ResetSDHost (
1095 IN EFI_SD_HOST_IO_PROTOCOL *This,
1096 IN RESET_TYPE ResetType
1097 )
1098 {
1099 SDHOST_DATA *SDHostData;
1100 EFI_PCI_IO_PROTOCOL *PciIo;
1101 UINT32 Data;
1102 UINT16 ErrStatus;
1103 UINT32 Mask;
1104 UINT32 TimeOutCount;
1105 UINT16 SaveClkCtl;
1106 UINT16 ZeroClkCtl;
1107
1108 SDHostData = SDHOST_DATA_FROM_THIS (This);
1109 PciIo = SDHostData->PciIo;
1110 Mask = 0;
1111 ErrStatus = 0;
1112
1113 if (ResetType == Reset_Auto) {
1114 PciIo->Mem.Read (
1115 PciIo,
1116 EfiPciIoWidthUint16,
1117 0,
1118 (UINT64)MMIO_ERINTSTS,
1119 1,
1120 &ErrStatus
1121 );
1122 if ((ErrStatus & 0xF) != 0) {
1123 //
1124 //Command Line
1125 //
1126 Mask |= BIT1;
1127 }
1128 if ((ErrStatus & 0x70) != 0) {
1129 //
1130 //Data Line
1131 //
1132 Mask |= BIT2;
1133 }
1134 }
1135
1136
1137 if (ResetType == Reset_DAT || ResetType == Reset_DAT_CMD) {
1138 Mask |= BIT2;
1139 }
1140 if (ResetType == Reset_CMD || ResetType == Reset_DAT_CMD) {
1141 Mask |= BIT1;
1142 }
1143 if (ResetType == Reset_All) {
1144 Mask = BIT0;
1145 }
1146
1147 if (Mask == 0) {
1148 return EFI_SUCCESS;
1149 }
1150
1151 //
1152 // To improve SD stability, we zero the MMIO_CLKCTL register and
1153 // stall for 50 microseconds before resetting the controller. We
1154 // restore the register setting following the reset operation.
1155 //
1156 PciIo->Mem.Read (
1157 PciIo,
1158 EfiPciIoWidthUint16,
1159 0,
1160 (UINT64)MMIO_CLKCTL,
1161 1,
1162 &SaveClkCtl
1163 );
1164
1165 ZeroClkCtl = (UINT16) 0;
1166 PciIo->Mem.Write (
1167 PciIo,
1168 EfiPciIoWidthUint16,
1169 0,
1170 (UINT64)MMIO_CLKCTL,
1171 1,
1172 &ZeroClkCtl
1173 );
1174
1175 gBS->Stall (50);
1176
1177 //
1178 // Reset the SD host controller
1179 //
1180 PciIo->Mem.Write (
1181 PciIo,
1182 EfiPciIoWidthUint8,
1183 0,
1184 (UINT64)MMIO_SWRST,
1185 1,
1186 &Mask
1187 );
1188
1189 Data = 0;
1190 TimeOutCount = TIME_OUT_1S;
1191 do {
1192
1193 gBS->Stall (1 * 1000);
1194
1195 TimeOutCount --;
1196
1197 PciIo->Mem.Read (
1198 PciIo,
1199 EfiPciIoWidthUint8,
1200 0,
1201 (UINT64)MMIO_SWRST,
1202 1,
1203 &Data
1204 );
1205 if ((Data & Mask) == 0) {
1206 break;
1207 }
1208 } while (TimeOutCount > 0);
1209
1210 //
1211 // We now restore the MMIO_CLKCTL register which we set to 0 above.
1212 //
1213 PciIo->Mem.Write (
1214 PciIo,
1215 EfiPciIoWidthUint16,
1216 0,
1217 (UINT64)MMIO_CLKCTL,
1218 1,
1219 &SaveClkCtl
1220 );
1221
1222 if (TimeOutCount == 0) {
1223 DEBUG ((EFI_D_ERROR, "ResetSDHost: Time out \r\n"));
1224 return EFI_TIMEOUT;
1225 }
1226
1227 return EFI_SUCCESS;
1228 }
1229
1230
1231 /**
1232 Enable auto stop on the host controller.
1233
1234 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
1235 @param Enable TRUE to enable, FALSE to disable.
1236
1237 @retval EFI_SUCCESS
1238 @retval EFI_TIMEOUT
1239
1240 **/
1241 EFI_STATUS
1242 EFIAPI
1243 EnableAutoStopCmd (
1244 IN EFI_SD_HOST_IO_PROTOCOL *This,
1245 IN BOOLEAN Enable
1246 )
1247 {
1248 SDHOST_DATA *SDHostData;
1249
1250 SDHostData = SDHOST_DATA_FROM_THIS (This);
1251
1252 SDHostData->IsAutoStopCmd = Enable;
1253
1254 return EFI_SUCCESS;
1255 }
1256
1257 /**
1258 Set the Block length on the host controller.
1259
1260 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
1261 @param BlockLength card supportes block length.
1262
1263 @retval EFI_SUCCESS
1264 @retval EFI_TIMEOUT
1265
1266 **/
1267 EFI_STATUS
1268 EFIAPI
1269 SetBlockLength (
1270 IN EFI_SD_HOST_IO_PROTOCOL *This,
1271 IN UINT32 BlockLength
1272 )
1273 {
1274 SDHOST_DATA *SDHostData;
1275
1276 SDHostData = SDHOST_DATA_FROM_THIS (This);
1277
1278 DEBUG ((EFI_D_INFO, "Block length on the host controller: %d \r\n", BlockLength));
1279 SDHostData->BlockLength = BlockLength;
1280
1281 return EFI_SUCCESS;
1282 }
1283
1284
1285 /**
1286 Find whether these is a card inserted into the slot. If so init the host.
1287 If not, return EFI_NOT_FOUND.
1288
1289 @param This A pointer to the EFI_SD_HOST_IO_PROTOCOL instance.
1290
1291 @retval EFI_SUCCESS
1292 @retval EFI_NOT_FOUND
1293
1294 **/
1295 EFI_STATUS
1296 EFIAPI
1297 DetectCardAndInitHost (
1298 IN EFI_SD_HOST_IO_PROTOCOL *This
1299 )
1300 {
1301 SDHOST_DATA *SDHostData;
1302 EFI_PCI_IO_PROTOCOL *PciIo;
1303 UINT32 Data;
1304 EFI_STATUS Status;
1305 UINT8 Voltages[] = { 33, 30, 18 };
1306 UINTN Loop;
1307
1308 SDHostData = SDHOST_DATA_FROM_THIS (This);
1309 PciIo = SDHostData->PciIo;
1310 Status = EFI_NOT_FOUND;
1311
1312 Data = 0;
1313 PciIo->Mem.Read (
1314 PciIo,
1315 EfiPciIoWidthUint32,
1316 0,
1317 (UINT64)MMIO_PSTATE,
1318 1,
1319 &Data
1320 );
1321
1322 if ((Data & (BIT16 | BIT17 | BIT18)) != (BIT16 | BIT17 | BIT18)) {
1323 //
1324 // Has no card inserted
1325 //
1326 DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: No Cards \r\n"));
1327 Status = EFI_NOT_FOUND;
1328 goto Exit;
1329 }
1330 DEBUG ((EFI_D_INFO, "DetectCardAndInitHost: Find Cards \r\n"));
1331
1332 Status = EFI_NOT_FOUND;
1333 for (Loop = 0; Loop < sizeof (Voltages); Loop++) {
1334 DEBUG ((
1335 EFI_D_INFO,
1336 "DetectCardAndInitHost: SetHostVoltage %d.%dV \r\n",
1337 Voltages[Loop] / 10,
1338 Voltages[Loop] % 10
1339 ));
1340 Status = SetHostVoltage (This, Voltages[Loop]);
1341 if (EFI_ERROR (Status)) {
1342 DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [failed]\n"));
1343 } else {
1344 DEBUG ((EFI_D_INFO, "DetectCardAndInitHost set voltages: [success]\n"));
1345 break;
1346 }
1347 }
1348 if (EFI_ERROR (Status)) {
1349 DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set voltage \r\n"));
1350 goto Exit;
1351 }
1352
1353 Status = SetClockFrequency (This, FREQUENCY_OD);
1354 if (EFI_ERROR (Status)) {
1355 DEBUG ((EFI_D_ERROR, "DetectCardAndInitHost: Fail to set frequency \r\n"));
1356 goto Exit;
1357 }
1358 SetBusWidth (This, 1);
1359
1360 //
1361 //Enable normal status change
1362 //
1363
1364 Data = (BIT0 | BIT1);
1365
1366 PciIo->Mem.Write (
1367 PciIo,
1368 EfiPciIoWidthUint16,
1369 0,
1370 (UINT64)MMIO_NINTEN,
1371 1,
1372 &Data
1373 );
1374
1375 //
1376 //Enable error status change
1377 //
1378 PciIo->Mem.Read (
1379 PciIo,
1380 EfiPciIoWidthUint16,
1381 0,
1382 (UINT64)MMIO_ERINTEN,
1383 1,
1384 &Data
1385 );
1386
1387 Data |= (BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8);
1388
1389 PciIo->Mem.Write (
1390 PciIo,
1391 EfiPciIoWidthUint16,
1392 0,
1393 (UINT64)MMIO_ERINTEN,
1394 1,
1395 &Data
1396 );
1397
1398 //
1399 //Data transfer Timeout control
1400 //
1401 Data = 0x0E;
1402
1403 PciIo->Mem.Write (
1404 PciIo,
1405 EfiPciIoWidthUint8,
1406 0,
1407 (UINT64)MMIO_TOCTL,
1408 1,
1409 &Data
1410 );
1411 //
1412 //Set Default Bus width as 1 bit
1413 //
1414
1415 Exit:
1416 return Status;
1417
1418 }
1419
1420 /**
1421 Entry point for EFI drivers.
1422
1423 @param ImageHandle EFI_HANDLE.
1424 @param SystemTable EFI_SYSTEM_TABLE.
1425
1426 @retval EFI_SUCCESS Driver is successfully loaded.
1427 @return Others Failed.
1428
1429 **/
1430 EFI_STATUS
1431 EFIAPI
1432 InitializeSDController (
1433 IN EFI_HANDLE ImageHandle,
1434 IN EFI_SYSTEM_TABLE *SystemTable
1435 )
1436 {
1437 return EfiLibInstallDriverBindingComponentName2 (
1438 ImageHandle,
1439 SystemTable,
1440 &gSDControllerDriverBinding,
1441 ImageHandle,
1442 &gSDControllerName,
1443 &gSDControllerName2
1444 );
1445 }
1446
1447
1448 /**
1449 Test to see if this driver supports ControllerHandle. Any
1450 ControllerHandle that has SDHostIoProtocol installed will be supported.
1451
1452 @param This Protocol instance pointer.
1453 @param Controller Handle of device to test.
1454 @param RemainingDevicePath Not used.
1455
1456 @return EFI_SUCCESS This driver supports this device.
1457 @return EFI_UNSUPPORTED This driver does not support this device.
1458
1459 **/
1460 EFI_STATUS
1461 EFIAPI
1462 SDControllerSupported (
1463 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1464 IN EFI_HANDLE Controller,
1465 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1466 )
1467 {
1468 EFI_STATUS OpenStatus;
1469 EFI_STATUS Status;
1470 EFI_PCI_IO_PROTOCOL *PciIo;
1471 PCI_CLASSC PciClass;
1472 EFI_SD_HOST_IO_PROTOCOL *SdHostIo;
1473 Status = gBS->OpenProtocol (
1474 Controller,
1475 &gEfiSDHostIoProtocolGuid,
1476 (VOID **)&SdHostIo,
1477 This->DriverBindingHandle,
1478 Controller,
1479 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1480 );
1481 if (!EFI_ERROR (Status)) {
1482 DEBUG (( DEBUG_INFO, "SdHost controller is already started\n"));
1483 return EFI_ALREADY_STARTED;
1484 }
1485
1486 //
1487 // Test whether there is PCI IO Protocol attached on the controller handle.
1488 //
1489 OpenStatus = gBS->OpenProtocol (
1490 Controller,
1491 &gEfiPciIoProtocolGuid,
1492 (VOID **) &PciIo,
1493 This->DriverBindingHandle,
1494 Controller,
1495 EFI_OPEN_PROTOCOL_BY_DRIVER
1496 );
1497
1498 if (EFI_ERROR (OpenStatus)) {
1499 return OpenStatus;
1500 }
1501
1502 Status = PciIo->Pci.Read (
1503 PciIo,
1504 EfiPciIoWidthUint8,
1505 PCI_CLASSCODE_OFFSET,
1506 sizeof (PCI_CLASSC) / sizeof (UINT8),
1507 &PciClass
1508 );
1509
1510 if (EFI_ERROR (Status)) {
1511 Status = EFI_UNSUPPORTED;
1512 goto ON_EXIT;
1513 }
1514
1515 //
1516 // Test whether the controller belongs to SD type
1517 //
1518 if ((PciClass.BaseCode != PCI_CLASS_SYSTEM_PERIPHERAL) ||
1519 (PciClass.SubClassCode != PCI_SUBCLASS_SD_HOST_CONTROLLER) ||
1520 ((PciClass.PI != PCI_IF_STANDARD_HOST_NO_DMA) && (PciClass.PI != PCI_IF_STANDARD_HOST_SUPPORT_DMA))
1521 ) {
1522
1523 Status = EFI_UNSUPPORTED;
1524 }
1525
1526 ON_EXIT:
1527 gBS->CloseProtocol (
1528 Controller,
1529 &gEfiPciIoProtocolGuid,
1530 This->DriverBindingHandle,
1531 Controller
1532 );
1533
1534 return Status;
1535 }
1536 /**
1537 Starting the SD Host Controller Driver.
1538
1539 @param This Protocol instance pointer.
1540 @param Controller Handle of device to test.
1541 @param RemainingDevicePath Not used.
1542
1543 @retval EFI_SUCCESS This driver supports this device.
1544 @retval EFI_UNSUPPORTED This driver does not support this device.
1545 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
1546 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
1547
1548 **/
1549 EFI_STATUS
1550 EFIAPI
1551 SDControllerStart (
1552 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1553 IN EFI_HANDLE Controller,
1554 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1555 )
1556 {
1557 EFI_STATUS Status;
1558 EFI_PCI_IO_PROTOCOL *PciIo;
1559 SDHOST_DATA *SDHostData;
1560 UINT32 Data;
1561
1562
1563 SDHostData = NULL;
1564 Data = 0;
1565
1566 //
1567 // Open PCI I/O Protocol and save pointer to open protocol
1568 // in private data area.
1569 //
1570 Status = gBS->OpenProtocol (
1571 Controller,
1572 &gEfiPciIoProtocolGuid,
1573 (VOID **) &PciIo,
1574 This->DriverBindingHandle,
1575 Controller,
1576 EFI_OPEN_PROTOCOL_BY_DRIVER
1577 );
1578
1579 if (EFI_ERROR (Status)) {
1580 goto Exit;
1581 }
1582
1583 //
1584 // Enable the SD Host Controller MMIO space
1585 //
1586 Status = PciIo->Attributes (
1587 PciIo,
1588 EfiPciIoAttributeOperationEnable,
1589 EFI_PCI_DEVICE_ENABLE,
1590 NULL
1591 );
1592 if (EFI_ERROR (Status)) {
1593 Status = EFI_OUT_OF_RESOURCES;
1594 goto Exit;
1595 }
1596
1597
1598 SDHostData = (SDHOST_DATA*)AllocateZeroPool(sizeof (SDHOST_DATA));
1599 if (SDHostData == NULL) {
1600 Status = EFI_OUT_OF_RESOURCES;
1601 goto Exit;
1602 }
1603
1604 SDHostData->Signature = SDHOST_DATA_SIGNATURE;
1605 SDHostData->PciIo = PciIo;
1606
1607 CopyMem (&SDHostData->SDHostIo, &mSDHostIo, sizeof (EFI_SD_HOST_IO_PROTOCOL));
1608
1609 ResetSDHost (&SDHostData->SDHostIo, Reset_All);
1610
1611 PciIo->Mem.Read (
1612 PciIo,
1613 EfiPciIoWidthUint16,
1614 0,
1615 (UINT64)MMIO_CTRLRVER,
1616 1,
1617 &Data
1618 );
1619 SDHostData->SDHostIo.HostCapability.HostVersion = Data & 0xFF;
1620 DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: HostVersion 0x%x \r\n", SDHostData->SDHostIo.HostCapability.HostVersion));
1621
1622 PciIo->Mem.Read (
1623 PciIo,
1624 EfiPciIoWidthUint32,
1625 0,
1626 (UINT64)MMIO_CAP,
1627 1,
1628 &Data
1629 );
1630 DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: MMIO_CAP 0x%x \r\n", Data));
1631 if ((Data & BIT18) != 0) {
1632 SDHostData->SDHostIo.HostCapability.BusWidth8 = TRUE;
1633 }
1634
1635 if ((Data & BIT21) != 0) {
1636 SDHostData->SDHostIo.HostCapability.HighSpeedSupport = TRUE;
1637 }
1638
1639 if ((Data & BIT24) != 0) {
1640 SDHostData->SDHostIo.HostCapability.V33Support = TRUE;
1641 }
1642
1643 if ((Data & BIT25) != 0) {
1644 SDHostData->SDHostIo.HostCapability.V30Support = TRUE;
1645 }
1646
1647 if ((Data & BIT26) != 0) {
1648 SDHostData->SDHostIo.HostCapability.V18Support = TRUE;
1649 }
1650
1651 SDHostData->SDHostIo.HostCapability.BusWidth4 = TRUE;
1652
1653 if(SDHostData->SDHostIo.HostCapability.HostVersion < SDHCI_SPEC_300) {
1654
1655
1656
1657 SDHostData->BaseClockInMHz = (Data >> 8) & 0x3F;
1658 }
1659 else {
1660 SDHostData->BaseClockInMHz = (Data >> 8) & 0xFF;
1661
1662 }
1663
1664 SDHostData->BlockLength = 512 << ((Data >> 16) & 0x03);
1665 DEBUG ((EFI_D_INFO, "SdHostDriverBindingStart: BlockLength 0x%x \r\n", SDHostData->BlockLength));
1666 SDHostData->IsAutoStopCmd = TRUE;
1667
1668 Status = gBS->InstallProtocolInterface (
1669 &Controller,
1670 &gEfiSDHostIoProtocolGuid,
1671 EFI_NATIVE_INTERFACE,
1672 &SDHostData->SDHostIo
1673 );
1674 if (EFI_ERROR (Status)) {
1675 goto Exit;
1676 }
1677
1678 //
1679 // Install the component name protocol
1680 //
1681 SDHostData->ControllerNameTable = NULL;
1682
1683 AddUnicodeString2 (
1684 "eng",
1685 gSDControllerName.SupportedLanguages,
1686 &SDHostData->ControllerNameTable,
1687 L"SD Host Controller",
1688 TRUE
1689 );
1690 AddUnicodeString2 (
1691 "en",
1692 gSDControllerName2.SupportedLanguages,
1693 &SDHostData->ControllerNameTable,
1694 L"SD Host Controller",
1695 FALSE
1696 );
1697
1698 Exit:
1699 if (EFI_ERROR (Status)) {
1700 if (SDHostData != NULL) {
1701 FreePool (SDHostData);
1702 }
1703 }
1704
1705 return Status;
1706 }
1707
1708
1709 /**
1710 Stop this driver on ControllerHandle. Support stopping any child handles
1711 created by this driver.
1712
1713 @param This Protocol instance pointer.
1714 @param Controller Handle of device to stop driver on.
1715 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
1716 @param ChildHandleBuffer List of handles for the children we need to stop.
1717
1718 @return EFI_SUCCESS
1719 @return others
1720
1721 **/
1722 EFI_STATUS
1723 EFIAPI
1724 SDControllerStop (
1725 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1726 IN EFI_HANDLE Controller,
1727 IN UINTN NumberOfChildren,
1728 IN EFI_HANDLE *ChildHandleBuffer
1729 )
1730 {
1731 EFI_STATUS Status;
1732 EFI_SD_HOST_IO_PROTOCOL *SDHostIo;
1733 SDHOST_DATA *SDHostData;
1734
1735 Status = gBS->OpenProtocol (
1736 Controller,
1737 &gEfiSDHostIoProtocolGuid,
1738 (VOID **) &SDHostIo,
1739 This->DriverBindingHandle,
1740 Controller,
1741 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1742 );
1743
1744 //
1745 // Test whether the Controller handler passed in is a valid
1746 // Usb controller handle that should be supported, if not,
1747 // return the error status directly
1748 //
1749 if (EFI_ERROR (Status)) {
1750 return Status;
1751 }
1752
1753 SetHostVoltage (SDHostIo, 0);
1754
1755 SDHostData = SDHOST_DATA_FROM_THIS(SDHostIo);
1756
1757 //
1758 // Uninstall Block I/O protocol from the device handle
1759 //
1760 Status = gBS->UninstallProtocolInterface (
1761 Controller,
1762 &gEfiSDHostIoProtocolGuid,
1763 SDHostIo
1764 );
1765 if (EFI_ERROR (Status)) {
1766 return Status;
1767 }
1768
1769 FreeUnicodeStringTable (SDHostData->ControllerNameTable);
1770
1771 FreePool (SDHostData);
1772
1773 gBS->CloseProtocol (
1774 Controller,
1775 &gEfiPciIoProtocolGuid,
1776 This->DriverBindingHandle,
1777 Controller
1778 );
1779
1780 return EFI_SUCCESS;
1781 }
1782
1783
1784