static void goldfish_mmc_cmd_done(struct goldfish_mmc_host *host, struct mmc_command *cmd) { host->cmd = NULL; if (cmd->flags & MMC_RSP_PRESENT) { if (cmd->flags & MMC_RSP_136) { /* response type 2 */ cmd->resp[3] = GOLDFISH_MMC_READ(host, MMC_RESP_0); cmd->resp[2] = GOLDFISH_MMC_READ(host, MMC_RESP_1); cmd->resp[1] = GOLDFISH_MMC_READ(host, MMC_RESP_2); cmd->resp[0] = GOLDFISH_MMC_READ(host, MMC_RESP_3); } else { /* response types 1, 1b, 3, 4, 5, 6 */ cmd->resp[0] = GOLDFISH_MMC_READ(host, MMC_RESP_0); } } if (host->data == NULL || cmd->error) { host->mrq = NULL; mmc_request_done(host->mmc, cmd->mrq); } }
static int goldfish_mmc_get_ro(struct mmc_host *mmc) { uint32_t state; struct goldfish_mmc_host *host = mmc_priv(mmc); state = GOLDFISH_MMC_READ(host, MMC_STATE); return ((state & MMC_STATE_READ_ONLY) != 0); }
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; }