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