예제 #1
0
/*
 * MMC controller IRQ handler
 */
static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
{
	struct mmc_omap_host *host = dev_id;
	int end_cmd = 0, end_trans = 0, status;

	if (host->cmd == NULL && host->data == NULL) {
		OMAP_HSMMC_WRITE(host->base, STAT,
			OMAP_HSMMC_READ(host->base, STAT));
		return IRQ_HANDLED;
	}

	status = OMAP_HSMMC_READ(host->base, STAT);
	dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);

	if (status & ERR) {
		if ((status & CMD_TIMEOUT) ||
			(status & CMD_CRC)) {
			if (host->cmd) {
				if (status & CMD_TIMEOUT)
					host->cmd->error = -ETIMEDOUT;
				else
					host->cmd->error = -EILSEQ;
				end_cmd = 1;
			}
			if (host->data)
				mmc_dma_cleanup(host);
		}
		if ((status & DATA_TIMEOUT) ||
			(status & DATA_CRC)) {
			if (host->data) {
				if (status & DATA_TIMEOUT)
					mmc_dma_cleanup(host);
				else
					host->data->error = -EILSEQ;
				end_trans = 1;
			}
		}
		if (status & CARD_ERR) {
			dev_dbg(mmc_dev(host->mmc),
				"Ignoring card err CMD%d\n", host->cmd->opcode);
			if (host->cmd)
				end_cmd = 1;
			if (host->data)
				end_trans = 1;
		}
	}

	OMAP_HSMMC_WRITE(host->base, STAT, status);

	if (end_cmd || (status & CC))
		mmc_omap_cmd_done(host, host->cmd);
	if (end_trans || (status & TC))
		mmc_omap_xfer_done(host, host->data);

	return IRQ_HANDLED;
}
예제 #2
0
/*
 * MMC controller IRQ handler
 */
static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
{
	struct mmc_omap_host *host = dev_id;
	struct mmc_data *data;
	int end_cmd = 0, end_trans = 0, status;

	omap_hsmmc_enable_clks(host);

	if (host->cmd == NULL && host->data == NULL) {
		OMAP_HSMMC_WRITE(host->base, STAT,
			OMAP_HSMMC_READ(host->base, STAT));
		return IRQ_HANDLED;
	}

	data = host->data;
	status = OMAP_HSMMC_READ(host->base, STAT);
	dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);

	if (status & ERR) {
#ifdef CONFIG_MMC_DEBUG
		mmc_omap_report_irq(host, status);
#endif
		if ((status & CMD_TIMEOUT) ||
			(status & CMD_CRC) ||
			(status & CMD_CEB) ||
			(status & CMD_CIE)) {
			if (host->cmd) {
				if (status & CMD_TIMEOUT) {
					mmc_omap_reset_controller_fsm(host, SRC);
					host->cmd->error = -ETIMEDOUT;
				} else {
					host->cmd->error = -EILSEQ;
				}
				end_cmd = 1;
			}
			if (host->data) {
				mmc_dma_cleanup(host, -ETIMEDOUT);
				mmc_omap_reset_controller_fsm(host, SRD);
			}
		}
		if ((status & DATA_TIMEOUT) ||
			(status & DATA_CRC) ||
			(status & DATA_DEB)) {
			if (host->data) {
				if (status & DATA_TIMEOUT)
					mmc_dma_cleanup(host, -ETIMEDOUT);
				else
					mmc_dma_cleanup(host, -EILSEQ);
				mmc_omap_reset_controller_fsm(host, SRD);
				end_trans = 1;
			}
		}
		if (status & CARD_ERR) {
			dev_dbg(mmc_dev(host->mmc),
				"Ignoring card err CMD%d\n", host->cmd->opcode);
			if (host->cmd)
				end_cmd = 1;
			if (host->data)
				end_trans = 1;
		}
	}

	OMAP_HSMMC_WRITE(host->base, STAT, status);

	if (end_cmd || (status & CC))
		mmc_omap_cmd_done(host, host->cmd);
	if (end_trans || (status & TC))
		mmc_omap_xfer_done(host, data);

	/* Perform one dummy read to ensure the previous write actually went through */
	status = OMAP_HSMMC_READ(host->base, STAT);

	return IRQ_HANDLED;
}
예제 #3
0
/*
 * MMC controller IRQ handler
 */
static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
{
	struct mmc_omap_host *host = dev_id;
	struct mmc_data *data;
	int end_cmd = 0, end_trans = 0, status;

	/*
	 * TODO:
	 * Is this necessary? The fact that we have taken
	 * an interrupt is a premise that CLKs are ON.
	 */
	mmc_clk_try_enable(host);

	if (host->cmd == NULL && host->data == NULL) {
		OMAP_HSMMC_WRITE(host->base, STAT,
			OMAP_HSMMC_READ(host->base, STAT));
		return IRQ_HANDLED;
	}

	data = host->data;
	status = OMAP_HSMMC_READ(host->base, STAT);
	dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);

	if (status & ERR) {
#ifdef CONFIG_MMC_DEBUG
		mmc_omap_report_irq(host, status);
#endif
		if ((status & CMD_TIMEOUT) ||
			(status & CMD_CRC)) {
			if (host->cmd) {
				if (status & CMD_TIMEOUT) {
					OMAP_HSMMC_WRITE(host->base, SYSCTL,
						OMAP_HSMMC_READ(host->base,
								SYSCTL) | SRC);
					while (OMAP_HSMMC_READ(host->base,
								SYSCTL) & SRC) ;
					host->cmd->error = -ETIMEDOUT;
				} else {
					host->cmd->error = -EILSEQ;
				}
				end_cmd = 1;
			}
			if (host->data)
				mmc_dma_cleanup(host);
		}
		if ((status & DATA_TIMEOUT) ||
			(status & DATA_CRC)) {
			if (host->data) {
				if (status & DATA_TIMEOUT) {
					dev_info(mmc_dev(host->mmc),
						"MMC DATA TIMEOUT\n");
					mmc_dma_cleanup(host);
				} else {
					dev_info(mmc_dev(host->mmc),
						"MMC DATA CRC\n");
					host->data->error = -EILSEQ;
				}
				end_trans = 1;
			}
		}
		if (status & CARD_ERR) {
			dev_dbg(mmc_dev(host->mmc),
				"Ignoring card err CMD%d\n", host->cmd->opcode);
			if (host->cmd)
				end_cmd = 1;
			if (host->data)
				end_trans = 1;
		}
	}

	OMAP_HSMMC_WRITE(host->base, STAT, status);

	if (end_cmd || (status & CC))
		mmc_omap_cmd_done(host, host->cmd);
	if (end_trans || (status & TC))
		mmc_omap_xfer_done(host, data);

	return IRQ_HANDLED;
}