From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
To: Marcin Wojtas <mw@semihalf.com>
Cc: "edk2-devel@lists.01.org" <edk2-devel@lists.01.org>,
"Leif Lindholm" <leif.lindholm@linaro.org>,
"Wu, Hao A" <hao.a.wu@intel.com>,
"Nadav Haklai" <nadavh@marvell.com>,
"Jan Dąbroś" <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 17:59:14 -0800 [thread overview]
Message-ID: <CAKv+Gu_0YJOeppst2eviJreoWUJti7+y4wsbbEuDk3-aqS+ANA@mail.gmail.com> (raw)
In-Reply-To: <CAPv3WKfJDOovYf6D5x-3K02c9W60Dnp15X_9tvgxs3CZ2wuRFw@mail.gmail.com>
On Sun, 18 Nov 2018 at 14:20, Marcin Wojtas <mw@semihalf.com> wrote:
>
> 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.
>
Fair enough.
> > > + 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
> > >
prev parent reply other threads:[~2018-11-19 1:59 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
2018-11-19 1:59 ` Ard Biesheuvel [this message]
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=CAKv+Gu_0YJOeppst2eviJreoWUJti7+y4wsbbEuDk3-aqS+ANA@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