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::143; helo=mail-it1-x143.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-it1-x143.google.com (mail-it1-x143.google.com [IPv6:2607:f8b0:4864:20::143]) (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 6DAA52117FD54 for ; Thu, 15 Nov 2018 16:56:54 -0800 (PST) Received: by mail-it1-x143.google.com with SMTP id m15so32083479itl.4 for ; Thu, 15 Nov 2018 16:56:54 -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=ICT0uZdaHJWLnhx+YxZFqbuDUCLSiG5gYE9Iq1mwWRs=; b=Ng6oqfz6jeDK9srNXl1FrycEKFuYMwXbpeGNcHNc0GicsYe7rFjHij3NG6hCns3oBQ cpnt8jJZ3kT9tHwC52HSWSAQ996qEA7z8guLBh+6t45zBt7DzycjjiXYI5DQd+G7adyn kF5FlwdgbUU4YJmBs2f7rB6g+ag0cwqw76t0A= 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=ICT0uZdaHJWLnhx+YxZFqbuDUCLSiG5gYE9Iq1mwWRs=; b=EN7Bx85q8WjLx1uyByOGl9Cwk1xQnD0GdGSI6OQ/nrTw3mmwQl2tNeoKIGOOSxx+Ni 29DyBeRjo/zKyH1zegkQ83uJPwfAPooMEaNssiayKKRPdk7DeNi/jzJUO4SWxLhASnEY xMJEkaLe5+Hj223Y/+mxtQ3tebzNbJgauHcLAhY9ODaZ/9PHPCkEkHGd4HjFluj58szW UkbKyD/dAYKuKOMJrDifopU6mM40zBcM1s4jmf/nivF0A7/L+9m8advXFNS6F0AmSBlP KdRYoA2+zP1Ol/zprXkdpBRhNlCvvG5AtEOuYSVd2+H8ubkGn0kY0o5DzAJk63hY/ycC 2NDQ== X-Gm-Message-State: AGRZ1gLiWjQ0OKPp/hfg3kn+MJM9zEL0nI3y5t0Ing3nZydgQi+cEa7Y Slr6TurSwE/OjFH3P8hPrHvQdeaLGOEyn3h4Fvq2T9tkGx8= X-Google-Smtp-Source: AJdET5dmWwDFk9x7Qmxye7vzf1uCA45nPmzB8T1LW9uCjqlK/beQkxtgR9YKp8FLXwcZIx+vJPbLGBDmbYBqSEVesro= X-Received: by 2002:a24:2190:: with SMTP id e138-v6mr8356145ita.71.1542329813200; Thu, 15 Nov 2018 16:56:53 -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: <1542112371-32546-9-git-send-email-mw@semihalf.com> From: Ard Biesheuvel Date: Thu, 15 Nov 2018 16:56:42 -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: Fri, 16 Nov 2018 00:56:54 -0000 Content-Type: text/plain; charset="UTF-8" On Tue, 13 Nov 2018 at 04:33, Marcin Wojtas wrote: > > From: Tomasz Michalec > > XenonDxe was copy of SdMmcPciHcDxe from edk2/MdeModulePkg. > > Now it implements SdMmcOverride protocol which allows > to add quirks to the generic SdMmcPciHcDxe. > > Platforms that were using XenonDxe/SdMmcPciHcDxe have fixed *.fdf > and *.dsc.inc files to use new implementation of XenonDxe. > > In the new version of the driver apart from using SdMmcOverride > protocol, this patch utilizes newly added controllers' > description in MvBoardDesc protocol, as well as improved > PHY configuration sequence. > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Marcin Wojtas > --- > Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc | 2 + > Silicon/Marvell/Armada7k8k/Armada7k8k.fdf | 2 + > Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf | 55 +++ > Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonPciHci.h | 151 +++++++ > Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdMmcOverride.h | 53 +++ > Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdhci.h | 131 +++++- > Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonPciHci.c | 321 +++++++++++++++ > Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdMmcOverride.c | 432 ++++++++++++++++++++ > Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdhci.c | 408 ++++++++++++------ > 9 files changed, 1402 insertions(+), 153 deletions(-) > create mode 100644 Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf > create mode 100644 Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonPciHci.h > create mode 100644 Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdMmcOverride.h > create mode 100644 Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonPciHci.c > create mode 100644 Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdMmcOverride.c > > diff --git a/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc b/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc > index 041fe90..14a1bda 100644 > --- a/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc > +++ b/Silicon/Marvell/Armada7k8k/Armada7k8k.dsc.inc > @@ -509,6 +509,8 @@ > # SD/MMC > MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf > MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf > + MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf > + Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf > > # Console packages > MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf > diff --git a/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf b/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf > index 6ad7c87..e143517 100644 > --- a/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf > +++ b/Silicon/Marvell/Armada7k8k/Armada7k8k.fdf > @@ -171,6 +171,8 @@ FvNameGuid = 5eda4200-2c5f-43cb-9da3-0baf74b1b30c > # SD/MMC > INF MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf > INF MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf > + INF MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf > + INF Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf > > # Multiple Console IO support > INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf > diff --git a/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf > new file mode 100644 > index 0000000..f966e5f > --- /dev/null > +++ b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonDxe.inf > @@ -0,0 +1,55 @@ > +## @file > +# SdMmcPciHcDxe driver is used to manage those host controllers which comply with SD > +# Host Controller Simplified Specifiction version 3.0. > +# > +# It will produce EFI_SD_MMC_PASS_THRU_PROTOCOL to allow sending SD/MMC/eMMC cmds > +# to specified devices from upper layer. > +# > +# Copyright (c) 2015, Intel Corporation. All rights reserved.
> +# Copyright (C) 2018, Marvell International Ltd. All rights reserved.
> +# > +# This program and the accompanying materials > +# are licensed and made available under the terms and conditions of the BSD License > +# which accompanies this distribution. The full text of the license may be found at > +# http://opensource.org/licenses/bsd-license.php > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +# > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001A > + BASE_NAME = XenonDxe > + FILE_GUID = 17f56b40-f7c1-435c-ab8d-404872da951e > + MODULE_TYPE = UEFI_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = InitializeXenonDxe > + > +[Sources] > + XenonPciHci.c > + XenonPciHci.h > + XenonSdhci.c > + XenonSdhci.h > + XenonSdMmcOverride.c > + XenonSdMmcOverride.h > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + Silicon/Marvell/Marvell.dec > + > +[LibraryClasses] > + BaseLib > + DebugLib > + MemoryAllocationLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + UefiLib > + UefiRuntimeServicesTableLib > + > +[Protocols] > + gEdkiiSdMmcOverrideProtocolGuid ## BY_START Please change the annotation to ## PRODUCES > + gEdkiiNonDiscoverableDeviceProtocolGuid ## TO_START > + gEfiPciIoProtocolGuid ## TO_START > + gMarvellBoardDescProtocolGuid ## TO_START > diff --git a/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonPciHci.h b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonPciHci.h > new file mode 100644 > index 0000000..152ba96 > --- /dev/null > +++ b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonPciHci.h > @@ -0,0 +1,151 @@ > +/** @file > + > + Provides some data structure definitions used by the SD/MMC host controller driver. > + > + Copyright (c) 2015, Intel Corporation. All rights reserved.
> + Copyright (c) 2018, Marvell International, Ltd. All rights reserved.
> + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > +**/ > + > +#ifndef _XENON_PCI_HCI_H_ > +#define _XENON_PCI_HCI_H_ > + > +/** > + Read/Write 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] Read A boolean to indicate it's read or write operation. > + @param[in] Count The width of the mmio register in bytes. > + Must be 1, 2 , 4 or 8 bytes. > + @param[in, out] Data For read operations, the destination buffer to store > + the results. For write operations, the source buffer > + to write data from. 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 Data is NULL or the Count is not valid. > + @retval EFI_SUCCESS The read/write operation succeeds. > + @retval Others The read/write operation fails. > + > +**/ > +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 > + ); > + > +/** > + 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 > + ); > + > +/** > + 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 > + ); > + > +/** > + 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 > + ); > + > +#endif > diff --git a/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdMmcOverride.h b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdMmcOverride.h > new file mode 100644 > index 0000000..0c7a0b7 > --- /dev/null > +++ b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdMmcOverride.h > @@ -0,0 +1,53 @@ > +/******************************************************************************* > +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. > + > +*******************************************************************************/ > +#ifndef _XENON_SD_MMC_OVERRIDE_H_ > +#define _XENON_SD_MMC_OVERRIDE_H_ > + > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > + > +#include "XenonPciHci.h" > +#include "XenonSdhci.h" > + > +#endif > diff --git a/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdhci.h b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdhci.h > index 2be0ee6..8bf1835 100644 > --- a/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdhci.h > +++ b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonSdhci.h > @@ -32,15 +32,65 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > > *******************************************************************************/ > > -#include "SdMmcPciHcDxe.h" > - > +#include > +#include > #include > > +#include > +#include > + > +#include "XenonPciHci.h" > + > #define SD_BAR_INDEX 0 > > #define SIZE_512B 0x200 > > -/* Register Offset of SD Host Controller SOCP self-defined register */ > +/* Register Offset of SD Host Controller */ > +#define SDHC_SDMA_ADDR 0x0000 > +#define SDHC_ARG2 0x0000 > +#define SDHC_BLK_SIZE 0x0004 > +#define SDHC_BLK_COUNT 0x0006 > +#define SDHC_ARG1 0x0008 > +#define SDHC_TRANS_MOD 0x000C > +#define SDHC_COMMAND 0x000E > +#define SDHC_RESPONSE 0x0010 > +#define SDHC_BUF_DAT_PORT 0x0020 > +#define SDHC_PRESENT_STATE 0x0024 > +#define SDHC_HOST_CTRL1 0x0028 > +#define SDHC_POWER_CTRL 0x0029 > +#define SDHC_BLK_GAP_CTRL 0x002A > +#define SDHC_WAKEUP_CTRL 0x002B > +#define SDHC_CLOCK_CTRL 0x002C > +#define SDHC_TIMEOUT_CTRL 0x002E > +#define SDHC_SW_RST 0x002F > +#define SDHC_NOR_INT_STS 0x0030 > +#define SDHC_ERR_INT_STS 0x0032 > +#define SDHC_NOR_INT_STS_EN 0x0034 > +#define SDHC_ERR_INT_STS_EN 0x0036 > +#define SDHC_NOR_INT_SIG_EN 0x0038 > +#define SDHC_ERR_INT_SIG_EN 0x003A > +#define SDHC_AUTO_CMD_ERR_STS 0x003C > +#define SDHC_HOST_CTRL2 0x003E > +#define UHS_MODE_SELECT_MASK 0x7 > +#define SDHC_CAP 0x0040 > +#define SDHC_CAP_BUS_WIDTH8 BIT18 > +#define SDHC_CAP_VOLTAGE_33 BIT24 > +#define SDHC_CAP_VOLTAGE_30 BIT25 > +#define SDHC_CAP_VOLTAGE_18 BIT26 > +#define SDHC_CAP_SLOT_TYPE_OFFSET 30 > +#define SDHC_CAP_SLOT_TYPE_MASK (BIT30 | BIT31) > +#define SDHC_CAP_SDR50 BIT32 > +#define SDHC_CAP_SDR104 BIT33 > +#define SDHC_CAP_DDR50 BIT34 > +#define SDHC_MAX_CURRENT_CAP 0x0048 > +#define SDHC_FORCE_EVT_AUTO_CMD 0x0050 > +#define SDHC_FORCE_EVT_ERR_INT 0x0052 > +#define SDHC_ADMA_ERR_STS 0x0054 > +#define SDHC_ADMA_SYS_ADDR 0x0058 > +#define SDHC_PRESET_VAL 0x0060 > +#define SDHC_SHARED_BUS_CTRL 0x00E0 > +#define SDHC_SLOT_INT_STS 0x00FC > +#define SDHC_CTRL_VER 0x00FE > > #define SDHC_IPID 0x0100 > #define SDHC_SYS_CFG_INFO 0x0104 > @@ -52,10 +102,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > > #define SDHC_SYS_OP_CTRL 0x0108 > #define AUTO_CLKGATE_DISABLE_MASK (0x1<<20) > -#define SDCLK_IDLEOFF_ENABLE_SHIFT 8 > +#define SDCLK_IDLEOFF_ENABLE_MASK (1 << 8) > #define SLOT_ENABLE_SHIFT 0 > > #define SDHC_SYS_EXT_OP_CTRL 0x010c > +#define MASK_CMD_CONFLICT_ERR (1 << 8) > + > #define SDHC_TEST_OUT 0x0110 > #define SDHC_TESTOUT_MUXSEL 0x0114 > > @@ -169,11 +221,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > #define TMR_RETUN_NO_PRESENT 0xf > #define XENON_MAX_TUN_COUNT 0xb > > +#define XENON_SLOT_OP_STATUS_CTRL 0x0128 > +#define TUN_CONSECUTIVE_TIMES_SHIFT 16 > +#define TUN_CONSECUTIVE_TIMES_MASK 0x7 > +#define TUN_CONSECUTIVE_TIMES 0x4 > +#define TUNING_STEP_SHIFT 12 > +#define TUNING_STEP_MASK 0xF > + > +#define XENON_SLOT_EMMC_CTRL 0x130 > +#define ENABLE_DATA_STROBE (1 << 24) > + > +#define XENON_SLOT_EXT_PRESENT_STATE 0x014C > +#define DLL_LOCK_STATE 0x1 > + > +#define XENON_SLOT_DLL_CUR_DLY_VAL 0x0150 > + > #define EMMC_PHY_REG_BASE 0x170 > #define EMMC_PHY_TIMING_ADJUST EMMC_PHY_REG_BASE > #define OUTPUT_QSN_PHASE_SELECT (1 << 17) > #define SAMPL_INV_QSP_PHASE_SELECT (1 << 18) > #define SAMPL_INV_QSP_PHASE_SELECT_SHIFT 18 > +#define QSN_PHASE_SLOW_MODE_BIT (1 << 29) > #define PHY_INITIALIZAION (1 << 31) > #define WAIT_CYCLE_BEFORE_USING_MASK 0xf > #define WAIT_CYCLE_BEFORE_USING_SHIFT 12 > @@ -199,20 +267,42 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > #define FC_QSN_RECEN (1 << 27) > #define OEN_QSN (1 << 28) > #define AUTO_RECEN_CTRL (1 << 30) > +#define FC_ALL_CMOS_RECEIVER 0xF000 > > #define EMMC_PHY_PAD_CONTROL1 (EMMC_PHY_REG_BASE + 0xc) > +#define EMMC5_1_FC_QSP_PD (1 << 9) > +#define EMMC5_1_FC_QSP_PU (1 << 25) > +#define EMMC5_1_FC_CMD_PD (1 << 8) > +#define EMMC5_1_FC_CMD_PU (1 << 24) > +#define EMMC5_1_FC_DQ_PD 0xFF > +#define EMMC5_1_FC_DQ_PU (0xFF << 16) > + > #define EMMC_PHY_PAD_CONTROL2 (EMMC_PHY_REG_BASE + 0x10) > +#define ZNR_MASK 0x1F > +#define ZNR_SHIFT 8 > +#define ZPR_MASK 0x1F > +#define ZNR_DEF_VALUE 0xF > +#define ZPR_DEF_VALUE 0xF > + > #define EMMC_PHY_DLL_CONTROL (EMMC_PHY_REG_BASE + 0x14) > -#define DLL_DELAY_TEST_LOWER_SHIFT 8 > -#define DLL_DELAY_TEST_LOWER_MASK 0xff > -#define DLL_BYPASS_EN 0x1 > +#define DLL_ENABLE (1 << 31) > +#define DLL_UPDATE_STROBE_5_0 (1 << 30) > +#define DLL_REFCLK_SEL (1 << 30) > +#define DLL_UPDATE (1 << 23) > +#define DLL_PHSEL1_SHIFT 24 > +#define DLL_PHSEL0_SHIFT 16 > +#define DLL_PHASE_MASK 0x3F > +#define DLL_PHASE_90_DEGREE 0x1F > +#define DLL_FAST_LOCK (1 << 5) > +#define DLL_GAIN2X (1 << 3) > +#define DLL_BYPASS_EN (1 << 0) > > #define EMMC_LOGIC_TIMING_ADJUST (EMMC_PHY_REG_BASE + 0x18) > #define EMMC_LOGIC_TIMING_ADJUST_LOW (EMMC_PHY_REG_BASE + 0x1c) > > #define LOGIC_TIMING_VALUE 0x5a54 /* Recommend by HW team */ > > -#define QSN_PHASE_SLOW_MODE_BIT (1 << 29) > +#define TUNING_STEP_DIVIDER_SHIFT 6 > > /* XENON only have one slot 0 */ > #define XENON_MMC_SLOT_ID (0) > @@ -227,6 +317,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > #define MMC_TIMING_UHS_DDR50 7 > #define MMC_TIMING_MMC_HS200 8 > #define MMC_TIMING_MMC_HS400 10 > +#define MMC_TIMING_MMC_DDR52 11 > + > +/* Custom UHS signaling field values */ > +#define XENON_SD_MMC_HC_CTRL_HS200 0x5 > +#define XENON_SD_MMC_HC_CTRL_HS400 0x6 > > /* Data time out default value 0xE: TMCLK x 227 */ > #define DATA_TIMEOUT_DEF_VAL 0xE > @@ -305,7 +400,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > UINTN > XenonSetClk ( > IN EFI_PCI_IO_PROTOCOL *PciIo, > - IN SD_MMC_HC_PRIVATE_DATA *Private, > IN UINT32 Clock > ); > > @@ -316,14 +410,14 @@ XenonPhyInit ( > > VOID > XenonReset ( > - IN SD_MMC_HC_PRIVATE_DATA *Private, > + IN EFI_PCI_IO_PROTOCOL *PciIo, > IN UINT8 Slot, > IN UINT8 Mask > ); > > 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, > @@ -334,13 +428,16 @@ 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_STATUS > -SdCardSendStatus ( > - IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, > - IN UINT8 Slot, > - IN UINT16 Rca, > - OUT UINT32 *DevStatus > +XenonSetPhy ( > + IN EFI_PCI_IO_PROTOCOL *PciIo, > + IN BOOLEAN SlowMode, > + IN UINT8 TuningStepDivisor, > + IN SD_MMC_BUS_MODE Timing > ); > diff --git a/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonPciHci.c b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonPciHci.c > new file mode 100644 > index 0000000..8a22046 > --- /dev/null > +++ b/Silicon/Marvell/Drivers/SdMmc/XenonDxe/XenonPciHci.c > @@ -0,0 +1,321 @@ > +/** @file > + This driver is used to manage SD/MMC PCI host controllers which are compliance > + with SD Host Controller Simplified Specification version 3.00. > + > + It would expose EFI_SD_MMC_PASS_THRU_PROTOCOL for upper layer use. > + > + Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
> + Copyright (c) 2018, Marvell International, Ltd. All rights reserved.
> + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > +**/ > + > +#include "XenonSdMmcOverride.h" > + > +/** > + Read/Write 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] Read A boolean to indicate it's read or write operation. > + @param[in] Count The width of the mmio register in bytes. > + Must be 1, 2 , 4 or 8 bytes. > + @param[in, out] Data For read operations, the destination buffer to store > + the results. For write operations, the source buffer > + to write data from. 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 Data is NULL or the Count is not valid. > + @retval EFI_SUCCESS The read/write operation succeeds. > + @retval Others The read/write operation fails. > + > +**/ > +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? > + 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 >