From patchwork Tue Mar 1 09:58:20 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Zhu X-Patchwork-Id: 261 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:41:16 -0000 Delivered-To: patches@linaro.org Received: by 10.224.19.208 with SMTP id c16cs131018qab; Tue, 1 Mar 2011 01:59:05 -0800 (PST) Received: by 10.223.113.73 with SMTP id z9mr2381523fap.41.1298973534815; Tue, 01 Mar 2011 01:58:54 -0800 (PST) Received: from DB3EHSOBE003.bigfish.com (db3ehsobe003.messaging.microsoft.com [213.199.154.141]) by mx.google.com with ESMTPS id l20si5238313fam.39.2011.03.01.01.58.54 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 01 Mar 2011 01:58:54 -0800 (PST) Received-SPF: neutral (google.com: 213.199.154.141 is neither permitted nor denied by best guess record for domain of Hong-Xing.Zhu@freescale.com) client-ip=213.199.154.141; Authentication-Results: mx.google.com; spf=neutral (google.com: 213.199.154.141 is neither permitted nor denied by best guess record for domain of Hong-Xing.Zhu@freescale.com) smtp.mail=Hong-Xing.Zhu@freescale.com Received: from mail79-db3-R.bigfish.com (10.3.81.249) by DB3EHSOBE003.bigfish.com (10.3.84.23) with Microsoft SMTP Server id 14.1.225.8; Tue, 1 Mar 2011 09:58:54 +0000 Received: from mail79-db3 (localhost.localdomain [127.0.0.1]) by mail79-db3-R.bigfish.com (Postfix) with ESMTP id CF5EC880105; Tue, 1 Mar 2011 09:58:53 +0000 (UTC) X-SpamScore: -2 X-BigFish: VS-2(zzbb2cKzz1202hzz8275bh1497iz2dh2a8h668h61h) X-Spam-TCS-SCL: 0:0 X-Forefront-Antispam-Report: KIP:(null); UIP:(null); IPVD:NLI; H:de01egw02.freescale.net; RD:de01egw02.freescale.net; EFVD:NLI Received: from mail79-db3 (localhost.localdomain [127.0.0.1]) by mail79-db3 (MessageSwitch) id 1298973533413426_25986; Tue, 1 Mar 2011 09:58:53 +0000 (UTC) Received: from DB3EHSMHS002.bigfish.com (unknown [10.3.81.248]) by mail79-db3.bigfish.com (Postfix) with ESMTP id 562B33F804E; Tue, 1 Mar 2011 09:58:53 +0000 (UTC) Received: from de01egw02.freescale.net (192.88.165.103) by DB3EHSMHS002.bigfish.com (10.3.87.102) with Microsoft SMTP Server (TLS) id 14.1.225.8; Tue, 1 Mar 2011 09:58:51 +0000 Received: from az33smr02.freescale.net (az33smr02.freescale.net [10.64.34.200]) by de01egw02.freescale.net (8.14.3/8.14.3) with ESMTP id p219wiNX024258; Tue, 1 Mar 2011 02:58:44 -0700 (MST) Received: from x-VirtualBox.ap.freescale.net (x-VirtualBox.ap.freescale.net [10.192.242.62]) by az33smr02.freescale.net (8.13.1/8.13.0) with ESMTP id p219wPVa026111; Tue, 1 Mar 2011 03:58:39 -0600 (CST) From: Richard Zhu To: CC: , , , , , , , , , Richard Zhu Subject: [PATCH V4 4/4] mmc: sdhci-esdhc: enable esdhc on imx53 Date: Tue, 1 Mar 2011 17:58:20 +0800 Message-ID: <1298973500-2858-4-git-send-email-Hong-Xing.Zhu@freescale.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1298973500-2858-1-git-send-email-Hong-Xing.Zhu@freescale.com> References: <1298973500-2858-1-git-send-email-Hong-Xing.Zhu@freescale.com> MIME-Version: 1.0 X-OriginatorOrg: freescale.com Fix the NO INT in the Multi-BLK IO in SD/MMC, and Multi-BLK read in SDIO The CMDTYPE of the CMD register(offset 0xE) should be set to "11" when the STOP CMD12 is issued on imx53 to abort one open ended multi-blk IO. Otherwise one the TC INT wouldn't be generated. In exact block transfer, the controller doesn't complete the operations automatically as required at the end of the transfer and remains on hold if the abort command is not sent. As a result, the TC flag is not asserted and SW received timeout exeception. set bit1 of Vendor Spec registor to fix it Signed-off-by: Richard Zhu Signed-off-by: Richard Zhao --- drivers/mmc/host/sdhci-esdhc-imx.c | 76 ++++++++++++++++++++++++++++++++++- drivers/mmc/host/sdhci-pltfm.h | 2 +- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 9b82910..5ea4b5f 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -15,13 +15,42 @@ #include #include #include +#include #include #include +#include +#include #include #include "sdhci.h" #include "sdhci-pltfm.h" #include "sdhci-esdhc.h" +/* Abort type definition in the command register */ +#define SDHCI_CMD_ABORTCMD 0xC0 +/* VENDOR SPEC register */ +#define SDHCI_VENDOR_SPEC 0xC0 + #define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002 + +/* + * The CMDTYPE of the CMD register(offset 0xE) should be set to + * "11" when the STOP CMD12 is issued on imx53 to abort one + * open ended multi-blk IO. Otherwise the TC INT wouldn't + * be generated. + * In exact block transfer, the controller doesn't complete the + * operations automatically as required at the end of the + * transfer and remains on hold if the abort command is not sent. + * As a result, the TC flag is not asserted and SW received timeout + * exeception. Bit1 of Vendor Spec registor is used to fix it. + */ +#define IMX_MULTIBLK_NO_INT (1 << 0) + +struct pltfm_imx_data { + int flags; + u32 mod_val; +}; + +static struct sdhci_ops sdhci_esdhc_ops; + static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg) { void __iomem *base = host->ioaddr + (reg & ~0x3); @@ -38,20 +67,49 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg) return readw(host->ioaddr + reg); } +static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) +{ + switch (reg) { + case SDHCI_INT_STATUS: + if (val & SDHCI_INT_DATA_END) { + u32 v; + v = readl(host->ioaddr + SDHCI_VENDOR_SPEC); + v &= ~SDHCI_VENDOR_SPEC_SDIO_QUIRK; + writel(v, host->ioaddr + SDHCI_VENDOR_SPEC); + } + break; + } + writel(val, host->ioaddr + reg); +} + static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = + (struct pltfm_imx_data *)pltfm_host->priv; switch (reg) { case SDHCI_TRANSFER_MODE: + if ((host->cmd->opcode == SD_IO_RW_EXTENDED) + && (host->cmd->data->blocks > 1) + && (host->cmd->data->flags & MMC_DATA_READ) + && (imx_data->flags & IMX_MULTIBLK_NO_INT)) { + u32 v; + v = readl(host->ioaddr + SDHCI_VENDOR_SPEC); + v |= SDHCI_VENDOR_SPEC_SDIO_QUIRK; + writel(v, host->ioaddr + SDHCI_VENDOR_SPEC); + } /* * Postpone this write, we must do it together with a * command write that is down below. */ - pltfm_host->scratchpad = val; + imx_data->mod_val = val; return; case SDHCI_COMMAND: - writel(val << 16 | pltfm_host->scratchpad, + if ((host->cmd->opcode == MMC_STOP_TRANSMISSION) + && (imx_data->flags & IMX_MULTIBLK_NO_INT)) + val |= SDHCI_CMD_ABORTCMD; + writel(val << 16 | imx_data->mod_val, host->ioaddr + SDHCI_TRANSFER_MODE); return; case SDHCI_BLOCK_SIZE: @@ -104,6 +162,10 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct clk *clk; + struct pltfm_imx_data *imx_data; + + imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL); + pltfm_host->priv = (void *)imx_data; clk = clk_get(mmc_dev(host->mmc), NULL); if (IS_ERR(clk)) { @@ -113,22 +175,30 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd clk_enable(clk); pltfm_host->clk = clk; - if (cpu_is_mx35() || cpu_is_mx51()) + if (!cpu_is_mx25()) host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; /* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */ if (cpu_is_mx25() || cpu_is_mx35()) host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK; + if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51())) { + imx_data->flags |= IMX_MULTIBLK_NO_INT; + sdhci_esdhc_ops.write_l = esdhc_writel_le; + } + return 0; } static void esdhc_pltfm_exit(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = + (struct pltfm_imx_data *)pltfm_host->priv; clk_disable(pltfm_host->clk); clk_put(pltfm_host->clk); + kfree(imx_data); } static struct sdhci_ops sdhci_esdhc_ops = { diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h index ea2e44d..2b37016 100644 --- a/drivers/mmc/host/sdhci-pltfm.h +++ b/drivers/mmc/host/sdhci-pltfm.h @@ -17,7 +17,7 @@ struct sdhci_pltfm_host { struct clk *clk; - u32 scratchpad; /* to handle quirks across io-accessor calls */ + void *priv; /* to handle quirks across io-accessor calls */ }; extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata;