From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4864:20::141; helo=mail-it1-x141.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-it1-x141.google.com (mail-it1-x141.google.com [IPv6:2607:f8b0:4864:20::141]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 89B6C21A09130 for ; Sun, 18 Nov 2018 17:59:27 -0800 (PST) Received: by mail-it1-x141.google.com with SMTP id a205-v6so5929986itd.4 for ; Sun, 18 Nov 2018 17:59:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=m6XBVXHzN8/OS+S8e5fWFj/sVJmdZ4kQGXy8R1CPcl8=; b=gPgDYkWRiSlfMqCeaW0t+5o98dllLUWO1Hq60QOpAcN8BH8cEKzfngMWeh7lu4yjce HgXFzNYvXkjUGNbeArlQw9lXVgqSZAVwUjG+rlMnGuSbXr0vr7EeAncdGaftBrccsK9x MwuYtiWBwGbtWQ7xarcUFiRuA4d9nz2377MCg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=m6XBVXHzN8/OS+S8e5fWFj/sVJmdZ4kQGXy8R1CPcl8=; b=Hh9SZBk4OEZeLGmZVNA8/0+8ejOA+7OA9z5HjqEtK/FXO4PnpPsU88rUzeMdSbAazR qFqs0UfF94PJDVHPZD9/41AX0//3raqLUN9xgNuqxDAf08Vlmy0Z3EtogkqK69tpUyR4 E7SodQpk+C1wJOdnb/PolIVamjLpw39jg8R4PknI0CmtMBMJ0XkkK0uD1kli9xQsYSEY 7pMsVa6ITPzh62kh2e/n8f0Ix1FFsbcXlTS4DWmq9WORj+Q8PKAeuxpXGatAlExCrF9/ olZHcJ684Tmzu6K33CcnEs4xa2CEj4Lr9yotvEaOZYKom1IUN8a6VTjZQ0VMHzrDioIz mc0g== X-Gm-Message-State: AGRZ1gJCAknF+P670SlziQQoraKCnxYlVDVaa56/mAVCWC93KGkGogyQ nWj3Kyj01XdFCKqt62RiS6TSuc1ED9BqlF9H9VAm9Q== X-Google-Smtp-Source: AFSGD/XoslPFre6IFVvkQjg/rBrN1Pnd8NiQob+k5Y4HnakOV/WXIOOjDiMZXJ4/YohVt7MSG9l/haQyvMxx68Lt7Wc= X-Received: by 2002:a24:2190:: with SMTP id e138-v6mr6932551ita.71.1542592766205; Sun, 18 Nov 2018 17:59:26 -0800 (PST) MIME-Version: 1.0 References: <1542112371-32546-1-git-send-email-mw@semihalf.com> <1542112371-32546-9-git-send-email-mw@semihalf.com> In-Reply-To: From: Ard Biesheuvel Date: Sun, 18 Nov 2018 17:59:14 -0800 Message-ID: To: Marcin Wojtas Cc: "edk2-devel@lists.01.org" , Leif Lindholm , "Wu, Hao A" , Nadav Haklai , =?UTF-8?B?SmFuIETEhWJyb8Wb?= , Grzegorz Jaszczyk , Kostya Porotchkin , Tomasz Michalec Subject: Re: [platforms: PATCH v5 8/8] Marvell/Drivers: XenonDxe: Switch to use generic SdMmcPciHcDxe X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Nov 2018 01:59:27 -0000 Content-Type: text/plain; charset="UTF-8" On Sun, 18 Nov 2018 at 14:20, Marcin Wojtas 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 > > >