spi-gpio: Implement spidelay for busses that need it.
[openwrt.git] / target / linux / s3c24xx / patches-2.6.24 / 1292-fix-glamo-mci-slow-clock-until-first-bulk.patch.patch
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
5
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.
9
10 glamo_mci.sd_post_power_clock=1000000
11
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
17 at default 16MHz.
18
19 Subsequently, the card can handle 16MHz SD Clock and timeout durations
20 okay.
21
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.
26
27 Signed-off-by: Andy Green <andy@openmoko.com>
28 ---
29 drivers/mfd/glamo/glamo-mci.c | 108 +++++++++++++++++++++++++----------------
30 drivers/mfd/glamo/glamo-mci.h | 2 +
31 2 files changed, 68 insertions(+), 42 deletions(-)
32
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);
39
40 /*
41 + * Post-power SD clock rate
42 + *
43 + * you can override this on kernel commandline using
44 + *
45 + * glamo_mci.sd_post_power_clock=1000000
46 + *
47 + * for example
48 + *
49 + * After changing power to card, clock is held at this rate until first bulk
50 + * transfer completes
51 + */
52 +
53 +static int sd_post_power_clock = 1000000;
54 +module_param(sd_post_power_clock, int, 0644);
55 +
56 +
57 +/*
58 * SD Signal drive strength
59 *
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);
65 - } else {
66 - /* set the nearest prescaler factor
67 - *
68 - * register shared with SCLK divisor -- no chance of race because
69 - * we don't use sensor interface
70 - */
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);
78 +
79 + goto done;
80 }
81
82 + if (host->force_slow_during_powerup)
83 + div = host->clk_rate / sd_post_power_clock;
84 + else
85 + if (host->pdata->glamo_mci_use_slow)
86 + if ((host->pdata->glamo_mci_use_slow)())
87 + div = div * sd_slow_ratio;
88 +
89 + if (div > 255)
90 + div = 255;
91 +
92 + /*
93 + * set the nearest prescaler factor
94 + *
95 + * register shared with SCLK divisor -- no chance of race because
96 + * we don't use sensor interface
97 + */
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);
105 +
106 +done:
107 spin_unlock_irqrestore(&clock_lock, flags);
108 }
109
110 @@ -284,7 +315,7 @@ static int __glamo_mci_set_card_clock(struct glamo_mci_host *host, int freq,
111 if (division)
112 *division = 0xff;
113
114 - if (!sd_idleclk)
115 + if (!sd_idleclk && !host->force_slow_during_powerup)
116 /* clock off */
117 __glamo_mci_fix_card_div(host, -1);
118 }
119 @@ -327,6 +358,10 @@ static void glamo_mci_irq(unsigned int irq, struct irq_desc *desc)
120 goto done;
121 }
122
123 + /* disable the initial slow start after first bulk transfer */
124 + if (host->force_slow_during_powerup)
125 + host->force_slow_during_powerup--;
126 +
127 if (host->pio_active == XFER_READ)
128 do_pio_read(host);
129
130 @@ -341,7 +376,7 @@ static void glamo_mci_irq(unsigned int irq, struct irq_desc *desc)
131 host->cmd_is_stop = 0;
132 }
133
134 - if (!sd_idleclk)
135 + if (!sd_idleclk && !host->force_slow_during_powerup)
136 /* clock off */
137 __glamo_mci_fix_card_div(host, -1);
138
139 @@ -357,7 +392,6 @@ static int glamo_mci_send_command(struct glamo_mci_host *host,
140 {
141 u8 u8a[6];
142 u16 fire = 0;
143 - u16 timeout = 0xfff; /* max glamo MMC timeout, in units of 16 clocks */
144
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" */
149 break;
150 }
151 - /* enforce timeout, clipping at default 65520 clocks if larger */
152 - if (cmd->data)
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 */
158
159 - writew(timeout, host->base + GLAMO_REG_MMC_TIMEOUT);
160 + /* always largest timeout */
161 + writew(0xfff, host->base + GLAMO_REG_MMC_TIMEOUT);
162
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
168 */
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 *
172 - sd_slow_ratio);
173 - else
174 - __glamo_mci_fix_card_div(host, host->clk_div);
175 - else
176 - __glamo_mci_fix_card_div(host, host->clk_div);
177 + __glamo_mci_fix_card_div(host, host->clk_div);
178
179 if (glamo_mci_send_command(host, cmd))
180 goto bail;
181 @@ -633,6 +654,7 @@ static void glamo_mci_send_request(struct mmc_host *mmc)
182 goto done;
183 if (!(cmd->data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)))
184 goto done;
185 +
186 /*
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:
190 host->mrq = NULL;
191 mmc_request_done(host->mmc, cmd->mrq);
192 bail:
193 - if (!sd_idleclk)
194 + if (!sd_idleclk && !host->force_slow_during_powerup)
195 /* stop the clock to card */
196 __glamo_mci_fix_card_div(host, -1);
197 }
198 @@ -718,6 +740,12 @@ static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
199 switch(ios->power_mode) {
200 case MMC_POWER_ON:
201 case MMC_POWER_UP:
202 + /*
203 + * we should use very slow clock until first bulk
204 + * transfer completes OK
205 + */
206 + host->force_slow_during_powerup = 1;
207 +
208 if (host->vdd_current != ios->vdd) {
209 host->pdata->glamo_set_mci_power(ios->power_mode,
210 ios->vdd);
211 @@ -734,6 +762,9 @@ static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
212 default:
213 if (host->power_mode_current == MMC_POWER_OFF)
214 break;
215 + /* never want clocking with dead card */
216 + __glamo_mci_fix_card_div(host, -1);
217 +
218 glamo_engine_disable(glamo_mci_def_pdata.pglamo,
219 GLAMO_ENGINE_MMC);
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)
222 if (powering)
223 msleep(1);
224
225 - if (!sd_idleclk)
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);
229
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
232 * resume
233 */
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 *
237 - sd_slow_ratio);
238 - else
239 - __glamo_mci_fix_card_div(host, host->clk_div);
240 - else
241 - __glamo_mci_fix_card_div(host, host->clk_div);
242 + __glamo_mci_fix_card_div(host, host->clk_div);
243
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;
252 u8 prescaler;
253
254 + int force_slow_during_powerup;
255 +
256 unsigned sdiimsk;
257 int dodma;
258
259 --
260 1.5.6.5
261
This page took 0.068938 seconds and 5 git commands to generate.