From patchwork Wed Nov 16 16:00:52 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ritesh Harjani X-Patchwork-Id: 9432083 X-Patchwork-Delegate: sboyd@codeaurora.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 41A3A60469 for ; Wed, 16 Nov 2016 16:03:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2FA9927CE7 for ; Wed, 16 Nov 2016 16:03:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 23DD928422; Wed, 16 Nov 2016 16:03:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 649B028F87 for ; Wed, 16 Nov 2016 16:03:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932911AbcKPQDw (ORCPT ); Wed, 16 Nov 2016 11:03:52 -0500 Received: from smtp.codeaurora.org ([198.145.29.96]:50996 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932870AbcKPQDs (ORCPT ); Wed, 16 Nov 2016 11:03:48 -0500 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id E090761613; Wed, 16 Nov 2016 16:03:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1479312227; bh=NZZVPFLL5R0230+WFtZ3eca4eije6LXVhUxSit8a7Ec=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SqS3Fkp92+Qci0WYkD0kj4QSBFktNUgr30e8IzJ7fK6S1yqNfUPPYrKv1oRCoLa1U RU4UvF10uI4D8ZNnSBc7SW875WzfaxdgDInUxjlfcWZryVd9SgY+KUwTC3v3Z/Filp Sm3L4BaWoG+fCkkbwumc/z7xzlyVjS+Gz8vx7Py4= Received: from rharjani-linux.qualcomm.com (unknown [202.46.23.54]) (using TLSv1.1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: riteshh@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 075906162A; Wed, 16 Nov 2016 16:03:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1479312222; bh=NZZVPFLL5R0230+WFtZ3eca4eije6LXVhUxSit8a7Ec=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NNya5EBEQLKWZBWtXP/rU8cScSJrJPdLLFo8MMFFoIsEBdbStWdtc1ojYE5BR8yDu zMPLfUAnSTyFg/sdt7UEHgHYE1XfKhxIcFA3RY7/LkU0fJnZfIWwlVNYz1dIE70jqg ho1XDwMj7O2IjzZrn8bkydlJNRjUM1k5/jk+IeLI= DMARC-Filter: OpenDMARC Filter v1.3.1 smtp.codeaurora.org 075906162A Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=pass smtp.mailfrom=riteshh@codeaurora.org From: Ritesh Harjani To: ulf.hansson@linaro.org, linux-mmc@vger.kernel.org, adrian.hunter@intel.com, sboyd@codeaurora.org, andy.gross@linaro.org Cc: shawn.lin@rock-chips.com, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, david.brown@linaro.org, linux-arm-msm@vger.kernel.org, georgi.djakov@linaro.org, alex.lemberg@sandisk.com, mateusz.nowak@intel.com, Yuliy.Izrailov@sandisk.com, asutoshd@codeaurora.org, david.griego@linaro.org, stummala@codeaurora.org, venkatg@codeaurora.org, rnayak@codeaurora.org, pramod.gurav@linaro.org, jeremymc@redhat.com, Ritesh Harjani , Krishna Konda Subject: [PATCH v8 16/16] sdhci: sdhci-msm: update dll configuration Date: Wed, 16 Nov 2016 21:30:52 +0530 Message-Id: <1479312052-22396-17-git-send-email-riteshh@codeaurora.org> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1479312052-22396-1-git-send-email-riteshh@codeaurora.org> References: <1479312052-22396-1-git-send-email-riteshh@codeaurora.org> Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The newer msm sdhci's cores use a different DLL hardware for HS400. Update the configuration and calibration of the newer DLL block. The HS400 DLL block used previously is CDC LP 533 and requires programming multiple registers and waiting for configuration to complete and then enable it. It has about 18 register writes and two register reads. The newer HS400 DLL block is SDC4 DLL and requires two register writes for configuration and one register read to confirm that it is initialized. There is an additional register write to enable the power save mode for SDC4 DLL block. Signed-off-by: Ritesh Harjani Signed-off-by: Krishna Konda Acked-by: Adrian Hunter --- drivers/mmc/host/sdhci-msm.c | 125 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 47379f4..49907f4 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -52,6 +52,7 @@ #define INT_MASK 0xf #define MAX_PHASES 16 #define CORE_DLL_LOCK BIT(7) +#define CORE_DDR_DLL_LOCK BIT(11) #define CORE_DLL_EN BIT(16) #define CORE_CDR_EN BIT(17) #define CORE_CK_OUT_EN BIT(18) @@ -63,6 +64,7 @@ #define CORE_DLL_STATUS 0x108 #define CORE_DLL_CONFIG_2 0x1b4 +#define CORE_DDR_CAL_EN BIT(0) #define CORE_FLL_CYCLE_CNT BIT(18) #define CORE_DLL_CLOCK_DISABLE BIT(21) @@ -101,6 +103,11 @@ #define CORE_DDR_200_CFG 0x184 #define CORE_CDC_T4_DLY_SEL BIT(0) #define CORE_START_CDC_TRAFFIC BIT(6) +#define CORE_VENDOR_SPEC3 0x1b0 +#define CORE_PWRSAVE_DLL BIT(3) + +#define CORE_DDR_CONFIG 0x1b8 +#define DDR_CONFIG_POR_VAL 0x80040853 #define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c @@ -128,6 +135,7 @@ struct sdhci_msm_host { bool tuning_done; bool calibration_done; u8 saved_tuning_phase; + bool use_cdclp533; }; /* Platform specific tuning */ @@ -569,6 +577,87 @@ static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host) return ret; } +static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host) +{ + u32 dll_status, config; + int ret; + + pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__); + + /* + * Currently the CORE_DDR_CONFIG register defaults to desired + * configuration on reset. Currently reprogramming the power on + * reset (POR) value in case it might have been modified by + * bootloaders. In the future, if this changes, then the desired + * values will need to be programmed appropriately. + */ + writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + CORE_DDR_CONFIG); + + config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2); + config |= CORE_DDR_CAL_EN; + writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2); + + ret = readl_relaxed_poll_timeout(host->ioaddr + CORE_DLL_STATUS, + dll_status, + (dll_status & CORE_DDR_DLL_LOCK), + 10, 1000); + + if (ret == -ETIMEDOUT) { + pr_err("%s: %s: CM_DLL_SDC4 calibration was not completed\n", + mmc_hostname(host->mmc), __func__); + goto out; + } + + config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC3); + config |= CORE_PWRSAVE_DLL; + writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC3); + + /* + * Drain writebuffer to ensure above DLL calibration + * and PWRSAVE DLL is enabled. + */ + wmb(); +out: + pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc), + __func__, ret); + return ret; +} + +static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); + int ret; + u32 config; + + pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__); + + /* + * Retuning in HS400 (DDR mode) will fail, just reset the + * tuning block and restore the saved tuning phase. + */ + ret = msm_init_cm_dll(host); + if (ret) + goto out; + + /* Set the selected phase in delay line hw block */ + ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase); + if (ret) + goto out; + + config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); + config |= CORE_CMD_DAT_TRACK_SEL; + writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); + if (msm_host->use_cdclp533) + ret = sdhci_msm_cdclp533_calibration(host); + else + ret = sdhci_msm_cm_dll_sdc4_calibration(host); +out: + pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc), + __func__, ret); + return ret; +} + static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode) { int tuning_seq_cnt = 3; @@ -715,7 +804,7 @@ static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host, if (host->clock > CORE_FREQ_100MHZ && msm_host->tuning_done && !msm_host->calibration_done && mmc->ios.timing == MMC_TIMING_MMC_HS400) - if (!sdhci_msm_cdclp533_calibration(host)) + if (!sdhci_msm_hs400_dll_calibration(host)) msm_host->calibration_done = true; spin_lock_irq(&host->lock); } @@ -805,7 +894,7 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); struct mmc_ios curr_ios = host->mmc->ios; - u32 config; + u32 config, dll_lock; int rc; if (!clock) { @@ -862,7 +951,32 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) config |= CORE_HC_SELECT_IN_EN; writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC); } + if (!msm_host->clk_rate && !msm_host->use_cdclp533) { + /* + * Poll on DLL_LOCK or DDR_DLL_LOCK bits in + * CORE_DLL_STATUS to be set. This should get set + * within 15 us at 200 MHz. + */ + rc = readl_relaxed_poll_timeout(host->ioaddr + + CORE_DLL_STATUS, + dll_lock, + (dll_lock & + (CORE_DLL_LOCK | + CORE_DDR_DLL_LOCK)), 10, + 1000); + if (rc == -ETIMEDOUT) + pr_err("%s: Unable to get DLL_LOCK/DDR_DLL_LOCK, dll_status: 0x%08x\n", + mmc_hostname(host->mmc), dll_lock); + } } else { + if (!msm_host->use_cdclp533) { + config = readl_relaxed(host->ioaddr + + CORE_VENDOR_SPEC3); + config &= ~CORE_PWRSAVE_DLL; + writel_relaxed(config, host->ioaddr + + CORE_VENDOR_SPEC3); + } + config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC); config &= ~CORE_HC_MCLK_SEL_MASK; config |= CORE_HC_MCLK_SEL_DFLT; @@ -1055,6 +1169,13 @@ static int sdhci_msm_probe(struct platform_device *pdev) msm_host->use_14lpp_dll_reset = true; /* + * SDCC 5 controller with major version 1, minor version 0x34 and later + * with HS 400 mode support will use CM DLL instead of CDC LP 533 DLL. + */ + if (core_major == 1 && core_minor < 0x34) + msm_host->use_cdclp533 = true; + + /* * Support for some capabilities is not advertised by newer * controller versions and must be explicitly enabled. */