Hi Ard,

> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +XenonHcRwMmio (
> > +  IN     EFI_PCI_IO_PROTOCOL   *PciIo,
> > +  IN     UINT8                 BarIndex,
> > +  IN     UINT32                Offset,
> > +  IN     BOOLEAN               Read,
> > +  IN     UINT8                 Count,
> > +  IN OUT VOID                  *Data
> > +  )
> > +{
> > +  EFI_STATUS                   Status;
> > +
> > +  if ((PciIo == NULL) || (Data == NULL))  {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  if ((Count != 1) && (Count != 2) && (Count != 4) && (Count != 8)) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  if (Read) {
> > +    Status = PciIo->Mem.Read (
> > +                          PciIo,
> > +                          EfiPciIoWidthUint8,
> > +                          BarIndex,
> > +                          (UINT64) Offset,
> > +                          Count,
> > +                          Data
> > +                          );
> > +  } else {
> > +    Status = PciIo->Mem.Write (
> > +                          PciIo,
> > +                          EfiPciIoWidthUint8,
> > +                          BarIndex,
> > +                          (UINT64) Offset,
> > +                          Count,
> > +                          Data
> > +                          );
> > +  }
> > +
>
> I guess this is an issue that existed before in the code, but it looks
> like you are only doing byte for byte reads and writes here. Is that
> intentional?
>

XenonHcRwMmio is 1:1 to generic MdeModulePkg's SdMmcHcRwMmio, as well
as all other SdMmc mmio accessors. I really prefer not to modify any
of them and keep the code aligned as-is.

Best regards,
Marcin

> > +  return Status;
> > +}
> > +
> > +/**
> > +  Do OR operation with the value of the specified SD/MMC host controller 
> > mmio register.
> > +
> > +  @param[in] PciIo             The PCI IO protocol instance.
> > +  @param[in] BarIndex          The BAR index of the standard PCI 
> > Configuration
> > +                               header to use as the base address for the 
> > memory
> > +                               operation to perform.
> > +  @param[in] Offset            The offset within the selected BAR to start 
> > the
> > +                               memory operation.
> > +  @param[in] Count             The width of the mmio register in bytes.
> > +                               Must be 1, 2 , 4 or 8 bytes.
> > +  @param[in] OrData            The pointer to the data used to do OR 
> > operation.
> > +                               The caller is responsible for having 
> > ownership of
> > +                               the data buffer and ensuring its size not 
> > less than
> > +                               Count bytes.
> > +
> > +  @retval EFI_INVALID_PARAMETER The PciIo or OrData is NULL or the Count 
> > is not valid.
> > +  @retval EFI_SUCCESS           The OR operation succeeds.
> > +  @retval Others                The OR operation fails.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +XenonHcOrMmio (
> > +  IN  EFI_PCI_IO_PROTOCOL      *PciIo,
> > +  IN  UINT8                    BarIndex,
> > +  IN  UINT32                   Offset,
> > +  IN  UINT8                    Count,
> > +  IN  VOID                     *OrData
> > +  )
> > +{
> > +  EFI_STATUS                   Status;
> > +  UINT64                       Data;
> > +  UINT64                       Or;
> > +
> > +  Status = XenonHcRwMmio (PciIo, BarIndex, Offset, TRUE, Count, &Data);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  if (Count == 1) {
> > +    Or = *(UINT8*) OrData;
> > +  } else if (Count == 2) {
> > +    Or = *(UINT16*) OrData;
> > +  } else if (Count == 4) {
> > +    Or = *(UINT32*) OrData;
> > +  } else if (Count == 8) {
> > +    Or = *(UINT64*) OrData;
> > +  } else {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Data  |= Or;
> > +  Status = XenonHcRwMmio (PciIo, BarIndex, Offset, FALSE, Count, &Data);
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Do AND operation with the value of the specified SD/MMC host controller 
> > mmio register.
> > +
> > +  @param[in] PciIo             The PCI IO protocol instance.
> > +  @param[in] BarIndex          The BAR index of the standard PCI 
> > Configuration
> > +                               header to use as the base address for the 
> > memory
> > +                               operation to perform.
> > +  @param[in] Offset            The offset within the selected BAR to start 
> > the
> > +                               memory operation.
> > +  @param[in] Count             The width of the mmio register in bytes.
> > +                               Must be 1, 2 , 4 or 8 bytes.
> > +  @param[in] AndData           The pointer to the data used to do AND 
> > operation.
> > +                               The caller is responsible for having 
> > ownership of
> > +                               the data buffer and ensuring its size not 
> > less than
> > +                               Count bytes.
> > +
> > +  @retval EFI_INVALID_PARAMETER The PciIo or AndData is NULL or the Count 
> > is not valid.
> > +  @retval EFI_SUCCESS           The AND operation succeeds.
> > +  @retval Others                The AND operation fails.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +XenonHcAndMmio (
> > +  IN  EFI_PCI_IO_PROTOCOL      *PciIo,
> > +  IN  UINT8                    BarIndex,
> > +  IN  UINT32                   Offset,
> > +  IN  UINT8                    Count,
> > +  IN  VOID                     *AndData
> > +  )
> > +{
> > +  EFI_STATUS                   Status;
> > +  UINT64                       Data;
> > +  UINT64                       And;
> > +
> > +  Status = XenonHcRwMmio (PciIo, BarIndex, Offset, TRUE, Count, &Data);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  if (Count == 1) {
> > +    And = *(UINT8*) AndData;
> > +  } else if (Count == 2) {
> > +    And = *(UINT16*) AndData;
> > +  } else if (Count == 4) {
> > +    And = *(UINT32*) AndData;
> > +  } else if (Count == 8) {
> > +    And = *(UINT64*) AndData;
> > +  } else {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Data  &= And;
> > +  Status = XenonHcRwMmio (PciIo, BarIndex, Offset, FALSE, Count, &Data);
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Wait for the value of the specified MMIO register set to the test value.
> > +
> > +  @param[in]  PciIo         The PCI IO protocol instance.
> > +  @param[in]  BarIndex      The BAR index of the standard PCI Configuration
> > +                            header to use as the base address for the 
> > memory
> > +                            operation to perform.
> > +  @param[in]  Offset        The offset within the selected BAR to start the
> > +                            memory operation.
> > +  @param[in]  Count         The width of the mmio register in bytes.
> > +                            Must be 1, 2, 4 or 8 bytes.
> > +  @param[in]  MaskValue     The mask value of memory.
> > +  @param[in]  TestValue     The test value of memory.
> > +
> > +  @retval EFI_NOT_READY     The MMIO register hasn't set to the expected 
> > value.
> > +  @retval EFI_SUCCESS       The MMIO register has expected value.
> > +  @retval Others            The MMIO operation fails.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +XenonHcCheckMmioSet (
> > +  IN  EFI_PCI_IO_PROTOCOL       *PciIo,
> > +  IN  UINT8                     BarIndex,
> > +  IN  UINT32                    Offset,
> > +  IN  UINT8                     Count,
> > +  IN  UINT64                    MaskValue,
> > +  IN  UINT64                    TestValue
> > +  )
> > +{
> > +  EFI_STATUS            Status;
> > +  UINT64                Value;
> > +
> > +  //
> > +  // Access PCI MMIO space to see if the value is the tested one.
> > +  //
> > +  Value  = 0;
> > +  Status = XenonHcRwMmio (PciIo, BarIndex, Offset, TRUE, Count, &Value);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  Value &= MaskValue;
> > +
> > +  if (Value == TestValue) {
> > +    return EFI_SUCCESS;
> > +  }
> > +
> > +  return EFI_NOT_READY;
> > +}
> > +
> > +/**
> > +  Wait for the value of the specified MMIO register set to the test value.
> > +
> > +  @param[in]  PciIo         The PCI IO protocol instance.
> > +  @param[in]  BarIndex      The BAR index of the standard PCI Configuration
> > +                            header to use as the base address for the 
> > memory
> > +                            operation to perform.
> > +  @param[in]  Offset        The offset within the selected BAR to start the
> > +                            memory operation.
> > +  @param[in]  Count         The width of the mmio register in bytes.
> > +                            Must be 1, 2, 4 or 8 bytes.
> > +  @param[in]  MaskValue     The mask value of memory.
> > +  @param[in]  TestValue     The test value of memory.
> > +  @param[in]  Timeout       The time out value for wait memory set, uses 1
> > +                            microsecond as a unit.
> > +
> > +  @retval EFI_TIMEOUT       The MMIO register hasn't expected value in 
> > timeout
> > +                            range.
> > +  @retval EFI_SUCCESS       The MMIO register has expected value.
> > +  @retval Others            The MMIO operation fails.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +XenonHcWaitMmioSet (
> > +  IN  EFI_PCI_IO_PROTOCOL       *PciIo,
> > +  IN  UINT8                     BarIndex,
> > +  IN  UINT32                    Offset,
> > +  IN  UINT8                     Count,
> > +  IN  UINT64                    MaskValue,
> > +  IN  UINT64                    TestValue,
> > +  IN  UINT64                    Timeout
> > +  )
> > +{
> > +  EFI_STATUS            Status;
> > +  BOOLEAN               InfiniteWait;
> > +
> > +  if (Timeout == 0) {
> > +    InfiniteWait = TRUE;
> > +  } else {
> > +    InfiniteWait = FALSE;
> > +  }
> > +
> > +  while (InfiniteWait || (Timeout > 0)) {
> > +    Status = XenonHcCheckMmioSet (
> > +               PciIo,
> > +               BarIndex,
> > +               Offset,
> > +               Count,
> > +               MaskValue,
> > +               TestValue
> > +               );
> > +    if (Status != EFI_NOT_READY) {
> > +      return Status;
> > +    }
> > +
> > +    //
> > +    // Stall for 1 microsecond.
> > +    //
> > +    gBS->Stall (1);
> > +
> > +    Timeout--;
> > +  }
> > +
> > +  return EFI_TIMEOUT;
> > +}
> > diff --git a/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdMmcOverride.c 
> > b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdMmcOverride.c
> > new file mode 100644
> > index 0000000..7babda1
> > --- /dev/null
> > +++ b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdMmcOverride.c
> > @@ -0,0 +1,432 @@
> > +/*******************************************************************************
> > +Copyright (C) 2018 Marvell International Ltd.
> > +
> > +Marvell BSD License Option
> > +
> > +If you received this File from Marvell, you may opt to use, redistribute 
> > and/or
> > +modify this File under the following licensing terms.
> > +Redistribution and use in source and binary forms, with or without 
> > modification,
> > +are permitted provided that the following conditions are met:
> > +
> > +* Redistributions of source code must retain the above copyright notice,
> > +  this list of conditions and the following disclaimer.
> > +
> > +* Redistributions in binary form must reproduce the above copyright
> > +  notice, this list of conditions and the following disclaimer in the
> > +  documentation and/or other materials provided with the distribution.
> > +
> > +* Neither the name of Marvell nor the names of its contributors may be
> > +  used to endorse or promote products derived from this software without
> > +  specific prior written permission.
> > +
> > +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
> > IS" AND
> > +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
> > IMPLIED
> > +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> > +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
> > LIABLE FOR
> > +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
> > DAMAGES
> > +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
> > SERVICES;
> > +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
> > AND ON
> > +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> > +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
> > THIS
> > +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> > +
> > +*******************************************************************************/
> > +
> > +#include "XenonSdMmcOverride.h"
> > +
> > +STATIC EFI_HANDLE              mXenonSdMmcOverrideHandle;
> > +STATIC EDKII_SD_MMC_OVERRIDE  *mSdMmcOverride;
> > +
> > +STATIC
> > +EFI_STATUS
> > +EFIAPI
> > +XenonGetSdMmcDesc (
> > +  IN      EFI_HANDLE              ControllerHandle,
> > +  IN OUT  MV_BOARD_SDMMC_DESC     *SdMmcDesc
> > +  )
> > +{
> > +  EFI_STATUS                      Status;
> > +  MV_BOARD_SDMMC_DESC             *SdMmcDescs;
> > +  NON_DISCOVERABLE_DEVICE         *Device;
> > +  MARVELL_BOARD_DESC_PROTOCOL     *BoardDescProtocol;
> > +  UINTN                           Index;
> > +
> > +  Device = NULL;
> > +  Status = gBS->OpenProtocol (ControllerHandle,
> > +                  &gEdkiiNonDiscoverableDeviceProtocolGuid,
> > +                  (VOID **) &Device,
> > +                  mXenonSdMmcOverrideHandle,
> > +                  ControllerHandle,
> > +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  BoardDescProtocol = NULL;
> > +  Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid,
> > +                  NULL,
> > +                  (VOID **) &BoardDescProtocol);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  Status = BoardDescProtocol->BoardDescSdMmcGet (BoardDescProtocol, 
> > &SdMmcDescs);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  for (Index = 0; Index < SdMmcDescs->SdMmcDevCount; Index++) {
> > +    if (SdMmcDescs[Index].SoC->SdMmcBaseAddress ==
> > +        Device->Resources[0].AddrRangeMin) {
> > +      *SdMmcDesc = SdMmcDescs[Index];
> > +      break;
> > +    }
> > +  }
> > +
> > +  if (Index == SdMmcDescs->SdMmcDevCount) {
> > +    BoardDescProtocol->BoardDescFree (SdMmcDescs);
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  BoardDescProtocol->BoardDescFree (SdMmcDescs);
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +STATIC
> > +EFI_STATUS
> > +XenonGetPciIo (
> > +  IN      EFI_HANDLE              ControllerHandle,
> > +  IN OUT  EFI_PCI_IO_PROTOCOL     **PciIo
> > +  )
> > +{
> > +  EFI_STATUS Status;
> > +
> > +  *PciIo  = NULL;
> > +  Status = gBS->OpenProtocol (ControllerHandle,
> > +                  &gEfiPciIoProtocolGuid,
> > +                  (VOID **) PciIo,
> > +                  mXenonSdMmcOverrideHandle,
> > +                  ControllerHandle,
> > +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL);
> > +  return Status;
> > +}
> > +
> > +/**
> > +  Set SD Host Controler control 2 registry according to selected speed.
> > +
>
> Controller
>
> > +  @param[in] ControllerHandle The EFI_HANDLE of the controller.
> > +  @param[in] Slot             The slot number of the SD card to send the 
> > command to.
> > +  @param[in] Timing           The timing to select.
> > +
> > +  @retval EFI_SUCCESS         The override function completed successfully.
> > +  @retval EFI_NOT_FOUND       The specified controller or slot does not 
> > exist.
> > +**/
> > +STATIC
> > +EFI_STATUS
> > +XenonSdMmcHcUhsSignaling (
> > +  IN EFI_HANDLE             ControllerHandle,
> > +  IN UINT8                  Slot,
> > +  IN SD_MMC_BUS_MODE        Timing
> > +  )
> > +{
> > +  EFI_PCI_IO_PROTOCOL      *PciIo;
> > +  EFI_STATUS                Status;
> > +  UINT8                     HostCtrl2;
> > +  UINT8                     XenonUhsSelect;
> > +
> > +  if (Slot != 0) {
> > +    return EFI_NOT_FOUND;
> > +  }
> > +
> > +  //
> > +  // Update Host Control Register 2 only for HS200/HS400.
> > +  //
> > +  switch (Timing) {
> > +    case SdMmcMmcHs200:
> > +      XenonUhsSelect = XENON_SD_MMC_HC_CTRL_HS200;
> > +      break;
> > +    case SdMmcMmcHs400:
> > +      XenonUhsSelect = XENON_SD_MMC_HC_CTRL_HS400;
> > +      break;
> > +    default:
> > +      return EFI_SUCCESS;
> > +  }
> > +
> > +  Status = XenonGetPciIo (ControllerHandle, &PciIo);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  HostCtrl2 = (UINT8)~UHS_MODE_SELECT_MASK;
> > +  Status = XenonHcAndMmio (PciIo,
> > +             Slot,
> > +             SDHC_HOST_CTRL2,
> > +             sizeof (HostCtrl2),
> > +             &HostCtrl2);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  Status = XenonHcOrMmio (PciIo,
> > +             Slot,
> > +             SDHC_HOST_CTRL2,
> > +             sizeof (XenonUhsSelect),
> > +             &XenonUhsSelect);
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +
> > +  Additional operations specific for host controller
> > +
> > +  @param[in]      ControllerHandle      The EFI_HANDLE of the controller.
> > +  @param[in]      Slot                  The 0 based slot index.
> > +  @param[in]      Timing                The timing which should be set by
> > +                                        host controller.
> > +
> > +  @retval EFI_SUCCESS           The override function completed 
> > successfully.
> > +  @retval EFI_NOT_FOUND         The specified controller or slot does not 
> > exist.
> > +
> > +**/
> > +STATIC
> > +EFI_STATUS
> > +XenonSwitchClockFreqPost (
> > +  IN      EFI_HANDLE                      ControllerHandle,
> > +  IN      UINT8                           Slot,
> > +  IN      SD_MMC_BUS_MODE                 Timing
> > +  )
> > +{
> > +  EFI_STATUS                      Status;
> > +  MV_BOARD_SDMMC_DESC             SdMmcDesc;
> > +  EFI_PCI_IO_PROTOCOL             *PciIo;
> > +
> > +  if (Slot != 0) {
> > +    return EFI_NOT_FOUND;
> > +  }
> > +
> > +  Status = XenonGetPciIo (ControllerHandle, &PciIo);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +  Status = XenonGetSdMmcDesc (ControllerHandle, &SdMmcDesc);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  Status = XenonSetPhy (PciIo,
> > +             SdMmcDesc.XenonSlowModeEnabled,
> > +             SdMmcDesc.XenonTuningStepDivisor,
> > +             Timing);
> > +
> > +  return Status;
> > +}
> > +
> > +/**
> > +
> > +  Override function for SDHCI controller operations
> > +
> > +  @param[in]      ControllerHandle      The EFI_HANDLE of the controller.
> > +  @param[in]      Slot                  The 0 based slot index.
> > +  @param[in]      PhaseType             The type of operation and whether 
> > the
> > +                                        hook is invoked right before (pre) 
> > or
> > +                                        right after (post)
> > +  @param[in]      PhaseData             The pointer to a phase-specific 
> > data.
> > +
> > +  @retval EFI_SUCCESS           The override function completed 
> > successfully.
> > +  @retval EFI_NOT_FOUND         The specified controller or slot does not 
> > exist.
> > +  @retval EFI_UNSUPPORTED       Nothing has been done in connection of 
> > PhaseType
> > +  @retval EFI_INVALID_PARAMETER PhaseType is invalid
> > +
> > +**/
> > +STATIC
> > +EFI_STATUS
> > +EFIAPI
> > +XenonSdMmcNotifyPhase (
> > +  IN      EFI_HANDLE                      ControllerHandle,
> > +  IN      UINT8                           Slot,
> > +  IN      EDKII_SD_MMC_PHASE_TYPE         PhaseType,
> > +  IN OUT  VOID                           *PhaseData
> > +  )
> > +{
> > +  EFI_STATUS                      Status;
> > +  MV_BOARD_SDMMC_DESC             SdMmcDesc;
> > +  EFI_PCI_IO_PROTOCOL             *PciIo;
> > +  SD_MMC_BUS_MODE                 *Timing;
> > +
> > +  if (Slot != 0) {
> > +    return EFI_NOT_FOUND;
> > +  }
> > +
> > +  switch (PhaseType) {
> > +    case EdkiiSdMmcInitHostPre:
> > +      Status = XenonGetPciIo (ControllerHandle, &PciIo);
> > +      if (EFI_ERROR (Status)) {
> > +        return Status;
> > +      }
> > +
> > +      Status = XenonGetSdMmcDesc (ControllerHandle, &SdMmcDesc);
> > +      if (EFI_ERROR (Status)) {
> > +        return Status;
> > +      }
> > +
> > +      Status = XenonInit (PciIo,
> > +                 SdMmcDesc.Xenon1v8Enabled,
> > +                 SdMmcDesc.XenonSlowModeEnabled,
> > +                 SdMmcDesc.XenonTuningStepDivisor);
> > +      return Status;
> > +    case EdkiiSdMmcUhsSignaling:
> > +      if (PhaseData == NULL) {
> > +        return EFI_INVALID_PARAMETER;
> > +      }
> > +
> > +      Timing = (SD_MMC_BUS_MODE *)PhaseData;
> > +
> > +      Status = XenonSdMmcHcUhsSignaling (ControllerHandle,
> > +                 Slot,
> > +                 *Timing);
> > +      if (EFI_ERROR (Status)) {
> > +        return Status;
> > +      }
> > +      break;
> > +    case EdkiiSdMmcSwitchClockFreqPost:
> > +      if (PhaseData == NULL) {
> > +        return EFI_INVALID_PARAMETER;
> > +      }
> > +
> > +      Timing = (SD_MMC_BUS_MODE *)PhaseData;
> > +
> > +      Status = XenonSwitchClockFreqPost (ControllerHandle,
> > +                 Slot,
> > +                 *Timing);
> > +      if (EFI_ERROR (Status)) {
> > +        return Status;
> > +      }
> > +      break;
> > +    default:
> > +      return EFI_SUCCESS;
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +
> > +  Override function for SDHCI capability bits
> > +
> > +  @param[in]      ControllerHandle      The EFI_HANDLE of the controller.
> > +  @param[in]      Slot                  The 0 based slot index.
> > +  @param[in,out]  SdMmcHcSlotCapability The SDHCI capability structure.
> > +  @param[in,out]  BaseClkFreq           The base clock frequency value that
> > +                                        optionally can be updated.
> > +
> > +  @retval EFI_SUCCESS           The override function completed 
> > successfully.
> > +  @retval EFI_NOT_FOUND         The specified controller or slot does not 
> > exist.
> > +  @retval EFI_INVALID_PARAMETER SdMmcHcSlotCapability is NULL
> > +
> > +**/
> > +STATIC
> > +EFI_STATUS
> > +EFIAPI
> > +XenonSdMmcCapability (
> > +  IN      EFI_HANDLE                      ControllerHandle,
> > +  IN      UINT8                           Slot,
> > +  IN OUT  VOID                            *SdMmcHcSlotCapability,
> > +  IN OUT  UINT32                          *BaseClkFreq
> > +  )
> > +{
> > +  EFI_STATUS           Status;
> > +  MV_BOARD_SDMMC_DESC  SdMmcDesc;
> > +  UINT64               Capability;
> > +
> > +  if (SdMmcHcSlotCapability == NULL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +  if (Slot != 0) {
> > +    return EFI_NOT_FOUND;
> > +  }
> > +  Status = XenonGetSdMmcDesc (ControllerHandle, &SdMmcDesc);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  Capability = ReadUnaligned64 (SdMmcHcSlotCapability);
> > +
> > +  //
> > +  // Override capabilities structure according to board configuration.
> > +  //
> > +  if (SdMmcDesc.Xenon1v8Enabled) {
> > +    Capability &= ~(UINT64)(SDHC_CAP_VOLTAGE_33 | SDHC_CAP_VOLTAGE_30);
> > +  } else {
> > +    Capability &= ~(UINT64)(SDHC_CAP_SDR104 | SDHC_CAP_DDR50 |
> > +                            SDHC_CAP_SDR50 | SDHC_CAP_VOLTAGE_18);
> > +  }
> > +
> > +  if (!SdMmcDesc.Xenon8BitBusEnabled) {
> > +    Capability &= ~(UINT64)(SDHC_CAP_BUS_WIDTH8);
> > +  }
> > +
> > +  if (SdMmcDesc.XenonSlowModeEnabled) {
> > +    Capability &= ~(UINT64)(SDHC_CAP_SDR104 | SDHC_CAP_DDR50);
> > +  }
> > +
> > +  Capability &= ~(UINT64)(SDHC_CAP_SLOT_TYPE_MASK);
> > +  Capability |= SdMmcDesc.SlotType << SDHC_CAP_SLOT_TYPE_OFFSET;
> > +
> > +  WriteUnaligned64 (SdMmcHcSlotCapability, Capability);
> > +
> > +  //
> > +  // Override inappropriate base clock frequency from Capabilities 
> > Register 1.
> > +  // Actual clock speed of Xenon controller is 400MHz.
> > +  //
> > +  *BaseClkFreq = XENON_MMC_MAX_CLK / 1000 / 1000;
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  The entry point for Xenon driver, used to install SdMMcOverrideProtocol
> > +  on the ImageHandle.
> > +
> > +  @param[in]  ImageHandle   The firmware allocated handle for this driver 
> > image.
> > +  @param[in]  SystemTable   Pointer to the EFI system table.
> > +
> > +  @retval EFI_SUCCESS   Driver loaded.
> > +  @retval other         Driver not loaded.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +InitializeXenonDxe (
> > +  IN EFI_HANDLE        ImageHandle,
> > +  IN EFI_SYSTEM_TABLE  *SystemTable
> > +  )
> > +{
> > +  EFI_STATUS Status;
> > +
> > +  mSdMmcOverride = AllocateZeroPool (sizeof (EDKII_SD_MMC_OVERRIDE));
> > +  if (mSdMmcOverride == NULL) {
> > +    DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__));
> > +    return EFI_OUT_OF_RESOURCES;
> > +  }
> > +
> > +  mSdMmcOverride->Version = EDKII_SD_MMC_OVERRIDE_PROTOCOL_VERSION;
> > +  mSdMmcOverride->Capability = XenonSdMmcCapability;
> > +  mSdMmcOverride->NotifyPhase = XenonSdMmcNotifyPhase;
> > +
> > +  Status = gBS->InstallProtocolInterface (&ImageHandle,
> > +                  &gEdkiiSdMmcOverrideProtocolGuid,
> > +                  EFI_NATIVE_INTERFACE,
> > +                  mSdMmcOverride);
> > +  if (EFI_ERROR (Status)) {
> > +    DEBUG ((DEBUG_ERROR,
> > +      "%a: Filed to install SdMmcOverride protocol\n",
> > +      __FUNCTION__));
> > +    return Status;
> > +  }
> > +
> > +  mXenonSdMmcOverrideHandle = ImageHandle;
> > +
> > +  return Status;
> > +}
> > diff --git a/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdhci.c 
> > b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdhci.c
> > index 6bbe5bc..0b4949d 100755
> > --- a/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdhci.c
> > +++ b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdhci.c
> > @@ -41,7 +41,7 @@ XenonReadVersion (
> >    OUT UINT32 *ControllerVersion
> >    )
> >  {
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CTRL_VER, TRUE, 
> > SDHC_REG_SIZE_2B, ControllerVersion);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_CTRL_VER, TRUE, 
> > SDHC_REG_SIZE_2B, ControllerVersion);
> >  }
> >
> >  // Auto Clock Gating
> > @@ -54,7 +54,7 @@ XenonSetAcg (
> >  {
> >    UINT32 Var;
> >
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SYS_OP_CTRL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SYS_OP_CTRL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> >
> >    if (Enable) {
> >      Var &= ~AUTO_CLKGATE_DISABLE_MASK;
> > @@ -62,7 +62,7 @@ XenonSetAcg (
> >      Var |= AUTO_CLKGATE_DISABLE_MASK;
> >    }
> >
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SYS_OP_CTRL, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SYS_OP_CTRL, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> >  }
> >
> >  STATIC
> > @@ -75,14 +75,17 @@ XenonSetSlot (
> >  {
> >    UINT32 Var;
> >
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SYS_OP_CTRL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SYS_OP_CTRL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> >    if (Enable) {
> >      Var |= ((0x1 << Slot) << SLOT_ENABLE_SHIFT);
> >    } else {
> >      Var &= ~((0x1 << Slot) << SLOT_ENABLE_SHIFT);
> >    }
> >
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SYS_OP_CTRL, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  // Enable SDCLK off while idle
> > +  Var |= SDCLK_IDLEOFF_ENABLE_MASK;
> > +
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SYS_OP_CTRL, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> >  }
> >
> >  //
> > @@ -111,7 +114,6 @@ XenonSetPower (
> >    )
> >  {
> >    UINT8 Pwr = 0;
> > -  UINT32 Ctrl = 0;
> >
> >    // Below statement calls routine to set voltage for SDIO devices in 
> > either HIGH (1) or LOW (0) mode
> >    switch (Vcc) {
> > @@ -141,39 +143,36 @@ XenonSetPower (
> >    }
> >
> >    if (Pwr == 0) {
> > -    SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_POWER_CTRL, FALSE, 
> > SDHC_REG_SIZE_1B, &Pwr);
> > +    XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_POWER_CTRL, FALSE, 
> > SDHC_REG_SIZE_1B, &Pwr);
> >      return;
> >    }
> >
> >    Pwr |= SDHCI_POWER_ON;
> >
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX,SD_MMC_HC_POWER_CTRL, FALSE, 
> > SDHC_REG_SIZE_1B, &Pwr);
> > -
> > -  // Set VCCQ
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SLOT_eMMC_CTRL, TRUE, 
> > SDHC_REG_SIZE_4B, &Ctrl);
> > -  Ctrl |= Vccq;
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_SLOT_eMMC_CTRL, FALSE, 
> > SDHC_REG_SIZE_4B, &Ctrl);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_POWER_CTRL, FALSE, 
> > SDHC_REG_SIZE_1B, &Pwr);
> >  }
> >
> >  UINTN
> >  XenonSetClk (
> >    IN EFI_PCI_IO_PROTOCOL   *PciIo,
> > -  IN SD_MMC_HC_PRIVATE_DATA *Private,
> >    IN UINT32 Clock
> >    )
> >  {
> >    UINT32 Div;
> >    UINT32 Clk;
> >    UINT32 Retry;
> > +  UINT32 ControllerVersion;
> >    UINT16 Value = 0;
> >
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, FALSE, 
> > SDHC_REG_SIZE_2B, &Value);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_CLOCK_CTRL, FALSE, 
> > SDHC_REG_SIZE_2B, &Value);
> >
> >    if (Clock == 0) {
> >      return 0;
> >    }
> >
> > -  if (Private->ControllerVersion >= SDHCI_SPEC_300) {
> > +  XenonReadVersion (PciIo, &ControllerVersion);
> > +
> > +  if (ControllerVersion >= SDHCI_SPEC_300) {
> >      // Version 3.00 Divisors must be a multiple of 2
> >      if (XENON_MMC_MAX_CLK <= Clock) {
> >        Div = 1;
> > @@ -196,7 +195,7 @@ XenonSetClk (
> >    Clk |= ((Div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) << 
> > SDHCI_DIVIDER_HI_SHIFT;
> >    Clk |= SDHCI_CLOCK_INT_EN;
> >
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, FALSE, 
> > SDHC_REG_SIZE_2B, &Clk);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_CLOCK_CTRL, FALSE, 
> > SDHC_REG_SIZE_2B, &Clk);
> >
> >    //
> >    // Poll for internal controller clock to be stabilised
> > @@ -205,7 +204,7 @@ XenonSetClk (
> >    Retry = 200;
> >
> >    do {
> > -    SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, TRUE, 
> > SDHC_REG_SIZE_2B, &Clk);
> > +    XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_CLOCK_CTRL, TRUE, 
> > SDHC_REG_SIZE_2B, &Clk);
> >      if (Retry == 0) {
> >        DEBUG((DEBUG_ERROR, "SD/MMC: Internal Clock never stabilised\n"));
> >        return -1;
> > @@ -219,7 +218,7 @@ XenonSetClk (
> >    } while (!(Clk & SDHCI_CLOCK_INT_STABLE));
> >
> >    Clk |= SDHCI_CLOCK_CARD_EN;
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, FALSE, 
> > SDHC_REG_SIZE_2B, &Clk);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_CLOCK_CTRL, FALSE, 
> > SDHC_REG_SIZE_2B, &Clk);
> >
> >    return 0;
> >  }
> > @@ -231,54 +230,11 @@ XenonPhyInit (
> >  {
> >    UINT32 Var, Wait, Time;
> >    UINT32 Clock = XENON_MMC_MAX_CLK;
> > -  UINT16 ClkCtrl;
> > -
> > -  // Need to disable the clock to set EMMC_PHY_TIMING_ADJUST register
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, TRUE, 
> > SDHC_REG_SIZE_2B, &ClkCtrl);
> > -  ClkCtrl &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN);
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, FALSE, 
> > SDHC_REG_SIZE_2B, &ClkCtrl);
> > -
> > -  // Enable QSP PHASE SELECT
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > -  Var |= SAMPL_INV_QSP_PHASE_SELECT;
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > -
> > -  // Enable internal clock
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, TRUE, 
> > SDHC_REG_SIZE_2B, &ClkCtrl);
> > -  ClkCtrl |= SDHCI_CLOCK_INT_EN;
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, FALSE, 
> > SDHC_REG_SIZE_2B, &ClkCtrl);
> > -
> > -  //
> > -  // Poll for host MMC PHY clock init to be stable
> > -  // Wait up to 100us
> > -  //
> > -  Time = 100;
> > -  while (Time--) {
> > -    SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > -    if (Var & SDHCI_CLOCK_INT_STABLE) {
> > -      break;
> > -    }
> > -
> > -    // Poll interval for MMC PHY clock to be stable is 1us
> > -    gBS->Stall (1);
> > -  }
> > -  if (Time <= 0) {
> > -    DEBUG((DEBUG_ERROR, "SD/MMC: Failed to enable MMC internal clock in 
> > Time\n"));
> > -    return;
> > -  }
> > -
> > -  // Enable bus clock
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, TRUE, 
> > SDHC_REG_SIZE_2B, &ClkCtrl);
> > -  ClkCtrl |= SDHCI_CLOCK_CARD_EN;
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_CLOCK_CTRL, FALSE, 
> > SDHC_REG_SIZE_2B, &ClkCtrl);
> > -
> > -  // Delay 200us to wait for the completion of bus clock
> > -  gBS->Stall (200);
> >
> >    // Init PHY
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> >    Var |= PHY_INITIALIZAION;
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> >
> >    // Add duration of FC_SYNC_RST
> >    Wait = ((Var >> FC_SYNC_RST_DURATION_SHIFT) & FC_SYNC_RST_DURATION_MASK);
> > @@ -308,7 +264,7 @@ XenonPhyInit (
> >    // Poll for host eMMC PHY init to complete, wait up to 100us
> >    Time = 100;
> >    while (Time--) {
> > -    Var = SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, 
> > TRUE, SDHC_REG_SIZE_4B, &Var);
> > +    Var = XenonHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, 
> > TRUE, SDHC_REG_SIZE_4B, &Var);
> >      Var &= PHY_INITIALIZAION;
> >      if (!Var) {
> >        break;
> > @@ -326,52 +282,227 @@ XenonPhyInit (
> >    return;
> >  }
> >
> > +//
> > +// Enable eMMC PHY HW DLL
> > +// DLL should be enabled and stable before HS200/SDR104 tuning,
> > +// and before HS400 data strobe setting.
> > +//
> >  STATIC
> > -VOID
> > +EFI_STATUS
> > +EmmcPhyEnableDll (
> > +  IN EFI_PCI_IO_PROTOCOL   *PciIo
> > +  )
> > +{
> > +  UINT32 Var;
> > +  UINT16 SlotState;
> > +  UINT8 Retry;
> > +
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_DLL_CONTROL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  if (Var & DLL_ENABLE) {
> > +    return EFI_SUCCESS;
> > +  }
> > +
> > +  // Enable DLL
> > +  Var |= (DLL_ENABLE | DLL_FAST_LOCK);
> > +
> > +  //
> > +  // Set Phase as 90 degree, which is most common value.
> > +  //
> > +  Var &= ~((DLL_PHASE_MASK << DLL_PHSEL0_SHIFT) |
> > +           (DLL_PHASE_MASK << DLL_PHSEL1_SHIFT));
> > +  Var |= ((DLL_PHASE_90_DEGREE << DLL_PHSEL0_SHIFT) |
> > +          (DLL_PHASE_90_DEGREE << DLL_PHSEL1_SHIFT));
> > +
> > +  Var &= ~(DLL_BYPASS_EN | DLL_REFCLK_SEL);
> > +  Var |= DLL_UPDATE;
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_DLL_CONTROL, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +
> > +  // Wait max 32 ms for the DLL to lock
> > +  Retry = 32;
> > +  do {
> > +    XenonHcRwMmio (PciIo, SD_BAR_INDEX, XENON_SLOT_EXT_PRESENT_STATE, 
> > TRUE, SDHC_REG_SIZE_2B, &SlotState);
> > +
> > +    if (Retry == 0) {
> > +      DEBUG ((DEBUG_ERROR, "SD/MMC: Fail to lock DLL\n"));
> > +      return EFI_TIMEOUT;
> > +    }
> > +
> > +    gBS->Stall (1000);
> > +    Retry--;
> > +
> > +  } while (!(SlotState & DLL_LOCK_STATE));
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +//
> > +// Config to eMMC PHY to prepare for tuning.
> > +// Enable HW DLL and set the TUNING_STEP
> > +//
> > +STATIC
> > +EFI_STATUS
> > +EmmcPhyConfigTuning (
> > +  IN EFI_PCI_IO_PROTOCOL   *PciIo,
> > +  IN UINT8 TuningStepDivisor
> > +  )
> > +{
> > +  UINT32 Var, TuningStep;
> > +  EFI_STATUS Status;
> > +
> > +  Status = EmmcPhyEnableDll (PciIo);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> > +
> > +  // Achieve TUNING_STEP with HW DLL help
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, XENON_SLOT_DLL_CUR_DLY_VAL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  TuningStep = Var / TuningStepDivisor;
> > +  if (TuningStep > TUNING_STEP_MASK) {
> > +      DEBUG ((DEBUG_ERROR, "HS200 TUNING_STEP %d is larger than MAX 
> > value\n", TuningStep));
> > +    TuningStep = TUNING_STEP_MASK;
> > +  }
> > +
> > +  // Set TUNING_STEP for later tuning
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, XENON_SLOT_OP_STATUS_CTRL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  Var &= ~(TUN_CONSECUTIVE_TIMES_MASK << TUN_CONSECUTIVE_TIMES_SHIFT);
> > +  Var |= (TUN_CONSECUTIVE_TIMES << TUN_CONSECUTIVE_TIMES_SHIFT);
> > +  Var &= ~(TUNING_STEP_MASK << TUNING_STEP_SHIFT);
> > +  Var |= (TuningStep << TUNING_STEP_SHIFT);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, XENON_SLOT_OP_STATUS_CTRL, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +STATIC
> > +BOOLEAN
> > +XenonPhySlowMode (
> > +  IN EFI_PCI_IO_PROTOCOL   *PciIo,
> > +  IN SD_MMC_BUS_MODE        Timing,
> > +  IN BOOLEAN SlowMode
> > +  )
> > +{
> > +  UINT32 Var = 0;
> > +
> > +  // Check if Slow Mode is required in lower speed mode in SDR mode
> > +  if (((Timing == SdMmcUhsSdr50) ||
> > +       (Timing == SdMmcUhsSdr25) ||
> > +       (Timing == SdMmcUhsSdr12) ||
> > +       (Timing == SdMmcMmcHsDdr) ||
> > +       (Timing == SdMmcMmcHsSdr) ||
> > +       (Timing == SdMmcMmcLegacy)) && SlowMode) {
> > +    Var = QSN_PHASE_SLOW_MODE_BIT;
> > +    XenonHcOrMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, 
> > SDHC_REG_SIZE_4B, &Var);
> > +    return TRUE;
> > +  }
> > +
> > +  Var = ~QSN_PHASE_SLOW_MODE_BIT;
> > +  XenonHcAndMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  return FALSE;
> > +}
> > +
> > +EFI_STATUS
> >  XenonSetPhy (
> >    IN EFI_PCI_IO_PROTOCOL   *PciIo,
> > -  UINT8 Timing
> > +  IN BOOLEAN               SlowMode,
> > +  IN UINT8                 TuningStepDivisor,
> > +  IN SD_MMC_BUS_MODE       Timing
> >    )
> >  {
> >    UINT32 Var = 0;
> > +  UINT16 ClkCtrl;
> >
> > -  // Setup pad, set bit[30], bit[28] and bits[26:24]
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_PAD_CONTROL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > -  Var |= (AUTO_RECEN_CTRL | OEN_QSN | FC_QSP_RECEN | FC_CMD_RECEN | 
> > FC_DQ_RECEN);
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_PAD_CONTROL, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  // Setup pad, bit[28] and bits[26:24]
> > +  Var = OEN_QSN | FC_QSP_RECEN | FC_CMD_RECEN | FC_DQ_RECEN;
> > +  // All FC_XX_RECEIVCE should be set as CMOS Type
> > +  Var |= FC_ALL_CMOS_RECEIVER;
> > +  XenonHcOrMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_PAD_CONTROL, 
> > SDHC_REG_SIZE_4B, &Var);
> > +
> > +  // Set CMD and DQ Pull Up
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_PAD_CONTROL1, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  Var |= (EMMC5_1_FC_CMD_PU | EMMC5_1_FC_DQ_PU);
> > +  Var &= ~(EMMC5_1_FC_CMD_PD | EMMC5_1_FC_DQ_PD);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_PAD_CONTROL1, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +
> > +  if (Timing == SdMmcUhsSdr12) {
> > +    if (SlowMode) {
> > +      XenonHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +      Var |= QSN_PHASE_SLOW_MODE_BIT;
> > +      XenonHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +    }
> > +
> > +    goto PhyInit;
> > +  }
> >
> >    //
> >    // If Timing belongs to high speed, set bit[17] of
> >    // EMMC_PHY_TIMING_ADJUST register
> >    //
> > -  if ((Timing == MMC_TIMING_MMC_HS400) ||
> > -      (Timing == MMC_TIMING_MMC_HS200) ||
> > -      (Timing == MMC_TIMING_UHS_SDR50) ||
> > -      (Timing == MMC_TIMING_UHS_SDR104) ||
> > -      (Timing == MMC_TIMING_UHS_DDR50) ||
> > -      (Timing == MMC_TIMING_UHS_SDR25)) {
> > -
> > -    SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > -
> > -    // Set SLOW_MODE for PHY
> > -    Var |= OUTPUT_QSN_PHASE_SELECT | QSN_PHASE_SLOW_MODE_BIT;
> > -    SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  if ((Timing == SdMmcMmcHs400) ||
> > +      (Timing == SdMmcMmcHs200) ||
> > +      (Timing == SdMmcUhsDdr50) ||
> > +      (Timing == SdMmcUhsSdr50) ||
> > +      (Timing == SdMmcUhsSdr104) ||
> > +      (Timing == SdMmcUhsSdr25)) {
> > +    Var = ~OUTPUT_QSN_PHASE_SELECT;
> > +    XenonHcAndMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_TIMING_ADJUST, 
> > SDHC_REG_SIZE_4B, &Var);
> >    }
> >
> > -  SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_PHY_FUNC_CONTROL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > -  Var |= (DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) | CMD_DDR_MODE;
> > -  SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_PHY_FUNC_CONTROL, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  if (XenonPhySlowMode (PciIo, Timing, SlowMode)) {
> > +    goto PhyInit;
> > +  }
> > +
> > +  // Set default ZNR and ZPR value
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_PAD_CONTROL2, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  Var &= ~((ZNR_MASK << ZNR_SHIFT) | ZPR_MASK);
> > +  Var |= ((ZNR_DEF_VALUE << ZNR_SHIFT) | ZPR_DEF_VALUE);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_PAD_CONTROL2, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +
> > +  // Need to disable the clock to set EMMC_PHY_FUNC_CONTROL register
> > +  ClkCtrl = ~SDHCI_CLOCK_CARD_EN;
> > +  XenonHcAndMmio (PciIo, SD_BAR_INDEX, SDHC_CLOCK_CTRL, SDHC_REG_SIZE_2B, 
> > &ClkCtrl);
> > +
> > +  if ((Timing == SdMmcMmcHs400) ||
> > +      (Timing == SdMmcUhsDdr50)) {
> > +    Var = (DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) | CMD_DDR_MODE;
> > +    XenonHcOrMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_FUNC_CONTROL, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  } else {
> > +    Var = ~((DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) | CMD_DDR_MODE);
> > +    XenonHcAndMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_FUNC_CONTROL, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  }
> > +
> > +  if (Timing == SdMmcMmcHs400) {
> > +    Var = ~DQ_ASYNC_MODE;
> > +    XenonHcAndMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_FUNC_CONTROL, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  } else {
> > +    Var = DQ_ASYNC_MODE;
> > +    XenonHcOrMmio (PciIo, SD_BAR_INDEX, EMMC_PHY_FUNC_CONTROL, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  }
> >
> > -  if (Timing == MMC_TIMING_MMC_HS400) {
> > -    SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_PHY_FUNC_CONTROL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > -    Var &= ~DQ_ASYNC_MODE;
> > -    SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_PHY_FUNC_CONTROL, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  // Enable bus clock
> > +  ClkCtrl = SDHCI_CLOCK_CARD_EN;
> > +  XenonHcOrMmio (PciIo, SD_BAR_INDEX, SDHC_CLOCK_CTRL, SDHC_REG_SIZE_2B, 
> > &ClkCtrl);
> >
> > +  // Delay 200us to wait for the completion of bus clock
> > +  gBS->Stall (200);
> > +
> > +  if (Timing == SdMmcMmcHs400) {
> >      Var = LOGIC_TIMING_VALUE;
> > -    SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, EMMC_LOGIC_TIMING_ADJUST, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +    XenonHcRwMmio (PciIo, SD_BAR_INDEX, EMMC_LOGIC_TIMING_ADJUST, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  } else {
> > +    // Disable data strobe
> > +    Var = ~ENABLE_DATA_STROBE;
> > +    XenonHcAndMmio (PciIo, SD_BAR_INDEX, XENON_SLOT_EMMC_CTRL, 
> > SDHC_REG_SIZE_4B, &Var);
> >    }
> >
> > +PhyInit:
> >    XenonPhyInit (PciIo);
> > +
> > +  if ((Timing == SdMmcMmcHs200) ||
> > +      (Timing == SdMmcUhsSdr104)) {
> > +    return EmmcPhyConfigTuning (PciIo, TuningStepDivisor);
> > +  }
> > +
> > +  return EFI_SUCCESS;
> >  }
> >
> >  STATIC
> > @@ -384,16 +515,16 @@ XenonConfigureInterrupts (
> >
> >    // Clear interrupt status
> >    Var = SDHC_CLR_ALL_IRQ_MASK;
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_NOR_INT_STS, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_NOR_INT_STS, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_NOR_INT_STS, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_NOR_INT_STS, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> >
> >    // Enable only interrupts served by the SD controller
> >    Var = SDHC_CLR_ALL_IRQ_MASK & ~(NOR_INT_STS_CARD_INS | 
> > NOR_INT_STS_CARD_INT);
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_NOR_INT_STS_EN, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_NOR_INT_STS_EN, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> >
> >    // Mask all sdhci interrupt sources
> >    Var = SDHC_CLR_ALL_IRQ_MASK & ~NOR_INT_SIG_EN_CARD_INT;
> > -  SdMmcHcRwMmio (PciIo, SD_BAR_INDEX, SD_MMC_HC_NOR_INT_SIG_EN, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio (PciIo, SD_BAR_INDEX, SDHC_NOR_INT_SIG_EN, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> >  }
> >
> >  // Enable Parallel Transfer Mode
> > @@ -407,7 +538,7 @@ XenonSetParallelTransfer (
> >  {
> >    UINT32 Var;
> >
> > -  SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, SDHC_SYS_EXT_OP_CTRL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio(PciIo, SD_BAR_INDEX, SDHC_SYS_EXT_OP_CTRL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> >
> >    if (Enable) {
> >      Var |= (0x1 << Slot);
> > @@ -415,7 +546,10 @@ XenonSetParallelTransfer (
> >      Var &= ~(0x1 << Slot);
> >    }
> >
> > -  SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, SDHC_SYS_EXT_OP_CTRL, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  // Mask command conflict error
> > +  Var |= MASK_CMD_CONFLICT_ERR;
> > +
> > +  XenonHcRwMmio(PciIo, SD_BAR_INDEX, SDHC_SYS_EXT_OP_CTRL, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> >  }
> >
> >  STATIC
> > @@ -429,7 +563,7 @@ XenonSetTuning (
> >    UINT32 Var;
> >
> >    // Set the Re-Tuning Request functionality
> > -  SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, SDHC_SLOT_RETUNING_REQ_CTRL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio(PciIo, SD_BAR_INDEX, SDHC_SLOT_RETUNING_REQ_CTRL, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> >
> >    if (Enable) {
> >      Var |= RETUNING_COMPATIBLE;
> > @@ -437,10 +571,10 @@ XenonSetTuning (
> >      Var &= ~RETUNING_COMPATIBLE;
> >    }
> >
> > -  SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, SDHC_SLOT_RETUNING_REQ_CTRL, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio(PciIo, SD_BAR_INDEX, SDHC_SLOT_RETUNING_REQ_CTRL, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> >
> >    // Set the Re-tuning Event Signal Enable
> > -  SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, SDHCI_SIGNAL_ENABLE, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio(PciIo, SD_BAR_INDEX, SDHCI_SIGNAL_ENABLE, TRUE, 
> > SDHC_REG_SIZE_4B, &Var);
> >
> >    if (Enable) {
> >      Var |= SDHCI_RETUNE_EVT_INTSIG;
> > @@ -448,12 +582,12 @@ XenonSetTuning (
> >      Var &= ~SDHCI_RETUNE_EVT_INTSIG;
> >    }
> >
> > -  SdMmcHcRwMmio(PciIo, SD_BAR_INDEX, SDHCI_SIGNAL_ENABLE, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> > +  XenonHcRwMmio(PciIo, SD_BAR_INDEX, SDHCI_SIGNAL_ENABLE, FALSE, 
> > SDHC_REG_SIZE_4B, &Var);
> >  }
> >
> >  VOID
> >  XenonReset (
> > -  IN SD_MMC_HC_PRIVATE_DATA *Private,
> > +  IN EFI_PCI_IO_PROTOCOL *PciIo,
> >    IN UINT8 Slot,
> >    IN UINT8 Mask
> >    )
> > @@ -463,19 +597,19 @@ XenonReset (
> >
> >    SwReset = Mask;
> >
> > -  SdMmcHcRwMmio (
> > -          Private->PciIo,
> > +  XenonHcRwMmio (
> > +          PciIo,
> >            Slot,
> > -          SD_MMC_HC_SW_RST,
> > +          SDHC_SW_RST,
> >            FALSE,
> >            sizeof (SwReset),
> >            &SwReset
> >          );
> >
> > -  SdMmcHcRwMmio (
> > -          Private->PciIo,
> > +  XenonHcRwMmio (
> > +          PciIo,
> >            Slot,
> > -          SD_MMC_HC_SW_RST,
> > +          SDHC_SW_RST,
> >            TRUE,
> >            sizeof (SwReset),
> >            &SwReset
> > @@ -491,10 +625,10 @@ XenonReset (
> >
> >      // Poll interval for SwReset is 100us according to SDHCI spec
> >      gBS-> Stall (100);
> > -    SdMmcHcRwMmio (
> > -            Private->PciIo,
> > +    XenonHcRwMmio (
> > +            PciIo,
> >              Slot,
> > -            SD_MMC_HC_SW_RST,
> > +            SDHC_SW_RST,
> >              TRUE,
> >              sizeof (SwReset),
> >              &SwReset
> > @@ -505,7 +639,6 @@ XenonReset (
> >  STATIC
> >  VOID
> >  XenonTransferPio (
> > -  IN SD_MMC_HC_PRIVATE_DATA *Private,
> >    IN UINT8 Slot,
> >    IN OUT VOID *Buffer,
> >    IN UINT16 BlockSize,
> > @@ -532,7 +665,7 @@ XenonTransferPio (
> >
> >  EFI_STATUS
> >  XenonTransferData (
> > -  IN SD_MMC_HC_PRIVATE_DATA *Private,
> > +  IN EFI_PCI_IO_PROTOCOL *PciIo,
> >    IN UINT8 Slot,
> >    IN OUT VOID *Buffer,
> >    IN UINT32 DataLen,
> > @@ -552,10 +685,10 @@ XenonTransferData (
> >    Mask = PRESENT_STATE_BUFFER_RD_EN | PRESENT_STATE_BUFFER_WR_EN;
> >
> >    do {
> > -    SdMmcHcRwMmio (
> > -            Private->PciIo,
> > +    XenonHcRwMmio (
> > +            PciIo,
> >              Slot,
> > -            SD_MMC_HC_NOR_INT_STS,
> > +            SDHC_NOR_INT_STS,
> >              TRUE,
> >              sizeof (IntStatus),
> >              &IntStatus
> > @@ -567,10 +700,10 @@ XenonTransferData (
> >      }
> >
> >      if (IntStatus & Rdy) {
> > -      SdMmcHcRwMmio (
> > -              Private->PciIo,
> > +      XenonHcRwMmio (
> > +              PciIo,
> >                Slot,
> > -              SD_MMC_HC_PRESENT_STATE,
> > +              SDHC_PRESENT_STATE,
> >                TRUE,
> >                sizeof (PresentState),
> >                &PresentState
> > @@ -580,16 +713,16 @@ XenonTransferData (
> >          continue;
> >        }
> >
> > -      SdMmcHcRwMmio (
> > -              Private->PciIo,
> > +      XenonHcRwMmio (
> > +              PciIo,
> >                Slot,
> > -              SD_MMC_HC_NOR_INT_STS,
> > +              SDHC_NOR_INT_STS,
> >                FALSE,
> >                sizeof (Rdy),
> >                &Rdy
> >              );
> >
> > -      XenonTransferPio (Private, Slot, Buffer, BlockSize, Read);
> > +      XenonTransferPio (Slot, Buffer, BlockSize, Read);
> >
> >        Buffer += BlockSize;
> >        if (++Block >= Blocks) {
> > @@ -612,13 +745,13 @@ XenonTransferData (
> >
> >  EFI_STATUS
> >  XenonInit (
> > -  IN SD_MMC_HC_PRIVATE_DATA *Private
> > +  IN EFI_PCI_IO_PROTOCOL *PciIo,
> > +  IN BOOLEAN             Support1v8,
> > +  IN BOOLEAN             SlowMode,
> > +  IN UINT8               TuningStepDivisor
> >    )
> >  {
> > -  EFI_PCI_IO_PROTOCOL *PciIo = Private->PciIo;
> > -
> > -  // Read XENON version
> > -  XenonReadVersion (PciIo, &Private->ControllerVersion);
> > +  EFI_STATUS Status;
> >
> >    // Disable auto clock generator
> >    XenonSetAcg (PciIo, FALSE);
> > @@ -626,11 +759,11 @@ XenonInit (
> >    // XENON has only one port
> >    XenonSetSlot (PciIo, XENON_MMC_SLOT_ID, TRUE);
> >
> > -  XenonSetPower (PciIo, MMC_VDD_165_195, eMMC_VCCQ_1_8V, 
> > XENON_MMC_MODE_SD_SDIO);
> > -
> > -  // Set MAX_CLOCK for configuring PHY
> > -  XenonSetClk (PciIo, Private, XENON_MMC_MAX_CLK);
> > -  XenonSetPhy (PciIo, MMC_TIMING_UHS_SDR50);
> > +  if (Support1v8) {
> > +    XenonSetPower (PciIo, MMC_VDD_165_195, eMMC_VCCQ_1_8V, 
> > XENON_MMC_MODE_SD_SDIO);
> > +  } else {
> > +    XenonSetPower (PciIo, MMC_VDD_32_33, eMMC_VCCQ_3_3V, 
> > XENON_MMC_MODE_SD_SDIO);
> > +  }
> >
> >    XenonConfigureInterrupts (PciIo);
> >
> > @@ -641,9 +774,12 @@ XenonInit (
> >    // Enable auto clock generator
> >    XenonSetAcg (PciIo, TRUE);
> >
> > -  // Set proper clock for PHY configuration
> > -  XenonSetClk (PciIo, Private, XENON_MMC_BASE_CLK);
> > -  XenonPhyInit (PciIo);
> > +  // Set lowest clock and the PHY for the initialization phase
> > +  XenonSetClk (PciIo, XENON_MMC_BASE_CLK);
> > +  Status = XenonSetPhy (PciIo, SlowMode, TuningStepDivisor, SdMmcUhsSdr12);
> > +  if (EFI_ERROR (Status)) {
> > +    return Status;
> > +  }
> >
> >    return EFI_SUCCESS;
> >  }
> > --
> > 2.7.4
> >
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to