提交 58ac8177 编写于 作者: R Richard Zhu 提交者: Chris Ball

mmc: sdhci-esdhc: enable esdhc on imx53

Fix the NO INT in the Multi-BLK IO in SD/MMC, and Multi-BLK read in
SDIO on imx53.

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 on imx53.

As a result, the TC flag is not asserted and SW receives timeout
exception. Set bit1 of Vendor Spec register to fix it.
Signed-off-by: NRichard Zhu <Hong-Xing.Zhu@freescale.com>
Signed-off-by: NRichard Zhao <richard.zhao@freescale.com>
Reviewed-by: NWolfram Sang <w.sang@pengutronix.de>
Signed-off-by: NChris Ball <cjb@laptop.org>
上级 e149860d
...@@ -19,13 +19,31 @@ ...@@ -19,13 +19,31 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/sdhci-pltfm.h> #include <linux/mmc/sdhci-pltfm.h>
#include <linux/mmc/mmc.h>
#include <linux/mmc/sdio.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/esdhc.h> #include <mach/esdhc.h>
#include "sdhci.h" #include "sdhci.h"
#include "sdhci-pltfm.h" #include "sdhci-pltfm.h"
#include "sdhci-esdhc.h" #include "sdhci-esdhc.h"
/* VENDOR SPEC register */
#define SDHCI_VENDOR_SPEC 0xC0
#define SDHCI_VENDOR_SPEC_SDIO_QUIRK 0x00000002
#define ESDHC_FLAG_GPIO_FOR_CD_WP (1 << 0) #define ESDHC_FLAG_GPIO_FOR_CD_WP (1 << 0)
/*
* 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 ESDHC_FLAG_MULTIBLK_NO_INT (1 << 1)
struct pltfm_imx_data { struct pltfm_imx_data {
int flags; int flags;
...@@ -78,6 +96,15 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) ...@@ -78,6 +96,15 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
*/ */
val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT); val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
if (unlikely((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
&& (reg == SDHCI_INT_STATUS)
&& (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);
}
writel(val, host->ioaddr + reg); writel(val, host->ioaddr + reg);
} }
...@@ -100,9 +127,21 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) ...@@ -100,9 +127,21 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
* Postpone this write, we must do it together with a * Postpone this write, we must do it together with a
* command write that is down below. * command write that is down below.
*/ */
if ((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
&& (host->cmd->opcode == SD_IO_RW_EXTENDED)
&& (host->cmd->data->blocks > 1)
&& (host->cmd->data->flags & MMC_DATA_READ)) {
u32 v;
v = readl(host->ioaddr + SDHCI_VENDOR_SPEC);
v |= SDHCI_VENDOR_SPEC_SDIO_QUIRK;
writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
}
imx_data->scratchpad = val; imx_data->scratchpad = val;
return; return;
case SDHCI_COMMAND: case SDHCI_COMMAND:
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, writel(val << 16 | imx_data->scratchpad,
host->ioaddr + SDHCI_TRANSFER_MODE); host->ioaddr + SDHCI_TRANSFER_MODE);
return; return;
...@@ -215,6 +254,9 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd ...@@ -215,6 +254,9 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro; sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
} }
if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
if (boarddata) { if (boarddata) {
err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP"); err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
if (err) { if (err) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册