summaryrefslogtreecommitdiffstats
path: root/target/linux/s3c24xx/patches-2.6.24/1292-fix-glamo-mci-slow-clock-until-first-bulk.patch.patch
blob: 642f5454ee105773df3415f3c7a7e49dd4cfd7d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
From 9e7ba57b104e9293f746342b7450b10d5fa0c4cd Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Mon, 22 Sep 2008 22:38:03 +0100
Subject: [PATCH] fix-glamo-mci-slow-clock-until-first-bulk.patch

This patch adds another module parameter to glamo-mci which sets the
SD Card clock rate used inbetween powering the card and the completion of
the first bulk transfer.  You can set it from kernel commandline like this.

glamo_mci.sd_post_power_clock=1000000

The period between changing the power state and the first bulk transfer
completion is critical because larger SDHC cards take longer to initialize
before they can service the bulk transfer, and the Glamo MMC unit has a
fixed timeout length of a maximum of 4095 x 16 x SD Card clocks.  Large
cards like 8GB Sandisk SDHC are not ready before this timeout is used up
at default 16MHz.

Subsequently, the card can handle 16MHz SD Clock and timeout durations
okay.

By default this patch operates the SD Clock at only 1MHz until the first
bulk transfer is completed after each powerup action from the MCI stack.  It
also keeps the SD Clock running during this time, and disables the SD Clock
if the card is not present and the MCI stack removes power.

Signed-off-by: Andy Green <andy@openmoko.com>
---
 drivers/mfd/glamo/glamo-mci.c |  108 +++++++++++++++++++++++++----------------
 drivers/mfd/glamo/glamo-mci.h |    2 +
 2 files changed, 68 insertions(+), 42 deletions(-)

diff --git a/drivers/mfd/glamo/glamo-mci.c b/drivers/mfd/glamo/glamo-mci.c
index 3eece08..cff43db 100644
--- a/drivers/mfd/glamo/glamo-mci.c
+++ b/drivers/mfd/glamo/glamo-mci.c
@@ -74,6 +74,23 @@ static int sd_slow_ratio = 8;
 module_param(sd_slow_ratio, int, 0644);
 
 /*
+ * Post-power SD clock rate
+ *
+ * you can override this on kernel commandline using
+ *
+ *   glamo_mci.sd_post_power_clock=1000000
+ *
+ * for example
+ *
+ * After changing power to card, clock is held at this rate until first bulk
+ * transfer completes
+ */
+
+static int sd_post_power_clock = 1000000;
+module_param(sd_post_power_clock, int, 0644);
+
+
+/*
  * SD Signal drive strength
  *
  * you can override this on kernel commandline using
@@ -240,21 +257,35 @@ static void __glamo_mci_fix_card_div(struct glamo_mci_host *host, int div)
 		writew(readw(glamo_mci_def_pdata.pglamo->base +
 		     GLAMO_REG_CLOCK_GEN5_1) & (~GLAMO_CLOCK_GEN51_EN_DIV_TCLK),
 		     glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1);
-	} else {
-		/* set the nearest prescaler factor
-		*
-		* register shared with SCLK divisor -- no chance of race because
-		* we don't use sensor interface
-		*/
-		writew_dly((readw(glamo_mci_def_pdata.pglamo->base +
-				GLAMO_REG_CLOCK_GEN8) & 0xff00) | div,
-		       glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN8);
-		/* enable clock to divider input */
-		writew_dly(readw(glamo_mci_def_pdata.pglamo->base +
-			GLAMO_REG_CLOCK_GEN5_1) | GLAMO_CLOCK_GEN51_EN_DIV_TCLK,
-		     glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1);
+
+		goto done;
 	}
 
+	if (host->force_slow_during_powerup)
+		div = host->clk_rate / sd_post_power_clock;
+	else
+		if (host->pdata->glamo_mci_use_slow)
+			if ((host->pdata->glamo_mci_use_slow)())
+				div = div * sd_slow_ratio;
+
+	if (div > 255)
+		div = 255;
+
+	/*
+	 * set the nearest prescaler factor
+	 *
+	 * register shared with SCLK divisor -- no chance of race because
+	 * we don't use sensor interface
+	 */
+	writew_dly((readw(glamo_mci_def_pdata.pglamo->base +
+			GLAMO_REG_CLOCK_GEN8) & 0xff00) | div,
+		glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN8);
+	/* enable clock to divider input */
+	writew_dly(readw(glamo_mci_def_pdata.pglamo->base +
+		GLAMO_REG_CLOCK_GEN5_1) | GLAMO_CLOCK_GEN51_EN_DIV_TCLK,
+		glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1);
+
+done:
 	spin_unlock_irqrestore(&clock_lock, flags);
 }
 
@@ -284,7 +315,7 @@ static int __glamo_mci_set_card_clock(struct glamo_mci_host *host, int freq,
 		if (division)
 			*division = 0xff;
 
-		if (!sd_idleclk)
+		if (!sd_idleclk && !host->force_slow_during_powerup)
 			/* clock off */
 			__glamo_mci_fix_card_div(host, -1);
 	}
@@ -327,6 +358,10 @@ static void glamo_mci_irq(unsigned int irq, struct irq_desc *desc)
 		goto done;
 	}
 
+	/* disable the initial slow start after first bulk transfer */
+	if (host->force_slow_during_powerup)
+		host->force_slow_during_powerup--;
+
 	if (host->pio_active == XFER_READ)
 		do_pio_read(host);
 
@@ -341,7 +376,7 @@ static void glamo_mci_irq(unsigned int irq, struct irq_desc *desc)
 		host->cmd_is_stop = 0;
 	}
 
