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: 598721 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p219wf4f031047 for ; Tue, 1 Mar 2011 09:59:03 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756041Ab1CAJ7C (ORCPT ); Tue, 1 Mar 2011 04:59:02 -0500 Received: from db3ehsobe003.messaging.microsoft.com ([213.199.154.141]:58795 "EHLO DB3EHSOBE003.bigfish.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755948Ab1CAJ7B (ORCPT ); Tue, 1 Mar 2011 04:59:01 -0500 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 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Tue, 01 Mar 2011 09:59:03 +0000 (UTC) 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;