1 From 9e7ba57b104e9293f746342b7450b10d5fa0c4cd Mon Sep 17 00:00:00 2001
2 From: Andy Green <andy@openmoko.com>
3 Date: Mon, 22 Sep 2008 22:38:03 +0100
4 Subject: [PATCH] fix-glamo-mci-slow-clock-until-first-bulk.patch
6 This patch adds another module parameter to glamo-mci which sets the
7 SD Card clock rate used inbetween powering the card and the completion of
8 the first bulk transfer. You can set it from kernel commandline like this.
10 glamo_mci.sd_post_power_clock=1000000
12 The period between changing the power state and the first bulk transfer
13 completion is critical because larger SDHC cards take longer to initialize
14 before they can service the bulk transfer, and the Glamo MMC unit has a
15 fixed timeout length of a maximum of 4095 x 16 x SD Card clocks. Large
16 cards like 8GB Sandisk SDHC are not ready before this timeout is used up
19 Subsequently, the card can handle 16MHz SD Clock and timeout durations
22 By default this patch operates the SD Clock at only 1MHz until the first
23 bulk transfer is completed after each powerup action from the MCI stack. It
24 also keeps the SD Clock running during this time, and disables the SD Clock
25 if the card is not present and the MCI stack removes power.
27 Signed-off-by: Andy Green <andy@openmoko.com>
29 drivers/mfd/glamo/glamo-mci.c | 108 +++++++++++++++++++++++++----------------
30 drivers/mfd/glamo/glamo-mci.h | 2 +
31 2 files changed, 68 insertions(+), 42 deletions(-)
33 diff --git a/drivers/mfd/glamo/glamo-mci.c b/drivers/mfd/glamo/glamo-mci.c
34 index 3eece08..cff43db 100644
35 --- a/drivers/mfd/glamo/glamo-mci.c
36 +++ b/drivers/mfd/glamo/glamo-mci.c
37 @@ -74,6 +74,23 @@ static int sd_slow_ratio = 8;
38 module_param(sd_slow_ratio, int, 0644);
41 + * Post-power SD clock rate
43 + * you can override this on kernel commandline using
45 + * glamo_mci.sd_post_power_clock=1000000
49 + * After changing power to card, clock is held at this rate until first bulk
50 + * transfer completes
53 +static int sd_post_power_clock = 1000000;
54 +module_param(sd_post_power_clock, int, 0644);
58 * SD Signal drive strength
60 * you can override this on kernel commandline using
61 @@ -240,21 +257,35 @@ static void __glamo_mci_fix_card_div(struct glamo_mci_host *host, int div)
62 writew(readw(glamo_mci_def_pdata.pglamo->base +
63 GLAMO_REG_CLOCK_GEN5_1) & (~GLAMO_CLOCK_GEN51_EN_DIV_TCLK),
64 glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1);
66 - /* set the nearest prescaler factor
68 - * register shared with SCLK divisor -- no chance of race because
69 - * we don't use sensor interface
71 - writew_dly((readw(glamo_mci_def_pdata.pglamo->base +
72 - GLAMO_REG_CLOCK_GEN8) & 0xff00) | div,
73 - glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN8);
74 - /* enable clock to divider input */
75 - writew_dly(readw(glamo_mci_def_pdata.pglamo->base +
76 - GLAMO_REG_CLOCK_GEN5_1) | GLAMO_CLOCK_GEN51_EN_DIV_TCLK,
77 - glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1);
82 + if (host->force_slow_during_powerup)
83 + div = host->clk_rate / sd_post_power_clock;
85 + if (host->pdata->glamo_mci_use_slow)
86 + if ((host->pdata->glamo_mci_use_slow)())
87 + div = div * sd_slow_ratio;
93 + * set the nearest prescaler factor
95 + * register shared with SCLK divisor -- no chance of race because
96 + * we don't use sensor interface
98 + writew_dly((readw(glamo_mci_def_pdata.pglamo->base +
99 + GLAMO_REG_CLOCK_GEN8) & 0xff00) | div,
100 + glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN8);
101 + /* enable clock to divider input */
102 + writew_dly(readw(glamo_mci_def_pdata.pglamo->base +
103 + GLAMO_REG_CLOCK_GEN5_1) | GLAMO_CLOCK_GEN51_EN_DIV_TCLK,
104 + glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1);
107 spin_unlock_irqrestore(&clock_lock, flags);
110 @@ -284,7 +315,7 @@ static int __glamo_mci_set_card_clock(struct glamo_mci_host *host, int freq,
115 + if (!sd_idleclk && !host->force_slow_during_powerup)
117 __glamo_mci_fix_card_div(host, -1);
119 @@ -327,6 +358,10 @@ static void glamo_mci_irq(unsigned int irq, struct irq_desc *desc)
123 + /* disable the initial slow start after first bulk transfer */
124 + if (host->force_slow_during_powerup)
125 + host->force_slow_during_powerup--;
127 if (host->pio_active == XFER_READ)
130 @@ -341,7 +376,7 @@ static void glamo_mci_irq(unsigned int irq, struct irq_desc *desc)
131 host->cmd_is_stop = 0;
135 + if (!sd_idleclk && !host->force_slow_during_powerup)
137 __glamo_mci_fix_card_div(host, -1);
139 @@ -357,7 +392,6 @@ static int glamo_mci_send_command(struct glamo_mci_host *host,
143 - u16 timeout = 0xfff; /* max glamo MMC timeout, in units of 16 clocks */
145 /* if we can't do it, reject as busy */
146 if (!readw_dly(host->base + GLAMO_REG_MMC_RB_STAT1) &
147 @@ -467,15 +501,9 @@ static int glamo_mci_send_command(struct glamo_mci_host *host,
148 fire |= GLAMO_FIRE_MMC_CC_BASIC; /* "basic command" */
151 - /* enforce timeout, clipping at default 65520 clocks if larger */
153 - /* so long as there is one... */
154 - if (cmd->data->timeout_clks &&
155 - /* ... and it is not longer than we can handle */
156 - (cmd->data->timeout_clks <= 0xffff))
157 - timeout = cmd->data->timeout_clks >> 4; /* / 16 clks */
159 - writew(timeout, host->base + GLAMO_REG_MMC_TIMEOUT);
160 + /* always largest timeout */
161 + writew(0xfff, host->base + GLAMO_REG_MMC_TIMEOUT);
163 /* Generate interrupt on txfer */
164 writew_dly((readw_dly(host->base + GLAMO_REG_MMC_BASIC) & 0x3e) |
165 @@ -576,14 +604,7 @@ static void glamo_mci_send_request(struct mmc_host *mmc)
166 /* resume requested clock rate
167 * scale it down by sd_slow_ratio if platform requests it
169 - if (host->pdata->glamo_mci_use_slow)
170 - if ((host->pdata->glamo_mci_use_slow)())
171 - __glamo_mci_fix_card_div(host, host->clk_div *
174 - __glamo_mci_fix_card_div(host, host->clk_div);
176 - __glamo_mci_fix_card_div(host, host->clk_div);
177 + __glamo_mci_fix_card_div(host, host->clk_div);
179 if (glamo_mci_send_command(host, cmd))
181 @@ -633,6 +654,7 @@ static void glamo_mci_send_request(struct mmc_host *mmc)
183 if (!(cmd->data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)))
187 * Otherwise can can use the interrupt as async completion --
188 * if there is read data coming, or we wait for write data to complete,
189 @@ -676,7 +698,7 @@ done:
191 mmc_request_done(host->mmc, cmd->mrq);
194 + if (!sd_idleclk && !host->force_slow_during_powerup)
195 /* stop the clock to card */
196 __glamo_mci_fix_card_div(host, -1);
198 @@ -718,6 +740,12 @@ static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
199 switch(ios->power_mode) {
203 + * we should use very slow clock until first bulk
204 + * transfer completes OK
206 + host->force_slow_during_powerup = 1;
208 if (host->vdd_current != ios->vdd) {
209 host->pdata->glamo_set_mci_power(ios->power_mode,
211 @@ -734,6 +762,9 @@ static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
213 if (host->power_mode_current == MMC_POWER_OFF)
215 + /* never want clocking with dead card */
216 + __glamo_mci_fix_card_div(host, -1);
218 glamo_engine_disable(glamo_mci_def_pdata.pglamo,
220 host->pdata->glamo_set_mci_power(MMC_POWER_OFF, 0);
221 @@ -751,7 +782,7 @@ static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
226 + if (!sd_idleclk && !host->force_slow_during_powerup)
227 /* stop the clock to card, because we are idle until transfer */
228 __glamo_mci_fix_card_div(host, -1);
230 @@ -954,14 +985,7 @@ static int glamo_mci_suspend(struct platform_device *dev, pm_message_t state)
231 * make sure the clock was running during suspend and consequently
234 - if (host->pdata->glamo_mci_use_slow)
235 - if ((host->pdata->glamo_mci_use_slow)())
236 - __glamo_mci_fix_card_div(host, host->clk_div *
239 - __glamo_mci_fix_card_div(host, host->clk_div);
241 - __glamo_mci_fix_card_div(host, host->clk_div);
242 + __glamo_mci_fix_card_div(host, host->clk_div);
244 /* we are going to do more commands to override this in
245 * mmc_suspend_host(), so we need to change sd_idleclk for the
246 diff --git a/drivers/mfd/glamo/glamo-mci.h b/drivers/mfd/glamo/glamo-mci.h
247 index f3f170e..38f6376 100644
248 --- a/drivers/mfd/glamo/glamo-mci.h
249 +++ b/drivers/mfd/glamo/glamo-mci.h
250 @@ -44,6 +44,8 @@ struct glamo_mci_host {
251 unsigned long real_rate;
254 + int force_slow_during_powerup;