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;
}
Esempio n. 4
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;
}