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;
}
Beispiel #3
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);
	}
	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;
}