Home | History | Annotate | Download | only in DwSdDxe
      1 /** @file
      2   This file implement the MMC Host Protocol for the DesignWare SD.
      3 
      4   Copyright (c) 2014-2016, Linaro Limited. All rights reserved.
      5   Copyright (c) 2014-2016, Hisilicon Limited. All rights reserved.
      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 #include <Library/BaseMemoryLib.h>
     18 #include <Library/CacheMaintenanceLib.h>
     19 #include <Library/DebugLib.h>
     20 #include <Library/DevicePathLib.h>
     21 #include <Library/IoLib.h>
     22 #include <Library/MemoryAllocationLib.h>
     23 #include <Library/PcdLib.h>
     24 #include <Library/TimerLib.h>
     25 #include <Library/UefiBootServicesTableLib.h>
     26 #include <Library/UefiLib.h>
     27 #include <Protocol/MmcHost.h>
     28 
     29 #include <Library/PrintLib.h>
     30 #include <Library/SerialPortLib.h>
     31 
     32 #include "DwSd.h"
     33 
     34 #define DWSD_DESC_PAGE		1
     35 #define DWSD_BLOCK_SIZE	        512
     36 #define DWSD_DMA_BUF_SIZE	(512 * 8)
     37 
     38 #define DWSD_DMA_THRESHOLD	16
     39 
     40 #define MAX_IDLE_LOOPS		1000000
     41 
     42 typedef struct {
     43   UINT32		Des0;
     44   UINT32		Des1;
     45   UINT32		Des2;
     46   UINT32		Des3;
     47 } DWSD_IDMAC_DESCRIPTOR;
     48 
     49 EFI_MMC_HOST_PROTOCOL     *gpMmcHost;
     50 DWSD_IDMAC_DESCRIPTOR     *gpIdmacDesc;
     51 EFI_GUID mDwSdDevicePathGuid = EFI_CALLER_ID_GUID;
     52 STATIC UINT32 mDwSdCommand;
     53 STATIC UINT32 mDwSdArgument;
     54 
     55 EFI_STATUS
     56 DwSdSendCommand (
     57   IN EFI_MMC_HOST_PROTOCOL     *This,
     58   IN MMC_CMD                    MmcCmd,
     59   IN UINT32                     Argument
     60   );
     61 EFI_STATUS
     62 DwSdReceiveResponse (
     63   IN EFI_MMC_HOST_PROTOCOL     *This,
     64   IN MMC_RESPONSE_TYPE          Type,
     65   IN UINT32*                    Buffer
     66   );
     67 
     68 EFI_STATUS
     69 DwSdReadBlockData (
     70   IN EFI_MMC_HOST_PROTOCOL     *This,
     71   IN EFI_LBA                    Lba,
     72   IN UINTN                      Length,
     73   IN UINT32*                    Buffer
     74   );
     75 
     76 BOOLEAN
     77 DwSdIsPowerOn (
     78   VOID
     79   )
     80 {
     81     return TRUE;
     82 }
     83 
     84 EFI_STATUS
     85 DwSdInitialize (
     86   VOID
     87   )
     88 {
     89     DEBUG ((EFI_D_BLKIO, "DwSdInitialize()"));
     90     return EFI_SUCCESS;
     91 }
     92 
     93 BOOLEAN
     94 DwSdIsCardPresent (
     95   IN EFI_MMC_HOST_PROTOCOL     *This
     96   )
     97 {
     98   UINT32    Value;
     99 
    100   /*
    101    * FIXME
    102    * At first, reading GPIO pin shouldn't exist in SD driver. We need to
    103    * add some callbacks to handle settings for hardware platform.
    104    * In the second, reading GPIO pin should be based on GPIO driver. Now
    105    * GPIO driver could only be used for one PL061 gpio controller. And it's
    106    * used to detect jumper setting. As a workaround, we have to read the gpio
    107    * register instead at here.
    108    *
    109    */
    110   Value = MmioRead32 (0xf8012000 + (1 << 2));
    111   if (Value)
    112     return FALSE;
    113   return TRUE;
    114 }
    115 
    116 BOOLEAN
    117 DwSdIsReadOnly (
    118   IN EFI_MMC_HOST_PROTOCOL     *This
    119   )
    120 {
    121   /* FIXME */
    122   return FALSE;
    123 }
    124 
    125 EFI_STATUS
    126 DwSdBuildDevicePath (
    127   IN EFI_MMC_HOST_PROTOCOL      *This,
    128   IN EFI_DEVICE_PATH_PROTOCOL   **DevicePath
    129   )
    130 {
    131   EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
    132 
    133   NewDevicePathNode = CreateDeviceNode (HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH));
    134   CopyGuid (& ((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &mDwSdDevicePathGuid);
    135 
    136   *DevicePath = NewDevicePathNode;
    137   return EFI_SUCCESS;
    138 }
    139 
    140 EFI_STATUS
    141 DwSdUpdateClock (
    142   VOID
    143   )
    144 {
    145   UINT32 Data;
    146 
    147   /* CMD_UPDATE_CLK */
    148   Data = BIT_CMD_WAIT_PRVDATA_COMPLETE | BIT_CMD_UPDATE_CLOCK_ONLY |
    149 	 BIT_CMD_START;
    150   MmioWrite32 (DWSD_CMD, Data);
    151   while (1) {
    152     Data = MmioRead32 (DWSD_CMD);
    153     if (!(Data & CMD_START_BIT))
    154       break;
    155     Data = MmioRead32 (DWSD_RINTSTS);
    156     if (Data & DWSD_INT_HLE)
    157     {
    158       Print (L"failed to update mmc clock frequency\n");
    159       return EFI_DEVICE_ERROR;
    160     }
    161   }
    162   return EFI_SUCCESS;
    163 }
    164 
    165 EFI_STATUS
    166 DwSdSetClock (
    167   IN UINTN                     ClockFreq
    168   )
    169 {
    170   UINT32 Divider, Rate, Data, Count;
    171   EFI_STATUS Status;
    172   BOOLEAN Found = FALSE;
    173 
    174   for (Divider = 1; Divider < 256; Divider++) {
    175     Rate = PcdGet32 (PcdDwSdDxeClockFrequencyInHz);
    176     if ((Rate / (2 * Divider)) <= ClockFreq) {
    177       Found = TRUE;
    178       break;
    179     }
    180   }
    181   if (Found == FALSE)
    182     return EFI_NOT_FOUND;
    183 
    184   // Wait until MMC is idle
    185   Count = 0;
    186   do {
    187     Data = MmioRead32 (DWSD_STATUS);
    188     if (Count++ > MAX_IDLE_LOOPS)
    189       break;
    190   } while (Data & DWSD_STS_DATA_BUSY);
    191 
    192   // Disable MMC clock first
    193   MmioWrite32 (DWSD_CLKENA, 0);
    194   Status = DwSdUpdateClock ();
    195   ASSERT (!EFI_ERROR (Status));
    196 
    197   MmioWrite32 (DWSD_CLKDIV, Divider);
    198   Status = DwSdUpdateClock ();
    199   ASSERT (!EFI_ERROR (Status));
    200 
    201   // Enable MMC clock
    202   MmioWrite32 (DWSD_CLKENA, 1);
    203   MmioWrite32 (DWSD_CLKSRC, 0);
    204   Status = DwSdUpdateClock ();
    205   ASSERT (!EFI_ERROR (Status));
    206   return EFI_SUCCESS;
    207 }
    208 
    209 EFI_STATUS
    210 DwSdNotifyState (
    211   IN EFI_MMC_HOST_PROTOCOL     *This,
    212   IN MMC_STATE                 State
    213   )
    214 {
    215   UINT32      Data;
    216   EFI_STATUS  Status;
    217 
    218   switch (State) {
    219   case MmcInvalidState:
    220     ASSERT (0);
    221     break;
    222   case MmcHwInitializationState:
    223     MmioWrite32 (DWSD_PWREN, 1);
    224 
    225     // If device already turn on then restart it
    226     Data = DWSD_CTRL_RESET_ALL;
    227     MmioWrite32 (DWSD_CTRL, Data);
    228     do {
    229       // Wait until reset operation finished
    230       Data = MmioRead32 (DWSD_CTRL);
    231     } while (Data & DWSD_CTRL_RESET_ALL);
    232 
    233     MmioWrite32 (DWSD_RINTSTS, ~0);
    234     MmioWrite32 (DWSD_INTMASK, 0);
    235     MmioWrite32 (DWSD_TMOUT, ~0);
    236     MmioWrite32 (DWSD_IDINTEN, 0);
    237     MmioWrite32 (DWSD_BMOD, DWSD_IDMAC_SWRESET);
    238 
    239     MmioWrite32 (DWSD_BLKSIZ, DWSD_BLOCK_SIZE);
    240     do {
    241       Data = MmioRead32 (DWSD_BMOD);
    242     } while (Data & DWSD_IDMAC_SWRESET);
    243 
    244 
    245     Data = DWSD_DMA_BURST_SIZE(2) | DWSD_FIFO_TWMARK(8) | DWSD_FIFO_RWMARK(7) | (2 << 28);
    246     MmioWrite32 (DWSD_FIFOTH, Data);
    247     Data = DWSD_CARD_RD_THR(512) | DWSD_CARD_RD_THR_EN;
    248     MmioWrite32 (DWSD_CARDTHRCTL, Data);
    249 
    250     // Set Data Length & Data Timer
    251     MmioWrite32 (DWSD_CTYPE, 0);
    252     MmioWrite32 (DWSD_DEBNCE, 0x00ffffff);
    253 
    254     // Setup clock that could not be higher than 400KHz.
    255     Status = DwSdSetClock (400000);
    256     ASSERT (!EFI_ERROR (Status));
    257     MicroSecondDelay (100);
    258 
    259     break;
    260   case MmcIdleState:
    261     break;
    262   case MmcReadyState:
    263     break;
    264   case MmcIdentificationState:
    265     break;
    266   case MmcStandByState:
    267     break;
    268   case MmcTransferState:
    269     break;
    270   case MmcSendingDataState:
    271     break;
    272   case MmcReceiveDataState:
    273     break;
    274   case MmcProgrammingState:
    275     break;
    276   case MmcDisconnectState:
    277     break;
    278   default:
    279     ASSERT (0);
    280   }
    281   return EFI_SUCCESS;
    282 }
    283 
    284 EFI_STATUS
    285 SendCommand (
    286   IN MMC_CMD                    MmcCmd,
    287   IN UINT32                     Argument
    288   )
    289 {
    290   UINT32      Data, ErrMask, Count;
    291 
    292   MmioWrite32 (DWSD_RINTSTS, ~0);
    293   MmioWrite32 (DWSD_CMDARG, Argument);
    294   MicroSecondDelay(500);
    295   // Wait until MMC is idle
    296   Count = 0;
    297   do {
    298     Data = MmioRead32 (DWSD_STATUS);
    299     if (Count++ > MAX_IDLE_LOOPS)
    300       break;
    301   } while (Data & DWSD_STS_DATA_BUSY);
    302 
    303   MmioWrite32 (DWSD_CMD, MmcCmd);
    304 
    305   ErrMask = DWSD_INT_EBE | DWSD_INT_HLE | DWSD_INT_RTO |
    306             DWSD_INT_RCRC | DWSD_INT_RE;
    307   ErrMask |= DWSD_INT_DCRC | DWSD_INT_DRT | DWSD_INT_SBE;
    308   do {
    309     MicroSecondDelay(500);
    310     Data = MmioRead32 (DWSD_RINTSTS);
    311 
    312     if (Data & ErrMask) {
    313       DEBUG ((EFI_D_ERROR, "Data:%x, ErrMask:%x, TBBCNT:%x, TCBCNT:%x, BYTCNT:%x, BLKSIZ:%x\n", Data, ErrMask, MmioRead32 (DWSD_TBBCNT), MmioRead32 (DWSD_TCBCNT), MmioRead32 (DWSD_BYTCNT), MmioRead32 (DWSD_BLKSIZ)));
    314       return EFI_DEVICE_ERROR;
    315     }
    316     if (Data & DWSD_INT_DTO)	// Transfer Done
    317       break;
    318   } while (!(Data & DWSD_INT_CMD_DONE));
    319   MmcCmd &= 0x3f;
    320   if (MmcCmd == 17)
    321     MicroSecondDelay(100);
    322   else if (MmcCmd != 13)
    323     MicroSecondDelay(5000);
    324 
    325   return EFI_SUCCESS;
    326 }
    327 
    328 UINTN ACmd = 0;
    329 
    330 EFI_STATUS
    331 DwSdSendCommand (
    332   IN EFI_MMC_HOST_PROTOCOL     *This,
    333   IN MMC_CMD                    MmcCmd,
    334   IN UINT32                     Argument
    335   )
    336 {
    337   UINT32       Cmd = 0;
    338   EFI_STATUS   Status = EFI_SUCCESS;
    339   BOOLEAN      Pending = FALSE;
    340   UINT32       Data;
    341 
    342   switch (MMC_GET_INDX(MmcCmd)) {
    343   case MMC_INDX(0):
    344     //Cmd = BIT_CMD_SEND_INIT;
    345     Cmd = BIT_CMD_WAIT_PRVDATA_COMPLETE;
    346     break;
    347   case MMC_INDX(1):
    348     Cmd = BIT_CMD_RESPONSE_EXPECT;
    349     break;
    350   case MMC_INDX(2):
    351     Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_LONG_RESPONSE |
    352            BIT_CMD_CHECK_RESPONSE_CRC | BIT_CMD_WAIT_PRVDATA_COMPLETE;
    353     break;
    354   case MMC_INDX(3):
    355     Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
    356            BIT_CMD_WAIT_PRVDATA_COMPLETE;
    357     break;
    358   case MMC_INDX(6):
    359     if (!ACmd) {
    360       Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
    361 	    BIT_CMD_DATA_EXPECTED | BIT_CMD_WAIT_PRVDATA_COMPLETE;
    362     } else {
    363       Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
    364 	    BIT_CMD_WAIT_PRVDATA_COMPLETE;
    365     }
    366     if (!ACmd)
    367       Pending = TRUE;
    368     break;
    369   case MMC_INDX(7):
    370     if (Argument)
    371         Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
    372 	       BIT_CMD_WAIT_PRVDATA_COMPLETE;
    373     else
    374         Cmd = 0;
    375     break;
    376   case MMC_INDX(8):
    377     Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
    378            BIT_CMD_READ |
    379            BIT_CMD_WAIT_PRVDATA_COMPLETE;
    380     break;
    381   case MMC_INDX(9):
    382     Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
    383            BIT_CMD_LONG_RESPONSE | BIT_CMD_WAIT_PRVDATA_COMPLETE;
    384     break;
    385   case MMC_INDX(12):
    386     Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
    387            BIT_CMD_STOP_ABORT_CMD;
    388     break;
    389   case MMC_INDX(13):
    390     Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
    391     break;
    392   case MMC_INDX(17):
    393   case MMC_INDX(18):
    394     Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
    395            BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
    396            BIT_CMD_WAIT_PRVDATA_COMPLETE;
    397     Pending = TRUE;
    398     Data = MmioRead32 (DWSD_CTRL);
    399     Data |= DWSD_CTRL_FIFO_RESET;
    400     MmioWrite32 (DWSD_CTRL, Data);
    401     while (MmioRead32 (DWSD_CTRL) & DWSD_CTRL_FIFO_RESET) {
    402     };
    403     break;
    404   case MMC_INDX(24):
    405   case MMC_INDX(25):
    406     Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
    407            BIT_CMD_DATA_EXPECTED | BIT_CMD_WRITE |
    408            BIT_CMD_WAIT_PRVDATA_COMPLETE;
    409     Pending = TRUE;
    410     break;
    411   case MMC_INDX(30):
    412     Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
    413            BIT_CMD_DATA_EXPECTED;
    414     break;
    415   case MMC_INDX(41):
    416     Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_WAIT_PRVDATA_COMPLETE;
    417     break;
    418   case MMC_INDX(51):
    419     Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC |
    420            BIT_CMD_DATA_EXPECTED | BIT_CMD_READ |
    421            BIT_CMD_WAIT_PRVDATA_COMPLETE;
    422     Pending = TRUE;
    423     break;
    424   case MMC_INDX(55):
    425     Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
    426     ACmd = 1;
    427     break;
    428   default:
    429     Cmd = BIT_CMD_RESPONSE_EXPECT | BIT_CMD_CHECK_RESPONSE_CRC;
    430     break;
    431   }
    432 
    433   Cmd |= MMC_GET_INDX(MmcCmd) | BIT_CMD_USE_HOLD_REG | BIT_CMD_START;
    434   if (Pending) {
    435     mDwSdCommand = Cmd;
    436     mDwSdArgument = Argument;
    437   } else {
    438     mDwSdCommand = 0;
    439     mDwSdArgument = 0;
    440     Status = SendCommand (Cmd, Argument);
    441   }
    442   /* Clear ACMD */
    443   if (MMC_GET_INDX(MmcCmd) != MMC_INDX(55))
    444     ACmd = 0;
    445   return Status;
    446 }
    447 
    448 EFI_STATUS
    449 DwSdReceiveResponse (
    450   IN EFI_MMC_HOST_PROTOCOL     *This,
    451   IN MMC_RESPONSE_TYPE          Type,
    452   IN UINT32*                    Buffer
    453   )
    454 {
    455   if (Buffer == NULL) {
    456     return EFI_INVALID_PARAMETER;
    457   }
    458 
    459   if (   (Type == MMC_RESPONSE_TYPE_R1)
    460       || (Type == MMC_RESPONSE_TYPE_R1b)
    461       || (Type == MMC_RESPONSE_TYPE_R3)
    462       || (Type == MMC_RESPONSE_TYPE_R6)
    463       || (Type == MMC_RESPONSE_TYPE_R7))
    464   {
    465     Buffer[0] = MmioRead32 (DWSD_RESP0);
    466   } else if (Type == MMC_RESPONSE_TYPE_R2) {
    467     Buffer[0] = MmioRead32 (DWSD_RESP0);
    468     Buffer[1] = MmioRead32 (DWSD_RESP1);
    469     Buffer[2] = MmioRead32 (DWSD_RESP2);
    470     Buffer[3] = MmioRead32 (DWSD_RESP3);
    471   }
    472   return EFI_SUCCESS;
    473 }
    474 
    475 EFI_STATUS
    476 PrepareDmaData (
    477   IN DWSD_IDMAC_DESCRIPTOR*    IdmacDesc,
    478   IN UINTN                      Length,
    479   IN UINT32*                    Buffer
    480   )
    481 {
    482   UINTN  Cnt, Idx, LastIdx, Blks;
    483 
    484   if (Length % 4) {
    485     DEBUG ((EFI_D_ERROR, "Length isn't aligned with 4\n"));
    486     return EFI_BAD_BUFFER_SIZE;
    487   }
    488   if (Length < DWSD_DMA_THRESHOLD) {
    489     return EFI_BUFFER_TOO_SMALL;
    490   }
    491   Cnt = (Length + DWSD_DMA_BUF_SIZE - 1) / DWSD_DMA_BUF_SIZE;
    492   Blks = (Length + DWSD_BLOCK_SIZE - 1 ) / DWSD_BLOCK_SIZE;
    493   Length = DWSD_BLOCK_SIZE * Blks;
    494 
    495   for (Idx = 0; Idx < Cnt; Idx++) {
    496     (IdmacDesc + Idx)->Des0 = DWSD_IDMAC_DES0_OWN | DWSD_IDMAC_DES0_CH |
    497 	    		      DWSD_IDMAC_DES0_DIC;
    498     (IdmacDesc + Idx)->Des1 = DWSD_IDMAC_DES1_BS1(DWSD_DMA_BUF_SIZE);
    499     /* Buffer Address */
    500     (IdmacDesc + Idx)->Des2 = (UINT32)((UINTN)Buffer + DWSD_DMA_BUF_SIZE * Idx);
    501     /* Next Descriptor Address */
    502     (IdmacDesc + Idx)->Des3 = (UINT32)((UINTN)IdmacDesc +
    503    	                               (sizeof(DWSD_IDMAC_DESCRIPTOR) * (Idx + 1)));
    504   }
    505   /* First Descriptor */
    506   IdmacDesc->Des0 |= DWSD_IDMAC_DES0_FS;
    507   /* Last Descriptor */
    508   LastIdx = Cnt - 1;
    509   (IdmacDesc + LastIdx)->Des0 |= DWSD_IDMAC_DES0_LD;
    510   (IdmacDesc + LastIdx)->Des0 &= ~(DWSD_IDMAC_DES0_DIC | DWSD_IDMAC_DES0_CH);
    511   (IdmacDesc + LastIdx)->Des1 = DWSD_IDMAC_DES1_BS1(Length -
    512    		                (LastIdx * DWSD_DMA_BUF_SIZE));
    513   /* Set the Next field of Last Descriptor */
    514   (IdmacDesc + LastIdx)->Des3 = 0;
    515   MmioWrite32 (DWSD_DBADDR, (UINT32)((UINTN)IdmacDesc));
    516 
    517   return EFI_SUCCESS;
    518 }
    519 
    520 VOID
    521 StartDma (
    522   UINTN    Length
    523   )
    524 {
    525   UINT32 Data;
    526 
    527   Data = MmioRead32 (DWSD_CTRL);
    528   Data |= DWSD_CTRL_INT_EN | DWSD_CTRL_DMA_EN | DWSD_CTRL_IDMAC_EN;
    529   MmioWrite32 (DWSD_CTRL, Data);
    530   Data = MmioRead32 (DWSD_BMOD);
    531   Data |= DWSD_IDMAC_ENABLE | DWSD_IDMAC_FB;
    532   MmioWrite32 (DWSD_BMOD, Data);
    533 
    534   MmioWrite32 (DWSD_BLKSIZ, DWSD_BLOCK_SIZE);
    535   MmioWrite32 (DWSD_BYTCNT, Length);
    536 }
    537 
    538 STATIC
    539 EFI_STATUS
    540 ReadFifo (
    541   IN UINTN                      Length,
    542   IN UINT32*                    Buffer
    543   )
    544 {
    545   UINT32      Data, Received, Count;
    546 
    547   Received = 0;
    548   Count = (Length + 3) / 4;
    549   while (Received < Count) {
    550     Data = MmioRead32 (DWSD_RINTSTS);
    551     if (Data & DWSD_INT_CMD_DONE) {
    552       *(Buffer + Received) = MmioRead32 (DWSD_FIFO_START);
    553       Received++;
    554     } else {
    555       DEBUG ((EFI_D_ERROR, "Received:%d, RINTSTS:%x\n", Received, Data));
    556     }
    557   }
    558   while (1) {
    559     Data = MmioRead32 (DWSD_RINTSTS);
    560     if (Data & DWSD_INT_DTO)
    561       break;
    562   }
    563   /* FIXME */
    564   MicroSecondDelay (1000);
    565   return EFI_SUCCESS;
    566 }
    567 
    568 EFI_STATUS
    569 DwSdReadBlockData (
    570   IN EFI_MMC_HOST_PROTOCOL     *This,
    571   IN EFI_LBA                    Lba,
    572   IN UINTN                      Length,
    573   IN UINT32*                   Buffer
    574   )
    575 {
    576   EFI_STATUS  Status;
    577   UINT32      DescPages, CountPerPage, Count, Data;
    578   EFI_TPL     Tpl;
    579 
    580   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
    581 
    582   CountPerPage = EFI_PAGE_SIZE / 16;
    583   Count = (Length + DWSD_DMA_BUF_SIZE - 1) / DWSD_DMA_BUF_SIZE;
    584   DescPages = (Count + CountPerPage - 1) / CountPerPage;
    585 
    586   InvalidateDataCacheRange (Buffer, Length);
    587 
    588   Status = PrepareDmaData (gpIdmacDesc, Length, Buffer);
    589   if (EFI_ERROR (Status)) {
    590     if (Status == EFI_BUFFER_TOO_SMALL) {
    591       Data = MmioRead32 (DWSD_CTRL);
    592       Data |= DWSD_CTRL_FIFO_RESET;
    593       MmioWrite32 (DWSD_CTRL, Data);
    594       while (MmioRead32 (DWSD_CTRL) & DWSD_CTRL_FIFO_RESET) {
    595       };
    596 
    597       Status = SendCommand (mDwSdCommand, mDwSdArgument);
    598       if (EFI_ERROR (Status)) {
    599 	DEBUG ((EFI_D_ERROR, "Failed to read data from FIFO, mDwSdCommand:%x, mDwSdArgument:%x, Status:%r\n", mDwSdCommand, mDwSdArgument, Status));
    600 	goto out;
    601       }
    602       Status = ReadFifo (Length, Buffer);
    603     }
    604     goto out;
    605   } else {
    606 
    607     WriteBackDataCacheRange (gpIdmacDesc, DescPages * EFI_PAGE_SIZE);
    608     StartDma (Length);
    609 
    610     Status = SendCommand (mDwSdCommand, mDwSdArgument);
    611     if (EFI_ERROR (Status)) {
    612       DEBUG ((EFI_D_ERROR, "Failed to read data, mDwSdCommand:%x, mDwSdArgument:%x, Status:%r\n", mDwSdCommand, mDwSdArgument, Status));
    613       goto out;
    614     }
    615 
    616     /* Wait until data transfer finished */
    617     while (MmioRead32 (DWSD_TCBCNT) < MmioRead32 (DWSD_BYTCNT)) {
    618     }
    619 
    620   }
    621 out:
    622   // Restore Tpl
    623   gBS->RestoreTPL (Tpl);
    624   return Status;
    625 }
    626 
    627 EFI_STATUS
    628 DwSdWriteBlockData (
    629   IN EFI_MMC_HOST_PROTOCOL     *This,
    630   IN EFI_LBA                    Lba,
    631   IN UINTN                      Length,
    632   IN UINT32*                    Buffer
    633   )
    634 {
    635   EFI_STATUS  Status;
    636   UINT32      DescPages, CountPerPage, Count;
    637   EFI_TPL     Tpl;
    638 
    639   Tpl = gBS->RaiseTPL (TPL_NOTIFY);
    640 
    641   CountPerPage = EFI_PAGE_SIZE / 16;
    642   Count = (Length + DWSD_DMA_BUF_SIZE - 1) / DWSD_DMA_BUF_SIZE;
    643   DescPages = (Count + CountPerPage - 1) / CountPerPage;
    644 
    645   WriteBackDataCacheRange (Buffer, Length);
    646 
    647   Status = PrepareDmaData (gpIdmacDesc, Length, Buffer);
    648   if (EFI_ERROR (Status))
    649     goto out;
    650 
    651   WriteBackDataCacheRange (gpIdmacDesc, DescPages * EFI_PAGE_SIZE);
    652   StartDma (Length);
    653 
    654   Status = SendCommand (mDwSdCommand, mDwSdArgument);
    655   if (EFI_ERROR (Status)) {
    656     DEBUG ((EFI_D_ERROR, "Failed to write data, mDwSdCommand:%x, mDwSdArgument:%x, Status:%r\n", mDwSdCommand, mDwSdArgument, Status));
    657     goto out;
    658   }
    659 out:
    660   // Restore Tpl
    661   gBS->RestoreTPL (Tpl);
    662   return Status;
    663 }
    664 
    665 EFI_STATUS
    666 DwSdSetIos (
    667   IN EFI_MMC_HOST_PROTOCOL      *This,
    668   IN  UINT32                    BusClockFreq,
    669   IN  UINT32                    BusWidth,
    670   IN  UINT32                    TimingMode
    671   )
    672 {
    673   EFI_STATUS Status = EFI_SUCCESS;
    674   UINT32    Data;
    675 
    676   if (TimingMode != EMMCBACKWARD) {
    677     Data = MmioRead32 (DWSD_UHSREG);
    678     switch (TimingMode) {
    679     case EMMCHS52DDR1V2:
    680     case EMMCHS52DDR1V8:
    681       Data |= 1 << 16;
    682       break;
    683     case EMMCHS52:
    684     case EMMCHS26:
    685       Data &= ~(1 << 16);
    686       break;
    687     default:
    688       return EFI_UNSUPPORTED;
    689     }
    690     MmioWrite32 (DWSD_UHSREG, Data);
    691   }
    692 
    693   switch (BusWidth) {
    694   case 1:
    695     MmioWrite32 (DWSD_CTYPE, 0);
    696     break;
    697   case 4:
    698     MmioWrite32 (DWSD_CTYPE, 1);
    699     break;
    700   case 8:
    701     MmioWrite32 (DWSD_CTYPE, 1 << 16);
    702     break;
    703   default:
    704     return EFI_UNSUPPORTED;
    705   }
    706   if (BusClockFreq) {
    707     Status = DwSdSetClock (BusClockFreq);
    708   }
    709   return Status;
    710 }
    711 
    712 BOOLEAN
    713 DwSdIsMultiBlock (
    714   IN EFI_MMC_HOST_PROTOCOL      *This
    715   )
    716 {
    717   return TRUE;
    718 }
    719 
    720 EFI_MMC_HOST_PROTOCOL gMciHost = {
    721   MMC_HOST_PROTOCOL_REVISION,
    722   DwSdIsCardPresent,
    723   DwSdIsReadOnly,
    724   DwSdBuildDevicePath,
    725   DwSdNotifyState,
    726   DwSdSendCommand,
    727   DwSdReceiveResponse,
    728   DwSdReadBlockData,
    729   DwSdWriteBlockData,
    730   DwSdSetIos,
    731   DwSdIsMultiBlock
    732 };
    733 
    734 EFI_STATUS
    735 DwSdDxeInitialize (
    736   IN EFI_HANDLE         ImageHandle,
    737   IN EFI_SYSTEM_TABLE   *SystemTable
    738   )
    739 {
    740   EFI_STATUS    Status;
    741   EFI_HANDLE    Handle;
    742 
    743   Handle = NULL;
    744 
    745   DEBUG ((EFI_D_BLKIO, "DwSdDxeInitialize()\n"));
    746 
    747   //Publish Component Name, BlockIO protocol interfaces
    748   Status = gBS->InstallMultipleProtocolInterfaces (
    749                   &Handle,
    750                   &gEfiMmcHostProtocolGuid,         &gMciHost,
    751                   NULL
    752                   );
    753   ASSERT_EFI_ERROR (Status);
    754 
    755   return EFI_SUCCESS;
    756 }
    757