aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorSan Mehat <san@google.com>2009-11-13 16:42:06 -0500
committerDaniel Walker <dwalker@codeaurora.org>2010-03-18 16:15:05 -0400
commit865c8064a2fb07100525097983966b8e789bde1a (patch)
tree986ccc9240af2343e4d12084217d1b8fcd6cdf6f /drivers/mmc
parent5b00f40f90e7b17c11cf388680f43e8466b3666d (diff)
mmc: msm_sdcc: Driver clocking/irq improvements
- Clocks are now disabled after 1 second of inactivity - Fixed issue which was causing us to loop through our ISR twice - Bump core clock enable delay to 30us 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.c89
-rw-r--r--drivers/mmc/host/msm_sdcc.h2
2 files changed, 63 insertions, 28 deletions
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 02bec7c739e0..b4b637223b75 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -57,6 +57,32 @@ static unsigned int msmsdcc_sdioirq;
57#define PIO_SPINMAX 30 57#define PIO_SPINMAX 30
58#define CMD_SPINMAX 20 58#define CMD_SPINMAX 20
59 59
60
61static inline int
62msmsdcc_enable_clocks(struct msmsdcc_host *host, int enable)
63{
64 int rc;
65 WARN_ON(enable == host->clks_on);
66 if (enable) {
67 rc = clk_enable(host->pclk);
68 if (rc)
69 return rc;
70 rc = clk_enable(host->clk);
71 if (rc) {
72 clk_disable(host->pclk);
73 return rc;
74 }
75 udelay(30);
76 host->clks_on = 1;
77 } else {
78 clk_disable(host->clk);
79 clk_disable(host->pclk);
80 host->clks_on = 0;
81 }
82 return 0;
83}
84
85
60static void 86static void
61msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, 87msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd,
62 u32 c); 88 u32 c);
@@ -76,6 +102,8 @@ msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq)
76 if (mrq->cmd->error == -ETIMEDOUT) 102 if (mrq->cmd->error == -ETIMEDOUT)
77 mdelay(5); 103 mdelay(5);
78 104
105 if (host->use_bustimer)
106 mod_timer(&host->busclk_timer, jiffies + HZ);
79 /* 107 /*
80 * Need to drop the host lock here; mmc_request_done may call 108 * Need to drop the host lock here; mmc_request_done may call
81 * back into the driver... 109 * back into the driver...
@@ -676,6 +704,12 @@ msmsdcc_irq(int irq, void *dev_id)
676 status &= (readl(base + MMCIMASK0) | MCI_DATABLOCKENDMASK); 704 status &= (readl(base + MMCIMASK0) | MCI_DATABLOCKENDMASK);
677 writel(status, base + MMCICLEAR); 705 writel(status, base + MMCICLEAR);
678 706
707 if (status & MCI_SDIOINTR)
708 status &= ~MCI_SDIOINTR;
709
710 if (!status)
711 break;
712
679 msmsdcc_handle_irq_data(host, status, base); 713 msmsdcc_handle_irq_data(host, status, base);
680 714
681 if (status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL | 715 if (status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL |
@@ -729,6 +763,8 @@ msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
729 } 763 }
730 764
731 host->curr.mrq = mrq; 765 host->curr.mrq = mrq;
766 if (!host->clks_on)
767 msmsdcc_enable_clocks(host, 1);
732 768
733 if (mrq->data && mrq->data->flags & MMC_DATA_READ) 769 if (mrq->data && mrq->data->flags & MMC_DATA_READ)
734 msmsdcc_start_data(host, mrq->data); 770 msmsdcc_start_data(host, mrq->data);
@@ -750,29 +786,6 @@ msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
750 spin_unlock_irqrestore(&host->lock, flags); 786 spin_unlock_irqrestore(&host->lock, flags);
751} 787}
752 788
753static int inline
754msmsdcc_enable_clocks(struct msmsdcc_host *host, int enable)
755{
756 int rc;
757 if (enable) {
758 rc = clk_enable(host->pclk);
759 if (rc)
760 return rc;
761 rc = clk_enable(host->clk);
762 if (rc) {
763 clk_disable(host->pclk);
764 return rc;
765 }
766 host->clks_on = 1;
767 udelay(10);
768 } else {
769 clk_disable(host->clk);
770 clk_disable(host->pclk);
771 host->clks_on = 0;
772 }
773 return 0;
774}
775
776static void 789static void
777msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 790msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
778{ 791{
@@ -782,10 +795,10 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
782 unsigned long flags; 795 unsigned long flags;
783 796
784 spin_lock_irqsave(&host->lock, flags); 797 spin_lock_irqsave(&host->lock, flags);
785 if (ios->clock) { 798 if (!host->clks_on)
799 msmsdcc_enable_clocks(host, 1);
786 800
787 if (!host->clks_on) 801 if (ios->clock) {
788 msmsdcc_enable_clocks(host, 1);
789 if (ios->clock != host->clk_rate) { 802 if (ios->clock != host->clk_rate) {
790 rc = clk_set_rate(host->clk, ios->clock); 803 rc = clk_set_rate(host->clk, ios->clock);
791 if (rc < 0) 804 if (rc < 0)
@@ -829,8 +842,7 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
829 host->pwr = pwr; 842 host->pwr = pwr;
830 writel(pwr, host->base + MMCIPOWER); 843 writel(pwr, host->base + MMCIPOWER);
831 } 844 }
832 845 if (host->clks_on)
833 if (!(clk & MCI_CLK_ENABLE) && host->clks_on)
834 msmsdcc_enable_clocks(host, 0); 846 msmsdcc_enable_clocks(host, 0);
835 spin_unlock_irqrestore(&host->lock, flags); 847 spin_unlock_irqrestore(&host->lock, flags);
836} 848}
@@ -909,6 +921,19 @@ msmsdcc_status_notify_cb(int card_present, void *dev_id)
909 msmsdcc_check_status((unsigned long) host); 921 msmsdcc_check_status((unsigned long) host);
910} 922}
911 923
924static void
925msmsdcc_busclk_expired(unsigned long _data)
926{
927 struct msmsdcc_host *host = (struct msmsdcc_host *) _data;
928 unsigned long flags;
929
930 spin_lock_irqsave(&host->lock, flags);
931 if (host->clks_on)
932 msmsdcc_enable_clocks(host, 0);
933
934 spin_unlock_irqrestore(&host->lock, flags);
935}
936
912/* 937/*
913 * called when a command expires. 938 * called when a command expires.
914 * Dump some debugging, and then error 939 * Dump some debugging, and then error
@@ -942,6 +967,8 @@ msmsdcc_command_expired(unsigned long _data)
942 host->curr.mrq = NULL; 967 host->curr.mrq = NULL;
943 host->curr.cmd = NULL; 968 host->curr.cmd = NULL;
944 969
970 if (host->clks_on)
971 msmsdcc_enable_clocks(host, 0);
945 spin_unlock_irqrestore(&host->lock, flags); 972 spin_unlock_irqrestore(&host->lock, flags);
946 mmc_request_done(host->mmc, mrq); 973 mmc_request_done(host->mmc, mrq);
947} 974}
@@ -1048,6 +1075,8 @@ msmsdcc_probe(struct platform_device *pdev)
1048 1075
1049 host->cmdpoll = 1; 1076 host->cmdpoll = 1;
1050 1077
1078 host->use_bustimer = 1;
1079
1051 host->base = ioremap(memres->start, PAGE_SIZE); 1080 host->base = ioremap(memres->start, PAGE_SIZE);
1052 if (!host->base) { 1081 if (!host->base) {
1053 ret = -ENOMEM; 1082 ret = -ENOMEM;
@@ -1167,6 +1196,10 @@ msmsdcc_probe(struct platform_device *pdev)
1167 host->command_timer.data = (unsigned long) host; 1196 host->command_timer.data = (unsigned long) host;
1168 host->command_timer.function = msmsdcc_command_expired; 1197 host->command_timer.function = msmsdcc_command_expired;
1169 1198
1199 init_timer(&host->busclk_timer);
1200 host->busclk_timer.data = (unsigned long) host;
1201 host->busclk_timer.function = msmsdcc_busclk_expired;
1202
1170 ret = request_irq(cmd_irqres->start, msmsdcc_irq, IRQF_SHARED, 1203 ret = request_irq(cmd_irqres->start, msmsdcc_irq, IRQF_SHARED,
1171 DRIVER_NAME " (cmd)", host); 1204 DRIVER_NAME " (cmd)", host);
1172 if (ret) 1205 if (ret)
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 8c8448469811..6846bd7dff22 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -214,6 +214,8 @@ struct msmsdcc_host {
214 struct clk *pclk; /* SDCC peripheral bus clock */ 214 struct clk *pclk; /* SDCC peripheral bus clock */
215 unsigned int clks_on; /* set if clocks are enabled */ 215 unsigned int clks_on; /* set if clocks are enabled */
216 struct timer_list command_timer; 216 struct timer_list command_timer;
217 struct timer_list busclk_timer;
218 int use_bustimer;
217 219
218 unsigned int eject; /* eject state */ 220 unsigned int eject; /* eject state */
219 221