summaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-4.4/0234-bcm2835-sdhost-Reset-the-clock-in-task-context.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-4.4/0234-bcm2835-sdhost-Reset-the-clock-in-task-context.patch')
-rw-r--r--target/linux/brcm2708/patches-4.4/0234-bcm2835-sdhost-Reset-the-clock-in-task-context.patch107
1 files changed, 107 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.4/0234-bcm2835-sdhost-Reset-the-clock-in-task-context.patch b/target/linux/brcm2708/patches-4.4/0234-bcm2835-sdhost-Reset-the-clock-in-task-context.patch
new file mode 100644
index 0000000000..006db3f861
--- /dev/null
+++ b/target/linux/brcm2708/patches-4.4/0234-bcm2835-sdhost-Reset-the-clock-in-task-context.patch
@@ -0,0 +1,107 @@
+From 6a5e76800cf6d16d01b8e186806decc047590e46 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Mon, 11 Apr 2016 12:50:58 +0100
+Subject: [PATCH 234/304] bcm2835-sdhost: Reset the clock in task context
+
+Since reprogramming the clock can now involve a round-trip to the
+firmware it must not be done at atomic context, and a tasklet
+is not a task.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/mmc/host/bcm2835-sdhost.c | 25 ++++++++++++++++++-------
+ 1 file changed, 18 insertions(+), 7 deletions(-)
+
+--- a/drivers/mmc/host/bcm2835-sdhost.c
++++ b/drivers/mmc/host/bcm2835-sdhost.c
+@@ -185,6 +185,7 @@ struct bcm2835_host {
+
+ unsigned int debug:1; /* Enable debug output */
+ unsigned int firmware_sets_cdiv:1; /* Let the firmware manage the clock */
++ unsigned int reset_clock:1; /* Reset the clock fore the next request */
+
+ /*DMA part*/
+ struct dma_chan *dma_chan_rxtx; /* DMA channel for reads and writes */
+@@ -1505,6 +1506,7 @@ void bcm2835_sdhost_set_clock(struct bcm
+ {
+ int div = 0; /* Initialized for compiler warning */
+ unsigned int input_clock = clock;
++ unsigned long flags;
+
+ if (host->debug)
+ pr_info("%s: set_clock(%d)\n", mmc_hostname(host->mmc), clock);
+@@ -1544,13 +1546,17 @@ void bcm2835_sdhost_set_clock(struct bcm
+ &msg, sizeof(msg));
+
+ clock = max(msg[1], msg[2]);
++ spin_lock_irqsave(&host->lock, flags);
+ } else {
++ spin_lock_irqsave(&host->lock, flags);
+ if (clock < 100000) {
+ /* Can't stop the clock, but make it as slow as
+ * possible to show willing
+ */
+ host->cdiv = SDCDIV_MAX_CDIV;
+ bcm2835_sdhost_write(host, host->cdiv, SDCDIV);
++ mmiowb();
++ spin_unlock_irqrestore(&host->lock, flags);
+ return;
+ }
+
+@@ -1605,6 +1611,11 @@ void bcm2835_sdhost_set_clock(struct bcm
+ bcm2835_sdhost_write(host, clock/2, SDTOUT);
+
+ host->mmc->actual_clock = clock;
++ host->clock = input_clock;
++ host->reset_clock = 0;
++
++ mmiowb();
++ spin_unlock_irqrestore(&host->lock, flags);
+ }
+
+ static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq)
+@@ -1653,6 +1664,9 @@ static void bcm2835_sdhost_request(struc
+ (mrq->data->blocks > host->pio_limit))
+ bcm2835_sdhost_prepare_dma(host, mrq->data);
+
++ if (host->reset_clock)
++ bcm2835_sdhost_set_clock(host, host->clock);
++
+ spin_lock_irqsave(&host->lock, flags);
+
+ WARN_ON(host->mrq != NULL);
+@@ -1731,14 +1745,12 @@ static void bcm2835_sdhost_set_ios(struc
+
+ bcm2835_sdhost_write(host, host->hcfg, SDHCFG);
+
+- if (!ios->clock || ios->clock != host->clock) {
+- bcm2835_sdhost_set_clock(host, ios->clock);
+- host->clock = ios->clock;
+- }
+-
+ mmiowb();
+
+ spin_unlock_irqrestore(&host->lock, flags);
++
++ if (!ios->clock || ios->clock != host->clock)
++ bcm2835_sdhost_set_clock(host, ios->clock);
+ }
+
+ static struct mmc_host_ops bcm2835_sdhost_ops = {
+@@ -1810,7 +1822,7 @@ static void bcm2835_sdhost_tasklet_finis
+ host->overclock_50--;
+ pr_warn("%s: reducing overclock due to errors\n",
+ mmc_hostname(host->mmc));
+- bcm2835_sdhost_set_clock(host,50*MHZ);
++ host->reset_clock = 1;
+ mrq->cmd->error = -EILSEQ;
+ mrq->cmd->retries = 1;
+ }
+@@ -1979,7 +1991,6 @@ static int bcm2835_sdhost_probe(struct p
+ mmc->ops = &bcm2835_sdhost_ops;
+ host = mmc_priv(mmc);
+ host->mmc = mmc;
+- host->cmd_quick_poll_retries = 0;
+ host->pio_timeout = msecs_to_jiffies(500);
+ host->pio_limit = 1;
+ host->max_delay = 1; /* Warn if over 1ms */