Merge changes I3236496a,I579030b3,I428cedee into msm-3.0
* changes:
mmc: msm_sdcc: don't call udelay() from msmsdcc_delay()
msm: msm_sdcc: defer device resume until next transfer request comes
mmc: block: claim host in mmc_blk_set_blksize() only if required
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 93aacef..5dbf839 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1540,6 +1540,9 @@
{
int err;
+ if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card))
+ return 0;
+
mmc_claim_host(card->host);
err = mmc_set_blocklen(card, 512);
mmc_release_host(card->host);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index c4613ba..e91cf3e 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -142,6 +142,7 @@
static void
msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd,
u32 c);
+static inline void msmsdcc_sync_reg_wr(struct msmsdcc_host *host);
static inline void msmsdcc_delay(struct msmsdcc_host *host);
static void msmsdcc_dump_sdcc_state(struct msmsdcc_host *host);
static void msmsdcc_sg_start(struct msmsdcc_host *host);
@@ -260,9 +261,9 @@
* and CPSM (command path state machine).
*/
writel_relaxed(0, host->base + MMCICOMMAND);
- msmsdcc_delay(host);
+ msmsdcc_sync_reg_wr(host);
writel_relaxed(0, host->base + MMCIDATACTRL);
- msmsdcc_delay(host);
+ msmsdcc_sync_reg_wr(host);
}
static void msmsdcc_hard_reset(struct msmsdcc_host *host)
@@ -282,6 +283,7 @@
" with err %d\n", mmc_hostname(host->mmc),
host->clk_rate, ret);
+ mb();
/* Give some delay for clock reset to propogate to controller */
msmsdcc_delay(host);
}
@@ -324,9 +326,9 @@
/* Restore the contoller state */
writel_relaxed(host->pwr, host->base + MMCIPOWER);
- msmsdcc_delay(host);
+ msmsdcc_sync_reg_wr(host);
writel_relaxed(mci_clk, host->base + MMCICLOCK);
- msmsdcc_delay(host);
+ msmsdcc_sync_reg_wr(host);
writel_relaxed(mci_mask0, host->base + MMCIMASK0);
mb(); /* no delay required after writing to MASK0 register */
}
@@ -372,7 +374,7 @@
host->curr.got_auto_prog_done = 0;
writel_relaxed(readl_relaxed(host->base + MMCIDATACTRL) &
(~(MCI_DPSM_ENABLE)), host->base + MMCIDATACTRL);
- msmsdcc_delay(host); /* Allow the DPSM to be reset */
+ msmsdcc_sync_reg_wr(host); /* Allow the DPSM to be reset */
}
static inline uint32_t msmsdcc_fifo_addr(struct msmsdcc_host *host)
@@ -383,16 +385,15 @@
static inline unsigned int msmsdcc_get_min_sup_clk_rate(
struct msmsdcc_host *host);
-static inline void msmsdcc_delay(struct msmsdcc_host *host)
+static inline void msmsdcc_sync_reg_wr(struct msmsdcc_host *host)
{
- ktime_t start, diff;
-
mb();
- udelay(host->reg_write_delay);
+ if (!host->sdcc_version)
+ udelay(host->reg_write_delay);
+ else if (readl_relaxed(host->base + MCI_STATUS2) &
+ MCI_MCLK_REG_WR_ACTIVE) {
+ ktime_t start, diff;
- if (host->sdcc_version &&
- (readl_relaxed(host->base + MCI_STATUS2) &
- MCI_MCLK_REG_WR_ACTIVE)) {
start = ktime_get();
while (readl_relaxed(host->base + MCI_STATUS2) &
MCI_MCLK_REG_WR_ACTIVE) {
@@ -408,6 +409,12 @@
}
}
+static inline void msmsdcc_delay(struct msmsdcc_host *host)
+{
+ udelay(host->reg_write_delay);
+
+}
+
static inline void
msmsdcc_start_command_exec(struct msmsdcc_host *host, u32 arg, u32 c)
{
@@ -431,7 +438,7 @@
writel_relaxed((unsigned int)host->curr.xfer_size,
host->base + MMCIDATALENGTH);
writel_relaxed(host->cmd_datactrl, host->base + MMCIDATACTRL);
- msmsdcc_delay(host); /* Force delay prior to ADM or command */
+ msmsdcc_sync_reg_wr(host); /* Force delay prior to ADM or command */
if (host->cmd_cmd) {
msmsdcc_start_command_exec(host,
@@ -1146,18 +1153,20 @@
(~(MCI_IRQ_PIO))) | pio_irqmask,
host->base + MMCIMASK0);
writel_relaxed(datactrl, base + MMCIDATACTRL);
- /*
- * We don't need delay after writing to DATA_CTRL register
- * if we are not writing to CMD register immediately after
- * this. As we already have delay before sending the
- * command, we just need mb() here.
- */
- mb();
if (cmd) {
- msmsdcc_delay(host); /* Delay between data/command */
+ /* Delay between data/command */
+ msmsdcc_sync_reg_wr(host);
/* Daisy-chain the command if requested */
msmsdcc_start_command(host, cmd, c);
+ } else {
+ /*
+ * We don't need delay after writing to DATA_CTRL
+ * register if we are not writing to CMD register
+ * immediately after this. As we already have delay
+ * before sending the command, we just need mb() here.
+ */
+ mb();
}
}
}
@@ -1650,7 +1659,7 @@
/* Allow clear to take effect*/
if (host->clk_rate <=
msmsdcc_get_min_sup_clk_rate(host))
- msmsdcc_delay(host);
+ msmsdcc_sync_reg_wr(host);
#if IRQ_DEBUG
msmsdcc_print_status(host, "irq0-p", status);
#endif
@@ -2212,8 +2221,10 @@
if (!IS_ERR(host->pclk))
clk_enable(host->pclk);
clk_enable(host->clk);
+ mb();
msmsdcc_delay(host);
} else {
+ mb();
msmsdcc_delay(host);
clk_disable(host->clk);
if (!IS_ERR(host->pclk))
@@ -2457,11 +2468,13 @@
* are disabling clocks, enable bit 22 in MASK0
* to handle asynchronous SDIO interrupts.
*/
- if (enable_wakeup_irq)
+ if (enable_wakeup_irq) {
writel_relaxed(MCI_SDIOINTMASK, host->base + MMCIMASK0);
- else
+ mb();
+ } else {
writel_relaxed(MCI_SDIOINTMASK, host->base + MMCICLEAR);
- mb();
+ msmsdcc_sync_reg_wr(host);
+ }
goto out;
} else if (!mmc_card_wake_sdio_irq(mmc)) {
/*
@@ -2504,7 +2517,7 @@
* handler as the clocks might be off at that time.
*/
writel_relaxed(MCI_SDIOINTMASK, host->base + MMCICLEAR);
- mb();
+ msmsdcc_sync_reg_wr(host);
if (host->plat->cfg_mpm_sdiowakeup)
host->plat->cfg_mpm_sdiowakeup(
mmc_dev(mmc), SDC_DAT1_DISWAKE);
@@ -2597,6 +2610,7 @@
* give atleast 2 MCLK cycles delay for clocks
* and SDCC core to stabilize
*/
+ mb();
msmsdcc_delay(host);
clk |= MCI_CLK_ENABLE;
}
@@ -2642,12 +2656,12 @@
if (host->clks_on) {
if (readl_relaxed(host->base + MMCICLOCK) != clk) {
writel_relaxed(clk, host->base + MMCICLOCK);
- msmsdcc_delay(host);
+ msmsdcc_sync_reg_wr(host);
}
if (readl_relaxed(host->base + MMCIPOWER) != pwr) {
host->pwr = pwr;
writel_relaxed(pwr, host->base + MMCIPOWER);
- msmsdcc_delay(host);
+ msmsdcc_sync_reg_wr(host);
}
}
@@ -2682,7 +2696,7 @@
else
clk &= ~MCI_CLK_PWRSAVE;
writel_relaxed(clk, host->base + MMCICLOCK);
- msmsdcc_delay(host);
+ msmsdcc_sync_reg_wr(host);
return 0;
}
@@ -2902,7 +2916,7 @@
/* Stop SD CLK output. */
writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
- msmsdcc_delay(host);
+ msmsdcc_sync_reg_wr(host);
spin_unlock_irqrestore(&host->lock, flags);
/*
@@ -2916,7 +2930,7 @@
spin_lock_irqsave(&host->lock, flags);
writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
IO_PAD_PWR_SWITCH), host->base + MMCICLOCK);
- msmsdcc_delay(host);
+ msmsdcc_sync_reg_wr(host);
host->io_pad_pwr_switch = 1;
spin_unlock_irqrestore(&host->lock, flags);
@@ -2927,7 +2941,7 @@
/* Disable PWRSAVE would make sure that SD CLK is always running */
writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
& ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
- msmsdcc_delay(host);
+ msmsdcc_sync_reg_wr(host);
spin_unlock_irqrestore(&host->lock, flags);
/*
@@ -2951,6 +2965,7 @@
/* Enable PWRSAVE */
writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
+ msmsdcc_sync_reg_wr(host);
spin_unlock_irqrestore(&host->lock, flags);
out:
return rc;
@@ -2999,6 +3014,7 @@
*/
writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
& ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
+ msmsdcc_sync_reg_wr(host);
/* Write 1 to DLL_RST bit of MCI_DLL_CONFIG register */
writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
@@ -3044,6 +3060,7 @@
/* re-enable PWRSAVE */
writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
+ msmsdcc_sync_reg_wr(host);
spin_unlock_irqrestore(&host->lock, flags);
return rc;
@@ -3280,13 +3297,11 @@
WARN(host->sdcc_irq_disabled, "SDCC IRQ is disabled\n");
host->tuning_in_progress = 1;
- msmsdcc_delay(host);
if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) &&
(mmc->ios.bus_width == MMC_BUS_WIDTH_8)) {
tuning_block_pattern = tuning_block_128;
size = sizeof(tuning_block_128);
}
-
spin_unlock_irqrestore(&host->lock, flags);
/* first of all reset the tuning block */
@@ -3367,7 +3382,6 @@
kfree(data_buf);
out:
spin_lock_irqsave(&host->lock, flags);
- msmsdcc_delay(host);
host->tuning_in_progress = 0;
spin_unlock_irqrestore(&host->lock, flags);
exit:
@@ -4526,6 +4540,7 @@
writel_relaxed(0, host->base + MMCIMASK0);
writel_relaxed(MCI_CLEAR_STATIC_MASK, host->base + MMCICLEAR);
+ msmsdcc_sync_reg_wr(host);
writel_relaxed(MCI_IRQENABLE, host->base + MMCIMASK0);
mb();
@@ -5060,8 +5075,23 @@
if (host->plat->status_irq)
disable_irq(host->plat->status_irq);
- if (!pm_runtime_suspended(dev))
- rc = msmsdcc_runtime_suspend(dev);
+ if (!pm_runtime_suspended(dev)) {
+ if (!(mmc->card && mmc_card_sdio(mmc->card))) {
+ /*
+ * decrement power.usage_counter if it's
+ * not zero earlier
+ */
+ pm_runtime_put_noidle(dev);
+ rc = pm_runtime_suspend(dev);
+ }
+
+ /*
+ * if device runtime PM status is still not suspended
+ * then perform suspend here.
+ */
+ if (!pm_runtime_suspended(dev))
+ rc = msmsdcc_runtime_suspend(dev);
+ }
return rc;
}