|
@@ -150,6 +150,7 @@ struct mmc_omap_host {
|
|
|
int initstr;
|
|
|
int slot_id;
|
|
|
int dbclk_enabled;
|
|
|
+ int response_busy;
|
|
|
struct omap_mmc_platform_data *pdata;
|
|
|
};
|
|
|
|
|
@@ -244,10 +245,14 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
|
|
|
OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
|
|
|
OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
|
|
|
|
|
|
+ host->response_busy = 0;
|
|
|
if (cmd->flags & MMC_RSP_PRESENT) {
|
|
|
if (cmd->flags & MMC_RSP_136)
|
|
|
resptype = 1;
|
|
|
- else
|
|
|
+ else if (cmd->flags & MMC_RSP_BUSY) {
|
|
|
+ resptype = 3;
|
|
|
+ host->response_busy = 1;
|
|
|
+ } else
|
|
|
resptype = 2;
|
|
|
}
|
|
|
|
|
@@ -282,6 +287,15 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
|
|
|
static void
|
|
|
mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
|
|
|
{
|
|
|
+ if (!data) {
|
|
|
+ struct mmc_request *mrq = host->mrq;
|
|
|
+
|
|
|
+ host->mrq = NULL;
|
|
|
+ mmc_omap_fclk_lazy_disable(host);
|
|
|
+ mmc_request_done(host->mmc, mrq);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
host->data = NULL;
|
|
|
|
|
|
if (host->use_dma && host->dma_ch != -1)
|
|
@@ -323,7 +337,7 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
|
|
|
cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10);
|
|
|
}
|
|
|
}
|
|
|
- if (host->data == NULL || cmd->error) {
|
|
|
+ if ((host->data == NULL && !host->response_busy) || cmd->error) {
|
|
|
host->mrq = NULL;
|
|
|
mmc_request_done(host->mmc, cmd->mrq);
|
|
|
}
|
|
@@ -413,7 +427,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
|
|
|
struct mmc_data *data;
|
|
|
int end_cmd = 0, end_trans = 0, status;
|
|
|
|
|
|
- if (host->cmd == NULL && host->data == NULL) {
|
|
|
+ if (host->mrq == NULL) {
|
|
|
OMAP_HSMMC_WRITE(host->base, STAT,
|
|
|
OMAP_HSMMC_READ(host->base, STAT));
|
|
|
return IRQ_HANDLED;
|
|
@@ -438,18 +452,24 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
|
|
|
}
|
|
|
end_cmd = 1;
|
|
|
}
|
|
|
- if (host->data) {
|
|
|
- mmc_dma_cleanup(host, -ETIMEDOUT);
|
|
|
+ if (host->data || host->response_busy) {
|
|
|
+ if (host->data)
|
|
|
+ mmc_dma_cleanup(host, -ETIMEDOUT);
|
|
|
+ host->response_busy = 0;
|
|
|
mmc_omap_reset_controller_fsm(host, SRD);
|
|
|
}
|
|
|
}
|
|
|
if ((status & DATA_TIMEOUT) ||
|
|
|
(status & DATA_CRC)) {
|
|
|
- if (host->data) {
|
|
|
- if (status & DATA_TIMEOUT)
|
|
|
- mmc_dma_cleanup(host, -ETIMEDOUT);
|
|
|
+ if (host->data || host->response_busy) {
|
|
|
+ int err = (status & DATA_TIMEOUT) ?
|
|
|
+ -ETIMEDOUT : -EILSEQ;
|
|
|
+
|
|
|
+ if (host->data)
|
|
|
+ mmc_dma_cleanup(host, err);
|
|
|
else
|
|
|
- mmc_dma_cleanup(host, -EILSEQ);
|
|
|
+ host->mrq->cmd->error = err;
|
|
|
+ host->response_busy = 0;
|
|
|
mmc_omap_reset_controller_fsm(host, SRD);
|
|
|
end_trans = 1;
|
|
|
}
|