diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 103 |
1 files changed, 62 insertions, 41 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index a5dc5aae973e..b056400e34b1 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -668,10 +668,10 @@ void sdhci_adma_write_desc(struct sdhci_host *host, void **desc, /* 32-bit and 64-bit descriptors have these members in same position */ dma_desc->cmd = cpu_to_le16(cmd); dma_desc->len = cpu_to_le16(len); - dma_desc->addr_lo = cpu_to_le32((u32)addr); + dma_desc->addr_lo = cpu_to_le32(lower_32_bits(addr)); if (host->flags & SDHCI_USE_64_BIT_DMA) - dma_desc->addr_hi = cpu_to_le32((u64)addr >> 32); + dma_desc->addr_hi = cpu_to_le32(upper_32_bits(addr)); *desc += host->desc_sz; } @@ -816,6 +816,13 @@ static void sdhci_adma_table_post(struct sdhci_host *host, } } +static void sdhci_set_adma_addr(struct sdhci_host *host, dma_addr_t addr) +{ + sdhci_writel(host, lower_32_bits(addr), SDHCI_ADMA_ADDRESS); + if (host->flags & SDHCI_USE_64_BIT_DMA) + sdhci_writel(host, upper_32_bits(addr), SDHCI_ADMA_ADDRESS_HI); +} + static dma_addr_t sdhci_sdma_address(struct sdhci_host *host) { if (host->bounce_buffer) @@ -826,13 +833,10 @@ static dma_addr_t sdhci_sdma_address(struct sdhci_host *host) static void sdhci_set_sdma_addr(struct sdhci_host *host, dma_addr_t addr) { - if (host->v4_mode) { - sdhci_writel(host, addr, SDHCI_ADMA_ADDRESS); - if (host->flags & SDHCI_USE_64_BIT_DMA) - sdhci_writel(host, (u64)addr >> 32, SDHCI_ADMA_ADDRESS_HI); - } else { + if (host->v4_mode) + sdhci_set_adma_addr(host, addr); + else sdhci_writel(host, addr, SDHCI_DMA_ADDRESS); - } } static unsigned int sdhci_target_timeout(struct sdhci_host *host, @@ -1095,12 +1099,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) host->flags &= ~SDHCI_REQ_USE_DMA; } else if (host->flags & SDHCI_USE_ADMA) { sdhci_adma_table_pre(host, data, sg_cnt); - - sdhci_writel(host, host->adma_addr, SDHCI_ADMA_ADDRESS); - if (host->flags & SDHCI_USE_64_BIT_DMA) - sdhci_writel(host, - (u64)host->adma_addr >> 32, - SDHCI_ADMA_ADDRESS_HI); + sdhci_set_adma_addr(host, host->adma_addr); } else { WARN_ON(sg_cnt != 1); sdhci_set_sdma_addr(host, sdhci_sdma_address(host)); @@ -1636,8 +1635,8 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk) clk |= SDHCI_CLOCK_INT_EN; sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); - /* Wait max 20 ms */ - timeout = ktime_add_ms(ktime_get(), 20); + /* Wait max 150 ms */ + timeout = ktime_add_ms(ktime_get(), 150); while (1) { bool timedout = ktime_after(ktime_get(), timeout); @@ -1653,6 +1652,29 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk) udelay(10); } + if (host->version >= SDHCI_SPEC_410 && host->v4_mode) { + clk |= SDHCI_CLOCK_PLL_EN; + clk &= ~SDHCI_CLOCK_INT_STABLE; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + + /* Wait max 150 ms */ + timeout = ktime_add_ms(ktime_get(), 150); + while (1) { + bool timedout = ktime_after(ktime_get(), timeout); + + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + if (clk & SDHCI_CLOCK_INT_STABLE) + break; + if (timedout) { + pr_err("%s: PLL clock never stabilised.\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + return; + } + udelay(10); + } + } + clk |= SDHCI_CLOCK_CARD_EN; sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); } @@ -1849,7 +1871,9 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) ctrl_2 |= SDHCI_CTRL_UHS_SDR104; else if (timing == MMC_TIMING_UHS_SDR12) ctrl_2 |= SDHCI_CTRL_UHS_SDR12; - else if (timing == MMC_TIMING_UHS_SDR25) + else if (timing == MMC_TIMING_SD_HS || + timing == MMC_TIMING_MMC_HS || + timing == MMC_TIMING_UHS_SDR25) ctrl_2 |= SDHCI_CTRL_UHS_SDR25; else if (timing == MMC_TIMING_UHS_SDR50) ctrl_2 |= SDHCI_CTRL_UHS_SDR50; @@ -2120,11 +2144,6 @@ void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) pm_runtime_get_noresume(host->mmc->parent); spin_lock_irqsave(&host->lock, flags); - if (enable) - host->flags |= SDHCI_SDIO_IRQ_ENABLED; - else - host->flags &= ~SDHCI_SDIO_IRQ_ENABLED; - sdhci_enable_sdio_irq_nolock(host, enable); spin_unlock_irqrestore(&host->lock, flags); @@ -2139,8 +2158,7 @@ static void sdhci_ack_sdio_irq(struct mmc_host *mmc) unsigned long flags; spin_lock_irqsave(&host->lock, flags); - if (host->flags & SDHCI_SDIO_IRQ_ENABLED) - sdhci_enable_sdio_irq_nolock(host, true); + sdhci_enable_sdio_irq_nolock(host, true); spin_unlock_irqrestore(&host->lock, flags); } @@ -2305,7 +2323,7 @@ void sdhci_reset_tuning(struct sdhci_host *host) } EXPORT_SYMBOL_GPL(sdhci_reset_tuning); -static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) +void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) { sdhci_reset_tuning(host); @@ -2316,6 +2334,7 @@ static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) mmc_abort_tuning(host->mmc, opcode); } +EXPORT_SYMBOL_GPL(sdhci_abort_tuning); /* * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI @@ -2855,6 +2874,7 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) static void sdhci_adma_show_error(struct sdhci_host *host) { void *desc = host->adma_table; + dma_addr_t dma = host->adma_addr; sdhci_dumpregs(host); @@ -2862,18 +2882,21 @@ static void sdhci_adma_show_error(struct sdhci_host *host) struct sdhci_adma2_64_desc *dma_desc = desc; if (host->flags & SDHCI_USE_64_BIT_DMA) - DBG("%p: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n", - desc, le32_to_cpu(dma_desc->addr_hi), + SDHCI_DUMP("%08llx: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n", + (unsigned long long)dma, + le32_to_cpu(dma_desc->addr_hi), le32_to_cpu(dma_desc->addr_lo), le16_to_cpu(dma_desc->len), le16_to_cpu(dma_desc->cmd)); else - DBG("%p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", - desc, le32_to_cpu(dma_desc->addr_lo), + SDHCI_DUMP("%08llx: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", + (unsigned long long)dma, + le32_to_cpu(dma_desc->addr_lo), le16_to_cpu(dma_desc->len), le16_to_cpu(dma_desc->cmd)); desc += host->desc_sz; + dma += host->desc_sz; if (dma_desc->cmd & cpu_to_le16(ADMA2_END)) break; @@ -2949,7 +2972,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) != MMC_BUS_TEST_R) host->data->error = -EILSEQ; else if (intmask & SDHCI_INT_ADMA_ERROR) { - pr_err("%s: ADMA error\n", mmc_hostname(host->mmc)); + pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc), + intmask); sdhci_adma_show_error(host); host->data->error = -EIO; if (host->ops->adma_workaround) @@ -3024,7 +3048,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) spin_lock(&host->lock); - if (host->runtime_suspended && !sdhci_sdio_irq_enabled(host)) { + if (host->runtime_suspended) { spin_unlock(&host->lock); return IRQ_NONE; } @@ -3358,7 +3382,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset) host->runtime_suspended = false; /* Enable SDIO IRQ */ - if (host->flags & SDHCI_SDIO_IRQ_ENABLED) + if (sdio_irq_claimed(mmc)) sdhci_enable_sdio_irq_nolock(host, true); /* Enable Card Detection */ @@ -3565,7 +3589,8 @@ static int sdhci_set_dma_mask(struct sdhci_host *host) return ret; } -void __sdhci_read_caps(struct sdhci_host *host, u16 *ver, u32 *caps, u32 *caps1) +void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver, + const u32 *caps, const u32 *caps1) { u16 v; u64 dt_caps_mask = 0; @@ -3756,18 +3781,14 @@ int sdhci_setup_host(struct sdhci_host *host) host->flags &= ~SDHCI_USE_ADMA; } - /* - * It is assumed that a 64-bit capable device has set a 64-bit DMA mask - * and *must* do 64-bit DMA. A driver has the opportunity to change - * that during the first call to ->enable_dma(). Similarly - * SDHCI_QUIRK2_BROKEN_64_BIT_DMA must be left to the drivers to - * implement. - */ if (sdhci_can_64bit_dma(host)) host->flags |= SDHCI_USE_64_BIT_DMA; if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { - ret = sdhci_set_dma_mask(host); + if (host->ops->set_dma_mask) + ret = host->ops->set_dma_mask(host); + else + ret = sdhci_set_dma_mask(host); if (!ret && host->ops->enable_dma) ret = host->ops->enable_dma(host); |