From patchwork Mon Aug 31 03:25:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Heider X-Patchwork-Id: 1354090 X-Patchwork-Delegate: sr@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=B0EwFsOV; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BfwbG4R6Rz9sTF for ; Mon, 31 Aug 2020 13:26:18 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 43EC782272; Mon, 31 Aug 2020 05:26:08 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="B0EwFsOV"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id EC406821DE; Mon, 31 Aug 2020 05:25:58 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id A7CAD81BF1 for ; Mon, 31 Aug 2020 05:25:40 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=a.heider@gmail.com Received: by mail-wm1-x32c.google.com with SMTP id l9so144141wme.3 for ; Sun, 30 Aug 2020 20:25:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=th/2PtEltclU4/NrYKKamCux2LrTMmentS5qJf4h4QI=; b=B0EwFsOVz9puVuE57Q6zuR4fPZOHCtKNUFBVvSr8MbkOWtvt8882emGtx4lDzOtfUd N9pe2BNhh4h98Tug59ftWrQuGQ3XMnb3/pYJOSOzAZ5i1cGoDLpcUulmz/+Oe9HeUFoV mLK1Bef4JS3Q4qObZm2W3z2xp/xcPYL5SbWFSrZOZAUNEt5meEa1iiBoydRSESPd/wNY K4dNja7uixX42yJigOSwLDY01IVkVH2hh/EreXTrcwAoGb91aN3j5eovVGCGjh1OPW8P F9+BFWXEbHNw4PvjUA5IrDJq39Ro2echSTtAhXjrlpKQag+AWIp8esRWpElMKfVt4bkK 3/kw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=th/2PtEltclU4/NrYKKamCux2LrTMmentS5qJf4h4QI=; b=lmpNyz3Fr3CKs1UDKd3eek3jseVzePfyoM507XtsvReVbNoL6gOBVUv7b+sJjfuQhw HQIt79N8R81WCyiEGUsc0FhXUkM+T6kOskqivW4h70yZAWRaJVo+ibusYX6uoIXiQs1N d66bEB+xN0wNBRdHv4NlO50mKb6im9734M8HhoN/IkQD43H0pzpLtv98ZhMPgd4Qpz4u YKXLD2Vx6ljAR4JhAqz3IPrCrEgWvn8tKhT3v4T6a9cQfyHpNO0R4iVRDWZBAc0o0eeN mKuaBCkbDMecWuaptdRzvrQNzbxWbqErIHkFQd3OWDM7wPQiuAGGTTQev3GovMHbwUal 2E9Q== X-Gm-Message-State: AOAM531XXSRIwUQoyT4pAC4yhmFIup8p9aYLsm2HVx3EbbRulkdnD92m LzvoUycguqp766e8S405ILw= X-Google-Smtp-Source: ABdhPJxSr27Atk7BUumPSGxyBuZ8xiOU5xJ5RO2oIQmBT8gwM5+TRod5+NjgpavN/IVrGO+w7z/vLw== X-Received: by 2002:a1c:56d6:: with SMTP id k205mr8961004wmb.88.1598844340131; Sun, 30 Aug 2020 20:25:40 -0700 (PDT) Received: from localhost.localdomain (a89-183-75-181.net-htp.de. [89.183.75.181]) by smtp.gmail.com with ESMTPSA id d18sm1660351wrm.10.2020.08.30.20.25.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 30 Aug 2020 20:25:39 -0700 (PDT) From: Andre Heider To: Stefan Roese , Konstantin Porotchkin Cc: =?utf-8?q?Pali_Roh=C3=A1r?= , u-boot@lists.denx.de Subject: [PATCH 1/2] xenon_sdhci: support for HS200 mode Date: Mon, 31 Aug 2020 05:25:37 +0200 Message-Id: <20200831032538.467336-1-a.heider@gmail.com> X-Mailer: git-send-email 2.28.0 MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean From: Wojciech Macek Add support for Marvell Xenon SDHCI HS200 mode. Changes focue mostly on correct PHY initialization. All procedure is similar to the one done by Linux driver, but simplified. Change-Id: I5e2396eeb23784f495abc18ea5a2eb7a92390730 Signed-off-by: Wojciech Macek Reviewed-on: http://vgitil04.il.marvell.com:8080/59230 Tested-by: iSoC Platform CI Reviewed-by: Grzegorz Jaszczyk Reviewed-by: Kostya Porotchkin Reviewed-by: Igal Liberman [a.heider: adapt to mainline] Signed-off-by: Andre Heider --- Missing downstream patch, noticed while diffing branches: https://github.com/MarvellEmbeddedProcessors/u-boot-marvell/commit/387232507a0d9dda3990284221eaf87d7541dd02 drivers/mmc/xenon_sdhci.c | 335 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 323 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/xenon_sdhci.c b/drivers/mmc/xenon_sdhci.c index 7f9a579c83..ec255d30b0 100644 --- a/drivers/mmc/xenon_sdhci.c +++ b/drivers/mmc/xenon_sdhci.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -45,6 +46,7 @@ DECLARE_GLOBAL_DATA_PTR; #define SDHC_SLOT_EMMC_CTRL 0x0130 #define ENABLE_DATA_STROBE_SHIFT 24 +#define ENABLE_DATA_STROBE BIT(ENABLE_DATA_STROBE_SHIFT) #define SET_EMMC_RSTN_SHIFT 16 #define EMMC_VCCQ_MASK 0x3 #define EMMC_VCCQ_1_8V 0x1 @@ -64,6 +66,7 @@ DECLARE_GLOBAL_DATA_PTR; #define OUTPUT_QSN_PHASE_SELECT BIT(17) #define SAMPL_INV_QSP_PHASE_SELECT BIT(18) #define SAMPL_INV_QSP_PHASE_SELECT_SHIFT 18 +#define EMMC_PHY_SDIO_MODE BIT(28) #define EMMC_PHY_SLOW_MODE BIT(29) #define PHY_INITIALIZAION BIT(31) #define WAIT_CYCLE_BEFORE_USING_MASK 0xf @@ -90,6 +93,7 @@ DECLARE_GLOBAL_DATA_PTR; #define FC_QSN_RECEN BIT(27) #define OEN_QSN BIT(28) #define AUTO_RECEN_CTRL BIT(30) +#define FC_ALL_CMOS_RECEIVER (REC_EN_MASK << REC_EN_SHIFT) #define EMMC_PHY_PAD_CONTROL1 (EMMC_PHY_REG_BASE + 0xc) #define EMMC5_1_FC_QSP_PD BIT(9) @@ -99,10 +103,71 @@ DECLARE_GLOBAL_DATA_PTR; #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 SDHCI_RETUNE_EVT_INTSIG 0x00001000 +#define SDHCI_HOST_CONTROL2 0x3E +#define SDHCI_CTRL_UHS_MASK 0x0007 +#define SDHCI_CTRL_UHS_SDR12 0x0000 +#define SDHCI_CTRL_UHS_SDR25 0x0001 +#define SDHCI_CTRL_UHS_SDR50 0x0002 +#define SDHCI_CTRL_UHS_SDR104 0x0003 +#define SDHCI_CTRL_UHS_DDR50 0x0004 +#define SDHCI_CTRL_HS400 0x0005 /* Non-standard */ +#define SDHCI_CTRL_HS200_ONLY 0x0005 /* Non-standard */ +#define SDHCI_CTRL_HS400_ONLY 0x0006 /* Non-standard */ +#define SDHCI_CTRL_VDD_180 0x0008 +#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 +#define SDHCI_CTRL_DRV_TYPE_B 0x0000 +#define SDHCI_CTRL_DRV_TYPE_A 0x0010 +#define SDHCI_CTRL_DRV_TYPE_C 0x0020 +#define SDHCI_CTRL_DRV_TYPE_D 0x0030 +#define SDHCI_CTRL_EXEC_TUNING 0x0040 +#define SDHCI_CTRL_TUNED_CLK 0x0080 +#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000 + +/* + * Config to eMMC PHY to prepare for tuning. + * Enable HW DLL and set the TUNING_STEP + */ +#define XENON_SLOT_DLL_CUR_DLY_VAL 0x0150 + +#define XENON_SLOT_OP_STATUS_CTRL 0x0128 +#define XENON_TUN_CONSECUTIVE_TIMES_SHIFT 16 +#define XENON_TUN_CONSECUTIVE_TIMES_MASK 0x7 +#define XENON_TUN_CONSECUTIVE_TIMES 0x4 +#define XENON_TUNING_STEP_SHIFT 12 +#define XENON_TUNING_STEP_MASK 0xF +#define XENON_TUNING_STEP_DIVIDER BIT(6) + +#define XENON_EMMC_PHY_DLL_CONTROL (EMMC_PHY_REG_BASE + 0x14) +#define XENON_EMMC_5_0_PHY_DLL_CONTROL \ + (XENON_EMMC_5_0_PHY_REG_BASE + 0x10) +#define XENON_DLL_ENABLE BIT(31) +#define XENON_DLL_UPDATE_STROBE_5_0 BIT(30) +#define XENON_DLL_REFCLK_SEL BIT(30) +#define XENON_DLL_UPDATE BIT(23) +#define XENON_DLL_PHSEL1_SHIFT 24 +#define XENON_DLL_PHSEL0_SHIFT 16 +#define XENON_DLL_PHASE_MASK 0x3F +#define XENON_DLL_PHASE_90_DEGREE 0x1F +#define XENON_DLL_FAST_LOCK BIT(5) +#define XENON_DLL_GAIN2X BIT(3) +#define XENON_DLL_BYPASS_EN BIT(0) + +#define XENON_SLOT_EXT_PRESENT_STATE 0x014C +#define XENON_DLL_LOCK_STATE 0x1 + /* Hyperion only have one slot 0 */ #define XENON_MMC_SLOT_ID_HYPERION 0 +#define SLOT_MASK(slot) BIT(slot) + +#define XENON_EMMC_PHY_LOGIC_TIMING_ADJUST (EMMC_PHY_REG_BASE + 0x18) +#define XENON_LOGIC_TIMING_VALUE 0x00AA8977 #define MMC_TIMING_LEGACY 0 #define MMC_TIMING_MMC_HS 1 @@ -266,6 +331,176 @@ static int xenon_mmc_start_signal_voltage_switch(struct sdhci_host *host) return ret; } +/* + * Xenon defines different values for HS200 and HS400 + * in Host_Control_2 + */ +static void xenon_set_uhs_signaling(struct sdhci_host *host, + unsigned int timing) +{ + u16 ctrl_2; + + ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); + /* Select Bus Speed Mode for host */ + ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; + if (timing == MMC_TIMING_MMC_HS200) + ctrl_2 |= SDHCI_CTRL_HS200_ONLY; + else if (timing == MMC_TIMING_UHS_SDR104) + ctrl_2 |= SDHCI_CTRL_UHS_SDR104; + else if (timing == MMC_TIMING_UHS_SDR12) + ctrl_2 |= SDHCI_CTRL_UHS_SDR12; + else if (timing == MMC_TIMING_UHS_SDR25) + ctrl_2 |= SDHCI_CTRL_UHS_SDR25; + else if (timing == MMC_TIMING_UHS_SDR50) + ctrl_2 |= SDHCI_CTRL_UHS_SDR50; + else if ((timing == MMC_TIMING_UHS_DDR50) || + (timing == MMC_TIMING_MMC_DDR52)) + ctrl_2 |= SDHCI_CTRL_UHS_DDR50; + else if (timing == MMC_TIMING_MMC_HS400) + ctrl_2 |= SDHCI_CTRL_HS400_ONLY; + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); +} + +/* + * If eMMC PHY Slow Mode is required in lower speed mode (SDCLK < 55MHz) + * in SDR mode, enable Slow Mode to bypass eMMC PHY. + * SDIO slower SDR mode also requires Slow Mode. + * + * If Slow Mode is enabled, return 0. + * Otherwise, return -EINVAL. + */ +static int xenon_emmc_phy_slow_mode(struct sdhci_host *host, + unsigned char timing) +{ + u32 reg; + int ret = -EINVAL; + + if (host->mmc->tran_speed > 52000000) + return -EINVAL; + + reg = sdhci_readl(host, EMMC_PHY_TIMING_ADJUST); + /* When in slower SDR mode, enable Slow Mode for SDIO */ + switch (timing) { + case MMC_TIMING_LEGACY: + /* + * If Slow Mode is required, enable Slow Mode by default + * in early init phase to avoid any potential issue. + */ + reg |= EMMC_PHY_SLOW_MODE; + ret = 0; + break; + case MMC_TIMING_UHS_SDR25: + case MMC_TIMING_UHS_SDR12: + case MMC_TIMING_SD_HS: + case MMC_TIMING_MMC_HS: + if (IS_SD(host->mmc)) { + reg |= EMMC_PHY_SLOW_MODE; + ret = 0; + break; + } + default: + reg &= ~EMMC_PHY_SLOW_MODE; + ret = -EINVAL; + } + + sdhci_writel(host, reg, EMMC_PHY_TIMING_ADJUST); + return ret; +} + +static void xenon_emmc_phy_disable_data_strobe(struct sdhci_host *host) +{ + u32 reg; + + /* Disable SDHC Data Strobe */ + reg = sdhci_readl(host, SDHC_SLOT_EMMC_CTRL); + reg &= ~ENABLE_DATA_STROBE; + sdhci_writel(host, reg, SDHC_SLOT_EMMC_CTRL); +} + +/* + * Enable eMMC PHY HW DLL + * DLL should be enabled and stable before HS200/SDR104 tuning, + * and before HS400 data strobe setting. + */ +static int xenon_emmc_phy_enable_dll(struct sdhci_host *host) +{ + u32 reg; + u32 timeout; + + if (host->mmc->tran_speed <= 52000000) + return -EINVAL; + + reg = sdhci_readl(host, XENON_EMMC_PHY_DLL_CONTROL); + if (reg & XENON_DLL_ENABLE) + return 0; + + /* Enable DLL */ + reg = sdhci_readl(host, XENON_EMMC_PHY_DLL_CONTROL); + reg |= (XENON_DLL_ENABLE | XENON_DLL_FAST_LOCK); + + /* + * Set Phase as 90 degree, which is most common value. + * Might set another value if necessary. + * The granularity is 1 degree. + */ + reg &= ~((XENON_DLL_PHASE_MASK << XENON_DLL_PHSEL0_SHIFT) | + (XENON_DLL_PHASE_MASK << XENON_DLL_PHSEL1_SHIFT)); + reg |= ((XENON_DLL_PHASE_90_DEGREE << XENON_DLL_PHSEL0_SHIFT) | + (XENON_DLL_PHASE_90_DEGREE << XENON_DLL_PHSEL1_SHIFT)); + + reg &= ~(XENON_DLL_BYPASS_EN | XENON_DLL_REFCLK_SEL); + reg |= XENON_DLL_UPDATE; + sdhci_writel(host, reg, XENON_EMMC_PHY_DLL_CONTROL); + + /* Wait max 32 ms */ + timeout = 32; + while (!(sdhci_readw(host, XENON_SLOT_EXT_PRESENT_STATE) & + XENON_DLL_LOCK_STATE)) { + if (timeout > 32) { + printf("Wait for DLL Lock time-out\n"); + return -ETIMEDOUT; + } + udelay(1000); + timeout++; + } + return 0; +} + +static int xenon_emmc_phy_config_tuning(struct sdhci_host *host) +{ + u32 reg, tuning_step; + int ret; + + if (host->mmc->tran_speed <= 52000000) + return -EINVAL; + + ret = xenon_emmc_phy_enable_dll(host); + if (ret) + return ret; + + /* Achieve TUNING_STEP with HW DLL help */ + reg = sdhci_readl(host, XENON_SLOT_DLL_CUR_DLY_VAL); + tuning_step = reg / XENON_TUNING_STEP_DIVIDER; + if (unlikely(tuning_step > XENON_TUNING_STEP_MASK)) { + dev_warn(mmc_dev(host->mmc), + "HS200 TUNING_STEP %d is larger than MAX value\n", + tuning_step); + tuning_step = XENON_TUNING_STEP_MASK; + } + + /* Set TUNING_STEP for later tuning */ + reg = sdhci_readl(host, XENON_SLOT_OP_STATUS_CTRL); + reg &= ~(XENON_TUN_CONSECUTIVE_TIMES_MASK << + XENON_TUN_CONSECUTIVE_TIMES_SHIFT); + reg |= (XENON_TUN_CONSECUTIVE_TIMES << + XENON_TUN_CONSECUTIVE_TIMES_SHIFT); + reg &= ~(XENON_TUNING_STEP_MASK << XENON_TUNING_STEP_SHIFT); + reg |= (tuning_step << XENON_TUNING_STEP_SHIFT); + sdhci_writel(host, reg, XENON_SLOT_OP_STATUS_CTRL); + + return 0; +} + static void xenon_mmc_phy_set(struct sdhci_host *host) { struct xenon_sdhci_priv *priv = host->mmc->priv; @@ -273,8 +508,8 @@ static void xenon_mmc_phy_set(struct sdhci_host *host) /* Setup pad, set bit[30], bit[28] and bits[26:24] */ var = sdhci_readl(host, EMMC_PHY_PAD_CONTROL); - var |= AUTO_RECEN_CTRL | OEN_QSN | FC_QSP_RECEN | - FC_CMD_RECEN | FC_DQ_RECEN; + var |= OEN_QSN | FC_QSP_RECEN | FC_CMD_RECEN | FC_DQ_RECEN | + FC_ALL_CMOS_RECEIVER; sdhci_writel(host, var, EMMC_PHY_PAD_CONTROL); /* Set CMD and DQ Pull Up */ @@ -284,20 +519,45 @@ static void xenon_mmc_phy_set(struct sdhci_host *host) sdhci_writel(host, var, EMMC_PHY_PAD_CONTROL1); /* - * If timing belongs to high speed, set bit[17] of + * If Timing belongs to high speed, clear bit[17] of * EMMC_PHY_TIMING_ADJUST register */ + var = sdhci_readl(host, EMMC_PHY_TIMING_ADJUST); if ((priv->timing == MMC_TIMING_MMC_HS400) || (priv->timing == MMC_TIMING_MMC_HS200) || + (priv->timing == MMC_TIMING_MMC_DDR52) || (priv->timing == MMC_TIMING_UHS_SDR50) || (priv->timing == MMC_TIMING_UHS_SDR104) || (priv->timing == MMC_TIMING_UHS_DDR50) || - (priv->timing == MMC_TIMING_UHS_SDR25) || - (priv->timing == MMC_TIMING_MMC_DDR52)) { - var = sdhci_readl(host, EMMC_PHY_TIMING_ADJUST); - var |= OUTPUT_QSN_PHASE_SELECT; + (priv->timing == MMC_TIMING_UHS_SDR25)) { + var &= ~OUTPUT_QSN_PHASE_SELECT; sdhci_writel(host, var, EMMC_PHY_TIMING_ADJUST); } + if (priv->timing == MMC_TIMING_LEGACY) { + xenon_emmc_phy_slow_mode(host, priv->timing); + goto phy_init; + } + + /* + * If SDIO card, set SDIO Mode + * Otherwise, clear SDIO Mode + */ + var = sdhci_readl(host, EMMC_PHY_TIMING_ADJUST); + if (IS_SD(host->mmc)) + var |= EMMC_PHY_SDIO_MODE; + else + var &= ~EMMC_PHY_SDIO_MODE; + sdhci_writel(host, var, EMMC_PHY_TIMING_ADJUST); + + /* + * Set preferred ZNR and ZPR value + * The ZNR and ZPR value vary between different boards. + * Define them both in sdhci-xenon-emmc-phy.h. + */ + var = sdhci_readl(host, EMMC_PHY_PAD_CONTROL2); + var &= ~((ZNR_MASK << ZNR_SHIFT) | ZPR_MASK); + var |= ((0xf << ZNR_SHIFT) | 0xf); + sdhci_writel(host, var, EMMC_PHY_PAD_CONTROL2); /* * When setting EMMC_PHY_FUNC_CONTROL register, @@ -308,11 +568,21 @@ static void xenon_mmc_phy_set(struct sdhci_host *host) sdhci_writew(host, var, SDHCI_CLOCK_CONTROL); var = sdhci_readl(host, EMMC_PHY_FUNC_CONTROL); - if (host->mmc->ddr_mode) { - var |= (DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) | CMD_DDR_MODE; - } else { + switch (priv->timing) { + case MMC_TIMING_MMC_HS400: + var |= (DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) | + CMD_DDR_MODE; + var &= ~DQ_ASYNC_MODE; + break; + case MMC_TIMING_UHS_DDR50: + case MMC_TIMING_MMC_DDR52: + var |= (DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) | + CMD_DDR_MODE | DQ_ASYNC_MODE; + break; + default: var &= ~((DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) | CMD_DDR_MODE); + var |= DQ_ASYNC_MODE; } sdhci_writel(host, var, EMMC_PHY_FUNC_CONTROL); @@ -321,7 +591,26 @@ static void xenon_mmc_phy_set(struct sdhci_host *host) var |= SDHCI_CLOCK_CARD_EN; sdhci_writew(host, var, SDHCI_CLOCK_CONTROL); + udelay(1000); + + /* Quirk, value suggested by hardware team */ + if (priv->timing == MMC_TIMING_MMC_HS400) + /* Hardware team recommend a value for HS400 */ + sdhci_writel(host, XENON_EMMC_PHY_LOGIC_TIMING_ADJUST, + XENON_LOGIC_TIMING_VALUE); + else + xenon_emmc_phy_disable_data_strobe(host); + +phy_init: + + xenon_set_uhs_signaling(host, priv->timing); xenon_mmc_phy_init(host); + + if ((priv->timing == MMC_TIMING_MMC_HS400) || + (priv->timing == MMC_TIMING_MMC_HS200)) { + if (xenon_emmc_phy_config_tuning(host) != 0) + printf("Error, failed to tune MMC PHY\n"); + } } /* Enable/Disable the Auto Clock Gating function of this slot */ @@ -338,8 +627,6 @@ static void xenon_mmc_set_acg(struct sdhci_host *host, bool enable) sdhci_writel(host, var, SDHC_SYS_OP_CTRL); } -#define SLOT_MASK(slot) BIT(slot) - /* Enable specific slot */ static void xenon_mmc_enable_slot(struct sdhci_host *host, u8 slot) { @@ -391,6 +678,7 @@ static int xenon_sdhci_set_ios_post(struct sdhci_host *host) struct xenon_sdhci_priv *priv = host->mmc->priv; uint speed = host->mmc->tran_speed; int pwr_18v = 0; + u32 reg; /* * Signal Voltage Switching is only applicable for Host Controllers @@ -423,12 +711,22 @@ static int xenon_sdhci_set_ios_post(struct sdhci_host *host) /* eMMC */ if (host->mmc->ddr_mode) priv->timing = MMC_TIMING_MMC_DDR52; + else if (speed == 200000000) + priv->timing = MMC_TIMING_MMC_HS200; else if (speed <= 26000000) priv->timing = MMC_TIMING_LEGACY; else priv->timing = MMC_TIMING_MMC_HS; } + if ((priv->timing == MMC_TIMING_MMC_HS400) || + (priv->timing == MMC_TIMING_MMC_HS200) || + (priv->timing == MMC_TIMING_MMC_HS)) { + reg = sdhci_readw(host, SDHCI_HOST_CONTROL2); + reg &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; + sdhci_writew(host, reg, SDHCI_HOST_CONTROL2); + } + /* Re-init the PHY */ xenon_mmc_phy_set(host); @@ -447,6 +745,7 @@ static int xenon_sdhci_probe(struct udevice *dev) struct xenon_sdhci_priv *priv = dev_get_priv(dev); struct sdhci_host *host = dev_get_priv(dev); int ret; + int len; host->mmc = &plat->mmc; host->mmc->priv = host; @@ -500,6 +799,18 @@ static int xenon_sdhci_probe(struct udevice *dev) return -EINVAL; } + /* Support for High Speed modes */ + if (fdt_getprop(gd->fdt_blob, + dev_of_offset(dev), "mmc-hs400-1_8v", &len) != NULL) { + host->host_caps |= (MMC_MODE_HS400 | MMC_MODE_HS200); + sdhci_writeb(host, SDHCI_POWER_180 | + SDHCI_POWER_ON, SDHCI_POWER_CONTROL); + } + if (fdt_getprop(gd->fdt_blob, + dev_of_offset(dev), "mmc-hs200-1_8v", &len) != NULL) { + host->host_caps |= MMC_MODE_HS200; + } + host->ops = &xenon_sdhci_ops; host->max_clk = XENON_MMC_MAX_CLK; From patchwork Mon Aug 31 03:25:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Heider X-Patchwork-Id: 1354089 X-Patchwork-Delegate: sr@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=tbz9hFgV; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Bfwb922XLz9sTF for ; Mon, 31 Aug 2020 13:26:10 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 542A981BF1; Mon, 31 Aug 2020 05:25:59 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="tbz9hFgV"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id B291E82229; Mon, 31 Aug 2020 05:25:57 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 6D5DE821DE for ; Mon, 31 Aug 2020 05:25:41 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=a.heider@gmail.com Received: by mail-wr1-x441.google.com with SMTP id z1so977883wrt.3 for ; Sun, 30 Aug 2020 20:25:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=L8sNb0l/GiTeqGL1UH620RGcVwCly8EZXdDIpvdRNiY=; b=tbz9hFgV8IKZ1Cd1rXzkS48c7xcoJbhzoEkHMrDKzrhP3YS/UxAiRfE2qTE/dp5eKc NcsSfPPwMziXHUfnxa1M42LWrgeV62XwT78Ye1QslgiUKGqgov8FDsr6ZN35gfC37OUb BlK+L1NCTrwym69WF90Fc1epNReFqH+3PFHxljISkZTktEM03CimO7EVBJdEP1SY9BUt TwSIl1JEeYKgGFveP9RNCRRD4CdnyV/CS+6eqNtEalnRNhphYqY13n1x7KcD9NRjh+gB TcZSmJC/P8kumR6lkxPSltBpp/4GpKVE02DbdWWCbnDKfbZ+R5hyFJ+fvuMJuJVxesFj tJxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=L8sNb0l/GiTeqGL1UH620RGcVwCly8EZXdDIpvdRNiY=; b=U2WdR/pq4C1pdkeJqkshDk8YW7NOS8Kc5XM8Za2RBS8YkYpmKixewATah2tVk49/ce J/6ycTRNnIibTRkzOWQFbnUNYj/YB5KaVPg+H0i0FIxSq7RLC6QAGBT7pgBryJaVAkl2 RkY31gi12rb5yhBSd3nobpQFbFnaKNCyO3s3zQ1Sbhl7yibWUtfBxZZJyMM3R75qCTeU kZpxjaZ0JxrAzUFNGLV1wWqQsoHOOSDE0Bi6oNMbfNLLSh4/H/R2BtMDO8ScDAVIqjhZ 6WERuc6bT0Wc09OtT5jqctw/AppHaSDgnlCJRb5f2kRIAyZN/7iYmXInLqs4CW44qPu8 +/cQ== X-Gm-Message-State: AOAM533vc7jP9sveUT4C3RZ7nLiGBJ4ldYX3pmWNNmCAA9Jqoc7nTor5 0dBLVDHQRzNmsQZKtvlO6ZE= X-Google-Smtp-Source: ABdhPJzQyWTxN1hzqCN+E2MbmW4EWAnXRxpY47MFt6BZLuFqKTWJVNiNij4yByo//2gmJVWXN2RpRg== X-Received: by 2002:adf:f88b:: with SMTP id u11mr4738492wrp.376.1598844341074; Sun, 30 Aug 2020 20:25:41 -0700 (PDT) Received: from localhost.localdomain (a89-183-75-181.net-htp.de. [89.183.75.181]) by smtp.gmail.com with ESMTPSA id d18sm1660351wrm.10.2020.08.30.20.25.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 30 Aug 2020 20:25:40 -0700 (PDT) From: Andre Heider To: Stefan Roese , Konstantin Porotchkin Cc: =?utf-8?q?Pali_Roh=C3=A1r?= , u-boot@lists.denx.de Subject: [PATCH 2/2] pcie: pcie_advk: move setting of reference clock to the pcie driver Date: Mon, 31 Aug 2020 05:25:38 +0200 Message-Id: <20200831032538.467336-2-a.heider@gmail.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20200831032538.467336-1-a.heider@gmail.com> References: <20200831032538.467336-1-a.heider@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean From: Grzegorz Jaszczyk The settings of reference clock is done via pcie address space and not comphy address space - move the settings in appropriate place. This aligns hw initialization of pcie advk with Linux and also will allow to get rid of not comphy related operation from the comphy driver. Change-Id: I9cc2e8f3e415a880dfb01d10cc8db73b7e81a605 Signed-off-by: Grzegorz Jaszczyk Reviewed-on: http://vgitil04.il.marvell.com:8080/59619 Reviewed-by: Igal Liberman Tested-by: iSoC Platform CI [a.heider: adapt to mainline] Signed-off-by: Andre Heider --- Missing downstream patch, noticed while diffing branches: https://github.com/MarvellEmbeddedProcessors/u-boot-marvell/commit/e3d9c015d434f755578a86a4b6b3acd17d69238a drivers/pci/pci-aardvark.c | 8 ++++++++ drivers/phy/marvell/comphy_a3700.c | 4 ++-- drivers/phy/marvell/comphy_a3700.h | 5 ----- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/pci/pci-aardvark.c b/drivers/pci/pci-aardvark.c index b2c417701f..8d1748ec0a 100644 --- a/drivers/pci/pci-aardvark.c +++ b/drivers/pci/pci-aardvark.c @@ -95,6 +95,11 @@ #define PCIE_CORE_CTRL2_STRICT_ORDER_ENABLE BIT(5) #define PCIE_CORE_CTRL2_ADDRWIN_MAP_ENABLE BIT(6) +#define PCIE_PHY_REF_CLOCK (CONTROL_BASE_ADDR + 0x14) +#define PCIE_PHY_CTRL_OFF 16 +#define PCIE_PHY_BUF_CTRL_OFF 0 +#define PCIE_PHY_BUF_CTRL_INIT_VAL 0x1342 + /* LMI registers base address and register offsets */ #define LMI_BASE_ADDR 0x6000 #define CFG_REG (LMI_BASE_ADDR + 0x0) @@ -515,6 +520,9 @@ static int pcie_advk_setup_hw(struct pcie_advk *pcie) { u32 reg; + /* Set HW Reference Clock Buffer Control */ + advk_writel(pcie, PCIE_PHY_BUF_CTRL_INIT_VAL, PCIE_PHY_REF_CLOCK); + /* Set to Direct mode */ reg = advk_readl(pcie, CTRL_CONFIG_REG); reg &= ~(CTRL_MODE_MASK << CTRL_MODE_SHIFT); diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index 4606de6f48..d460dc345a 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -202,9 +202,9 @@ static int comphy_pcie_power_up(u32 speed, u32 invert) 0xA00D | rb_clk500m_en | rb_clk100m_125m_en, 0xFFFF); /* - * 7. Enable TX + * 7. Enable TX, PCIE global register, 0xd0074814, it is done in + * PCI-E driver */ - reg_set(PCIE_REF_CLK_ADDR, 0x1342, 0xFFFFFFFF); /* * 8. Check crystal jumper setting and program the Power and PLL diff --git a/drivers/phy/marvell/comphy_a3700.h b/drivers/phy/marvell/comphy_a3700.h index b0941ffb37..db69393c1b 100644 --- a/drivers/phy/marvell/comphy_a3700.h +++ b/drivers/phy/marvell/comphy_a3700.h @@ -45,9 +45,6 @@ /* * PCIe/USB/SGMII definitions */ -#define PCIE_BASE MVEBU_REG(0x070000) -#define PCIETOP_BASE MVEBU_REG(0x080000) -#define PCIE_RAMBASE MVEBU_REG(0x08C000) #define PCIEPHY_BASE MVEBU_REG(0x01F000) #define PCIEPHY_SHFT 2 @@ -166,8 +163,6 @@ static inline void __iomem *phy_addr(enum phy_unit unit, u32 addr) #define PWR_MGM_TIM1 0x1d0 -#define PCIE_REF_CLK_ADDR (PCIE_BASE + 0x4814) - #define USB3_CTRPUL_VAL_REG (0x20 + USB32_BASE) #define USB3H_CTRPUL_VAL_REG (0x3454 + USB32H_BASE) #define rb_usb3_ctr_100ns 0xff000000