Date:2011-06-19 10:57:18 (12 years 9 months ago)
Author:Maarten ter Huurne
Commit:cdde9cf73945d547acd3e96f9508c79e84ad0bf1
Message: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.
Files: drivers/mmc/host/jz4740_mmc.c (6 diffs)

Change Details

drivers/mmc/host/jz4740_mmc.c
2323#include <linux/delay.h>
2424#include <linux/scatterlist.h>
2525#include <linux/clk.h>
26#include <linux/cpufreq.h>
2627
2728#include <linux/bitops.h>
2829#include <linux/gpio.h>
...... 
688689    jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable);
689690}
690691
692#ifdef CONFIG_CPU_FREQ
693
694static struct jz4740_mmc_host *cpufreq_host;
695
696static int jz4740_mmc_cpufreq_transition(struct notifier_block *nb,
697                     unsigned long val, void *data)
698{
699    /* TODO: We only have to take action when the PLL freq changes:
700             the main dividers have no influence on the MSC device clock. */
701
702    if (val == CPUFREQ_PRECHANGE) {
703        mmc_claim_host(cpufreq_host->mmc);
704        clk_disable(cpufreq_host->clk);
705    } else if (val == CPUFREQ_POSTCHANGE) {
706        struct mmc_ios *ios = &cpufreq_host->mmc->ios;
707        if (ios->clock)
708            jz4740_mmc_set_clock_rate(cpufreq_host, ios->clock);
709        if (ios->power_mode != MMC_POWER_OFF)
710            clk_enable(cpufreq_host->clk);
711        mmc_release_host(cpufreq_host->mmc);
712    }
713    return 0;
714}
715
716static struct notifier_block jz4740_mmc_cpufreq_nb = {
717    .notifier_call = jz4740_mmc_cpufreq_transition,
718};
719
720static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
721{
722    cpufreq_host = host;
723    return cpufreq_register_notifier(&jz4740_mmc_cpufreq_nb,
724                     CPUFREQ_TRANSITION_NOTIFIER);
725}
726
727static inline void jz4740_mmc_cpufreq_unregister(void)
728{
729    cpufreq_unregister_notifier(&jz4740_mmc_cpufreq_nb,
730                    CPUFREQ_TRANSITION_NOTIFIER);
731}
732
733#else
734
735static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
736{
737    return 0;
738}
739
740static inline void jz4740_mmc_cpufreq_unregister(void)
741{
742}
743
744#endif
745
691746static const struct mmc_host_ops jz4740_mmc_ops = {
692747    .request = jz4740_mmc_request,
693748    .set_ios = jz4740_mmc_set_ios,
...... 
837892        goto err_free_host;
838893    }
839894
895    ret = jz4740_mmc_cpufreq_register(host);
896    if (ret) {
897        dev_err(&pdev->dev,
898            "Failed to register cpufreq transition notifier\n");
899        goto err_clk_put;
900    }
901
840902    host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
841903    if (!host->mem) {
842904        ret = -ENOENT;
843905        dev_err(&pdev->dev, "Failed to get base platform memory\n");
844        goto err_clk_put;
906        goto err_cpufreq_unreg;
845907    }
846908
847909    host->mem = request_mem_region(host->mem->start,
...... 
849911    if (!host->mem) {
850912        ret = -EBUSY;
851913        dev_err(&pdev->dev, "Failed to request base memory region\n");
852        goto err_clk_put;
914        goto err_cpufreq_unreg;
853915    }
854916
855917    host->base = ioremap_nocache(host->mem->start, resource_size(host->mem));
...... 
932994    iounmap(host->base);
933995err_release_mem_region:
934996    release_mem_region(host->mem->start, resource_size(host->mem));
997err_cpufreq_unreg:
998    jz4740_mmc_cpufreq_unregister();
935999err_clk_put:
9361000    clk_put(host->clk);
9371001err_free_host:
...... 
9611025    iounmap(host->base);
9621026    release_mem_region(host->mem->start, resource_size(host->mem));
9631027
1028    jz4740_mmc_cpufreq_unregister();
9641029    clk_put(host->clk);
9651030
9661031    platform_set_drvdata(pdev, NULL);

Archive Download the corresponding diff file



interactive