From patchwork Thu Jan 25 10:51:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Jacques Hiblot X-Patchwork-Id: 125792 Delivered-To: patch@linaro.org Received: by 10.46.66.141 with SMTP id h13csp1029682ljf; Thu, 25 Jan 2018 02:59:57 -0800 (PST) X-Google-Smtp-Source: AH8x227b9rF0Ev/CFDUFq38SwGOICAonWxOjcp+MOAYSBXQUZ4prHZTWx+rtUtHj/r7bjuYOsIGL X-Received: by 10.80.134.44 with SMTP id o41mr28502184edo.243.1516877997037; Thu, 25 Jan 2018 02:59:57 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516877997; cv=none; d=google.com; s=arc-20160816; b=na40p1pkNUlHoT/1I4ZUxsvXCDYmG1aBLYkbhHgJd3dIcd04gw8Mr0/OIvZRc2zqFd i7sBpWvU3JXFSrzoauCixE6zqwAiYJenTZ1DW51nN7F4NW0s4Qquxrz40dxZ5ELiuiYV hK3qDmXOazMEoT2fEsFP2VxKCDcposc2RiKFCEVnjG2d5CV73ALJnhIpkuc6zrA2+u3I W7LuhZof3srpmroVr/RUMIeVBZ5IPvaEbq1T1LFK2ujIHm7xEtnAJHF/T1CLQ10/K+36 723XSyDQ06NFrpaAMOiGRwL7uEYYOLgtAttTBpAW4o+nsjOnbzsIwBy5lL4WNXi+bcKx JBGg== 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=dY7KvaZ4kujGO55KCav/PdNyQu8gjuU6yr2juMRzP4Q=; b=VndY4AgkvaifiWEdeTuatiCMBrToWkD+tua4t5srI9PmyTzikQDXphSYzIfGHz7O2/ 5V0SjR6Hx0GWF9LwQzI/hIRerqzIbguVaJ3s4YP7Vp8+j3eCrGY9p9J+RyJbJNsXkKrP 8DeOko8aAoq8vYm28ViTunMgI0H5OAmbB73qBAFp5K34VvgUJTPJ17xu5fA0EQjSQKu2 nEael5/5RArw5T77/ZzU9FT/XnTkdeii0opEXOJtWjUufbHabNs/Z/j+nYqbomoKjreq wA3YMVGFM3EOYDX91NHmqohyKN0YiU1oYUsm1AveLsgv2VcLqFQQrb1MoXDL7W2ehUeZ 81KQ== 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=Bke89+uc; 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 k24si2020751edk.282.2018.01.25.02.59.56; Thu, 25 Jan 2018 02:59:57 -0800 (PST) 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=Bke89+uc; 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 9FF4EC223AF; Thu, 25 Jan 2018 10:55: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 C6B00C223C8; Thu, 25 Jan 2018 10:52:50 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id D8FEFC2236A; Thu, 25 Jan 2018 10:52:12 +0000 (UTC) Received: from fllnx210.ext.ti.com (fllnx210.ext.ti.com [198.47.19.17]) by lists.denx.de (Postfix) with ESMTPS id 01A8AC2239C for ; Thu, 25 Jan 2018 10:52:08 +0000 (UTC) Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by fllnx210.ext.ti.com (8.15.1/8.15.1) with ESMTP id w0PAq54B011659; Thu, 25 Jan 2018 04:52:05 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ti.com; s=ti-com-17Q1; t=1516877525; bh=SQh5jWIiURlKIYiLevWcY5zoLmT8ifYUzoL/dBNQWT0=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=Bke89+ucDznYHKx9/z5DRHn8M3IrNBciV2OG0s0oRDUS9I9ZR/B+O0XzdG36t2xqK YUAmKOYcKZjz25Vy7tXGdsj3BlXzb1giXrNq0zh6JRLzGDdYDpy/W4X7dUzsM4PMg5 cCXBirU+RNIUjbMqqpqvK5GnyN3dRJHOf7nOjIGY= Received: from DLEE104.ent.ti.com (dlee104.ent.ti.com [157.170.170.34]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id w0PAq5vb020313; Thu, 25 Jan 2018 04:52:05 -0600 Received: from DLEE104.ent.ti.com (157.170.170.34) by DLEE104.ent.ti.com (157.170.170.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1261.35; Thu, 25 Jan 2018 04:52:05 -0600 Received: from dlep32.itg.ti.com (157.170.170.100) by DLEE104.ent.ti.com (157.170.170.34) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1261.35 via Frontend Transport; Thu, 25 Jan 2018 04:52:05 -0600 Received: from localhost (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep32.itg.ti.com (8.14.3/8.13.8) with ESMTP id w0PAq4HW000370; Thu, 25 Jan 2018 04:52:04 -0600 From: Jean-Jacques Hiblot To: , , , Date: Thu, 25 Jan 2018 11:51:32 +0100 Message-ID: <1516877510-14863-7-git-send-email-jjhiblot@ti.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1516877510-14863-1-git-send-email-jjhiblot@ti.com> References: <1516877510-14863-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 v2 06/24] 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 | 122 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 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 5f5fd90..fb29a08 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,124 @@ static void omap_hsmmc_set_capabilities(struct mmc *mmc) writel(val, &mmc_base->capa); } + +#ifdef MMC_SUPPORTS_TUNING +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 #endif static int omap_hsmmc_init_setup(struct mmc *mmc) @@ -1048,6 +1167,9 @@ static const struct dm_mmc_ops omap_hsmmc_ops = { .get_cd = omap_hsmmc_getcd, .get_wp = omap_hsmmc_getwp, #endif +#ifdef MMC_SUPPORTS_TUNING + .execute_tuning = omap_hsmmc_execute_tuning, +#endif }; #else static const struct mmc_ops omap_hsmmc_ops = {