aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/omap_hsmmc.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 5ff2ca22beea..1f84bd4a3b27 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -150,6 +150,7 @@ struct mmc_omap_host {
150 int initstr; 150 int initstr;
151 int slot_id; 151 int slot_id;
152 int dbclk_enabled; 152 int dbclk_enabled;
153 int response_busy;
153 struct omap_mmc_platform_data *pdata; 154 struct omap_mmc_platform_data *pdata;
154}; 155};
155 156
@@ -244,10 +245,14 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
244 OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); 245 OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
245 OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); 246 OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
246 247
248 host->response_busy = 0;
247 if (cmd->flags & MMC_RSP_PRESENT) { 249 if (cmd->flags & MMC_RSP_PRESENT) {
248 if (cmd->flags & MMC_RSP_136) 250 if (cmd->flags & MMC_RSP_136)
249 resptype = 1; 251 resptype = 1;
250 else 252 else if (cmd->flags & MMC_RSP_BUSY) {
253 resptype = 3;
254 host->response_busy = 1;
255 } else
251 resptype = 2; 256 resptype = 2;
252 } 257 }
253 258
@@ -282,6 +287,15 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
282static void 287static void
283mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) 288mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
284{ 289{
290 if (!data) {
291 struct mmc_request *mrq = host->mrq;
292
293 host->mrq = NULL;
294 mmc_omap_fclk_lazy_disable(host);
295 mmc_request_done(host->mmc, mrq);
296 return;
297 }
298
285 host->data = NULL; 299 host->data = NULL;
286 300
287 if (host->use_dma && host->dma_ch != -1) 301 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)
323 cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10); 337 cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10);
324 } 338 }
325 } 339 }
326 if (host->data == NULL || cmd->error) { 340 if ((host->data == NULL && !host->response_busy) || cmd->error) {
327 host->mrq = NULL; 341 host->mrq = NULL;
328 mmc_request_done(host->mmc, cmd->mrq); 342 mmc_request_done(host->mmc, cmd->mrq);
329 } 343 }
@@ -413,7 +427,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
413 struct mmc_data *data; 427 struct mmc_data *data;
414 int end_cmd = 0, end_trans = 0, status; 428 int end_cmd = 0, end_trans = 0, status;
415 429
416 if (host->cmd == NULL && host->data == NULL) { 430 if (host->mrq == NULL) {
417 OMAP_HSMMC_WRITE(host->base, STAT, 431 OMAP_HSMMC_WRITE(host->base, STAT,
418 OMAP_HSMMC_READ(host->base, STAT)); 432 OMAP_HSMMC_READ(host->base, STAT));
419 return IRQ_HANDLED; 433 return IRQ_HANDLED;
@@ -438,18 +452,24 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
438 } 452 }
439 end_cmd = 1; 453 end_cmd = 1;
440 } 454 }
441 if (host->data) { 455 if (host->data || host->response_busy) {
442 mmc_dma_cleanup(host, -ETIMEDOUT); 456 if (host->data)
457 mmc_dma_cleanup(host, -ETIMEDOUT);
458 host->response_busy = 0;
443 mmc_omap_reset_controller_fsm(host, SRD); 459 mmc_omap_reset_controller_fsm(host, SRD);
444 } 460 }
445 } 461 }
446 if ((status & DATA_TIMEOUT) || 462 if ((status & DATA_TIMEOUT) ||
447 (status & DATA_CRC)) { 463 (status & DATA_CRC)) {
448 if (host->data) { 464 if (host->data || host->response_busy) {
449 if (status & DATA_TIMEOUT) 465 int err = (status & DATA_TIMEOUT) ?
450 mmc_dma_cleanup(host, -ETIMEDOUT); 466 -ETIMEDOUT : -EILSEQ;
467
468 if (host->data)
469 mmc_dma_cleanup(host, err);
451 else 470 else
452 mmc_dma_cleanup(host, -EILSEQ); 471 host->mrq->cmd->error = err;
472 host->response_busy = 0;
453 mmc_omap_reset_controller_fsm(host, SRD); 473 mmc_omap_reset_controller_fsm(host, SRD);
454 end_trans = 1; 474 end_trans = 1;
455 } 475 }