Loading drivers/mmc/host/sdhci.c +47 −16 Original line number Diff line number Diff line Loading @@ -838,9 +838,10 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) } static void sdhci_set_transfer_mode(struct sdhci_host *host, struct mmc_data *data) struct mmc_command *cmd) { u16 mode; struct mmc_data *data = cmd->data; if (data == NULL) return; Loading @@ -848,11 +849,14 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, WARN_ON(!host->data); mode = SDHCI_TRNS_BLK_CNT_EN; if (data->blocks > 1) { if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) mode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_ACMD12; else if (mmc_op_multi(cmd->opcode) || data->blocks > 1) { mode |= SDHCI_TRNS_MULTI; /* * If we are sending CMD23, CMD12 never gets sent * on successful completion (so no Auto-CMD12). */ if (!host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) mode |= SDHCI_TRNS_AUTO_CMD12; } if (data->flags & MMC_DATA_READ) mode |= SDHCI_TRNS_READ; Loading Loading @@ -893,7 +897,15 @@ static void sdhci_finish_data(struct sdhci_host *host) else data->bytes_xfered = data->blksz * data->blocks; if (data->stop) { /* * Need to send CMD12 if - * a) open-ended multiblock transfer (no CMD23) * b) error in multiblock transfer */ if (data->stop && (data->error || !host->mrq->sbc)) { /* * The controller needs a reset of internal state machines * upon error conditions. Loading Loading @@ -949,7 +961,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); sdhci_set_transfer_mode(host, cmd->data); sdhci_set_transfer_mode(host, cmd); if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { printk(KERN_ERR "%s: Unsupported response type!\n", Loading Loading @@ -1004,6 +1016,13 @@ static void sdhci_finish_command(struct sdhci_host *host) host->cmd->error = 0; /* Finished CMD23, now send actual command. */ if (host->cmd == host->mrq->sbc) { host->cmd = NULL; sdhci_send_command(host, host->mrq->cmd); } else { /* Processed actual command. */ if (host->data && host->data_early) sdhci_finish_data(host); Loading @@ -1012,6 +1031,7 @@ static void sdhci_finish_command(struct sdhci_host *host) host->cmd = NULL; } } static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) { Loading Loading @@ -1189,7 +1209,12 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) #ifndef SDHCI_USE_LEDS_CLASS sdhci_activate_led(host); #endif if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) { /* * Ensure we don't send the STOP for non-SET_BLOCK_COUNTED * requests if Auto-CMD12 is enabled. */ if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) { if (mrq->stop) { mrq->data->stop = NULL; mrq->stop = NULL; Loading Loading @@ -1227,6 +1252,9 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) host->mrq = mrq; } if (mrq->sbc) sdhci_send_command(host, mrq->sbc); else sdhci_send_command(host, mrq->cmd); } Loading Loading @@ -2455,7 +2483,10 @@ int sdhci_add_host(struct sdhci_host *host) } else mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE; mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23; if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) host->flags |= SDHCI_AUTO_CMD12; /* * A controller may support 8-bit width, but the board itself Loading drivers/mmc/host/sdhci.h +1 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,7 @@ #define SDHCI_TRANSFER_MODE 0x0C #define SDHCI_TRNS_DMA 0x01 #define SDHCI_TRNS_BLK_CNT_EN 0x02 #define SDHCI_TRNS_ACMD12 0x04 #define SDHCI_TRNS_AUTO_CMD12 0x04 #define SDHCI_TRNS_READ 0x10 #define SDHCI_TRNS_MULTI 0x20 Loading include/linux/mmc/sdhci.h +1 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,7 @@ struct sdhci_host { #define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */ #define SDHCI_SDR50_NEEDS_TUNING (1<<4) /* SDR50 needs tuning */ #define SDHCI_NEEDS_RETUNING (1<<5) /* Host needs retuning */ #define SDHCI_AUTO_CMD12 (1<<6) /* Auto CMD12 support */ unsigned int version; /* SDHCI spec. version */ Loading Loading
drivers/mmc/host/sdhci.c +47 −16 Original line number Diff line number Diff line Loading @@ -838,9 +838,10 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) } static void sdhci_set_transfer_mode(struct sdhci_host *host, struct mmc_data *data) struct mmc_command *cmd) { u16 mode; struct mmc_data *data = cmd->data; if (data == NULL) return; Loading @@ -848,11 +849,14 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, WARN_ON(!host->data); mode = SDHCI_TRNS_BLK_CNT_EN; if (data->blocks > 1) { if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) mode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_ACMD12; else if (mmc_op_multi(cmd->opcode) || data->blocks > 1) { mode |= SDHCI_TRNS_MULTI; /* * If we are sending CMD23, CMD12 never gets sent * on successful completion (so no Auto-CMD12). */ if (!host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) mode |= SDHCI_TRNS_AUTO_CMD12; } if (data->flags & MMC_DATA_READ) mode |= SDHCI_TRNS_READ; Loading Loading @@ -893,7 +897,15 @@ static void sdhci_finish_data(struct sdhci_host *host) else data->bytes_xfered = data->blksz * data->blocks; if (data->stop) { /* * Need to send CMD12 if - * a) open-ended multiblock transfer (no CMD23) * b) error in multiblock transfer */ if (data->stop && (data->error || !host->mrq->sbc)) { /* * The controller needs a reset of internal state machines * upon error conditions. Loading Loading @@ -949,7 +961,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); sdhci_set_transfer_mode(host, cmd->data); sdhci_set_transfer_mode(host, cmd); if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { printk(KERN_ERR "%s: Unsupported response type!\n", Loading Loading @@ -1004,6 +1016,13 @@ static void sdhci_finish_command(struct sdhci_host *host) host->cmd->error = 0; /* Finished CMD23, now send actual command. */ if (host->cmd == host->mrq->sbc) { host->cmd = NULL; sdhci_send_command(host, host->mrq->cmd); } else { /* Processed actual command. */ if (host->data && host->data_early) sdhci_finish_data(host); Loading @@ -1012,6 +1031,7 @@ static void sdhci_finish_command(struct sdhci_host *host) host->cmd = NULL; } } static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) { Loading Loading @@ -1189,7 +1209,12 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) #ifndef SDHCI_USE_LEDS_CLASS sdhci_activate_led(host); #endif if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) { /* * Ensure we don't send the STOP for non-SET_BLOCK_COUNTED * requests if Auto-CMD12 is enabled. */ if (!mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) { if (mrq->stop) { mrq->data->stop = NULL; mrq->stop = NULL; Loading Loading @@ -1227,6 +1252,9 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) host->mrq = mrq; } if (mrq->sbc) sdhci_send_command(host, mrq->sbc); else sdhci_send_command(host, mrq->cmd); } Loading Loading @@ -2455,7 +2483,10 @@ int sdhci_add_host(struct sdhci_host *host) } else mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200; mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE; mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23; if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) host->flags |= SDHCI_AUTO_CMD12; /* * A controller may support 8-bit width, but the board itself Loading
drivers/mmc/host/sdhci.h +1 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,7 @@ #define SDHCI_TRANSFER_MODE 0x0C #define SDHCI_TRNS_DMA 0x01 #define SDHCI_TRNS_BLK_CNT_EN 0x02 #define SDHCI_TRNS_ACMD12 0x04 #define SDHCI_TRNS_AUTO_CMD12 0x04 #define SDHCI_TRNS_READ 0x10 #define SDHCI_TRNS_MULTI 0x20 Loading
include/linux/mmc/sdhci.h +1 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,7 @@ struct sdhci_host { #define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */ #define SDHCI_SDR50_NEEDS_TUNING (1<<4) /* SDR50 needs tuning */ #define SDHCI_NEEDS_RETUNING (1<<5) /* Host needs retuning */ #define SDHCI_AUTO_CMD12 (1<<6) /* Auto CMD12 support */ unsigned int version; /* SDHCI spec. version */ Loading