diff options
| -rw-r--r-- | drivers/mmc/host/msm_sdcc.c | 61 |
1 files changed, 27 insertions, 34 deletions
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index 8329fd650c5f..47b1f2526521 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c | |||
| @@ -61,7 +61,7 @@ static unsigned int msmsdcc_sdioirq; | |||
| 61 | #define CMD_SPINMAX 20 | 61 | #define CMD_SPINMAX 20 |
| 62 | 62 | ||
| 63 | 63 | ||
| 64 | static inline void | 64 | static inline void |
| 65 | msmsdcc_disable_clocks(struct msmsdcc_host *host, int deferr) | 65 | msmsdcc_disable_clocks(struct msmsdcc_host *host, int deferr) |
| 66 | { | 66 | { |
| 67 | WARN_ON(!host->clks_on); | 67 | WARN_ON(!host->clks_on); |
| @@ -72,9 +72,14 @@ msmsdcc_disable_clocks(struct msmsdcc_host *host, int deferr) | |||
| 72 | mod_timer(&host->busclk_timer, jiffies + BUSCLK_TIMEOUT); | 72 | mod_timer(&host->busclk_timer, jiffies + BUSCLK_TIMEOUT); |
| 73 | } else { | 73 | } else { |
| 74 | del_timer_sync(&host->busclk_timer); | 74 | del_timer_sync(&host->busclk_timer); |
| 75 | clk_disable(host->clk); | 75 | /* Need to check clks_on again in case the busclk |
| 76 | clk_disable(host->pclk); | 76 | * timer fired |
| 77 | host->clks_on = 0; | 77 | */ |
| 78 | if (host->clks_on) { | ||
| 79 | clk_disable(host->clk); | ||
| 80 | clk_disable(host->pclk); | ||
| 81 | host->clks_on = 0; | ||
| 82 | } | ||
| 78 | } | 83 | } |
| 79 | } | 84 | } |
| 80 | 85 | ||
| @@ -83,21 +88,21 @@ msmsdcc_enable_clocks(struct msmsdcc_host *host) | |||
| 83 | { | 88 | { |
| 84 | int rc; | 89 | int rc; |
| 85 | 90 | ||
| 86 | WARN_ON(host->clks_on); | ||
| 87 | |||
| 88 | del_timer_sync(&host->busclk_timer); | 91 | del_timer_sync(&host->busclk_timer); |
| 89 | 92 | ||
| 90 | rc = clk_enable(host->pclk); | 93 | if (!host->clks_on) { |
| 91 | if (rc) | 94 | rc = clk_enable(host->pclk); |
| 92 | return rc; | 95 | if (rc) |
| 93 | rc = clk_enable(host->clk); | 96 | return rc; |
| 94 | if (rc) { | 97 | rc = clk_enable(host->clk); |
| 95 | clk_disable(host->pclk); | 98 | if (rc) { |
| 96 | return rc; | 99 | clk_disable(host->pclk); |
| 100 | return rc; | ||
| 101 | } | ||
| 102 | udelay(1 + ((3 * USEC_PER_SEC) / | ||
| 103 | (host->clk_rate ? host->clk_rate : msmsdcc_fmin))); | ||
| 104 | host->clks_on = 1; | ||
| 97 | } | 105 | } |
| 98 | udelay(1 + ((3 * USEC_PER_SEC) / | ||
| 99 | (host->clk_rate ? host->clk_rate : msmsdcc_fmin))); | ||
| 100 | host->clks_on = 1; | ||
| 101 | return 0; | 106 | return 0; |
| 102 | } | 107 | } |
| 103 | 108 | ||
| @@ -180,7 +185,8 @@ msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd) | |||
| 180 | struct msmsdcc_host *host = (struct msmsdcc_host *)cmd->data; | 185 | struct msmsdcc_host *host = (struct msmsdcc_host *)cmd->data; |
| 181 | 186 | ||
| 182 | msmsdcc_writel(host, host->cmd_timeout, MMCIDATATIMER); | 187 | msmsdcc_writel(host, host->cmd_timeout, MMCIDATATIMER); |
| 183 | msmsdcc_writel(host, (unsigned int)host->curr.xfer_size, MMCIDATALENGTH); | 188 | msmsdcc_writel(host, (unsigned int)host->curr.xfer_size, |
| 189 | MMCIDATALENGTH); | ||
| 184 | msmsdcc_writel(host, host->cmd_pio_irqmask, MMCIMASK1); | 190 | msmsdcc_writel(host, host->cmd_pio_irqmask, MMCIMASK1); |
| 185 | msmsdcc_writel(host, host->cmd_datactrl, MMCIDATACTRL); | 191 | msmsdcc_writel(host, host->cmd_datactrl, MMCIDATACTRL); |
| 186 | 192 | ||
| @@ -854,13 +860,7 @@ msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 854 | return; | 860 | return; |
| 855 | } | 861 | } |
| 856 | 862 | ||
| 857 | /* Need to drop the host lock here in case | 863 | msmsdcc_enable_clocks(host); |
| 858 | * the busclk wd fires | ||
| 859 | */ | ||
| 860 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 861 | if (!host->clks_on) | ||
| 862 | msmsdcc_enable_clocks(host); | ||
| 863 | spin_lock_irqsave(&host->lock, flags); | ||
| 864 | 864 | ||
| 865 | host->curr.mrq = mrq; | 865 | host->curr.mrq = mrq; |
| 866 | 866 | ||
| @@ -893,11 +893,10 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 893 | int rc; | 893 | int rc; |
| 894 | unsigned long flags; | 894 | unsigned long flags; |
| 895 | 895 | ||
| 896 | if (!host->clks_on) | ||
| 897 | msmsdcc_enable_clocks(host); | ||
| 898 | |||
| 899 | spin_lock_irqsave(&host->lock, flags); | 896 | spin_lock_irqsave(&host->lock, flags); |
| 900 | 897 | ||
| 898 | msmsdcc_enable_clocks(host); | ||
| 899 | |||
| 901 | if (ios->clock) { | 900 | if (ios->clock) { |
| 902 | if (ios->clock != host->clk_rate) { | 901 | if (ios->clock != host->clk_rate) { |
| 903 | rc = clk_set_rate(host->clk, ios->clock); | 902 | rc = clk_set_rate(host->clk, ios->clock); |
| @@ -1026,13 +1025,9 @@ static void | |||
| 1026 | msmsdcc_busclk_expired(unsigned long _data) | 1025 | msmsdcc_busclk_expired(unsigned long _data) |
| 1027 | { | 1026 | { |
| 1028 | struct msmsdcc_host *host = (struct msmsdcc_host *) _data; | 1027 | struct msmsdcc_host *host = (struct msmsdcc_host *) _data; |
| 1029 | unsigned long flags; | ||
| 1030 | 1028 | ||
| 1031 | spin_lock_irqsave(&host->lock, flags); | ||
| 1032 | dev_info(mmc_dev(host->mmc), "Bus clock timer expired\n"); | ||
| 1033 | if (host->clks_on) | 1029 | if (host->clks_on) |
| 1034 | msmsdcc_disable_clocks(host, 0); | 1030 | msmsdcc_disable_clocks(host, 0); |
| 1035 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 1036 | } | 1031 | } |
| 1037 | 1032 | ||
| 1038 | static int | 1033 | static int |
| @@ -1324,10 +1319,8 @@ msmsdcc_suspend(struct platform_device *dev, pm_message_t state) | |||
| 1324 | 1319 | ||
| 1325 | if (mmc->card && mmc->card->type != MMC_TYPE_SDIO) | 1320 | if (mmc->card && mmc->card->type != MMC_TYPE_SDIO) |
| 1326 | rc = mmc_suspend_host(mmc, state); | 1321 | rc = mmc_suspend_host(mmc, state); |
| 1327 | if (!rc) { | 1322 | if (!rc) |
| 1328 | msmsdcc_writel(host, 0, MMCIMASK0); | 1323 | msmsdcc_writel(host, 0, MMCIMASK0); |
| 1329 | |||
| 1330 | } | ||
| 1331 | if (host->clks_on) | 1324 | if (host->clks_on) |
| 1332 | msmsdcc_disable_clocks(host, 0); | 1325 | msmsdcc_disable_clocks(host, 0); |
| 1333 | } | 1326 | } |
