From patchwork Fri Oct 18 11:48:43 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aisheng Dong X-Patchwork-Id: 3066161 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 91FA0BF924 for ; Fri, 18 Oct 2013 12:05:23 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4202D20489 for ; Fri, 18 Oct 2013 12:05:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E43AF20480 for ; Fri, 18 Oct 2013 12:05:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753157Ab3JRMFT (ORCPT ); Fri, 18 Oct 2013 08:05:19 -0400 Received: from ch1ehsobe001.messaging.microsoft.com ([216.32.181.181]:48725 "EHLO ch1outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753018Ab3JRMFS (ORCPT ); Fri, 18 Oct 2013 08:05:18 -0400 Received: from mail178-ch1-R.bigfish.com (10.43.68.234) by CH1EHSOBE013.bigfish.com (10.43.70.63) with Microsoft SMTP Server id 14.1.225.22; Fri, 18 Oct 2013 12:05:18 +0000 Received: from mail178-ch1 (localhost [127.0.0.1]) by mail178-ch1-R.bigfish.com (Postfix) with ESMTP id D6D1C420082; Fri, 18 Oct 2013 12:05:17 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 6 X-BigFish: VS6(zcb8kzzz1f42h208ch1ee6h1de0h1fdah2073h1202h1e76h1d1ah1d2ah1fc6h1082kzz1de098h8275dh1de097h8275bhz2dh2a8h839hd24he5bhf0ah1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1ad9h1b0ah1b2fh1fb3h1d0ch1d2eh1d3fh1dfeh1dffh1e23h1fe8h1ff5h1155h) Received: from mail178-ch1 (localhost.localdomain [127.0.0.1]) by mail178-ch1 (MessageSwitch) id 1382097915594977_10946; Fri, 18 Oct 2013 12:05:15 +0000 (UTC) Received: from CH1EHSMHS012.bigfish.com (snatpool2.int.messaging.microsoft.com [10.43.68.234]) by mail178-ch1.bigfish.com (Postfix) with ESMTP id 8C3AC320100; Fri, 18 Oct 2013 12:05:15 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by CH1EHSMHS012.bigfish.com (10.43.70.12) with Microsoft SMTP Server (TLS) id 14.16.227.3; Fri, 18 Oct 2013 12:05:15 +0000 Received: from az84smr01.freescale.net (10.64.34.197) by 039-SN1MMR1-004.039d.mgd.msft.net (10.84.1.14) with Microsoft SMTP Server (TLS) id 14.3.158.2; Fri, 18 Oct 2013 12:05:14 +0000 Received: from shlinux2.ap.freescale.net (shlinux2.ap.freescale.net [10.192.224.44]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id r9IC581X011528; Fri, 18 Oct 2013 05:05:12 -0700 From: Dong Aisheng To: CC: , , , , , Subject: [PATCH v3 1/8] mmc: sdhci-esdhc-imx: add std tuning support for mx6sl Date: Fri, 18 Oct 2013 19:48:43 +0800 Message-ID: <1382096930-7964-2-git-send-email-b29396@freescale.com> X-Mailer: git-send-email 1.7.2.rc3 In-Reply-To: <1382096930-7964-1-git-send-email-b29396@freescale.com> References: <1382096930-7964-1-git-send-email-b29396@freescale.com> MIME-Version: 1.0 X-OriginatorOrg: freescale.com X-FOPE-CONNECTOR: Id%0$Dn%*$RO%0$TLS%0$FQDN%$TlsDn% Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Spam-Status: No, score=-7.3 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The mx6sl supports standard sdhci tuning, then esdhc_executing_tuning is only needed for mx6q/dl. We introduce is_imx6_usdhc() and is_imx6sl_usdhc() to handle the difference. The standard tuning is enabled by setting ESDHC_TUNE_CTRL_STD_TUNING_EN bit in new register ESDHC_TUNE_CTRL and operates with new tuning bits defined in SDHCI_ACMD12_ERR register. Note: mx6sl can also work on the old manually tuning mode as mx6q/dl if not enable standard tuning mode. Signed-off-by: Dong Aisheng Acked-by: Shawn Guo --- drivers/mmc/host/sdhci-esdhc-imx.c | 90 +++++++++++++++++++++++++++++------- 1 files changed, 73 insertions(+), 17 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index c84c808..3b9c94f 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -51,6 +51,11 @@ #define ESDHC_TUNE_CTRL_MIN 0 #define ESDHC_TUNE_CTRL_MAX ((1 << 7) - 1) +#define ESDHC_TUNING_CTRL 0xcc +#define ESDHC_STD_TUNING_EN (1 << 24) +/* NOTE: the minimum valid tuning start tap for mx6sl is 1 */ +#define ESDHC_TUNING_START_TAP 0x1 + #define ESDHC_TUNING_BLOCK_PATTERN_LEN 64 /* pinctrl state */ @@ -94,6 +99,12 @@ * integrated on the i.MX6 series. */ #define ESDHC_FLAG_USDHC BIT(3) +/* The IP supports manual tuning process */ +#define ESDHC_FLAG_MAN_TUNING BIT(4) +/* The IP supports standard tuning process */ +#define ESDHC_FLAG_STD_TUNING BIT(5) +/* The IP has SDHCI_CAPABILITIES_1 register */ +#define ESDHC_FLAG_HAVE_CAP1 BIT(6) struct esdhc_soc_data { u32 flags; @@ -116,7 +127,12 @@ static struct esdhc_soc_data esdhc_imx53_data = { }; static struct esdhc_soc_data usdhc_imx6q_data = { - .flags = ESDHC_FLAG_USDHC, + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING, +}; + +static struct esdhc_soc_data usdhc_imx6sl_data = { + .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING + | ESDHC_FLAG_HAVE_CAP1, }; struct pltfm_imx_data { @@ -159,6 +175,7 @@ static const struct of_device_id imx_esdhc_dt_ids[] = { { .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx35_data, }, { .compatible = "fsl,imx51-esdhc", .data = &esdhc_imx51_data, }, { .compatible = "fsl,imx53-esdhc", .data = &esdhc_imx53_data, }, + { .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, }, { .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, }, { /* sentinel */ } }; @@ -222,9 +239,16 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) } } - if (unlikely(reg == SDHCI_CAPABILITIES_1) && esdhc_is_usdhc(imx_data)) - val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104 - | SDHCI_SUPPORT_SDR50; + if (unlikely(reg == SDHCI_CAPABILITIES_1)) { + if (esdhc_is_usdhc(imx_data)) { + if (imx_data->socdata->flags & ESDHC_FLAG_HAVE_CAP1) + val = readl(host->ioaddr + SDHCI_CAPABILITIES) & 0xFFFF; + else + /* imx6q/dl does not have cap_1 register, fake one */ + val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104 + | SDHCI_SUPPORT_SDR50; + } + } if (unlikely(reg == SDHCI_MAX_CURRENT) && esdhc_is_usdhc(imx_data)) { val = 0; @@ -331,13 +355,18 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg) ret |= SDHCI_CTRL_VDD_180; if (esdhc_is_usdhc(imx_data)) { - val = readl(host->ioaddr + ESDHC_MIX_CTRL); - if (val & ESDHC_MIX_CTRL_EXE_TUNE) - ret |= SDHCI_CTRL_EXEC_TUNING; - if (val & ESDHC_MIX_CTRL_SMPCLK_SEL) - ret |= SDHCI_CTRL_TUNED_CLK; + if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) + val = readl(host->ioaddr + ESDHC_MIX_CTRL); + else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) + /* the std tuning bits is in ACMD12_ERR for imx6sl */ + val = readl(host->ioaddr + SDHCI_ACMD12_ERR); } + if (val & ESDHC_MIX_CTRL_EXE_TUNE) + ret |= SDHCI_CTRL_EXEC_TUNING; + if (val & ESDHC_MIX_CTRL_SMPCLK_SEL) + ret |= SDHCI_CTRL_TUNED_CLK; + ret |= (imx_data->uhs_mode & SDHCI_CTRL_UHS_MASK); ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; @@ -370,12 +399,37 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) new_val &= ~ESDHC_VENDOR_SPEC_VSELECT; writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); imx_data->uhs_mode = val & SDHCI_CTRL_UHS_MASK; - new_val = readl(host->ioaddr + ESDHC_MIX_CTRL); - if (val & SDHCI_CTRL_TUNED_CLK) - new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL; - else - new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; - writel(new_val , host->ioaddr + ESDHC_MIX_CTRL); + if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { + new_val = readl(host->ioaddr + ESDHC_MIX_CTRL); + if (val & SDHCI_CTRL_TUNED_CLK) + new_val |= ESDHC_MIX_CTRL_SMPCLK_SEL; + else + new_val &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; + writel(new_val , host->ioaddr + ESDHC_MIX_CTRL); + } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) { + u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR); + u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL); + new_val = readl(host->ioaddr + ESDHC_TUNING_CTRL); + if (val & SDHCI_CTRL_EXEC_TUNING) { + new_val |= ESDHC_STD_TUNING_EN | + ESDHC_TUNING_START_TAP; + v |= ESDHC_MIX_CTRL_EXE_TUNE; + m |= ESDHC_MIX_CTRL_FBCLK_SEL; + } else { + new_val &= ~ESDHC_STD_TUNING_EN; + v &= ~ESDHC_MIX_CTRL_EXE_TUNE; + m &= ~ESDHC_MIX_CTRL_FBCLK_SEL; + } + + if (val & SDHCI_CTRL_TUNED_CLK) + v |= ESDHC_MIX_CTRL_SMPCLK_SEL; + else + v &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; + + writel(new_val, host->ioaddr + ESDHC_TUNING_CTRL); + writel(v, host->ioaddr + SDHCI_ACMD12_ERR); + writel(m, host->ioaddr + ESDHC_MIX_CTRL); + } return; case SDHCI_TRANSFER_MODE: if ((imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) @@ -774,7 +828,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) return esdhc_change_pinstate(host, uhs); } -static const struct sdhci_ops sdhci_esdhc_ops = { +static struct sdhci_ops sdhci_esdhc_ops = { .read_l = esdhc_readl_le, .read_w = esdhc_readw_le, .write_l = esdhc_writel_le, @@ -786,7 +840,6 @@ static const struct sdhci_ops sdhci_esdhc_ops = { .get_ro = esdhc_pltfm_get_ro, .platform_bus_width = esdhc_pltfm_bus_width, .set_uhs_signaling = esdhc_set_uhs_signaling, - .platform_execute_tuning = esdhc_executing_tuning, }; static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { @@ -922,6 +975,9 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) if (esdhc_is_usdhc(imx_data)) writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL); + if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) + sdhci_esdhc_ops.platform_execute_tuning = + esdhc_executing_tuning; boarddata = &imx_data->boarddata; if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) { if (!host->mmc->parent->platform_data) {