static void goldfish_mmc_end_of_data(struct goldfish_mmc_host *host, struct mmc_data *data) { if (!host->dma_in_use) { goldfish_mmc_xfer_done(host, data); return; } if (host->dma_done) goldfish_mmc_xfer_done(host, data); }
static irqreturn_t goldfish_mmc_irq(int irq, void *dev_id) { struct goldfish_mmc_host * host = (struct goldfish_mmc_host *)dev_id; u16 status; int end_command = 0; int end_transfer = 0; int transfer_error = 0; int state_changed = 0; int cmd_timeout = 0; while ((status = GOLDFISH_MMC_READ(host, MMC_INT_STATUS)) != 0) { GOLDFISH_MMC_WRITE(host, MMC_INT_STATUS, status); if (status & MMC_STAT_END_OF_CMD) { end_command = 1; } if (status & MMC_STAT_END_OF_DATA) { end_transfer = 1; } if (status & MMC_STAT_STATE_CHANGE) { state_changed = 1; } if (status & MMC_STAT_CMD_TIMEOUT) { end_command = 0; cmd_timeout = 1; } } if (cmd_timeout) { struct mmc_request *mrq = host->mrq; mrq->cmd->error = -ETIMEDOUT; host->mrq = NULL; mmc_request_done(host->mmc, mrq); } if (end_command) { goldfish_mmc_cmd_done(host, host->cmd); } if (transfer_error) goldfish_mmc_xfer_done(host, host->data); else if (end_transfer) { host->dma_done = 1; goldfish_mmc_end_of_data(host, host->data); } else if (host->data != NULL && host->mrq->cmd->opcode == 13) { /* * WORKAROUND -- after porting this driver from 2.6 to 3.4, * this case pops up during device initialization. * This happens as the host stack is sending ACMD13 which * involves data read while goldfish emulator implementation * only supports CMD13 which does not have data phase. * The workaround works by passing garbage result to the stack. * TODO -- To implement proper response */ host->dma_done = 1; goldfish_mmc_end_of_data(host, host->data); } if (state_changed) { u32 state = GOLDFISH_MMC_READ(host, MMC_STATE); pr_info("%s: Card detect now %d\n", __func__, (state & MMC_STATE_INSERTED)); mmc_detect_change(host->mmc, 0); } if (!end_command && !end_transfer && !transfer_error && !state_changed && !cmd_timeout) { status = GOLDFISH_MMC_READ(host, MMC_INT_STATUS); dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status); if (status != 0) { GOLDFISH_MMC_WRITE(host, MMC_INT_STATUS, status); GOLDFISH_MMC_WRITE(host, MMC_INT_ENABLE, 0); } } return IRQ_HANDLED; }
static irqreturn_t goldfish_mmc_irq(int irq, void *dev_id) { struct goldfish_mmc_host * host = (struct goldfish_mmc_host *)dev_id; u16 status; int end_command = 0; int end_transfer = 0; int transfer_error = 0; int state_changed = 0; int cmd_timeout = 0; while ((status = GOLDFISH_MMC_READ(host, MMC_INT_STATUS)) != 0) { GOLDFISH_MMC_WRITE(host, MMC_INT_STATUS, status); if (status & MMC_STAT_END_OF_CMD) { end_command = 1; } if (status & MMC_STAT_END_OF_DATA) { end_transfer = 1; } if (status & MMC_STAT_STATE_CHANGE) { state_changed = 1; } if (status & MMC_STAT_CMD_TIMEOUT) { end_command = 0; cmd_timeout = 1; } } if (cmd_timeout) { struct mmc_request *mrq = host->mrq; mrq->cmd->error = -ETIMEDOUT; host->mrq = NULL; mmc_request_done(host->mmc, mrq); } if (end_command) { goldfish_mmc_cmd_done(host, host->cmd); } if (transfer_error) goldfish_mmc_xfer_done(host, host->data); else if (end_transfer) { host->dma_done = 1; goldfish_mmc_end_of_data(host, host->data); } if (state_changed) { u32 state = GOLDFISH_MMC_READ(host, MMC_STATE); pr_info("%s: Card detect now %d\n", __func__, (state & MMC_STATE_INSERTED)); mmc_detect_change(host->mmc, 0); } if (!end_command && !end_transfer && !transfer_error && !state_changed && !cmd_timeout) { status = GOLDFISH_MMC_READ(host, MMC_INT_STATUS); dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status); if (status != 0) { GOLDFISH_MMC_WRITE(host, MMC_INT_STATUS, status); GOLDFISH_MMC_WRITE(host, MMC_INT_ENABLE, 0); } } return IRQ_HANDLED; }