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