-	if (!sd_idleclk)
+	if (!sd_idleclk && !host->force_slow_during_powerup)
 		/* clock off */
 		__glamo_mci_fix_card_div(host, -1);
 
@@ -357,7 +392,6 @@ static int glamo_mci_send_command(struct glamo_mci_host *host,
 {
 	u8 u8a[6];
 	u16 fire = 0;
-	u16 timeout = 0xfff; /* max glamo MMC timeout, in units of 16 clocks */
 
 	/* if we can't do it, reject as busy */
 	if (!readw_dly(host->base + GLAMO_REG_MMC_RB_STAT1) &
@@ -467,15 +501,9 @@ static int glamo_mci_send_command(struct glamo_mci_host *host,
 		fire |= GLAMO_FIRE_MMC_CC_BASIC; /* "basic command" */
 		break;
 	}
-	/* enforce timeout, clipping at default 65520 clocks if larger */
-	if (cmd->data)
-		/* so long as there is one... */
-		if (cmd->data->timeout_clks &&
-		    /* ... and it is not longer than we can handle */
-		    (cmd->data->timeout_clks <= 0xffff))
-			timeout = cmd->data->timeout_clks >> 4; /* / 16 clks */
 
-	writew(timeout, host->base + GLAMO_REG_MMC_TIMEOUT);
+	/* always largest timeout */
+	writew(0xfff, host->base + GLAMO_REG_MMC_TIMEOUT);
 
 	/* Generate interrupt on txfer */
 	writew_dly((readw_dly(host->base + GLAMO_REG_MMC_BASIC) & 0x3e) |
@@ -576,14 +604,7 @@ static void glamo_mci_send_request(struct mmc_host *mmc)
 	/* resume requested clock rate
 	 * scale it down by sd_slow_ratio if platform requests it
 	 */
-	if (host->pdata->glamo_mci_use_slow)
-		if ((host->pdata->glamo_mci_use_slow)())
-			__glamo_mci_fix_card_div(host, host->clk_div *
-								 sd_slow_ratio);
-		else
-			__glamo_mci_fix_card_div(host, host->clk_div);
-	else
-		__glamo_mci_fix_card_div(host, host->clk_div);
+	__glamo_mci_fix_card_div(host, host->clk_div);
 
 	if (glamo_mci_send_command(host, cmd))
 		goto bail;
@@ -633,6 +654,7 @@ static void glamo_mci_send_request(struct mmc_host *mmc)
 		goto done;
 	if (!(cmd->data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)))
 		goto done;
+
 	/*
 	 * Otherwise can can use the interrupt as async completion --
 	 * if there is read data coming, or we wait for write data to complete,
@@ -676,7 +698,7 @@ done:
 	host->mrq = NULL;
 	mmc_request_done(host->mmc, cmd->mrq);
 bail:
-	if (!sd_idleclk)
+	if (!sd_idleclk && !host->force_slow_during_powerup)
 		/* stop the clock to card */
 		__glamo_mci_fix_card_div(host, -1);
 }
@@ -718,6 +740,12 @@ static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	switch(ios->power_mode) {
 	case MMC_POWER_ON:
 	case MMC_POWER_UP:
+		/*
+		 * we should use very slow clock until first bulk
+		 * transfer completes OK
+		 */
+		host->force_slow_during_powerup = 1;
+
 		if (host->vdd_current != ios->vdd) {
 			host->pdata->glamo_set_mci_power(ios->power_mode,
 							 ios->vdd);
@@ -734,6 +762,9 @@ static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	default:
 		if (host->power_mode_current == MMC_POWER_OFF)
 			break;
+		/* never want clocking with dead card */
+		__glamo_mci_fix_card_div(host, -1);
+
 		glamo_engine_disable(glamo_mci_def_pdata.pglamo,
 				     GLAMO_ENGINE_MMC);
 		host->pdata->glamo_set_mci_power(MMC_POWER_OFF, 0);
@@ -751,7 +782,7 @@ static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	if (powering)
 		msleep(1);
 
-	if (!sd_idleclk)
+	if (!sd_idleclk && !host->force_slow_during_powerup)
 		/* stop the clock to card, because we are idle until transfer */
 		__glamo_mci_fix_card_div(host, -1);
 
@@ -954,14 +985,7 @@ static int glamo_mci_suspend(struct platform_device *dev, pm_message_t state)
 	 * make sure the clock was running during suspend and consequently
 	 * resume
 	 */
-	if (host->pdata->glamo_mci_use_slow)
-		if ((host->pdata->glamo_mci_use_slow)())
-			__glamo_mci_fix_card_div(host, host->clk_div *
-								 sd_slow_ratio);
-		else
-			__glamo_mci_fix_card_div(host, host->clk_div);
-	else
-		__glamo_mci_fix_card_div(host, host->clk_div);
+	__glamo_mci_fix_card_div(host, host->clk_div);
 
 	/* we are going to do more commands to override this in
 	 * mmc_suspend_host(), so we need to change sd_idleclk for the
diff --git a/drivers/mfd/glamo/glamo-mci.h b/drivers/mfd/glamo/glamo-mci.h
index f3f170e..38f6376 100644
--- a/drivers/mfd/glamo/glamo-mci.h
+++ b/drivers/mfd/glamo/glamo-mci.h
@@ -44,6 +44,8 @@ struct glamo_mci_host {
 	unsigned long		real_rate;
 	u8			prescaler;
 
+	int			force_slow_during_powerup;
+
 	unsigned		sdiimsk;
 	int			dodma;
 
-- 
1.5.6.5