Date:2011-06-19 10:57:18 (9 years 3 months ago)
Author:Maarten ter Huurne
Commit:ff305ba89d4b0782ec3e71a7be52a977c7e4fcc3
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>
...... 
685686    jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable);
686687}
687688
689#ifdef CONFIG_CPU_FREQ
690
691static struct jz4740_mmc_host *cpufreq_host;
692
693static int jz4740_mmc_cpufreq_transition(struct notifier_block *nb,
694                     unsigned long val, void *data)
695{
696    struct cpufreq_freqs *freqs = data;
697
698    /* TODO: We only have to take action when the PLL freq changes:
699             the main dividers have no influence on the MSC device clock. */
700
701    if (val == CPUFREQ_PRECHANGE) {
702        mmc_claim_host(cpufreq_host->mmc);
703        clk_disable(cpufreq_host->clk);
704    } else if (val == CPUFREQ_POSTCHANGE) {
705        struct mmc_ios *ios = &cpufreq_host->mmc->ios;
706        if (ios->clock)
707            jz4740_mmc_set_clock_rate(cpufreq_host, ios->clock);
708        if (ios->power_mode != MMC_POWER_OFF)
709            clk_enable(cpufreq_host->clk);
710        mmc_release_host(cpufreq_host->mmc);
711    }
712    return 0;
713}
714
715static struct notifier_block jz4740_mmc_cpufreq_nb = {
716    .notifier_call = jz4740_mmc_cpufreq_transition,
717};
718
719static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
720{
721    cpufreq_host = host;
722    return cpufreq_register_notifier(&jz4740_mmc_cpufreq_nb,
723                     CPUFREQ_TRANSITION_NOTIFIER);
724}
725
726static inline void jz4740_mmc_cpufreq_unregister(void)
727{
728    cpufreq_unregister_notifier(&jz4740_mmc_cpufreq_nb,
729                    CPUFREQ_TRANSITION_NOTIFIER);
730}
731
732#else
733
734static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
735{
736    return 0;
737}
738
739static inline void jz4740_mmc_cpufreq_unregister(void)
740{
741}
742
743#endif
744
688745static const struct mmc_host_ops jz4740_mmc_ops = {
689746    .request = jz4740_mmc_request,
690747    .set_ios = jz4740_mmc_set_ios,
...... 
834891        goto err_free_host;
835892    }
836893
894    ret = jz4740_mmc_cpufreq_register(host);
895    if (ret) {
896        dev_err(&pdev->dev,
897            "Failed to register cpufreq transition notifier\n");
898        goto err_clk_put;
899    }
900
837901    host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
838902    if (!host->mem) {
839903        ret = -ENOENT;
840904        dev_err(&pdev->dev, "Failed to get base platform memory\n");
841        goto err_clk_put;
905        goto err_cpufreq_unreg;
842906    }
843907
844908    host->mem = request_mem_region(host->mem->start,
...... 
846910    if (!host->mem) {
847911        ret = -EBUSY;
848912        dev_err(&pdev->dev, "Failed to request base memory region\n");
849        goto err_clk_put;
913        goto err_cpufreq_unreg;
850914    }
851915
852916    host->base = ioremap_nocache(host->mem->start, resource_size(host->mem));
...... 
929993    iounmap(host->base);
930994err_release_mem_region:
931995    release_mem_region(host->mem->start, resource_size(host->mem));
996err_cpufreq_unreg:
997    jz4740_mmc_cpufreq_unregister();
932998err_clk_put:
933999    clk_put(host->clk);
9341000err_free_host:
...... 
9581024    iounmap(host->base);
9591025    release_mem_region(host->mem->start, resource_size(host->mem));
9601026
1027    jz4740_mmc_cpufreq_unregister();
9611028    clk_put(host->clk);
9621029
9631030    platform_set_drvdata(pdev, NULL);

Archive Download the corresponding diff file



interactive