예제 #1
0
/*
 * Handle a command that has been completed
 */
static void at91mci_completed_command(struct at91mci_host* host)
{
	struct mmc_command* cmd = host->cmd;
	unsigned int status;

	controller->MCI_IDR = 0xffffffff;

	cmd->resp[0] = controller->MCI_RSPR[0];
	cmd->resp[1] = controller->MCI_RSPR[1];
	cmd->resp[2] = controller->MCI_RSPR[2];
	cmd->resp[3] = controller->MCI_RSPR[3];

	if (host->buffer) {
		dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
		host->buffer = NULL;
	}

	status = controller->MCI_SR;

	DBG("Status = %08X [%08X %08X %08X %08X]\n",
		 status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);

	if (status & (AT91C_MCI_RINDE | AT91C_MCI_RDIRE | AT91C_MCI_RCRCE |
			AT91C_MCI_RENDE | AT91C_MCI_RTOE | AT91C_MCI_DCRCE |
			AT91C_MCI_DTOE | AT91C_MCI_OVRE | AT91C_MCI_UNRE)) {
		if ((cmd->opcode == MMC_SEND_OP_COND) || (cmd->opcode == SD_APP_OP_COND)) {
			cmd->error = MMC_ERR_NONE;
		}
		else {
			if (status & (AT91C_MCI_RTOE | AT91C_MCI_DTOE)) {
				cmd->error = MMC_ERR_TIMEOUT;
			}
			else if (status & (AT91C_MCI_RCRCE | AT91C_MCI_DCRCE)) {
				cmd->error = MMC_ERR_BADCRC;
			}
			else if (status & (AT91C_MCI_OVRE | AT91C_MCI_UNRE)) {
				cmd->error = MMC_ERR_FIFO;
			}
			else {
				cmd->error = MMC_ERR_FAILED;
			}

			DBG("Error detected and set to %d (cmd = %d, retries = %d)\n",
				 cmd->error, cmd->opcode, cmd->retries);
		}
	}
	else {
		cmd->error = MMC_ERR_NONE;
	}
	
	if ((cmd->opcode == SD_APP_SET_BUS_WIDTH) && (cmd->error == MMC_ERR_NONE)) {
		if (cmd->arg == 2)
			controller->MCI_SDCR |= 0x80;
		else
			controller->MCI_SDCR &= ~0x80;
	}

	at91mci_process_next(host);
}
예제 #2
0
파일: at91_mci.c 프로젝트: ivucica/linux
/*
 * Handle an MMC request
 */
static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
	struct at91mci_host *host = mmc_priv(mmc);
	host->request = mrq;
	host->flags = 0;

	at91mci_process_next(host);
}
예제 #3
0
파일: at91_mci.c 프로젝트: ivucica/linux
/*
 * Handle a command that has been completed
 */
static void at91mci_completed_command(struct at91mci_host *host)
{
	struct mmc_command *cmd = host->cmd;
	unsigned int status;

	at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);

	cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
	cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
	cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
	cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));

	if (host->buffer) {
		dma_free_coherent(NULL, host->total_length, host->buffer, host->physical_address);
		host->buffer = NULL;
	}

	status = at91_mci_read(host, AT91_MCI_SR);

	pr_debug("Status = %08X [%08X %08X %08X %08X]\n",
		 status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);

	if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE |
			AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE |
			AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) {
		if ((status & AT91_MCI_RCRCE) &&
			((cmd->opcode == MMC_SEND_OP_COND) || (cmd->opcode == SD_APP_OP_COND))) {
			cmd->error = MMC_ERR_NONE;
		}
		else {
			if (status & (AT91_MCI_RTOE | AT91_MCI_DTOE))
				cmd->error = MMC_ERR_TIMEOUT;
			else if (status & (AT91_MCI_RCRCE | AT91_MCI_DCRCE))
				cmd->error = MMC_ERR_BADCRC;
			else if (status & (AT91_MCI_OVRE | AT91_MCI_UNRE))
				cmd->error = MMC_ERR_FIFO;
			else
				cmd->error = MMC_ERR_FAILED;

			pr_debug("Error detected and set to %d (cmd = %d, retries = %d)\n",
				 cmd->error, cmd->opcode, cmd->retries);
		}
	}
	else
		cmd->error = MMC_ERR_NONE;

	at91mci_process_next(host);
}