static void finalize_request(struct s3cmci_host *host) { struct mmc_request *mrq = host->mrq; struct mmc_command *cmd = host->cmd_is_stop?mrq->stop:mrq->cmd; int debug_as_failure = 0; if (host->complete_what != COMPLETION_FINALIZE) return; if (!mrq) return; // if (cmd->data && (cmd->error == MMC_ERR_NONE) && // (cmd->data->error == MMC_ERR_NONE)) { if (cmd->data && (cmd->error == 0) && (cmd->data->error == 0)) { if (host->dodma && (!host->dma_complete)) { dbg(host, dbg_dma, "DMA Missing!\n"); return; } } // Read response cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0); cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1); cmd->resp[2] = readl(host->base + S3C2410_SDIRSP2); cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3); // reset clock speed, as it could still be set low for writel(host->prescaler, host->base + S3C2410_SDIPRE); if (cmd->error) debug_as_failure = 1; if (cmd->data && cmd->data->error) debug_as_failure = 1; //if(cmd->flags & MMC_RSP_MAYFAIL) debug_as_failure = 0; #ifdef CONFIG_MMC_DEBUG dbg_dumpcmd(host, cmd, debug_as_failure); #endif //Cleanup controller writel(0, host->base + S3C2410_SDICMDARG); writel(0, host->base + S3C2410_SDIDCON); writel(0, host->base + S3C2410_SDICMDCON); writel(0, host->base + host->sdiimsk); if (cmd->data && cmd->error) cmd->data->error = cmd->error; if (cmd->data && cmd->data->stop && (!host->cmd_is_stop)) { host->cmd_is_stop = 1; s3cmci_send_request(host->mmc); return; } // If we have no data transfer we are finished here if (!mrq->data) goto request_done; // Calulate the amout of bytes transfer, but only if there was // no error // if (mrq->data->error == MMC_ERR_NONE) { if (mrq->data->error == 0) { mrq->data->bytes_xfered = (mrq->data->blocks * mrq->data->blksz); } else { mrq->data->bytes_xfered = 0; } // If we had an error while transfering data we flush the // DMA channel and the fifo to clear out any garbage // if (mrq->data->error != MMC_ERR_NONE) { if (mrq->data->error != 0) { if (host->dodma) s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); if (host->is2440) { //Clear failure register and reset fifo writel(S3C2440_SDIFSTA_FIFORESET | S3C2440_SDIFSTA_FIFOFAIL, host->base + S3C2410_SDIFSTA); } else { u32 mci_con; //reset fifo mci_con = readl(host->base + S3C2410_SDICON); mci_con|= S3C2410_SDICON_FIFORESET; writel(mci_con, host->base + S3C2410_SDICON); } } request_done: host->complete_what = COMPLETION_NONE; host->mrq = NULL; mmc_request_done(host->mmc, mrq); }
static void finalize_request(struct s3cmci_host *host) { struct mmc_request *mrq = host->mrq; struct mmc_command *cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd; int debug_as_failure = 0; if (host->complete_what != COMPLETION_FINALIZE) return; if (!mrq) return; if (cmd->data && (cmd->error == 0) && (cmd->data->error == 0)) { if (host->dodma && (!host->dma_complete)) { dbg(host, dbg_dma, "DMA Missing!\n"); return; } } /* Read response from controller. */ cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0); cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1); cmd->resp[2] = readl(host->base + S3C2410_SDIRSP2); cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3); writel(host->prescaler, host->base + S3C2410_SDIPRE); if (cmd->error) debug_as_failure = 1; if (cmd->data && cmd->data->error) debug_as_failure = 1; dbg_dumpcmd(host, cmd, debug_as_failure); /* Cleanup controller */ writel(0, host->base + S3C2410_SDICMDARG); writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON); writel(0, host->base + S3C2410_SDICMDCON); writel(0, host->base + host->sdiimsk); if (cmd->data && cmd->error) cmd->data->error = cmd->error; if (cmd->data && cmd->data->stop && (!host->cmd_is_stop)) { host->cmd_is_stop = 1; s3cmci_send_request(host->mmc); return; } /* If we have no data transfer we are finished here */ if (!mrq->data) goto request_done; /* Calulate the amout of bytes transfer if there was no error */ if (mrq->data->error == 0) { mrq->data->bytes_xfered = (mrq->data->blocks * mrq->data->blksz); } else { mrq->data->bytes_xfered = 0; } /* If we had an error while transfering data we flush the * DMA channel and the fifo to clear out any garbage. */ if (mrq->data->error != 0) { if (host->dodma) s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); if (host->is2440) { /* Clear failure register and reset fifo. */ writel(S3C2440_SDIFSTA_FIFORESET | S3C2440_SDIFSTA_FIFOFAIL, host->base + S3C2410_SDIFSTA); } else { u32 mci_con; /* reset fifo */ mci_con = readl(host->base + S3C2410_SDICON); mci_con |= S3C2410_SDICON_FIFORESET; writel(mci_con, host->base + S3C2410_SDICON); } } request_done: host->complete_what = COMPLETION_NONE; host->mrq = NULL; mmc_request_done(host->mmc, mrq); }