Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 332841
b: refs/heads/master
c: f6ad0a4
h: refs/heads/master
i:
  332839: 40bda3f
v: v3
  • Loading branch information
Javier Martin authored and Chris Ball committed Oct 3, 2012
1 parent 96ae164 commit 4e78eac
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c4c8eeb4df00aabb641553d6fbcd46f458e56cd9
refs/heads/master: f6ad0a481342223b2e7ae9f55b154e14f1391ada
76 changes: 70 additions & 6 deletions trunk/drivers/mmc/host/mxcmmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <mach/hardware.h>

#define DRIVER_NAME "mxc-mmc"
#define MXCMCI_TIMEOUT_MS 10000

#define MMC_REG_STR_STP_CLK 0x00
#define MMC_REG_STATUS 0x04
Expand Down Expand Up @@ -150,6 +151,8 @@ struct mxcmci_host {
int dmareq;
struct dma_slave_config dma_slave_config;
struct imx_dma_data dma_data;

struct timer_list watchdog;
};

static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
Expand Down Expand Up @@ -271,9 +274,32 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
dmaengine_submit(host->desc);
dma_async_issue_pending(host->dma);

mod_timer(&host->watchdog, jiffies + msecs_to_jiffies(MXCMCI_TIMEOUT_MS));

return 0;
}

static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat);
static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat);

static void mxcmci_dma_callback(void *data)
{
struct mxcmci_host *host = data;
u32 stat;

del_timer(&host->watchdog);

stat = readl(host->base + MMC_REG_STATUS);
writel(stat & ~STATUS_DATA_TRANS_DONE, host->base + MMC_REG_STATUS);

dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat);

if (stat & STATUS_READ_OP_DONE)
writel(STATUS_READ_OP_DONE, host->base + MMC_REG_STATUS);

mxcmci_data_done(host, stat);
}

static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
unsigned int cmdat)
{
Expand Down Expand Up @@ -305,8 +331,14 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,

int_cntr = INT_END_CMD_RES_EN;

if (mxcmci_use_dma(host))
int_cntr |= INT_READ_OP_EN | INT_WRITE_OP_DONE_EN;
if (mxcmci_use_dma(host)) {
if (host->dma_dir == DMA_FROM_DEVICE) {
host->desc->callback = mxcmci_dma_callback;
host->desc->callback_param = host;
} else {
int_cntr |= INT_WRITE_OP_DONE_EN;
}
}

spin_lock_irqsave(&host->lock, flags);
if (host->use_sdio)
Expand Down Expand Up @@ -345,11 +377,9 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
struct mmc_data *data = host->data;
int data_error;

if (mxcmci_use_dma(host)) {
dmaengine_terminate_all(host->dma);
if (mxcmci_use_dma(host))
dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
host->dma_dir);
}

if (stat & STATUS_ERR_MASK) {
dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",
Expand Down Expand Up @@ -624,8 +654,10 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
mxcmci_cmd_done(host, stat);

if (mxcmci_use_dma(host) &&
(stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE)))
(stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) {
del_timer(&host->watchdog);
mxcmci_data_done(host, stat);
}

if (host->default_irq_mask &&
(stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL)))
Expand Down Expand Up @@ -836,6 +868,34 @@ static bool filter(struct dma_chan *chan, void *param)
return true;
}

static void mxcmci_watchdog(unsigned long data)
{
struct mmc_host *mmc = (struct mmc_host *)data;
struct mxcmci_host *host = mmc_priv(mmc);
struct mmc_request *req = host->req;
unsigned int stat = readl(host->base + MMC_REG_STATUS);

if (host->dma_dir == DMA_FROM_DEVICE) {
dmaengine_terminate_all(host->dma);
dev_err(mmc_dev(host->mmc),
"%s: read time out (status = 0x%08x)\n",
__func__, stat);
} else {
dev_err(mmc_dev(host->mmc),
"%s: write time out (status = 0x%08x)\n",
__func__, stat);
mxcmci_softreset(host);
}

/* Mark transfer as erroneus and inform the upper layers */

host->data->error = -ETIMEDOUT;
host->req = NULL;
host->cmd = NULL;
host->data = NULL;
mmc_request_done(host->mmc, req);
}

static const struct mmc_host_ops mxcmci_ops = {
.request = mxcmci_request,
.set_ios = mxcmci_set_ios,
Expand Down Expand Up @@ -968,6 +1028,10 @@ static int mxcmci_probe(struct platform_device *pdev)

mmc_add_host(mmc);

init_timer(&host->watchdog);
host->watchdog.function = &mxcmci_watchdog;
host->watchdog.data = (unsigned long)mmc;

return 0;

out_free_irq:
Expand Down

0 comments on commit 4e78eac

Please sign in to comment.