Home | History | Annotate | Download | only in DwUfsHcDxe
      1 /** @file
      2   UfsHcDxe driver is used to provide platform-dependent info, mainly UFS host controller
      3   MMIO base, to upper layer UFS drivers.
      4 
      5   Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
      6   Copyright (c) 2016 - 2017, Linaro Ltd. All rights reserved.
      7 
      8   This program and the accompanying materials
      9   are licensed and made available under the terms and conditions of the BSD License
     10   which accompanies this distribution.  The full text of the license may be found at
     11   http://opensource.org/licenses/bsd-license.php.
     12 
     13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     14   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     15 
     16 **/
     17 
     18 #include "DwUfsHcDxe.h"
     19 
     20 #include <IndustryStandard/Pci.h>
     21 
     22 #include <Protocol/PciIo.h>
     23 
     24 //
     25 // Ufs Host Controller Driver Binding Protocol Instance
     26 //
     27 EFI_DRIVER_BINDING_PROTOCOL gUfsHcDriverBinding = {
     28   UfsHcDriverBindingSupported,
     29   UfsHcDriverBindingStart,
     30   UfsHcDriverBindingStop,
     31   0x10,
     32   NULL,
     33   NULL
     34 };
     35 
     36 //
     37 // Template for Ufs host controller private data.
     38 //
     39 UFS_HOST_CONTROLLER_PRIVATE_DATA gUfsHcTemplate = {
     40   UFS_HC_PRIVATE_DATA_SIGNATURE,  // Signature
     41   NULL,                           // Handle
     42   {                               // UfsHcProtocol
     43     UfsHcGetMmioBar,
     44     UfsHcAllocateBuffer,
     45     UfsHcFreeBuffer,
     46     UfsHcMap,
     47     UfsHcUnmap,
     48     UfsHcFlush,
     49     UfsHcMmioRead,
     50     UfsHcMmioWrite,
     51     UfsHcPhyInit,
     52     UfsHcPhySetPowerMode,
     53   },
     54   0                               // RegBase
     55 };
     56 
     57 STATIC
     58 EFI_STATUS
     59 DwUfsDmeSet (
     60   IN  UINTN         RegBase,
     61   IN  UINT16        Attr,
     62   IN  UINT16        Index,
     63   IN  UINT32        Value
     64   )
     65 {
     66   UINT32            Data;
     67 
     68   Data = MmioRead32 (RegBase + UFS_HC_STATUS_OFFSET);
     69   if ((Data & UFS_HC_HCS_UCRDY) == 0) {
     70     return EFI_NOT_READY;
     71   }
     72   MmioWrite32 (RegBase + UFS_HC_IS_OFFSET, ~0);
     73   MmioWrite32 (RegBase + UFS_HC_UCMD_ARG1_OFFSET, (Attr << 16) | Index);
     74   MmioWrite32 (RegBase + UFS_HC_UCMD_ARG2_OFFSET, 0);
     75   MmioWrite32 (RegBase + UFS_HC_UCMD_ARG3_OFFSET, Value);
     76   MmioWrite32 (RegBase + UFS_HC_UIC_CMD_OFFSET, UFS_UIC_DME_SET);
     77   do {
     78     Data = MmioRead32 (RegBase + UFS_HC_IS_OFFSET);
     79     if (Data & UFS_HC_IS_UE) {
     80       return EFI_DEVICE_ERROR;
     81     }
     82   } while ((Data & UFS_HC_IS_UCCS) == 0);
     83   MmioWrite32 (RegBase + UFS_HC_IS_OFFSET, UFS_HC_IS_UCCS);
     84   Data = MmioRead32 (RegBase + UFS_HC_UCMD_ARG2_OFFSET);
     85   if (Data) {
     86     return EFI_DEVICE_ERROR;
     87   }
     88   return EFI_SUCCESS;
     89 }
     90 
     91 STATIC
     92 EFI_STATUS
     93 DwUfsDmeGet (
     94   IN  UINTN         RegBase,
     95   IN  UINT16        Attr,
     96   IN  UINT16        Index,
     97   OUT UINT32        *Value
     98   )
     99 {
    100   UINT32            Data;
    101 
    102   Data = MmioRead32 (RegBase + UFS_HC_STATUS_OFFSET);
    103   if ((Data & UFS_HC_HCS_UCRDY) == 0) {
    104     return EFI_NOT_READY;
    105   }
    106   MmioWrite32 (RegBase + UFS_HC_IS_OFFSET, ~0);
    107   MmioWrite32 (RegBase + UFS_HC_UCMD_ARG1_OFFSET, (Attr << 16) | Index);
    108   MmioWrite32 (RegBase + UFS_HC_UCMD_ARG2_OFFSET, 0);
    109   MmioWrite32 (RegBase + UFS_HC_UCMD_ARG3_OFFSET, 0);
    110   MmioWrite32 (RegBase + UFS_HC_UIC_CMD_OFFSET, UFS_UIC_DME_GET);
    111   do {
    112     Data = MmioRead32 (RegBase + UFS_HC_IS_OFFSET);
    113     if (Data & UFS_HC_IS_UE) {
    114       return EFI_DEVICE_ERROR;
    115     }
    116   } while ((Data & UFS_HC_IS_UCCS) == 0);
    117   MmioWrite32 (RegBase + UFS_HC_IS_OFFSET, UFS_HC_IS_UCCS);
    118   Data = MmioRead32 (RegBase + UFS_HC_UCMD_ARG2_OFFSET);
    119   if (Data) {
    120     return EFI_DEVICE_ERROR;
    121   }
    122   *Value = MmioRead32 (RegBase + UFS_HC_UCMD_ARG3_OFFSET);
    123   return EFI_SUCCESS;
    124 }
    125 
    126 /**
    127   Get the MMIO base of the UFS host controller.
    128 
    129   @param[in]   This             A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
    130   @param[out]  MmioBar          The MMIO base address of UFS host controller.
    131 
    132   @retval EFI_SUCCESS           The operation succeeds.
    133   @retval others                The operation fails.
    134 **/
    135 EFI_STATUS
    136 EFIAPI
    137 UfsHcGetMmioBar (
    138   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
    139      OUT UINTN                              *MmioBar
    140   )
    141 {
    142   UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
    143 
    144   if ((This == NULL) || (MmioBar == NULL)) {
    145     return EFI_INVALID_PARAMETER;
    146   }
    147 
    148   Private  = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
    149   *MmioBar = Private->RegBase;
    150   return EFI_SUCCESS;
    151 }
    152 
    153 /**
    154   Provides the UFS controller-specific addresses needed to access system memory.
    155 
    156   @param  This                  A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
    157   @param  Operation             Indicates if the bus master is going to read or write to system memory.
    158   @param  HostAddress           The system memory address to map to the UFS controller.
    159   @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
    160                                 that were mapped.
    161   @param  DeviceAddress         The resulting map address for the bus master UFS controller to use to
    162                                 access the hosts HostAddress.
    163   @param  Mapping               A resulting value to pass to Unmap().
    164 
    165   @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
    166   @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
    167   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
    168   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
    169   @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
    170 
    171 **/
    172 EFI_STATUS
    173 EFIAPI
    174 UfsHcMap (
    175   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *This,
    176   IN     EDKII_UFS_HOST_CONTROLLER_OPERATION  Operation,
    177   IN     VOID                                 *HostAddress,
    178   IN OUT UINTN                                *NumberOfBytes,
    179      OUT EFI_PHYSICAL_ADDRESS                 *DeviceAddress,
    180      OUT VOID                                 **Mapping
    181   )
    182 {
    183   DMA_MAP_OPERATION   DmaOperation;
    184 
    185   if ((This == NULL) || (HostAddress == NULL) || (NumberOfBytes == NULL) || (DeviceAddress == NULL) || (Mapping == NULL)) {
    186     return EFI_INVALID_PARAMETER;
    187   }
    188 
    189   if (Operation == EdkiiUfsHcOperationBusMasterRead) {
    190     DmaOperation = MapOperationBusMasterRead;
    191   } else if (Operation == EdkiiUfsHcOperationBusMasterWrite) {
    192     DmaOperation = MapOperationBusMasterWrite;
    193   } else if (Operation == EdkiiUfsHcOperationBusMasterCommonBuffer) {
    194     DmaOperation = MapOperationBusMasterCommonBuffer;
    195   } else {
    196     return EFI_INVALID_PARAMETER;
    197   }
    198 
    199   if ((*NumberOfBytes & (BIT0 | BIT1)) != 0) {
    200     *NumberOfBytes += BIT0 | BIT1;
    201     *NumberOfBytes &= ~(BIT0 | BIT1);
    202   }
    203 
    204   return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
    205 }
    206 
    207 /**
    208   Completes the Map() operation and releases any corresponding resources.
    209 
    210   @param  This                  A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
    211   @param  Mapping               The mapping value returned from Map().
    212 
    213   @retval EFI_SUCCESS           The range was unmapped.
    214   @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
    215 
    216 **/
    217 EFI_STATUS
    218 EFIAPI
    219 UfsHcUnmap (
    220   IN  EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
    221   IN  VOID                               *Mapping
    222   )
    223 {
    224   if ((This == NULL) || (Mapping == NULL)) {
    225     return EFI_INVALID_PARAMETER;
    226   }
    227 
    228   return DmaUnmap (Mapping);
    229 }
    230 
    231 /**
    232   Allocates pages that are suitable for an EfiUfsHcOperationBusMasterCommonBuffer
    233   mapping.
    234 
    235   @param  This                  A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
    236   @param  Type                  This parameter is not used and must be ignored.
    237   @param  MemoryType            The type of memory to allocate, EfiBootServicesData or
    238                                 EfiRuntimeServicesData.
    239   @param  Pages                 The number of pages to allocate.
    240   @param  HostAddress           A pointer to store the base system memory address of the
    241                                 allocated range.
    242   @param  Attributes            The requested bit mask of attributes for the allocated range.
    243 
    244   @retval EFI_SUCCESS           The requested memory pages were allocated.
    245   @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
    246                                 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
    247   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
    248   @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
    249 
    250 **/
    251 EFI_STATUS
    252 EFIAPI
    253 UfsHcAllocateBuffer (
    254   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
    255   IN     EFI_ALLOCATE_TYPE                  Type,
    256   IN     EFI_MEMORY_TYPE                    MemoryType,
    257   IN     UINTN                              Pages,
    258      OUT VOID                               **HostAddress,
    259   IN     UINT64                             Attributes
    260   )
    261 {
    262   if ((This == NULL) || (HostAddress == NULL)) {
    263     return EFI_INVALID_PARAMETER;
    264   }
    265 
    266   return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
    267 }
    268 
    269 /**
    270   Frees memory that was allocated with AllocateBuffer().
    271 
    272   @param  This                  A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
    273   @param  Pages                 The number of pages to free.
    274   @param  HostAddress           The base system memory address of the allocated range.
    275 
    276   @retval EFI_SUCCESS           The requested memory pages were freed.
    277   @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
    278                                 was not allocated with AllocateBuffer().
    279 
    280 **/
    281 EFI_STATUS
    282 EFIAPI
    283 UfsHcFreeBuffer (
    284   IN  EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
    285   IN  UINTN                              Pages,
    286   IN  VOID                               *HostAddress
    287   )
    288 {
    289   if ((This == NULL) || (HostAddress == NULL)) {
    290     return EFI_INVALID_PARAMETER;
    291   }
    292 
    293   return DmaFreeBuffer (Pages, HostAddress);
    294 }
    295 
    296 /**
    297   Flushes all posted write transactions from the UFS bus to attached UFS device.
    298 
    299   @param  This                  A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
    300 
    301   @retval EFI_SUCCESS           The posted write transactions were flushed from the UFS bus
    302                                 to attached UFS device.
    303   @retval EFI_DEVICE_ERROR      The posted write transactions were not flushed from the UFS
    304                                 bus to attached UFS device due to a hardware error.
    305 
    306 **/
    307 EFI_STATUS
    308 EFIAPI
    309 UfsHcFlush (
    310   IN  EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This
    311   )
    312 {
    313   ArmInstructionSynchronizationBarrier ();
    314   ArmDataSynchronizationBarrier ();
    315   return EFI_SUCCESS;
    316 }
    317 
    318 /**
    319   Enable a UFS bus driver to access UFS MMIO registers in the UFS Host Controller memory space.
    320 
    321   @param  This                  A pointer to the EDKII_UFS_HOST_CONTROLLER_PROTOCOL instance.
    322   @param  Width                 Signifies the width of the memory operations.
    323   @param  Offset                The offset within the UFS Host Controller MMIO space to start the
    324                                 memory operation.
    325   @param  Count                 The number of memory operations to perform.
    326   @param  Buffer                For read operations, the destination buffer to store the results.
    327                                 For write operations, the source buffer to write data from.
    328 
    329   @retval EFI_SUCCESS           The data was read from or written to the UFS host controller.
    330   @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
    331                                 valid for the UFS Host Controller memory space.
    332   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
    333   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
    334 
    335 **/
    336 EFI_STATUS
    337 EFIAPI
    338 UfsHcMmioRead (
    339   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL        *This,
    340   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH  Width,
    341   IN     UINT64                                    Offset,
    342   IN     UINTN                                     Count,
    343   IN OUT VOID                                      *Buffer
    344   )
    345 {
    346   UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
    347   UINTN                             Index;
    348 
    349   Private  = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
    350 
    351   switch (Width) {
    352   case EfiUfsHcWidthUint8:
    353     for (Index = 0; Index < Count; Index++) {
    354       *((UINT8 *)Buffer + Index) = MmioRead8 (Private->RegBase + Offset);
    355     }
    356     break;
    357   case EfiUfsHcWidthUint16:
    358     for (Index = 0; Index < Count; Index++) {
    359       *((UINT16 *)Buffer + Index) = MmioRead16 (Private->RegBase + Offset);
    360     }
    361     break;
    362   case EfiUfsHcWidthUint32:
    363     for (Index = 0; Index < Count; Index++) {
    364       *((UINT32 *)Buffer + Index) = MmioRead32 (Private->RegBase + Offset);
    365     }
    366     break;
    367   case EfiUfsHcWidthUint64:
    368     for (Index = 0; Index < Count; Index++) {
    369       *((UINT64 *)Buffer + Index) = MmioRead64 (Private->RegBase + Offset);
    370     }
    371     break;
    372   default:
    373     return EFI_INVALID_PARAMETER;
    374   }
    375 
    376   return EFI_SUCCESS;
    377 }
    378 
    379 /**
    380   Enable a UFS bus driver to access UFS MMIO registers in the UFS Host Controller memory space.
    381 
    382   @param  This                  A pointer to the EDKII_UFS_HOST_CONTROLLER_PROTOCOL instance.
    383   @param  Width                 Signifies the width of the memory operations.
    384   @param  Offset                The offset within the UFS Host Controller MMIO space to start the
    385                                 memory operation.
    386   @param  Count                 The number of memory operations to perform.
    387   @param  Buffer                For read operations, the destination buffer to store the results.
    388                                 For write operations, the source buffer to write data from.
    389 
    390   @retval EFI_SUCCESS           The data was read from or written to the UFS host controller.
    391   @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
    392                                 valid for the UFS Host Controller memory space.
    393   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
    394   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
    395 
    396 **/
    397 EFI_STATUS
    398 EFIAPI
    399 UfsHcMmioWrite (
    400   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL        *This,
    401   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH  Width,
    402   IN     UINT64                                    Offset,
    403   IN     UINTN                                     Count,
    404   IN OUT VOID                                      *Buffer
    405   )
    406 {
    407   UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
    408   EFI_STATUS                        Status = EFI_SUCCESS;
    409   UINTN                             Index;
    410 
    411   Private  = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
    412 
    413   switch (Width) {
    414   case EfiUfsHcWidthUint8:
    415     for (Index = 0; Index < Count; Index++) {
    416       Status = MmioWrite8 (Private->RegBase + Offset, *((UINT8 *)Buffer + Index));
    417     }
    418     break;
    419   case EfiUfsHcWidthUint16:
    420     for (Index = 0; Index < Count; Index++) {
    421       Status = MmioWrite16 (Private->RegBase + Offset, *((UINT16 *)Buffer + Index));
    422     }
    423     break;
    424   case EfiUfsHcWidthUint32:
    425     for (Index = 0; Index < Count; Index++) {
    426       Status = MmioWrite32 (Private->RegBase + Offset, *((UINT32 *)Buffer + Index));
    427     }
    428     break;
    429   case EfiUfsHcWidthUint64:
    430     for (Index = 0; Index < Count; Index++) {
    431       Status = MmioWrite64 (Private->RegBase + Offset, *((UINT64 *)Buffer + Index));
    432     }
    433     break;
    434   default:
    435     return EFI_INVALID_PARAMETER;
    436   }
    437 
    438   return Status;
    439 }
    440 
    441 EFI_STATUS
    442 EFIAPI
    443 UfsHcPhyInit (
    444   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL        *This
    445   )
    446 {
    447   UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
    448   EFI_STATUS                        Status;
    449   UINT32                            Data, Fsm0, Fsm1;
    450 
    451   Private  = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
    452   DwUfsDmeSet (Private->RegBase, 0xd0c1, 0, 1);
    453   DwUfsDmeSet (Private->RegBase, 0xd0c1, 0, 1);
    454   DwUfsDmeSet (Private->RegBase, 0x156a, 0, 2);
    455   DwUfsDmeSet (Private->RegBase, 0x8114, 0, 1);
    456   DwUfsDmeSet (Private->RegBase, 0x8121, 0, 0x2d);
    457   DwUfsDmeSet (Private->RegBase, 0x8122, 0, 1);
    458   DwUfsDmeSet (Private->RegBase, 0xd085, 0, 1);
    459   DwUfsDmeSet (Private->RegBase, 0x800d, 4, 0x58);
    460   DwUfsDmeSet (Private->RegBase, 0x800d, 5, 0x58);
    461   DwUfsDmeSet (Private->RegBase, 0x800e, 4, 0xb);
    462   DwUfsDmeSet (Private->RegBase, 0x800e, 5, 0xb);
    463   DwUfsDmeSet (Private->RegBase, 0x8009, 4, 0x1);
    464   DwUfsDmeSet (Private->RegBase, 0x8009, 5, 0x1);
    465   DwUfsDmeSet (Private->RegBase, 0xd085, 0, 1);
    466   DwUfsDmeSet (Private->RegBase, 0x8113, 0, 1);
    467   DwUfsDmeSet (Private->RegBase, 0xd085, 0, 1);
    468   DwUfsDmeSet (Private->RegBase, 0x0095, 4, 0x4a);
    469   DwUfsDmeSet (Private->RegBase, 0x0095, 5, 0x4a);
    470   DwUfsDmeSet (Private->RegBase, 0x0094, 4, 0x4a);
    471   DwUfsDmeSet (Private->RegBase, 0x0094, 5, 0x4a);
    472   DwUfsDmeSet (Private->RegBase, 0x008f, 4, 0x7);
    473   DwUfsDmeSet (Private->RegBase, 0x008f, 5, 0x7);
    474   DwUfsDmeSet (Private->RegBase, 0x000f, 0, 0x5);
    475   DwUfsDmeSet (Private->RegBase, 0x000f, 1, 0x5);
    476   DwUfsDmeSet (Private->RegBase, 0xd085, 0, 1);
    477 
    478   Status = DwUfsDmeGet (Private->RegBase, 0xd0c1, 0, &Data);
    479   ASSERT_EFI_ERROR (Status);
    480   ASSERT (Data == 1);
    481 
    482   DwUfsDmeSet (Private->RegBase, 0xd0c1, 0, 0);
    483   for (;;) {
    484     Status = DwUfsDmeGet (Private->RegBase, 0x0041, 0, &Fsm0);
    485     ASSERT_EFI_ERROR (Status);
    486     Status = DwUfsDmeGet (Private->RegBase, 0x0041, 1, &Fsm1);
    487     ASSERT_EFI_ERROR (Status);
    488     if ((Fsm0 == 1) && (Fsm1 == 1)) {
    489       break;
    490     }
    491   }
    492 
    493   MmioWrite32 (Private->RegBase + UFS_HC_HCLKDIV_OFFSET, 0xE4);
    494   Data = MmioRead32 (Private->RegBase + UFS_HC_AHIT_OFFSET);
    495   Data &= ~0x3FF;
    496   MmioWrite32 (Private->RegBase + UFS_HC_AHIT_OFFSET, Data);
    497 
    498   DwUfsDmeSet (Private->RegBase, 0x155e, 0, 0);
    499   DwUfsDmeSet (Private->RegBase, 0xd0ab, 0, 0);
    500 
    501   Status = DwUfsDmeGet (Private->RegBase, 0xd0ab, 0, &Data);
    502   ASSERT_EFI_ERROR ((Status) && (Data == 0));
    503 
    504   DwUfsDmeSet (Private->RegBase, 0x2044, 0, 0);
    505   DwUfsDmeSet (Private->RegBase, 0x2045, 0, 0);
    506   DwUfsDmeSet (Private->RegBase, 0x2040, 0, 9);
    507   return EFI_SUCCESS;
    508 }
    509 
    510 EFI_STATUS
    511 EFIAPI
    512 UfsHcPhySetPowerMode (
    513   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL        *This,
    514   IN     UINT32                                    DevQuirks
    515   )
    516 {
    517   UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
    518   UINT32                            Data, TxLanes, RxLanes;
    519 
    520   Private  = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
    521 
    522   if (DevQuirks & UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME) {
    523     DEBUG ((DEBUG_INFO | DEBUG_LOAD, "ufs: H**** device must set VS_DebugSaveConfigTime 0x10\n"));
    524     /* VS_DebugSaveConfigTime */
    525     DwUfsDmeSet (Private->RegBase, 0xD0A0, 0x0, 0x10);
    526     /* sync length */
    527     DwUfsDmeSet (Private->RegBase, 0x1556, 0x0, 0x48);
    528   }
    529 
    530   // PA_Tactive
    531   DwUfsDmeGet (Private->RegBase, 0x15A8, 0, &Data);
    532   if (Data < 7) {
    533     DwUfsDmeSet (Private->RegBase, 0x15A8, 4, 7);
    534   }
    535   DwUfsDmeGet (Private->RegBase, 0x1561, 0, &TxLanes);
    536   DwUfsDmeGet (Private->RegBase, 0x1581, 0, &RxLanes);
    537 
    538   // PA TxSkip
    539   DwUfsDmeSet (Private->RegBase, 0x155C, 0, 0);
    540   // PA TxGear
    541   DwUfsDmeSet (Private->RegBase, 0x1568, 0, 3);
    542   // PA RxGear
    543   DwUfsDmeSet (Private->RegBase, 0x1583, 0, 3);
    544   // PA HSSeries
    545   DwUfsDmeSet (Private->RegBase, 0x156A, 0, 2);
    546   // PA TxTermination
    547   DwUfsDmeSet (Private->RegBase, 0x1569, 0, 1);
    548   // PA RxTermination
    549   DwUfsDmeSet (Private->RegBase, 0x1584, 0, 1);
    550   // PA Scrambling
    551   DwUfsDmeSet (Private->RegBase, 0x1585, 0, 0);
    552   // PA ActiveTxDataLines
    553   DwUfsDmeSet (Private->RegBase, 0x1560, 0, TxLanes);
    554   // PA ActiveRxDataLines
    555   DwUfsDmeSet (Private->RegBase, 0x1580, 0, RxLanes);
    556   // PA_PWRModeUserData0 = 8191
    557   DwUfsDmeSet (Private->RegBase, 0x15B0, 0, 8191);
    558   // PA_PWRModeUserData1 = 65535
    559   DwUfsDmeSet (Private->RegBase, 0x15B1, 0, 65535);
    560   // PA_PWRModeUserData2 = 32767
    561   DwUfsDmeSet (Private->RegBase, 0x15B2, 0, 32767);
    562   // DME_FC0ProtectionTimeOutVal = 8191
    563   DwUfsDmeSet (Private->RegBase, 0xD041, 0, 8191);
    564   // DME_TC0ReplayTimeOutVal = 65535
    565   DwUfsDmeSet (Private->RegBase, 0xD042, 0, 65535);
    566   // DME_AFC0ReqTimeOutVal = 32767
    567   DwUfsDmeSet (Private->RegBase, 0xD043, 0, 32767);
    568   // PA_PWRModeUserData3 = 8191
    569   DwUfsDmeSet (Private->RegBase, 0x15B3, 0, 8191);
    570   // PA_PWRModeUserData4 = 65535
    571   DwUfsDmeSet (Private->RegBase, 0x15B4, 0, 65535);
    572   // PA_PWRModeUserData5 = 32767
    573   DwUfsDmeSet (Private->RegBase, 0x15B5, 0, 32767);
    574   // DME_FC1ProtectionTimeOutVal = 8191
    575   DwUfsDmeSet (Private->RegBase, 0xD044, 0, 8191);
    576   // DME_TC1ReplayTimeOutVal = 65535
    577   DwUfsDmeSet (Private->RegBase, 0xD045, 0, 65535);
    578   // DME_AFC1ReqTimeOutVal = 32767
    579   DwUfsDmeSet (Private->RegBase, 0xD046, 0, 32767);
    580 
    581   DwUfsDmeSet (Private->RegBase, 0x1571, 0, 0x11);
    582   do {
    583     Data = MmioRead32(Private->RegBase + UFS_HC_IS_OFFSET);
    584   } while ((Data & UFS_INT_UPMS) == 0);
    585   MmioWrite32(Private->RegBase + UFS_HC_IS_OFFSET, UFS_INT_UPMS);
    586   Data = MmioRead32(Private->RegBase + UFS_HC_STATUS_OFFSET);
    587   if ((Data & HCS_UPMCRS_MASK) == HCS_PWR_LOCAL) {
    588     DEBUG ((DEBUG_INFO, "ufs: change power mode success\n"));
    589   } else {
    590     DEBUG ((DEBUG_ERROR, "ufs: HCS.UPMCRS error, HCS:0x%x\n", Data));
    591   }
    592   return EFI_SUCCESS;
    593 }
    594 
    595 /**
    596   Tests to see if this driver supports a given controller. If a child device is provided,
    597   it further tests to see if this driver supports creating a handle for the specified child device.
    598 
    599   This function checks to see if the driver specified by This supports the device specified by
    600   ControllerHandle. Drivers will typically use the device path attached to
    601   ControllerHandle and/or the services from the bus I/O abstraction attached to
    602   ControllerHandle to determine if the driver supports ControllerHandle. This function
    603   may be called many times during platform initialization. In order to reduce boot times, the tests
    604   performed by this function must be very small, and take as little time as possible to execute. This
    605   function must not change the state of any hardware devices, and this function must be aware that the
    606   device specified by ControllerHandle may already be managed by the same driver or a
    607   different driver. This function must match its calls to AllocatePages() with FreePages(),
    608   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
    609   Since ControllerHandle may have been previously started by the same driver, if a protocol is
    610   already in the opened state, then it must not be closed with CloseProtocol(). This is required
    611   to guarantee the state of ControllerHandle is not modified by this function.
    612 
    613   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    614   @param[in]  ControllerHandle     The handle of the controller to test. This handle
    615                                    must support a protocol interface that supplies
    616                                    an I/O abstraction to the driver.
    617   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    618                                    parameter is ignored by device drivers, and is optional for bus
    619                                    drivers. For bus drivers, if this parameter is not NULL, then
    620                                    the bus driver must determine if the bus controller specified
    621                                    by ControllerHandle and the child controller specified
    622                                    by RemainingDevicePath are both supported by this
    623                                    bus driver.
    624 
    625   @retval EFI_SUCCESS              The device specified by ControllerHandle and
    626                                    RemainingDevicePath is supported by the driver specified by This.
    627   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
    628                                    RemainingDevicePath is already being managed by the driver
    629                                    specified by This.
    630   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
    631                                    RemainingDevicePath is already being managed by a different
    632                                    driver or an application that requires exclusive access.
    633                                    Currently not implemented.
    634   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
    635                                    RemainingDevicePath is not supported by the driver specified by This.
    636 **/
    637 EFI_STATUS
    638 EFIAPI
    639 UfsHcDriverBindingSupported (
    640   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    641   IN EFI_HANDLE                   Controller,
    642   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    643   )
    644 {
    645   EFI_STATUS                Status;
    646   BOOLEAN                   UfsHcFound;
    647   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath = NULL;
    648   EFI_PCI_IO_PROTOCOL       *PciIo = NULL;
    649   PCI_TYPE00                PciData;
    650 
    651   ParentDevicePath = NULL;
    652   UfsHcFound       = FALSE;
    653 
    654   //
    655   // UfsHcDxe is a device driver, and should ingore the
    656   // "RemainingDevicePath" according to EFI spec
    657   //
    658   Status = gBS->OpenProtocol (
    659                   Controller,
    660                   &gEfiDevicePathProtocolGuid,
    661                   (VOID *) &ParentDevicePath,
    662                   This->DriverBindingHandle,
    663                   Controller,
    664                   EFI_OPEN_PROTOCOL_BY_DRIVER
    665                   );
    666   if (EFI_ERROR (Status)) {
    667     //
    668     // EFI_ALREADY_STARTED is also an error
    669     //
    670     return Status;
    671   }
    672   //
    673   // Close the protocol because we don't use it here
    674   //
    675   gBS->CloseProtocol (
    676         Controller,
    677         &gEfiDevicePathProtocolGuid,
    678         This->DriverBindingHandle,
    679         Controller
    680         );
    681 
    682   //
    683   // Now test the EfiPciIoProtocol
    684   //
    685   Status = gBS->OpenProtocol (
    686                   Controller,
    687                   &gEfiPciIoProtocolGuid,
    688                   (VOID **) &PciIo,
    689                   This->DriverBindingHandle,
    690                   Controller,
    691                   EFI_OPEN_PROTOCOL_BY_DRIVER
    692                   );
    693   if (EFI_ERROR (Status)) {
    694     return Status;
    695   }
    696   //
    697   // Now further check the PCI header: Base class (offset 0x0B) and
    698   // Sub Class (offset 0x0A). This controller should be an UFS controller
    699   //
    700   Status = PciIo->Pci.Read (
    701                         PciIo,
    702                         EfiPciIoWidthUint8,
    703                         0,
    704                         sizeof (PciData),
    705                         &PciData
    706                         );
    707   if (EFI_ERROR (Status)) {
    708     gBS->CloseProtocol (
    709           Controller,
    710           &gEfiPciIoProtocolGuid,
    711           This->DriverBindingHandle,
    712           Controller
    713           );
    714     return EFI_UNSUPPORTED;
    715   }
    716 
    717   //
    718   // Since we already got the PciData, we can close protocol to avoid to carry it on for multiple exit points.
    719   //
    720   gBS->CloseProtocol (
    721         Controller,
    722         &gEfiPciIoProtocolGuid,
    723         This->DriverBindingHandle,
    724         Controller
    725         );
    726 
    727   //
    728   // Examine UFS Host Controller PCI Configuration table fields
    729   //
    730   if (PciData.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE) {
    731     if (PciData.Hdr.ClassCode[1] == 0x09 ) { //UFS Controller Subclass
    732       UfsHcFound = TRUE;
    733     }
    734   }
    735 
    736   if (!UfsHcFound) {
    737     return EFI_UNSUPPORTED;
    738   }
    739 
    740   return Status;
    741 }
    742 
    743 /**
    744   Starts a device controller or a bus controller.
    745 
    746   The Start() function is designed to be invoked from the EFI boot service ConnectController().
    747   As a result, much of the error checking on the parameters to Start() has been moved into this
    748   common boot service. It is legal to call Start() from other locations,
    749   but the following calling restrictions must be followed or the system behavior will not be deterministic.
    750   1. ControllerHandle must be a valid EFI_HANDLE.
    751   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
    752      EFI_DEVICE_PATH_PROTOCOL.
    753   3. Prior to calling Start(), the Supported() function for the driver specified by This must
    754      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
    755 
    756   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    757   @param[in]  ControllerHandle     The handle of the controller to start. This handle
    758                                    must support a protocol interface that supplies
    759                                    an I/O abstraction to the driver.
    760   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    761                                    parameter is ignored by device drivers, and is optional for bus
    762                                    drivers. For a bus driver, if this parameter is NULL, then handles
    763                                    for all the children of Controller are created by this driver.
    764                                    If this parameter is not NULL and the first Device Path Node is
    765                                    not the End of Device Path Node, then only the handle for the
    766                                    child device specified by the first Device Path Node of
    767                                    RemainingDevicePath is created by this driver.
    768                                    If the first Device Path Node of RemainingDevicePath is
    769                                    the End of Device Path Node, no child handle is created by this
    770                                    driver.
    771 
    772   @retval EFI_SUCCESS              The device was started.
    773   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
    774   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
    775   @retval Others                   The driver failded to start the device.
    776 
    777 **/
    778 EFI_STATUS
    779 EFIAPI
    780 UfsHcDriverBindingStart (
    781   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    782   IN EFI_HANDLE                   Controller,
    783   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    784   )
    785 {
    786   EFI_STATUS                        Status;
    787   EFI_PCI_IO_PROTOCOL               *PciIo;
    788   UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
    789   UINT64                            Supports;
    790   UINT8                             BarIndex;
    791   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;
    792   UINT32                            BaseAddress;
    793 
    794   PciIo    = NULL;
    795   Private  = NULL;
    796   Supports = 0;
    797   BarDesc  = NULL;
    798   BaseAddress = PcdGet32 (PcdDwUfsHcDxeBaseAddress);
    799 
    800   //
    801   // Now test and open the EfiPciIoProtocol
    802   //
    803   Status = gBS->OpenProtocol (
    804                   Controller,
    805                   &gEfiPciIoProtocolGuid,
    806                   (VOID **) &PciIo,
    807                   This->DriverBindingHandle,
    808                   Controller,
    809                   EFI_OPEN_PROTOCOL_BY_DRIVER
    810                   );
    811   //
    812   // Status == 0 - A normal execution flow, SUCCESS and the program proceeds.
    813   // Status == ALREADY_STARTED - A non-zero Status code returned. It indicates
    814   //           that the protocol has been opened and should be treated as a
    815   //           normal condition and the program proceeds. The Protocol will not
    816   //           opened 'again' by this call.
    817   // Status != ALREADY_STARTED - Error status, terminate program execution
    818   //
    819   if (EFI_ERROR (Status)) {
    820     //
    821     // EFI_ALREADY_STARTED is also an error
    822     //
    823     return Status;
    824   }
    825 
    826   //BaseAddress = PcdGet32 (PcdDwUfsHcDxeBaseAddress);
    827   Private = AllocateCopyPool (sizeof (UFS_HOST_CONTROLLER_PRIVATE_DATA), &gUfsHcTemplate);
    828   if (Private == NULL) {
    829     Status = EFI_OUT_OF_RESOURCES;
    830     goto Done;
    831   }
    832 
    833   Private->RegBase = (UINTN)BaseAddress;
    834   Private->PciIo = PciIo;
    835 
    836   for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {
    837     Status = PciIo->GetBarAttributes (
    838                       PciIo,
    839                       BarIndex,
    840                       NULL,
    841                       (VOID**) &BarDesc
    842                       );
    843     if (Status == EFI_UNSUPPORTED) {
    844       continue;
    845     } else if (EFI_ERROR (Status)) {
    846       goto Done;
    847     }
    848 
    849     if (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
    850       Private->BarIndex = BarIndex;
    851       FreePool (BarDesc);
    852       break;
    853     }
    854 
    855     FreePool (BarDesc);
    856   }
    857 
    858   Status = PciIo->Attributes (
    859                     PciIo,
    860                     EfiPciIoAttributeOperationGet,
    861                     0,
    862                     &Private->PciAttributes
    863                     );
    864 
    865   if (EFI_ERROR (Status)) {
    866     goto Done;
    867   }
    868 
    869   Status = PciIo->Attributes (
    870                     PciIo,
    871                     EfiPciIoAttributeOperationSupported,
    872                     0,
    873                     &Supports
    874                     );
    875 
    876   if (!EFI_ERROR (Status)) {
    877     Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
    878     Status    = PciIo->Attributes (
    879                          PciIo,
    880                          EfiPciIoAttributeOperationEnable,
    881                          Supports,
    882                          NULL
    883                          );
    884   } else {
    885     goto Done;
    886   }
    887 
    888   ///
    889   /// Install UFS_HOST_CONTROLLER protocol
    890   ///
    891   Status = gBS->InstallProtocolInterface (
    892                   &Controller,
    893                   &gEdkiiUfsHostControllerProtocolGuid,
    894                   EFI_NATIVE_INTERFACE,
    895                   (VOID*)&(Private->UfsHc)
    896                   );
    897 
    898 Done:
    899   if (EFI_ERROR (Status)) {
    900     if ((Private != NULL) && (Private->PciAttributes != 0)) {
    901       //
    902       // Restore original PCI attributes
    903       //
    904       Status = PciIo->Attributes (
    905                         PciIo,
    906                         EfiPciIoAttributeOperationSet,
    907                         Private->PciAttributes,
    908                         NULL
    909                         );
    910       ASSERT_EFI_ERROR (Status);
    911     }
    912     gBS->CloseProtocol (
    913           Controller,
    914           &gEfiPciIoProtocolGuid,
    915           This->DriverBindingHandle,
    916           Controller
    917           );
    918     if (Private != NULL) {
    919       FreePool (Private);
    920     }
    921   }
    922 
    923   return Status;
    924 }
    925 
    926 /**
    927   Stops a device controller or a bus controller.
    928 
    929   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
    930   As a result, much of the error checking on the parameters to Stop() has been moved
    931   into this common boot service. It is legal to call Stop() from other locations,
    932   but the following calling restrictions must be followed or the system behavior will not be deterministic.
    933   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
    934      same driver's Start() function.
    935   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
    936      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
    937      Start() function, and the Start() function must have called OpenProtocol() on
    938      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
    939 
    940   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    941   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
    942                                 support a bus specific I/O protocol for the driver
    943                                 to use to stop the device.
    944   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
    945   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
    946                                 if NumberOfChildren is 0.
    947 
    948   @retval EFI_SUCCESS           The device was stopped.
    949   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
    950 
    951 **/
    952 EFI_STATUS
    953 EFIAPI
    954 UfsHcDriverBindingStop (
    955   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
    956   IN  EFI_HANDLE                      Controller,
    957   IN  UINTN                           NumberOfChildren,
    958   IN  EFI_HANDLE                      *ChildHandleBuffer
    959   )
    960 {
    961   EFI_STATUS                          Status;
    962   UFS_HOST_CONTROLLER_PRIVATE_DATA    *Private;
    963   EDKII_UFS_HOST_CONTROLLER_PROTOCOL  *UfsHc;
    964 
    965   ///
    966   /// Get private data
    967   ///
    968   Status = gBS->OpenProtocol (
    969                   Controller,
    970                   &gEdkiiUfsHostControllerProtocolGuid,
    971                   (VOID **) &UfsHc,
    972                   This->DriverBindingHandle,
    973                   Controller,
    974                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    975                   );
    976 
    977   if (EFI_ERROR (Status)) {
    978     return EFI_DEVICE_ERROR;
    979   }
    980 
    981   Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (UfsHc);
    982 
    983   Status = gBS->UninstallProtocolInterface (
    984                   Controller,
    985                   &gEdkiiUfsHostControllerProtocolGuid,
    986                   &(Private->UfsHc)
    987                   );
    988   if (!EFI_ERROR (Status)) {
    989     //
    990     // Restore original PCI attributes
    991     //
    992     Status = Private->PciIo->Attributes (
    993                                Private->PciIo,
    994                                EfiPciIoAttributeOperationSet,
    995                                Private->PciAttributes,
    996                                NULL
    997                                );
    998     ASSERT_EFI_ERROR (Status);
    999 
   1000     //
   1001     // Close protocols opened by UFS host controller driver
   1002     //
   1003     gBS->CloseProtocol (
   1004            Controller,
   1005            &gEfiPciIoProtocolGuid,
   1006            This->DriverBindingHandle,
   1007            Controller
   1008            );
   1009 
   1010     FreePool (Private);
   1011   }
   1012 
   1013   return Status;
   1014 }
   1015 
   1016 /**
   1017   The entry point for UFS host controller driver, used to install this driver on the ImageHandle.
   1018 
   1019   @param[in]  ImageHandle   The firmware allocated handle for this driver image.
   1020   @param[in]  SystemTable   Pointer to the EFI system table.
   1021 
   1022   @retval EFI_SUCCESS   Driver loaded.
   1023   @retval other         Driver not loaded.
   1024 
   1025 **/
   1026 EFI_STATUS
   1027 EFIAPI
   1028 UfsHcDriverEntry (
   1029   IN EFI_HANDLE        ImageHandle,
   1030   IN EFI_SYSTEM_TABLE  *SystemTable
   1031   )
   1032 {
   1033   EFI_STATUS           Status;
   1034 
   1035   Status = EfiLibInstallDriverBindingComponentName2 (
   1036              ImageHandle,
   1037              SystemTable,
   1038              &gUfsHcDriverBinding,
   1039              ImageHandle,
   1040              &gUfsHcComponentName,
   1041              &gUfsHcComponentName2
   1042              );
   1043   ASSERT_EFI_ERROR (Status);
   1044 
   1045   return Status;
   1046 }
   1047