From patchwork Thu Sep 21 15:22:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Jacques Hiblot X-Patchwork-Id: 113282 Delivered-To: patch@linaro.org Received: by 10.140.106.117 with SMTP id d108csp2168513qgf; Thu, 21 Sep 2017 08:35:35 -0700 (PDT) X-Google-Smtp-Source: AOwi7QBzoIUcBnjXEo/mW8uai8/GV6CtOU8FCHbhzJQuxWiv58WdRmr4LdTY7albkUXvBo2xlK7V X-Received: by 10.80.179.47 with SMTP id q44mr1604744edd.123.1506008135157; Thu, 21 Sep 2017 08:35:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1506008135; cv=none; d=google.com; s=arc-20160816; b=p5PnsIyQ5rbhN8MM8P/ENPEIzMpn0Q+FvoN9ujWpi6ciIjMQ4U84KhHZh08xPFbvS8 Ic82rigMrkwnsuuHgHJaYW+V6v9T+AgI6UQm0+XPzdkw1rblpTAJM9schc6BKW9rlMsl LNzV+6KeS+itDN0nGVoAOchC/7sJqME1mmQV/lqCgd3TeW997Ug/qjG22h2RTom1C+UD 6voF3Qtej36av1EUkJ+lUk5lwN7nztOeOKvYGdfqmLEATb/7jRCnOFGXk+X9VJ2FBqwC qjDlvCdEyPRzO5APiiQugPHBkN5TIBSyU82PILt4t10lVyXpJZVfK5FEx+XT3jbJUvRB PvKg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :cc:mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:arc-authentication-results; bh=vd41RABdxN/i1KFHos+SAJWunL9ZsecrWMU0UtY6tPs=; b=g0UiOUqjMpb7/0/rP0YFR3Hb3FT6+CZ2RxBagddwo6QPZPDYSQZQc9eIUJsXCLaNWz P3HIuRd3/ZH6+VHs4tH+IbWH1aymqcsQfb+O/ClIQ+nKyf7jFeqNvNosOoBQnD53wFf8 +lRRfufos+WSP262I4UzhWMh80C2VvdcEy50TdmlP7dt3cN701GBKXQ+M7hHVG/uNF+s XKlpqvJYJTAxGG27JxxaYQTjSEigjql0wYOnakg1s2ZdEKfYAiPZPZZSJy5QIe6Qkvhy NbRuEcH3aZsqWZGaZtGTdvIXpmKkfAaC90ceMiEFwArGIFu0rcyTt8QLv7JmTaGjz7yk PVQA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@ti.com header.s=ti-com-17Q1 header.b=o2DpegYt; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Return-Path: Received: from lists.denx.de (dione.denx.de. [81.169.180.215]) by mx.google.com with ESMTP id b13si1733064edi.30.2017.09.21.08.35.34; Thu, 21 Sep 2017 08:35:35 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) client-ip=81.169.180.215; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@ti.com header.s=ti-com-17Q1 header.b=o2DpegYt; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Received: by lists.denx.de (Postfix, from userid 105) id B9215C22117; Thu, 21 Sep 2017 15:28:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_NONE, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id C458BC220B6; Thu, 21 Sep 2017 15:28:46 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 64F2CC22091; Thu, 21 Sep 2017 15:23:58 +0000 (UTC) Received: from fllnx209.ext.ti.com (fllnx209.ext.ti.com [198.47.19.16]) by lists.denx.de (Postfix) with ESMTPS id B588FC2205D for ; Thu, 21 Sep 2017 15:23:54 +0000 (UTC) Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by fllnx209.ext.ti.com (8.15.1/8.15.1) with ESMTP id v8LFMqJs009127; Thu, 21 Sep 2017 10:22:52 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ti.com; s=ti-com-17Q1; t=1506007372; bh=Ucm4lqVe13YFtZDnIHUxkESLqTrwu2lHDaw+tuZA0E0=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=o2DpegYtAZk9FpPc9IeOyf/ObvbguEz+0GJT0kLWODSHCGeUQ46eoWNeCrdM/TCV8 vUQUR2ADufoB3a2oIih5eCHSMZpp9ID9Om9ySGrLKR2KS9SWjffOv0Sn5v7NtK36U/ SNVYwwrrz7J6zGlnjKpnpazbrDWruCQL8Pi3r6Fw= Received: from DFLE105.ent.ti.com (dfle105.ent.ti.com [10.64.6.26]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id v8LFMlGi032760; Thu, 21 Sep 2017 10:22:47 -0500 Received: from DFLE115.ent.ti.com (10.64.6.36) by DFLE105.ent.ti.com (10.64.6.26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.1.845.34; Thu, 21 Sep 2017 10:22:47 -0500 Received: from dflp32.itg.ti.com (10.64.6.15) by DFLE115.ent.ti.com (10.64.6.36) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.845.34 via Frontend Transport; Thu, 21 Sep 2017 10:22:47 -0500 Received: from localhost (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id v8LFMkwu014784; Thu, 21 Sep 2017 10:22:46 -0500 From: Jean-Jacques Hiblot To: , , , , Date: Thu, 21 Sep 2017 17:22:09 +0200 Message-ID: <1506007346-10037-7-git-send-email-jjhiblot@ti.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1506007346-10037-1-git-send-email-jjhiblot@ti.com> References: <1506007346-10037-1-git-send-email-jjhiblot@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Cc: u-boot@lists.denx.de Subject: [U-Boot] [PATCH 06/23] mmc: omap_hsmmc: Add tuning support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" From: Kishon Vijay Abraham I HS200/SDR104 requires tuning command to be sent to the card. Use the mmc_send_tuning library function to send the tuning command and configure the internal DLL. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Jean-Jacques Hiblot --- arch/arm/include/asm/omap_mmc.h | 21 ++++++- drivers/mmc/omap_hsmmc.c | 118 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/omap_mmc.h b/arch/arm/include/asm/omap_mmc.h index 341a2e2..0293281 100644 --- a/arch/arm/include/asm/omap_mmc.h +++ b/arch/arm/include/asm/omap_mmc.h @@ -39,7 +39,9 @@ struct hsmmc { unsigned int sysstatus; /* 0x14 */ unsigned char res2[0x14]; unsigned int con; /* 0x2C */ - unsigned char res3[0xD4]; + unsigned int pwcnt; /* 0x30 */ + unsigned int dll; /* 0x34 */ + unsigned char res3[0xcc]; unsigned int blk; /* 0x104 */ unsigned int arg; /* 0x108 */ unsigned int cmd; /* 0x10C */ @@ -56,7 +58,8 @@ struct hsmmc { unsigned char res4[0x4]; unsigned int ac12; /* 0x13C */ unsigned int capa; /* 0x140 */ - unsigned char res5[0x10]; + unsigned int capa2; /* 0x144 */ + unsigned char res5[0xc]; unsigned int admaes; /* 0x154 */ unsigned int admasal; /* 0x158 */ }; @@ -173,6 +176,8 @@ struct omap_hsmmc_plat { #define IOV_1V8 1800000 #define AC12_ET (1 << 22) +#define AC12_V1V8_SIGEN (1 << 19) +#define AC12_SCLK_SEL (1 << 23) #define AC12_UHSMC_MASK (7 << 16) #define AC12_UHSMC_DDR50 (4 << 16) #define AC12_UHSMC_SDR104 (3 << 16) @@ -199,6 +204,18 @@ struct omap_hsmmc_plat { /* Clock Configurations and Macros */ #define MMC_CLOCK_REFERENCE 96 /* MHz */ +/* DLL */ +#define DLL_SWT (1 << 20) +#define DLL_FORCE_SR_C_SHIFT 13 +#define DLL_FORCE_SR_C_MASK 0x7f +#define DLL_FORCE_VALUE (1 << 12) +#define DLL_CALIB (1 << 1) + +#define MAX_PHASE_DELAY 0x7c + +/* CAPA2 */ +#define CAPA2_TSDR50 (1 << 13) + #define mmc_reg_out(addr, mask, val)\ writel((readl(addr) & (~(mask))) | ((val) & (mask)), (addr)) diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index d5cd826..321a091 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -124,6 +124,7 @@ static int mmc_write_data(struct hsmmc *mmc_base, const char *buf, unsigned int siz); static void omap_hsmmc_start_clock(struct hsmmc *mmc_base); static void omap_hsmmc_stop_clock(struct hsmmc *mmc_base); +static void mmc_reset_controller_fsm(struct hsmmc *mmc_base, u32 bit); static inline struct omap_hsmmc_data *omap_hsmmc_get_data(struct mmc *mmc) { @@ -355,6 +356,122 @@ static void omap_hsmmc_set_capabilities(struct mmc *mmc) writel(val, &mmc_base->capa); } + +static void omap_hsmmc_disable_tuning(struct mmc *mmc) +{ + struct hsmmc *mmc_base; + struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc); + u32 val; + + mmc_base = priv->base_addr; + val = readl(&mmc_base->ac12); + val &= ~(AC12_SCLK_SEL); + writel(val, &mmc_base->ac12); + + val = readl(&mmc_base->dll); + val &= ~(DLL_FORCE_VALUE | DLL_SWT); + writel(val, &mmc_base->dll); +} + +static void omap_hsmmc_set_dll(struct mmc *mmc, int count) +{ + int i; + struct hsmmc *mmc_base; + struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc); + u32 val; + + mmc_base = priv->base_addr; + val = readl(&mmc_base->dll); + val |= DLL_FORCE_VALUE; + val &= ~(DLL_FORCE_SR_C_MASK << DLL_FORCE_SR_C_SHIFT); + val |= (count << DLL_FORCE_SR_C_SHIFT); + writel(val, &mmc_base->dll); + + val |= DLL_CALIB; + writel(val, &mmc_base->dll); + for (i = 0; i < 1000; i++) { + if (readl(&mmc_base->dll) & DLL_CALIB) + break; + } + val &= ~DLL_CALIB; + writel(val, &mmc_base->dll); +} + +static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) +{ + struct omap_hsmmc_data *priv = dev_get_priv(dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct mmc *mmc = upriv->mmc; + struct hsmmc *mmc_base; + u32 val; + u8 cur_match, prev_match = 0; + int ret; + u32 phase_delay = 0; + u32 start_window = 0, max_window = 0; + u32 length = 0, max_len = 0; + + mmc_base = priv->base_addr; + val = readl(&mmc_base->capa2); + + /* clock tuning is not needed for upto 52MHz */ + if (!((mmc->selected_mode == MMC_HS_200) || + (mmc->selected_mode == UHS_SDR104) || + ((mmc->selected_mode == UHS_SDR50) && (val & CAPA2_TSDR50)))) + return 0; + + val = readl(&mmc_base->dll); + val |= DLL_SWT; + writel(val, &mmc_base->dll); + while (phase_delay <= MAX_PHASE_DELAY) { + omap_hsmmc_set_dll(mmc, phase_delay); + + cur_match = !mmc_send_tuning(mmc, opcode, NULL); + + if (cur_match) { + if (prev_match) { + length++; + } else { + start_window = phase_delay; + length = 1; + } + } + + if (length > max_len) { + max_window = start_window; + max_len = length; + } + + prev_match = cur_match; + phase_delay += 4; + } + + if (!max_len) { + ret = -EIO; + goto tuning_error; + } + + val = readl(&mmc_base->ac12); + if (!(val & AC12_SCLK_SEL)) { + ret = -EIO; + goto tuning_error; + } + + phase_delay = max_window + 4 * ((3 * max_len) >> 2); + omap_hsmmc_set_dll(mmc, phase_delay); + + mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD); + mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC); + + return 0; + +tuning_error: + + omap_hsmmc_disable_tuning(mmc); + mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD); + mmc_reset_controller_fsm(mmc_base, SYSCTL_SRC); + + return ret; +} #endif static int omap_hsmmc_init_setup(struct mmc *mmc) @@ -1046,6 +1163,7 @@ static const struct dm_mmc_ops omap_hsmmc_ops = { .get_cd = omap_hsmmc_getcd, .get_wp = omap_hsmmc_getwp, #endif + .execute_tuning = omap_hsmmc_execute_tuning, }; #else static const struct mmc_ops omap_hsmmc_ops = {