summaryrefslogtreecommitdiff
path: root/drivers/mmc/host/sdhci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r--drivers/mmc/host/sdhci.c85
1 files changed, 31 insertions, 54 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index c7ad32a75b57..f3af1bd0f7b9 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -270,6 +270,11 @@ enum sdhci_reset_reason {
static void sdhci_reset_for_reason(struct sdhci_host *host, enum sdhci_reset_reason reason)
{
+ if (host->quirks2 & SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER) {
+ sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+ return;
+ }
+
switch (reason) {
case SDHCI_RESET_FOR_INIT:
sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
@@ -526,7 +531,6 @@ static inline bool sdhci_has_requests(struct sdhci_host *host)
static void sdhci_read_block_pio(struct sdhci_host *host)
{
- unsigned long flags;
size_t blksize, len, chunk;
u32 scratch;
u8 *buf;
@@ -536,8 +540,6 @@ static void sdhci_read_block_pio(struct sdhci_host *host)
blksize = host->data->blksz;
chunk = 0;
- local_irq_save(flags);
-
while (blksize) {
BUG_ON(!sg_miter_next(&host->sg_miter));
@@ -564,13 +566,10 @@ static void sdhci_read_block_pio(struct sdhci_host *host)
}
sg_miter_stop(&host->sg_miter);
-
- local_irq_restore(flags);
}
static void sdhci_write_block_pio(struct sdhci_host *host)
{
- unsigned long flags;
size_t blksize, len, chunk;
u32 scratch;
u8 *buf;
@@ -581,8 +580,6 @@ static void sdhci_write_block_pio(struct sdhci_host *host)
chunk = 0;
scratch = 0;
- local_irq_save(flags);
-
while (blksize) {
BUG_ON(!sg_miter_next(&host->sg_miter));
@@ -609,8 +606,6 @@ static void sdhci_write_block_pio(struct sdhci_host *host)
}
sg_miter_stop(&host->sg_miter);
-
- local_irq_restore(flags);
}
static void sdhci_transfer_pio(struct sdhci_host *host)
@@ -706,16 +701,14 @@ static int sdhci_pre_dma_transfer(struct sdhci_host *host,
return sg_count;
}
-static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags)
+static char *sdhci_kmap_atomic(struct scatterlist *sg)
{
- local_irq_save(*flags);
- return kmap_atomic(sg_page(sg)) + sg->offset;
+ return kmap_local_page(sg_page(sg)) + sg->offset;
}
-static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags)
+static void sdhci_kunmap_atomic(void *buffer)
{
- kunmap_atomic(buffer);
- local_irq_restore(*flags);
+ kunmap_local(buffer);
}
void sdhci_adma_write_desc(struct sdhci_host *host, void **desc,
@@ -757,7 +750,6 @@ static void sdhci_adma_table_pre(struct sdhci_host *host,
struct mmc_data *data, int sg_count)
{
struct scatterlist *sg;
- unsigned long flags;
dma_addr_t addr, align_addr;
void *desc, *align;
char *buffer;
@@ -789,9 +781,9 @@ static void sdhci_adma_table_pre(struct sdhci_host *host,
SDHCI_ADMA2_MASK;
if (offset) {
if (data->flags & MMC_DATA_WRITE) {
- buffer = sdhci_kmap_atomic(sg, &flags);
+ buffer = sdhci_kmap_atomic(sg);
memcpy(align, buffer, offset);
- sdhci_kunmap_atomic(buffer, &flags);
+ sdhci_kunmap_atomic(buffer);
}
/* tran, valid */
@@ -852,7 +844,6 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
int i, size;
void *align;
char *buffer;
- unsigned long flags;
if (data->flags & MMC_DATA_READ) {
bool has_unaligned = false;
@@ -875,9 +866,9 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
size = SDHCI_ADMA2_ALIGN -
(sg_dma_address(sg) & SDHCI_ADMA2_MASK);
- buffer = sdhci_kmap_atomic(sg, &flags);
+ buffer = sdhci_kmap_atomic(sg);
memcpy(buffer, align, size);
- sdhci_kunmap_atomic(buffer, &flags);
+ sdhci_kunmap_atomic(buffer);
align += SDHCI_ADMA2_ALIGN;
}
@@ -1466,7 +1457,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
if (host->quirks2 &
SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) {
/* must not clear SDHCI_TRANSFER_MODE when tuning */
- if (cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200)
+ if (!mmc_op_tuning(cmd->opcode))
sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
} else {
/* clear Auto CMD settings for no data CMDs */
@@ -1707,8 +1698,7 @@ static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
flags |= SDHCI_CMD_INDEX;
/* CMD19 is special in that the Data Present Select should be set */
- if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK ||
- cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200)
+ if (cmd->data || mmc_op_tuning(cmd->opcode))
flags |= SDHCI_CMD_DATA;
timeout = jiffies;
@@ -2304,7 +2294,7 @@ static bool sdhci_timing_has_preset(unsigned char timing)
case MMC_TIMING_UHS_DDR50:
case MMC_TIMING_MMC_DDR52:
return true;
- };
+ }
return false;
}
@@ -2418,8 +2408,21 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (host->version >= SDHCI_SPEC_300) {
u16 clk, ctrl_2;
+ /*
+ * According to SDHCI Spec v3.00, if the Preset Value
+ * Enable in the Host Control 2 register is set, we
+ * need to reset SD Clock Enable before changing High
+ * Speed Enable to avoid generating clock glitches.
+ */
+ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ if (clk & SDHCI_CLOCK_CARD_EN) {
+ clk &= ~SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+ }
+
+ sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+
if (!host->preset_enabled) {
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
/*
* We only need to set Driver Strength if the
* preset value enable is not set.
@@ -2442,30 +2445,8 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
host->drv_type = ios->drv_type;
- } else {
- /*
- * According to SDHC Spec v3.00, if the Preset Value
- * Enable in the Host Control 2 register is set, we
- * need to reset SD Clock Enable before changing High
- * Speed Enable to avoid generating clock gliches.
- */
-
- /* Reset SD Clock Enable */
- clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
- clk &= ~SDHCI_CLOCK_CARD_EN;
- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-
- /* Re-enable SD Clock */
- host->ops->set_clock(host, host->clock);
}
- /* Reset SD Clock Enable */
- clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
- clk &= ~SDHCI_CLOCK_CARD_EN;
- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
-
host->ops->set_uhs_signaling(host, ios->timing);
host->timing = ios->timing;
@@ -3388,8 +3369,6 @@ static void sdhci_adma_show_error(struct sdhci_host *host)
static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
{
- u32 command;
-
/*
* CMD19 generates _only_ Buffer Read Ready interrupt if
* use sdhci_send_tuning.
@@ -3398,9 +3377,7 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
* SDHCI_INT_DATA_AVAIL always there, stuck in irq storm.
*/
if (intmask & SDHCI_INT_DATA_AVAIL && !host->data) {
- command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND));
- if (command == MMC_SEND_TUNING_BLOCK ||
- command == MMC_SEND_TUNING_BLOCK_HS200) {
+ if (mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)))) {
host->tuning_done = 1;
wake_up(&host->buf_ready_int);
return;