Date:2011-06-19 10:57:18 (8 years 11 months ago)
Author:Maarten ter Huurne
Commit:3c3d089603731848d0c6511e793146051cbc02af
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
2424#include <linux/delay.h>
2525#include <linux/scatterlist.h>
2626#include <linux/clk.h>
27#include <linux/cpufreq.h>
2728
2829#include <linux/bitops.h>
2930#include <linux/gpio.h>
...... 
899900    jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable);
900901}
901902
903#ifdef CONFIG_CPU_FREQ
904
905static struct jz4740_mmc_host *cpufreq_host;
906
907static int jz4740_mmc_cpufreq_transition(struct notifier_block *nb,
908                     unsigned long val, void *data)
909{
910    /* TODO: We only have to take action when the PLL freq changes:
911             the main dividers have no influence on the MSC device clock. */
912
913    if (val == CPUFREQ_PRECHANGE) {
914        mmc_claim_host(cpufreq_host->mmc);
915        clk_disable_unprepare(cpufreq_host->clk);
916    } else if (val == CPUFREQ_POSTCHANGE) {
917        struct mmc_ios *ios = &cpufreq_host->mmc->ios;
918        if (ios->clock)
919            jz4740_mmc_set_clock_rate(cpufreq_host, ios->clock);
920        if (ios->power_mode != MMC_POWER_OFF)
921            clk_prepare_enable(cpufreq_host->clk);
922        mmc_release_host(cpufreq_host->mmc);
923    }
924    return 0;
925}
926
927static struct notifier_block jz4740_mmc_cpufreq_nb = {
928    .notifier_call = jz4740_mmc_cpufreq_transition,
929};
930
931static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
932{
933    cpufreq_host = host;
934    return cpufreq_register_notifier(&jz4740_mmc_cpufreq_nb,
935                     CPUFREQ_TRANSITION_NOTIFIER);
936}
937
938static inline void jz4740_mmc_cpufreq_unregister(void)
939{
940    cpufreq_unregister_notifier(&jz4740_mmc_cpufreq_nb,
941                    CPUFREQ_TRANSITION_NOTIFIER);
942}
943
944#else
945
946static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
947{
948    return 0;
949}
950
951static inline void jz4740_mmc_cpufreq_unregister(void)
952{
953}
954
955#endif
956
902957static const struct mmc_host_ops jz4740_mmc_ops = {
903958    .request = jz4740_mmc_request,
904959    .pre_req = jz4740_mmc_pre_request,
...... 
10221077        goto err_free_host;
10231078    }
10241079
1080    ret = jz4740_mmc_cpufreq_register(host);
1081    if (ret) {
1082        dev_err(&pdev->dev,
1083            "Failed to register cpufreq transition notifier\n");
1084        goto err_free_host;
1085    }
1086
10251087    host->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
10261088    host->base = devm_ioremap_resource(&pdev->dev, host->mem_res);
10271089    if (IS_ERR(host->base)) {
...... 
10331095    ret = jz_gpio_bulk_request(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
10341096    if (ret) {
10351097        dev_err(&pdev->dev, "Failed to request mmc pins: %d\n", ret);
1036        goto err_free_host;
1098        goto err_cpufreq_unreg;
10371099    }
10381100
10391101    ret = jz4740_mmc_request_gpios(mmc, pdev);
...... 
11001162    if (host->use_dma)
11011163        jz4740_mmc_release_dma_channels(host);
11021164    jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
1165err_cpufreq_unreg:
1166    jz4740_mmc_cpufreq_unregister();
11031167err_free_host:
11041168    mmc_free_host(mmc);
11051169
...... 
11241188    if (host->use_dma)
11251189        jz4740_mmc_release_dma_channels(host);
11261190
1191    jz4740_mmc_cpufreq_unregister();
11271192    mmc_free_host(host->mmc);
11281193
11291194    return 0;

Archive Download the corresponding diff file



interactive