diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 38 |
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, | |||
282 | static void | 287 | static void |
283 | mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) | 288 | mmc_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 | } |