From: Marcin Wojtas <mw@semihalf.com>
To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: edk2-devel-01 <edk2-devel@lists.01.org>,
Leif Lindholm <leif.lindholm@linaro.org>,
hao.a.wu@intel.com, nadavh@marvell.com,
"jsd@semihalf.com" <jsd@semihalf.com>,
Grzegorz Jaszczyk <jaz@semihalf.com>,
Kostya Porotchkin <kostap@marvell.com>,
Tomasz Michalec <tm@semihalf.com>
Subject: Re: [platforms: PATCH v5 8/8] Marvell/Drivers: XenonDxe: Switch to use generic SdMmcPciHcDxe
Date: Sun, 18 Nov 2018 23:20:25 +0100 [thread overview]
Message-ID: <CAPv3WKfJDOovYf6D5x-3K02c9W60Dnp15X_9tvgxs3CZ2wuRFw@mail.gmail.com> (raw)
In-Reply-To: <CAKv+Gu_KqnjkUKHCyenfiod8pCD73Cq=CxNkdAGbthVugug3kg@mail.gmail.com>
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
> >
next prev parent reply other threads:[~2018-11-18 22:20 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-11-13 12:32 [platforms: PATCH v5 0/8] Armada7k8k Xenon driver rework Marcin Wojtas
2018-11-13 12:32 ` [platforms: PATCH v5 1/8] Silicon/SynQuacer/PlatformDxe: adjust to updated SdMmcOverride Marcin Wojtas
2018-11-13 12:32 ` [platforms: PATCH v5 2/8] Marvell/Library: ArmadaBoardDescLib: Extend SDMMC information Marcin Wojtas
2018-11-13 12:32 ` [platforms: PATCH v5 3/8] SolidRun/Armada80x0McBin: Introduce board description library Marcin Wojtas
2018-11-13 12:32 ` [platforms: PATCH v5 4/8] Marvell/Armada70x0Db: " Marcin Wojtas
2018-11-13 12:32 ` [platforms: PATCH v5 5/8] Marvell/Armada80x0Db: " Marcin Wojtas
2018-11-13 12:32 ` [platforms: PATCH v5 6/8] Marvell/Drivers: MvBoardDesc: Extend information for SdMmc Marcin Wojtas
2018-11-13 12:32 ` [platforms: PATCH v5 7/8] Marvell/Drivers: XenonDxe: Remove SdMmcPciHcDxe files Marcin Wojtas
2018-11-13 12:32 ` [platforms: PATCH v5 8/8] Marvell/Drivers: XenonDxe: Switch to use generic SdMmcPciHcDxe Marcin Wojtas
2018-11-16 0:56 ` Ard Biesheuvel
2018-11-18 22:20 ` Marcin Wojtas [this message]
2018-11-19 1:59 ` Ard Biesheuvel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAPv3WKfJDOovYf6D5x-3K02c9W60Dnp15X_9tvgxs3CZ2wuRFw@mail.gmail.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox