From patchwork Mon Sep 19 09:32:21 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shawn Guo X-Patchwork-Id: 4180 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 4342E23F58 for ; Mon, 19 Sep 2011 09:31:15 +0000 (UTC) Received: from mail-fx0-f52.google.com (mail-fx0-f52.google.com [209.85.161.52]) by fiordland.canonical.com (Postfix) with ESMTP id 2D06EA18115 for ; Mon, 19 Sep 2011 09:31:15 +0000 (UTC) Received: by fxe23 with SMTP id 23so5253200fxe.11 for ; Mon, 19 Sep 2011 02:31:15 -0700 (PDT) Received: by 10.223.61.66 with SMTP id s2mr4773069fah.27.1316424672560; Mon, 19 Sep 2011 02:31:12 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.152.18.198 with SMTP id y6cs29567lad; Mon, 19 Sep 2011 02:31:12 -0700 (PDT) Received: by 10.236.189.42 with SMTP id b30mr12342334yhn.73.1316424671405; Mon, 19 Sep 2011 02:31:11 -0700 (PDT) Received: from mail-yx0-f178.google.com (mail-yx0-f178.google.com [209.85.213.178]) by mx.google.com with ESMTPS id j12si45978and.57.2011.09.19.02.31.10 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 19 Sep 2011 02:31:11 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.213.178 is neither permitted nor denied by best guess record for domain of shawn.guo@linaro.org) client-ip=209.85.213.178; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.213.178 is neither permitted nor denied by best guess record for domain of shawn.guo@linaro.org) smtp.mail=shawn.guo@linaro.org Received: by yxj19 with SMTP id 19so23336666yxj.37 for ; Mon, 19 Sep 2011 02:31:10 -0700 (PDT) Received: by 10.68.1.100 with SMTP id 4mr4029805pbl.468.1316424669626; Mon, 19 Sep 2011 02:31:09 -0700 (PDT) Received: from localhost.localdomain ([117.82.22.90]) by mx.google.com with ESMTPS id q10sm27889311pbn.9.2011.09.19.02.30.47 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 19 Sep 2011 02:31:09 -0700 (PDT) From: Shawn Guo To: Chris Ball Cc: linux-mmc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, patches@linaro.org, Shawn Guo Subject: [PATCH] mmc: sdhci-esdhc-imx: add basic imx6q usdhc support Date: Mon, 19 Sep 2011 17:32:21 +0800 Message-Id: <1316424742-18502-1-git-send-email-shawn.guo@linaro.org> X-Mailer: git-send-email 1.7.4.1 This patch adds the basic support for imx6q usdhc, which is a derivative of esdhc controller. Signed-off-by: Shawn Guo --- drivers/mmc/host/Kconfig | 6 +++--- drivers/mmc/host/sdhci-esdhc-imx.c | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index c226d54..87d5067 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -130,13 +130,13 @@ config MMC_SDHCI_CNS3XXX If unsure, say N. config MMC_SDHCI_ESDHC_IMX - tristate "SDHCI platform support for the Freescale eSDHC i.MX controller" + tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller" depends on ARCH_MXC depends on MMC_SDHCI_PLTFM select MMC_SDHCI_IO_ACCESSORS help - This selects the Freescale eSDHC controller support on the platform - bus, found on i.MX25, i.MX35 and i.MX5x. + This selects the Freescale eSDHC/uSDHC controller support + found on i.MX25, i.MX35 i.MX5x and i.MX6x. If you have a controller with this interface, say Y or M here. diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 4557aa1..ae57769 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -32,6 +32,7 @@ /* VENDOR SPEC register */ #define SDHCI_VENDOR_SPEC 0xC0 #define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002 +#define SDHCI_MIX_CTRL 0x48 /* * There is an INT DMA ERR mis-match between eSDHC and STD SDHC SPEC: @@ -59,6 +60,7 @@ enum imx_esdhc_type { IMX35_ESDHC, IMX51_ESDHC, IMX53_ESDHC, + IMX6Q_USDHC, }; struct pltfm_imx_data { @@ -82,6 +84,9 @@ static struct platform_device_id imx_esdhc_devtype[] = { .name = "sdhci-esdhc-imx53", .driver_data = IMX53_ESDHC, }, { + .name = "sdhci-usdhc-imx6q", + .driver_data = IMX6Q_USDHC, + }, { /* sentinel */ } }; @@ -92,6 +97,7 @@ static const struct of_device_id imx_esdhc_dt_ids[] = { { .compatible = "fsl,imx35-esdhc", .data = &imx_esdhc_devtype[IMX35_ESDHC], }, { .compatible = "fsl,imx51-esdhc", .data = &imx_esdhc_devtype[IMX51_ESDHC], }, { .compatible = "fsl,imx53-esdhc", .data = &imx_esdhc_devtype[IMX53_ESDHC], }, + { .compatible = "fsl,imx6q-usdhc", .data = &imx_esdhc_devtype[IMX6Q_USDHC], }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids); @@ -116,6 +122,11 @@ static inline int is_imx53_esdhc(struct pltfm_imx_data *data) return data->devtype == IMX53_ESDHC; } +static inline int is_imx6q_usdhc(struct pltfm_imx_data *data) +{ + return data->devtype == IMX6Q_USDHC; +} + static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg) { void __iomem *base = host->ioaddr + (reg & ~0x3); @@ -220,8 +231,16 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) static u16 esdhc_readw_le(struct sdhci_host *host, int reg) { - if (unlikely(reg == SDHCI_HOST_VERSION)) - reg ^= 2; + if (unlikely(reg == SDHCI_HOST_VERSION)) { + u16 val = readw(host->ioaddr + (reg ^ 2)); + /* + * uSDHC supports SDHCI v3.0, but it's encoded as value + * 0x3 in host controller version register, which violates + * SDHCI_SPEC_300 definition. Work it around here. + */ + if ((val & SDHCI_SPEC_VER_MASK) == 3) + return --val; + } return readw(host->ioaddr + reg); } @@ -252,8 +271,17 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) if ((host->cmd->opcode == MMC_STOP_TRANSMISSION) && (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)) val |= SDHCI_CMD_ABORTCMD; - writel(val << 16 | imx_data->scratchpad, - host->ioaddr + SDHCI_TRANSFER_MODE); + + if (is_imx6q_usdhc(imx_data)) { + u32 m = readl(host->ioaddr + SDHCI_MIX_CTRL); + m = imx_data->scratchpad | (m & 0xffff0000); + writel(m, host->ioaddr + SDHCI_MIX_CTRL); + writel(val << 16, + host->ioaddr + SDHCI_TRANSFER_MODE); + } else { + writel(val << 16 | imx_data->scratchpad, + host->ioaddr + SDHCI_TRANSFER_MODE); + } return; case SDHCI_BLOCK_SIZE: val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);