[target/xburst] level up target xburst to linux kernel version 3.2.1
[openwrt.git] / target / linux / xburst / patches-3.2 / 0013-MMC-JZ4740-Added-support-for-CPU-frequency-changing.patch
diff --git a/target/linux/xburst/patches-3.2/0013-MMC-JZ4740-Added-support-for-CPU-frequency-changing.patch b/target/linux/xburst/patches-3.2/0013-MMC-JZ4740-Added-support-for-CPU-frequency-changing.patch
new file mode 100644 (file)
index 0000000..da1c4f1
--- /dev/null
@@ -0,0 +1,134 @@
+From b95144c1b702f98c7902c75beb83f323701eb7c5 Mon Sep 17 00:00:00 2001
+From: Maarten ter Huurne <maarten@treewalker.org>
+Date: Sun, 19 Jun 2011 10:57:18 +0200
+Subject: [PATCH 13/21] MMC: JZ4740: Added support for CPU frequency changing.
+
+The MSC device clock is stopped before the frequency change.
+After the change a new divider is computed and the clock is restarted.
+Also the frequency change is postponed if an I/O operation is in progress.
+---
+ drivers/mmc/host/jz4740_mmc.c |   69 +++++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 67 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c
+index 74218ad..6e40f1b 100644
+--- a/drivers/mmc/host/jz4740_mmc.c
++++ b/drivers/mmc/host/jz4740_mmc.c
+@@ -23,6 +23,7 @@
+ #include <linux/delay.h>
+ #include <linux/scatterlist.h>
+ #include <linux/clk.h>
++#include <linux/cpufreq.h>
+ #include <linux/bitops.h>
+ #include <linux/gpio.h>
+@@ -685,6 +686,60 @@ static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+       jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable);
+ }
++#ifdef CONFIG_CPU_FREQ
++
++static struct jz4740_mmc_host *cpufreq_host;
++
++static int jz4740_mmc_cpufreq_transition(struct notifier_block *nb,
++                                       unsigned long val, void *data)
++{
++      /* TODO: We only have to take action when the PLL freq changes:
++               the main dividers have no influence on the MSC device clock. */
++
++      if (val == CPUFREQ_PRECHANGE) {
++              mmc_claim_host(cpufreq_host->mmc);
++              clk_disable(cpufreq_host->clk);
++      } else if (val == CPUFREQ_POSTCHANGE) {
++              struct mmc_ios *ios = &cpufreq_host->mmc->ios;
++              if (ios->clock)
++                      jz4740_mmc_set_clock_rate(cpufreq_host, ios->clock);
++              if (ios->power_mode != MMC_POWER_OFF)
++                      clk_enable(cpufreq_host->clk);
++              mmc_release_host(cpufreq_host->mmc);
++      }
++      return 0;
++}
++
++static struct notifier_block jz4740_mmc_cpufreq_nb = {
++      .notifier_call = jz4740_mmc_cpufreq_transition,
++};
++
++static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
++{
++      cpufreq_host = host;
++      return cpufreq_register_notifier(&jz4740_mmc_cpufreq_nb,
++                                       CPUFREQ_TRANSITION_NOTIFIER);
++}
++
++static inline void jz4740_mmc_cpufreq_unregister(void)
++{
++      cpufreq_unregister_notifier(&jz4740_mmc_cpufreq_nb,
++                                  CPUFREQ_TRANSITION_NOTIFIER);
++}
++
++#else
++
++static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
++{
++      return 0;
++}
++
++static inline void jz4740_mmc_cpufreq_unregister(void)
++{
++}
++
++#endif
++
+ static const struct mmc_host_ops jz4740_mmc_ops = {
+       .request        = jz4740_mmc_request,
+       .set_ios        = jz4740_mmc_set_ios,
+@@ -834,11 +889,18 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev)
+               goto err_free_host;
+       }
++      ret = jz4740_mmc_cpufreq_register(host);
++      if (ret) {
++              dev_err(&pdev->dev,
++                      "Failed to register cpufreq transition notifier\n");
++              goto err_clk_put;
++      }
++
+       host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!host->mem) {
+               ret = -ENOENT;
+               dev_err(&pdev->dev, "Failed to get base platform memory\n");
+-              goto err_clk_put;
++              goto err_cpufreq_unreg;
+       }
+       host->mem = request_mem_region(host->mem->start,
+@@ -846,7 +908,7 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev)
+       if (!host->mem) {
+               ret = -EBUSY;
+               dev_err(&pdev->dev, "Failed to request base memory region\n");
+-              goto err_clk_put;
++              goto err_cpufreq_unreg;
+       }
+       host->base = ioremap_nocache(host->mem->start, resource_size(host->mem));
+@@ -929,6 +991,8 @@ err_iounmap:
+       iounmap(host->base);
+ err_release_mem_region:
+       release_mem_region(host->mem->start, resource_size(host->mem));
++err_cpufreq_unreg:
++      jz4740_mmc_cpufreq_unregister();
+ err_clk_put:
+       clk_put(host->clk);
+ err_free_host:
+@@ -958,6 +1022,7 @@ static int __devexit jz4740_mmc_remove(struct platform_device *pdev)
+       iounmap(host->base);
+       release_mem_region(host->mem->start, resource_size(host->mem));
++      jz4740_mmc_cpufreq_unregister();
+       clk_put(host->clk);
+       platform_set_drvdata(pdev, NULL);
+-- 
+1.7.5.4
+
This page took 0.038202 seconds and 4 git commands to generate.