예제 #1
0
/**
 *	ti_mmchs_intr_error - handles error interrupts
 *	@sc: pointer to the driver context
 *	@cmd: the command that was sent previously
 *	@stat_reg: the value that was in the status register
 *
 *
 *	LOCKING:
 *	Called from interrupt context
 *
 *	RETURNS:
 *	Return value indicates if the transaction is complete, not done = 0, done != 0
 */
static int
ti_mmchs_intr_error(struct ti_mmchs_softc *sc, struct mmc_command *cmd,
					 uint32_t stat_reg)
{
	ti_mmchs_dbg(sc, "error in xfer - stat 0x%08x\n", stat_reg);

	/* Ignore CRC errors on CMD2 and ACMD47, per relevant standards */
	if ((stat_reg & MMCHS_STAT_CCRC) && (cmd->opcode == MMC_SEND_OP_COND ||
	    cmd->opcode == ACMD_SD_SEND_OP_COND))
		cmd->error = MMC_ERR_NONE;
	else if (stat_reg & (MMCHS_STAT_CTO | MMCHS_STAT_DTO))
		cmd->error = MMC_ERR_TIMEOUT;
	else if (stat_reg & (MMCHS_STAT_CCRC | MMCHS_STAT_DCRC))
		cmd->error = MMC_ERR_BADCRC;
	else
		cmd->error = MMC_ERR_FAILED;

	/* If a dma transaction we should also stop the dma transfer */
	if (ti_mmchs_read_4(sc, MMCHS_CMD) & MMCHS_CMD_DE) {

		/* Abort the DMA transfer (DDIR bit tells direction) */
		if (ti_mmchs_read_4(sc, MMCHS_CMD) & MMCHS_CMD_DDIR)
			ti_sdma_stop_xfer(sc->sc_dmach_rd);
		else
			ti_sdma_stop_xfer(sc->sc_dmach_wr);

		/* If an error occure abort the DMA operation and free the dma map */
		if ((sc->sc_dmamapped > 0) && (cmd->error != MMC_ERR_NONE)) {
			bus_dmamap_unload(sc->sc_dmatag, sc->sc_dmamap);
			sc->sc_dmamapped--;
		}
	}

	/* Command error occured? ... if so issue a soft reset for the cmd fsm */
	if (stat_reg & (MMCHS_STAT_CCRC | MMCHS_STAT_CTO)) {
		ti_mmchs_reset_controller(sc, MMCHS_SYSCTL_SRC);
	}

	/* Data error occured? ... if so issue a soft reset for the data line */
	if (stat_reg & (MMCHS_STAT_DEB | MMCHS_STAT_DCRC | MMCHS_STAT_DTO)) {
		ti_mmchs_reset_controller(sc, MMCHS_SYSCTL_SRD);
	}

	/* On any error the command is cancelled ... so we are done */
	return 1;
}
예제 #2
0
파일: ti_mmchs.c 프로젝트: Alkzndr/freebsd
/**
 *	ti_mmchs_intr_error - handles error interrupts
 *	@sc: pointer to the driver context
 *	@cmd: the command that was sent previously
 *	@stat_reg: the value that was in the status register
 *
 *
 *	LOCKING:
 *	Called from interrupt context
 *
 *	RETURNS:
 *	Return value indicates if the transaction is complete, not done = 0, done != 0
 */
static int
ti_mmchs_intr_error(struct ti_mmchs_softc *sc, struct mmc_command *cmd,
					 uint32_t stat_reg)
{
	ti_mmchs_dbg(sc, "error in xfer - stat 0x%08x\n", stat_reg);

	/* Ignore CRC errors on CMD2 and ACMD47, per relevant standards */
	if ((stat_reg & MMCHS_STAT_CCRC) && (cmd->opcode == MMC_SEND_OP_COND ||
	    cmd->opcode == ACMD_SD_SEND_OP_COND))
		cmd->error = MMC_ERR_NONE;
	else if (stat_reg & (MMCHS_STAT_CTO | MMCHS_STAT_DTO))
		cmd->error = MMC_ERR_TIMEOUT;
	else if (stat_reg & (MMCHS_STAT_CCRC | MMCHS_STAT_DCRC))
		cmd->error = MMC_ERR_BADCRC;
	else
		cmd->error = MMC_ERR_FAILED;

	/* If a dma transaction we should also stop the dma transfer */
	if (ti_mmchs_read_4(sc, MMCHS_CMD) & MMCHS_CMD_DE) {

		/* Abort the DMA transfer (DDIR bit tells direction) */
		if (ti_mmchs_read_4(sc, MMCHS_CMD) & MMCHS_CMD_DDIR)
#ifdef SOC_TI_AM335X
			printf("%s: DMA unimplemented\n", __func__);
#else
			ti_sdma_stop_xfer(sc->sc_dmach_rd);
#endif
		else
#ifdef SOC_TI_AM335X
			printf("%s: DMA unimplemented\n", __func__);
#else
			ti_sdma_stop_xfer(sc->sc_dmach_wr);
#endif

		/* If an error occure abort the DMA operation and free the dma map */
		if ((sc->sc_dmamapped > 0) && (cmd->error != MMC_ERR_NONE)) {
			bus_dmamap_unload(sc->sc_dmatag, sc->sc_dmamap);
			sc->sc_dmamapped--;
		}
	}