static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, struct mmc_command *cmd, struct mmc_data *data) { u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); switch (mmc_resp_type(cmd)) { case MMC_RSP_NONE: break; case MMC_RSP_R1: mmccmd |= SD_CMD_RT_1; break; case MMC_RSP_R1B: mmccmd |= SD_CMD_RT_1B; break; case MMC_RSP_R2: mmccmd |= SD_CMD_RT_2; break; case MMC_RSP_R3: mmccmd |= SD_CMD_RT_3; break; default: printk(KERN_INFO "au1xmmc: unhandled response type %02x\n", mmc_resp_type(cmd)); return -EINVAL; } if (data) { if (data->flags & MMC_DATA_READ) { if (data->blocks > 1) mmccmd |= SD_CMD_CT_4; else mmccmd |= SD_CMD_CT_2; } else if (data->flags & MMC_DATA_WRITE) { if (data->blocks > 1) mmccmd |= SD_CMD_CT_3; else mmccmd |= SD_CMD_CT_1; } } au_writel(cmd->arg, HOST_CMDARG(host)); au_sync(); if (wait) IRQ_OFF(host, SD_CONFIG_CR); au_writel((mmccmd | SD_CMD_GO), HOST_CMD(host)); au_sync(); /* Wait for the command to go on the line */ while (au_readl(HOST_CMD(host)) & SD_CMD_GO) /* nop */; /* Wait for the command to come back */ if (wait) { u32 status = au_readl(HOST_STATUS(host)); while (!(status & SD_STATUS_CR)) status = au_readl(HOST_STATUS(host)); /* Clear the CR status */ au_writel(SD_STATUS_CR, HOST_STATUS(host)); IRQ_ON(host, SD_CONFIG_CR); } return 0; }
static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, struct mmc_command *cmd) { u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); switch(cmd->flags) { case MMC_RSP_R1: mmccmd |= SD_CMD_RT_1; break; case MMC_RSP_R1B: mmccmd |= SD_CMD_RT_1B; break; case MMC_RSP_R2: mmccmd |= SD_CMD_RT_2; break; case MMC_RSP_R3: mmccmd |= SD_CMD_RT_3; break; } switch(cmd->opcode) { case MMC_READ_SINGLE_BLOCK: case 51: mmccmd |= SD_CMD_CT_2; break; case MMC_READ_MULTIPLE_BLOCK: mmccmd |= SD_CMD_CT_4; break; case MMC_WRITE_BLOCK: mmccmd |= SD_CMD_CT_1; break; case MMC_WRITE_MULTIPLE_BLOCK: mmccmd |= SD_CMD_CT_3; break; case MMC_STOP_TRANSMISSION: mmccmd |= SD_CMD_CT_7; break; } au_writel(cmd->arg, HOST_CMDARG(host)); au_sync(); if (wait) IRQ_OFF(host, SD_CONFIG_CR); au_writel((mmccmd | SD_CMD_GO), HOST_CMD(host)); au_sync(); /* Wait for the command to go on the line */ while(1) { if (!(au_readl(HOST_CMD(host)) & SD_CMD_GO)) break; } /* Wait for the command to come back */ if (wait) { u32 status = au_readl(HOST_STATUS(host)); while(!(status & SD_STATUS_CR)) status = au_readl(HOST_STATUS(host)); /* Clear the CR status */ au_writel(SD_STATUS_CR, HOST_STATUS(host)); IRQ_ON(host, SD_CONFIG_CR); } return MMC_ERR_NONE; }