From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756155AbbCCKtD (ORCPT ); Tue, 3 Mar 2015 05:49:03 -0500 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:58223 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751625AbbCCKtA (ORCPT ); Tue, 3 Mar 2015 05:49:00 -0500 Message-ID: <54F5915C.6090707@st.com> Date: Tue, 3 Mar 2015 11:47:56 +0100 From: Maxime Coquelin User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: Peter Griffin , , , , , , CC: , , , Subject: Re: [PATCH v2 3/8] mmc: sdhci-st: Add delay management functions for top registers (eMMC). References: <1424956227-18258-1-git-send-email-peter.griffin@linaro.org> <1424956227-18258-4-git-send-email-peter.griffin@linaro.org> In-Reply-To: <1424956227-18258-4-git-send-email-peter.griffin@linaro.org> Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit X-Originating-IP: [10.201.23.80] X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.13.68,1.0.33,0.0.0000 definitions=2015-03-03_03:2015-03-03,2015-03-03,1970-01-01 signatures=0 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 02/26/2015 02:10 PM, Peter Griffin wrote: > Due to the tight timing constriants in some UHS modes, it is required to have s/constriant/constraints/ > some delay management in the design. Two types of delay management are supported > in the HW: - > > 1) Static delay management > 2) Dynamic delay management > > NB: The delay management is only there when eMMC interface is selected. > > 1: Static delay management: is used to provide PVT dependent static delay on the > clock/data lines to manage setup/hold requirements of the interface. The maximum > delay possible is 3.25ns. These delays are PVT dependent, and thus delay values > applied are not accurate and vary across provcess voltage and temperature range. > Due to this these delays must not be used on the very time critical paths. > > 2. Dynamic delay locked loop (DLL): is used to provide dynamic delay management. > The advantage of DLL is that it provides accurate & PVT indepedent delay. > > The DLL is used to provide delay on the loopback clock on "Read Path" to capture > read data reliably. On TX path the clock on which output data is transmitted is > delayed, resulting in delay of TX data. > > Signed-off-by: Peter Griffin > Signed-off-by: Giuseppe Cavallaro > --- > drivers/mmc/host/sdhci-st.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 58 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c > index 0101ae9..3443cc0 100644 > --- a/drivers/mmc/host/sdhci-st.c > +++ b/drivers/mmc/host/sdhci-st.c > @@ -122,6 +122,64 @@ struct st_mmc_platform_data { > ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \ > ST_TOP_MMC_START_DLL_LOCK) > > +/* > + * For clock speeds greater than 90MHz, we need to check that the > + * DLL procedure has finished before switching to ultra-speed modes. > + */ > +#define CLK_TO_CHECK_DLL_LOCK 90000000 > + > +static inline void st_mmcss_set_static_delay(void __iomem *ioaddr) > +{ > + if (ioaddr) { Maybe you could do: if (!ioaddr) return; writel_relaxed.... > + writel_relaxed(0x0, ioaddr + ST_TOP_MMC_DLY_CTRL); > + writel_relaxed(ST_TOP_MMC_DLY_MAX, > + ioaddr + ST_TOP_MMC_TX_CLK_DLY); > + } > +} > + > +static inline void st_mmcss_set_dll(void __iomem *ioaddr) > +{ > + if (ioaddr) { Ditto > + writel_relaxed(ST_TOP_MMC_DYN_DLY_CONF, > + ioaddr + ST_TOP_MMC_DLY_CTRL); > + writel_relaxed(ST_TOP_MMC_TX_DLL_STEP_DLY_VALID, > + ioaddr + ST_TOP_MMC_TX_DLL_STEP_DLY); > + } > +} > + > +static int st_mmcss_lock_dll(void __iomem *ioaddr) > +{ > + unsigned long curr, value; > + unsigned long finish = jiffies + HZ; > + > + /* Checks if the DLL procedure is finished */ > + do { > + curr = jiffies; > + value = readl(ioaddr + ST_MMC_STATUS_R); > + if (value & 0x1) > + return 0; > + > + cpu_relax(); > + } while (!time_after_eq(curr, finish)); > + > + return -EBUSY; > +} > + > +static int sdhci_st_set_dll_for_clock(struct sdhci_host *host) > +{ > + int ret = 0; > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > + struct st_mmc_platform_data *pdata = pltfm_host->priv; > + > + if (host->clock > CLK_TO_CHECK_DLL_LOCK) { > + st_mmcss_set_dll(pdata->top_ioaddr); > + ret = st_mmcss_lock_dll(host->ioaddr); > + } > + > + return ret; > +} > + > + > static u32 sdhci_st_readl(struct sdhci_host *host, int reg) > { > u32 ret;