aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorSan Mehat <san@google.com>2009-11-08 16:00:37 -0500
committerDaniel Walker <dwalker@codeaurora.org>2010-03-18 15:57:46 -0400
commit4adbbcc7b6cfb3dcf5ab49b06edb7752391b0e80 (patch)
treeeeb534208a0f77994594dfe0738c85d8ef8c27fa /drivers/mmc
parent5b8a2fb34f5670b1f07483bfa40de9ce539dbdb2 (diff)
mmc: msm_sdcc: Clean up clock management and add a 10us delay after enabling clocks
It appears that in some cases there may be a delay on the ARM9 in enabling our clock. As a result, we may put the controller into a bad state. Delay 10us after enabling clocks to let the peripheral settle. Note - this is all imperical. Also ensure set_ios() callback grabs the host lock. Signed-off-by: San Mehat <san@google.com> Signed-off-by: Daniel Walker <dwalker@codeaurora.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/msm_sdcc.c80
1 files changed, 40 insertions, 40 deletions
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 4c068e5fe6b2..977932a4bf4b 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -735,20 +735,42 @@ msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
735 spin_unlock_irqrestore(&host->lock, flags); 735 spin_unlock_irqrestore(&host->lock, flags);
736} 736}
737 737
738static int inline
739msmsdcc_enable_clocks(struct msmsdcc_host *host, int enable)
740{
741 int rc;
742 if (enable) {
743 rc = clk_enable(host->pclk);
744 if (rc)
745 return rc;
746 rc = clk_enable(host->clk);
747 if (rc) {
748 clk_disable(host->pclk);
749 return rc;
750 }
751 host->clks_on = 1;
752 udelay(10);
753 } else {
754 clk_disable(host->clk);
755 clk_disable(host->pclk);
756 host->clks_on = 0;
757 }
758 return 0;
759}
760
738static void 761static void
739msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 762msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
740{ 763{
741 struct msmsdcc_host *host = mmc_priv(mmc); 764 struct msmsdcc_host *host = mmc_priv(mmc);
742 u32 clk = 0, pwr = 0; 765 u32 clk = 0, pwr = 0;
743 int rc; 766 int rc;
767 unsigned long flags;
744 768
769 spin_lock_irqsave(&host->lock, flags);
745 if (ios->clock) { 770 if (ios->clock) {
746 771
747 if (!host->clks_on) { 772 if (!host->clks_on)
748 clk_enable(host->pclk); 773 msmsdcc_enable_clocks(host, 1);
749 clk_enable(host->clk);
750 host->clks_on = 1;
751 }
752 if (ios->clock != host->clk_rate) { 774 if (ios->clock != host->clk_rate) {
753 rc = clk_set_rate(host->clk, ios->clock); 775 rc = clk_set_rate(host->clk, ios->clock);
754 if (rc < 0) 776 if (rc < 0)
@@ -793,11 +815,9 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
793 writel(pwr, host->base + MMCIPOWER); 815 writel(pwr, host->base + MMCIPOWER);
794 } 816 }
795 817
796 if (!(clk & MCI_CLK_ENABLE) && host->clks_on) { 818 if (!(clk & MCI_CLK_ENABLE) && host->clks_on)
797 clk_disable(host->clk); 819 msmsdcc_enable_clocks(host, 0);
798 clk_disable(host->pclk); 820 spin_unlock_irqrestore(&host->lock, flags);
799 host->clks_on = 0;
800 }
801} 821}
802 822
803static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable) 823static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
@@ -899,7 +919,6 @@ msmsdcc_command_expired(unsigned long _data)
899 pr_err("%s: Command timeout (%p %p %p %p)\n", 919 pr_err("%s: Command timeout (%p %p %p %p)\n",
900 mmc_hostname(host->mmc), mrq, mrq->cmd, 920 mmc_hostname(host->mmc), mrq, mrq->cmd,
901 mrq->data, host->dma.sg); 921 mrq->data, host->dma.sg);
902
903 mrq->cmd->error = -ETIMEDOUT; 922 mrq->cmd->error = -ETIMEDOUT;
904 msmsdcc_stop_data(host); 923 msmsdcc_stop_data(host);
905 924
@@ -1031,31 +1050,21 @@ msmsdcc_probe(struct platform_device *pdev)
1031 */ 1050 */
1032 msmsdcc_init_dma(host); 1051 msmsdcc_init_dma(host);
1033 1052
1034 /* 1053 /* Get our clocks */
1035 * Setup main peripheral bus clock
1036 */
1037 host->pclk = clk_get(&pdev->dev, "sdc_pclk"); 1054 host->pclk = clk_get(&pdev->dev, "sdc_pclk");
1038 if (IS_ERR(host->pclk)) { 1055 if (IS_ERR(host->pclk)) {
1039 ret = PTR_ERR(host->pclk); 1056 ret = PTR_ERR(host->pclk);
1040 goto host_free; 1057 goto host_free;
1041 } 1058 }
1042 1059
1043 ret = clk_enable(host->pclk);
1044 if (ret)
1045 goto pclk_put;
1046
1047 host->pclk_rate = clk_get_rate(host->pclk);
1048
1049 /*
1050 * Setup SDC MMC clock
1051 */
1052 host->clk = clk_get(&pdev->dev, "sdc_clk"); 1060 host->clk = clk_get(&pdev->dev, "sdc_clk");
1053 if (IS_ERR(host->clk)) { 1061 if (IS_ERR(host->clk)) {
1054 ret = PTR_ERR(host->clk); 1062 ret = PTR_ERR(host->clk);
1055 goto pclk_disable; 1063 goto pclk_put;
1056 } 1064 }
1057 1065
1058 ret = clk_enable(host->clk); 1066 /* Enable clocks */
1067 ret = msmsdcc_enable_clocks(host, 1);
1059 if (ret) 1068 if (ret)
1060 goto clk_put; 1069 goto clk_put;
1061 1070
@@ -1065,10 +1074,9 @@ msmsdcc_probe(struct platform_device *pdev)
1065 goto clk_disable; 1074 goto clk_disable;
1066 } 1075 }
1067 1076
1077 host->pclk_rate = clk_get_rate(host->pclk);
1068 host->clk_rate = clk_get_rate(host->clk); 1078 host->clk_rate = clk_get_rate(host->clk);
1069 1079
1070 host->clks_on = 1;
1071
1072 /* 1080 /*
1073 * Setup MMC host structure 1081 * Setup MMC host structure
1074 */ 1082 */
@@ -1187,11 +1195,9 @@ msmsdcc_probe(struct platform_device *pdev)
1187 if (host->stat_irq) 1195 if (host->stat_irq)
1188 free_irq(host->stat_irq, host); 1196 free_irq(host->stat_irq, host);
1189 clk_disable: 1197 clk_disable:
1190 clk_disable(host->clk); 1198 msmsdcc_enable_clocks(host, 0);
1191 clk_put: 1199 clk_put:
1192 clk_put(host->clk); 1200 clk_put(host->clk);
1193 pclk_disable:
1194 clk_disable(host->pclk);
1195 pclk_put: 1201 pclk_put:
1196 clk_put(host->pclk); 1202 clk_put(host->pclk);
1197 host_free: 1203 host_free:
@@ -1217,11 +1223,8 @@ msmsdcc_suspend(struct platform_device *dev, pm_message_t state)
1217 if (!rc) { 1223 if (!rc) {
1218 writel(0, host->base + MMCIMASK0); 1224 writel(0, host->base + MMCIMASK0);
1219 1225
1220 if (host->clks_on) { 1226 if (host->clks_on)
1221 clk_disable(host->clk); 1227 msmsdcc_enable_clocks(host, 0);
1222 clk_disable(host->pclk);
1223 host->clks_on = 0;
1224 }
1225 } 1228 }
1226 } 1229 }
1227 return rc; 1230 return rc;
@@ -1238,11 +1241,8 @@ msmsdcc_resume(struct platform_device *dev)
1238 1241
1239 spin_lock_irqsave(&host->lock, flags); 1242 spin_lock_irqsave(&host->lock, flags);
1240 1243
1241 if (!host->clks_on) { 1244 if (!host->clks_on)
1242 clk_enable(host->pclk); 1245 msmsdcc_enable_clocks(host, 1);
1243 clk_enable(host->clk);
1244 host->clks_on = 1;
1245 }
1246 1246
1247 writel(host->saved_irq0mask, host->base + MMCIMASK0); 1247 writel(host->saved_irq0mask, host->base + MMCIMASK0);
1248 1248