brcm2708: update 3.10 patches with raspberrypi/rpi-3.10.y of 27 Apr. 2014
[openwrt/staging/blogic.git] / target / linux / brcm2708 / patches-3.10 / 0026-Add-low-latency-mode-to-sdcard-driver.-Disable-with-.patch
1 From 4ec6de1f59d1f0b5ed9cfebf3c1b4080d7215dc2 Mon Sep 17 00:00:00 2001
2 From: popcornmix <popcornmix@gmail.com>
3 Date: Sun, 12 May 2013 12:27:48 +0100
4 Subject: [PATCH 026/196] Add low-latency mode to sdcard driver. Disable with
5 sdhci-bcm2708.enable_llm=0. Thanks ddv2005.
6
7 ---
8 drivers/mmc/host/sdhci-bcm2708.c | 17 ++--
9 drivers/mmc/host/sdhci.c | 165 ++++++++++++++++++++++++++++++---------
10 drivers/mmc/host/sdhci.h | 6 ++
11 include/linux/mmc/sdhci.h | 1 +
12 4 files changed, 145 insertions(+), 44 deletions(-)
13
14 diff --git a/drivers/mmc/host/sdhci-bcm2708.c b/drivers/mmc/host/sdhci-bcm2708.c
15 index 7a703c2..7ce2829 100644
16 --- a/drivers/mmc/host/sdhci-bcm2708.c
17 +++ b/drivers/mmc/host/sdhci-bcm2708.c
18 @@ -135,6 +135,7 @@ static bool allow_highspeed = 1;
19 static int emmc_clock_freq = BCM2708_EMMC_CLOCK_FREQ;
20 static bool sync_after_dma = 1;
21 static bool missing_status = 1;
22 +bool enable_llm = 1;
23
24 #if 0
25 static void hptime_test(void)
26 @@ -871,12 +872,11 @@ static irqreturn_t sdhci_bcm2708_dma_irq(int irq, void *dev_id)
27 struct sdhci_host *host = dev_id;
28 struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host);
29 u32 dma_cs; /* control and status register */
30 - unsigned long flags;
31
32 BUG_ON(NULL == dev_id);
33 BUG_ON(NULL == host_priv->dma_chan_base);
34
35 - spin_lock_irqsave(&host->lock, flags);
36 + sdhci_spin_lock(host);
37
38 dma_cs = readl(host_priv->dma_chan_base + BCM2708_DMA_CS);
39
40 @@ -917,8 +917,7 @@ static irqreturn_t sdhci_bcm2708_dma_irq(int irq, void *dev_id)
41
42 result = IRQ_HANDLED;
43 }
44 -
45 - spin_unlock_irqrestore(&host->lock, flags);
46 + sdhci_spin_unlock(host);
47
48 return result;
49 }
50 @@ -1193,9 +1192,12 @@ static int sdhci_bcm2708_probe(struct platform_device *pdev)
51 sdhci_bcm2708_ops.missing_status = sdhci_bcm2708_missing_status;
52 }
53
54 + printk("sdhci: %s low-latency mode\n",enable_llm?"Enable":"Disable");
55 +
56 host->hw_name = "BCM2708_Arasan";
57 host->ops = &sdhci_bcm2708_ops;
58 host->irq = platform_get_irq(pdev, 0);
59 + host->second_irq = 0;
60
61 host->quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
62 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
63 @@ -1256,12 +1258,13 @@ static int sdhci_bcm2708_probe(struct platform_device *pdev)
64 }
65 host_priv->dma_chan = ret;
66
67 - ret = request_irq(host_priv->dma_irq, sdhci_bcm2708_dma_irq,
68 - IRQF_SHARED, DRIVER_NAME " (dma)", host);
69 + ret = request_irq(host_priv->dma_irq, sdhci_bcm2708_dma_irq,0,//IRQF_SHARED,
70 + DRIVER_NAME " (dma)", host);
71 if (ret) {
72 dev_err(&pdev->dev, "cannot set DMA IRQ\n");
73 goto err_add_dma_irq;
74 }
75 + host->second_irq = host_priv->dma_irq;
76 DBG("DMA CBs %p handle %08X DMA%d %p DMA IRQ %d\n",
77 host_priv->cb_base, (unsigned)host_priv->cb_handle,
78 host_priv->dma_chan, host_priv->dma_chan_base,
79 @@ -1384,6 +1387,7 @@ module_param(allow_highspeed, bool, 0444);
80 module_param(emmc_clock_freq, int, 0444);
81 module_param(sync_after_dma, bool, 0444);
82 module_param(missing_status, bool, 0444);
83 +module_param(enable_llm, bool, 0444);
84
85 MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver");
86 MODULE_AUTHOR("Broadcom <info@broadcom.com>");
87 @@ -1394,5 +1398,6 @@ MODULE_PARM_DESC(allow_highspeed, "Allow high speed transfers modes");
88 MODULE_PARM_DESC(emmc_clock_freq, "Specify the speed of emmc clock");
89 MODULE_PARM_DESC(sync_after_dma, "Block in driver until dma complete");
90 MODULE_PARM_DESC(missing_status, "Use the missing status quirk");
91 +MODULE_PARM_DESC(enable_llm, "Enable low-latency mode");
92
93
94 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
95 index 179e83e..470860b 100644
96 --- a/drivers/mmc/host/sdhci.c
97 +++ b/drivers/mmc/host/sdhci.c
98 @@ -124,6 +124,91 @@ static void sdhci_dumpregs(struct sdhci_host *host)
99 * Low level functions *
100 * *
101 \*****************************************************************************/
102 +extern bool enable_llm;
103 +static int sdhci_locked=0;
104 +void sdhci_spin_lock(struct sdhci_host *host)
105 +{
106 + spin_lock(&host->lock);
107 +#ifdef CONFIG_PREEMPT
108 + if(enable_llm)
109 + {
110 + disable_irq_nosync(host->irq);
111 + if(host->second_irq)
112 + disable_irq_nosync(host->second_irq);
113 + local_irq_enable();
114 + }
115 +#endif
116 +}
117 +
118 +void sdhci_spin_unlock(struct sdhci_host *host)
119 +{
120 +#ifdef CONFIG_PREEMPT
121 + if(enable_llm)
122 + {
123 + local_irq_disable();
124 + if(host->second_irq)
125 + enable_irq(host->second_irq);
126 + enable_irq(host->irq);
127 + }
128 +#endif
129 + spin_unlock(&host->lock);
130 +}
131 +
132 +void sdhci_spin_lock_irqsave(struct sdhci_host *host,unsigned long *flags)
133 +{
134 +#ifdef CONFIG_PREEMPT
135 + if(enable_llm)
136 + {
137 + while(sdhci_locked)
138 + {
139 + preempt_schedule();
140 + }
141 + spin_lock_irqsave(&host->lock,*flags);
142 + disable_irq(host->irq);
143 + if(host->second_irq)
144 + disable_irq(host->second_irq);
145 + local_irq_enable();
146 + }
147 + else
148 +#endif
149 + spin_lock_irqsave(&host->lock,*flags);
150 +}
151 +
152 +void sdhci_spin_unlock_irqrestore(struct sdhci_host *host,unsigned long flags)
153 +{
154 +#ifdef CONFIG_PREEMPT
155 + if(enable_llm)
156 + {
157 + local_irq_disable();
158 + if(host->second_irq)
159 + enable_irq(host->second_irq);
160 + enable_irq(host->irq);
161 + }
162 +#endif
163 + spin_unlock_irqrestore(&host->lock,flags);
164 +}
165 +
166 +static void sdhci_spin_enable_schedule(struct sdhci_host *host)
167 +{
168 +#ifdef CONFIG_PREEMPT
169 + if(enable_llm)
170 + {
171 + sdhci_locked = 1;
172 + preempt_enable();
173 + }
174 +#endif
175 +}
176 +
177 +static void sdhci_spin_disable_schedule(struct sdhci_host *host)
178 +{
179 +#ifdef CONFIG_PREEMPT
180 + if(enable_llm)
181 + {
182 + preempt_disable();
183 + sdhci_locked = 0;
184 + }
185 +#endif
186 +}
187
188 static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set)
189 {
190 @@ -289,7 +374,7 @@ static void sdhci_led_control(struct led_classdev *led,
191 struct sdhci_host *host = container_of(led, struct sdhci_host, led);
192 unsigned long flags;
193
194 - spin_lock_irqsave(&host->lock, flags);
195 + sdhci_spin_lock_irqsave(host, &flags);
196
197 if (host->runtime_suspended)
198 goto out;
199 @@ -299,7 +384,7 @@ static void sdhci_led_control(struct led_classdev *led,
200 else
201 sdhci_activate_led(host);
202 out:
203 - spin_unlock_irqrestore(&host->lock, flags);
204 + sdhci_spin_unlock_irqrestore(host, flags);
205 }
206 #endif
207
208 @@ -1007,7 +1092,9 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
209 return;
210 }
211 timeout--;
212 + sdhci_spin_enable_schedule(host);
213 mdelay(1);
214 + sdhci_spin_disable_schedule(host);
215 }
216 DBG("send cmd %d - wait 0x%X irq 0x%x\n", cmd->opcode, mask,
217 sdhci_readl(host, SDHCI_INT_STATUS));
218 @@ -1234,7 +1321,9 @@ clock_set:
219 return;
220 }
221 timeout--;
222 + sdhci_spin_enable_schedule(host);
223 mdelay(1);
224 + sdhci_spin_disable_schedule(host);
225 }
226
227 clk |= SDHCI_CLOCK_CARD_EN;
228 @@ -1330,7 +1419,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
229
230 sdhci_runtime_pm_get(host);
231
232 - spin_lock_irqsave(&host->lock, flags);
233 + sdhci_spin_lock_irqsave(host, &flags);
234
235 WARN_ON(host->mrq != NULL);
236
237 @@ -1388,9 +1477,9 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
238 mmc->card->type == MMC_TYPE_MMC ?
239 MMC_SEND_TUNING_BLOCK_HS200 :
240 MMC_SEND_TUNING_BLOCK;
241 - spin_unlock_irqrestore(&host->lock, flags);
242 + sdhci_spin_unlock_irqrestore(host, flags);
243 sdhci_execute_tuning(mmc, tuning_opcode);
244 - spin_lock_irqsave(&host->lock, flags);
245 + sdhci_spin_lock_irqsave(host, &flags);
246
247 /* Restore original mmc_request structure */
248 host->mrq = mrq;
249 @@ -1404,7 +1493,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
250 }
251
252 mmiowb();
253 - spin_unlock_irqrestore(&host->lock, flags);
254 + sdhci_spin_unlock_irqrestore(host, flags);
255 }
256
257 static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
258 @@ -1413,10 +1502,10 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
259 int vdd_bit = -1;
260 u8 ctrl;
261
262 - spin_lock_irqsave(&host->lock, flags);
263 + sdhci_spin_lock_irqsave(host, &flags);
264
265 if (host->flags & SDHCI_DEVICE_DEAD) {
266 - spin_unlock_irqrestore(&host->lock, flags);
267 + sdhci_spin_unlock_irqrestore(host, flags);
268 if (host->vmmc && ios->power_mode == MMC_POWER_OFF)
269 mmc_regulator_set_ocr(host->mmc, host->vmmc, 0);
270 return;
271 @@ -1443,9 +1532,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
272 vdd_bit = sdhci_set_power(host, ios->vdd);
273
274 if (host->vmmc && vdd_bit != -1) {
275 - spin_unlock_irqrestore(&host->lock, flags);
276 + sdhci_spin_unlock_irqrestore(host, flags);
277 mmc_regulator_set_ocr(host->mmc, host->vmmc, vdd_bit);
278 - spin_lock_irqsave(&host->lock, flags);
279 + sdhci_spin_lock_irqsave(host, &flags);
280 }
281
282 if (host->ops->platform_send_init_74_clocks)
283 @@ -1583,7 +1672,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
284 sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
285
286 mmiowb();
287 - spin_unlock_irqrestore(&host->lock, flags);
288 + sdhci_spin_unlock_irqrestore(host, flags);
289 }
290
291 static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
292 @@ -1631,7 +1720,7 @@ static int sdhci_check_ro(struct sdhci_host *host)
293 unsigned long flags;
294 int is_readonly;
295
296 - spin_lock_irqsave(&host->lock, flags);
297 + sdhci_spin_lock_irqsave(host, &flags);
298
299 if (host->flags & SDHCI_DEVICE_DEAD)
300 is_readonly = 0;
301 @@ -1641,7 +1730,7 @@ static int sdhci_check_ro(struct sdhci_host *host)
302 is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
303 & SDHCI_WRITE_PROTECT);
304
305 - spin_unlock_irqrestore(&host->lock, flags);
306 + sdhci_spin_unlock_irqrestore(host, flags);
307
308 /* This quirk needs to be replaced by a callback-function later */
309 return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ?
310 @@ -1714,9 +1803,9 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
311 struct sdhci_host *host = mmc_priv(mmc);
312 unsigned long flags;
313
314 - spin_lock_irqsave(&host->lock, flags);
315 + sdhci_spin_lock_irqsave(host, &flags);
316 sdhci_enable_sdio_irq_nolock(host, enable);
317 - spin_unlock_irqrestore(&host->lock, flags);
318 + sdhci_spin_unlock_irqrestore(host, flags);
319 }
320
321 static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
322 @@ -2060,7 +2149,7 @@ static void sdhci_card_event(struct mmc_host *mmc)
323 struct sdhci_host *host = mmc_priv(mmc);
324 unsigned long flags;
325
326 - spin_lock_irqsave(&host->lock, flags);
327 + sdhci_spin_lock_irqsave(host, &flags);
328
329 /* Check host->mrq first in case we are runtime suspended */
330 if (host->mrq &&
331 @@ -2077,7 +2166,7 @@ static void sdhci_card_event(struct mmc_host *mmc)
332 tasklet_schedule(&host->finish_tasklet);
333 }
334
335 - spin_unlock_irqrestore(&host->lock, flags);
336 + sdhci_spin_unlock_irqrestore(host, flags);
337 }
338
339 static const struct mmc_host_ops sdhci_ops = {
340 @@ -2116,14 +2205,14 @@ static void sdhci_tasklet_finish(unsigned long param)
341
342 host = (struct sdhci_host*)param;
343
344 - spin_lock_irqsave(&host->lock, flags);
345 + sdhci_spin_lock_irqsave(host, &flags);
346
347 /*
348 * If this tasklet gets rescheduled while running, it will
349 * be run again afterwards but without any active request.
350 */
351 if (!host->mrq) {
352 - spin_unlock_irqrestore(&host->lock, flags);
353 + sdhci_spin_unlock_irqrestore(host, flags);
354 return;
355 }
356
357 @@ -2161,7 +2250,7 @@ static void sdhci_tasklet_finish(unsigned long param)
358 #endif
359
360 mmiowb();
361 - spin_unlock_irqrestore(&host->lock, flags);
362 + sdhci_spin_unlock_irqrestore(host, flags);
363
364 mmc_request_done(host->mmc, mrq);
365 sdhci_runtime_pm_put(host);
366 @@ -2174,7 +2263,7 @@ static void sdhci_timeout_timer(unsigned long data)
367
368 host = (struct sdhci_host*)data;
369
370 - spin_lock_irqsave(&host->lock, flags);
371 + sdhci_spin_lock_irqsave(host, &flags);
372
373 if (host->mrq) {
374 pr_err("%s: Timeout waiting for hardware "
375 @@ -2195,7 +2284,7 @@ static void sdhci_timeout_timer(unsigned long data)
376 }
377
378 mmiowb();
379 - spin_unlock_irqrestore(&host->lock, flags);
380 + sdhci_spin_unlock_irqrestore(host, flags);
381 }
382
383 static void sdhci_tuning_timer(unsigned long data)
384 @@ -2205,11 +2294,11 @@ static void sdhci_tuning_timer(unsigned long data)
385
386 host = (struct sdhci_host *)data;
387
388 - spin_lock_irqsave(&host->lock, flags);
389 + sdhci_spin_lock_irqsave(host, &flags);
390
391 host->flags |= SDHCI_NEEDS_RETUNING;
392
393 - spin_unlock_irqrestore(&host->lock, flags);
394 + sdhci_spin_unlock_irqrestore(host, flags);
395 }
396
397 /*****************************************************************************\
398 @@ -2433,10 +2522,10 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
399 u32 intmask, unexpected = 0;
400 int cardint = 0, max_loops = 16;
401
402 - spin_lock(&host->lock);
403 + sdhci_spin_lock(host);
404
405 if (host->runtime_suspended) {
406 - spin_unlock(&host->lock);
407 + sdhci_spin_unlock(host);
408 pr_warning("%s: got irq while runtime suspended\n",
409 mmc_hostname(host->mmc));
410 return IRQ_HANDLED;
411 @@ -2540,7 +2629,7 @@ again:
412 if (intmask && --max_loops)
413 goto again;
414 out:
415 - spin_unlock(&host->lock);
416 + sdhci_spin_unlock(host);
417
418 if (unexpected) {
419 pr_err("%s: Unexpected interrupt 0x%08x.\n",
420 @@ -2702,15 +2791,15 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
421 host->flags &= ~SDHCI_NEEDS_RETUNING;
422 }
423
424 - spin_lock_irqsave(&host->lock, flags);
425 + sdhci_spin_lock_irqsave(host, &flags);
426 sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
427 - spin_unlock_irqrestore(&host->lock, flags);
428 + sdhci_spin_unlock_irqrestore(host, flags);
429
430 synchronize_irq(host->irq);
431
432 - spin_lock_irqsave(&host->lock, flags);
433 + sdhci_spin_lock_irqsave(host, &flags);
434 host->runtime_suspended = true;
435 - spin_unlock_irqrestore(&host->lock, flags);
436 + sdhci_spin_unlock_irqrestore(host, flags);
437
438 return ret;
439 }
440 @@ -2736,16 +2825,16 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
441 sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios);
442 if ((host_flags & SDHCI_PV_ENABLED) &&
443 !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {
444 - spin_lock_irqsave(&host->lock, flags);
445 + sdhci_spin_lock_irqsave(host, &flags);
446 sdhci_enable_preset_value(host, true);
447 - spin_unlock_irqrestore(&host->lock, flags);
448 + sdhci_spin_unlock_irqrestore(host, flags);
449 }
450
451 /* Set the re-tuning expiration flag */
452 if (host->flags & SDHCI_USING_RETUNING_TIMER)
453 host->flags |= SDHCI_NEEDS_RETUNING;
454
455 - spin_lock_irqsave(&host->lock, flags);
456 + sdhci_spin_lock_irqsave(host, &flags);
457
458 host->runtime_suspended = false;
459
460 @@ -2756,7 +2845,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
461 /* Enable Card Detection */
462 sdhci_enable_card_detection(host);
463
464 - spin_unlock_irqrestore(&host->lock, flags);
465 + sdhci_spin_unlock_irqrestore(host, flags);
466
467 return ret;
468 }
469 @@ -3248,7 +3337,7 @@ int sdhci_add_host(struct sdhci_host *host)
470 host->tuning_timer.function = sdhci_tuning_timer;
471 }
472
473 - ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
474 + ret = request_irq(host->irq, sdhci_irq, 0,//IRQF_SHARED,
475 mmc_hostname(mmc), host);
476 if (ret) {
477 pr_err("%s: Failed to request IRQ %d: %d\n",
478 @@ -3312,7 +3401,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
479 unsigned long flags;
480
481 if (dead) {
482 - spin_lock_irqsave(&host->lock, flags);
483 + sdhci_spin_lock_irqsave(host, &flags);
484
485 host->flags |= SDHCI_DEVICE_DEAD;
486
487 @@ -3324,7 +3413,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
488 tasklet_schedule(&host->finish_tasklet);
489 }
490
491 - spin_unlock_irqrestore(&host->lock, flags);
492 + sdhci_spin_unlock_irqrestore(host, flags);
493 }
494
495 sdhci_disable_card_detection(host);
496 diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
497 index f90574e..cc393af 100644
498 --- a/drivers/mmc/host/sdhci.h
499 +++ b/drivers/mmc/host/sdhci.h
500 @@ -441,4 +441,10 @@ extern int sdhci_runtime_suspend_host(struct sdhci_host *host);
501 extern int sdhci_runtime_resume_host(struct sdhci_host *host);
502 #endif
503
504 +extern void sdhci_spin_lock_irqsave(struct sdhci_host *host,unsigned long *flags);
505 +extern void sdhci_spin_unlock_irqrestore(struct sdhci_host *host,unsigned long flags);
506 +extern void sdhci_spin_lock(struct sdhci_host *host);
507 +extern void sdhci_spin_unlock(struct sdhci_host *host);
508 +
509 +
510 #endif /* __SDHCI_HW_H */
511 diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
512 index f3a39c1..58bfab0 100644
513 --- a/include/linux/mmc/sdhci.h
514 +++ b/include/linux/mmc/sdhci.h
515 @@ -97,6 +97,7 @@ struct sdhci_host {
516 #define SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1<<3)
517
518 int irq; /* Device IRQ */
519 + int second_irq; /* Additional IRQ to disable/enable in low-latency mode */
520 void __iomem *ioaddr; /* Mapped address */
521
522 const struct sdhci_ops *ops; /* Low level hw interface */
523 --
524 1.9.1
525