/** * 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; }
/** * 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--; } }