Date:2011-06-19 10:57:18 (12 years 9 months ago)
Author:Maarten ter Huurne
Commit:c9d94cdcee21e8aeed85632648c473235f14f3fe
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 (5 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>
...... 
667668    jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable);
668669}
669670
671#ifdef CONFIG_CPU_FREQ
672
673static struct jz4740_mmc_host *cpufreq_host;
674
675static int jz4740_mmc_cpufreq_transition(struct notifier_block *nb,
676                     unsigned long val, void *data)
677{
678    /* TODO: We only have to take action when the PLL freq changes:
679             the main dividers have no influence on the MSC device clock. */
680
681    if (val == CPUFREQ_PRECHANGE) {
682        mmc_claim_host(cpufreq_host->mmc);
683        clk_disable(cpufreq_host->clk);
684    } else if (val == CPUFREQ_POSTCHANGE) {
685        struct mmc_ios *ios = &cpufreq_host->mmc->ios;
686        if (ios->clock)
687            jz4740_mmc_set_clock_rate(cpufreq_host, ios->clock);
688        if (ios->power_mode != MMC_POWER_OFF)
689            clk_enable(cpufreq_host->clk);
690        mmc_release_host(cpufreq_host->mmc);
691    }
692    return 0;
693}
694
695static struct notifier_block jz4740_mmc_cpufreq_nb = {
696    .notifier_call = jz4740_mmc_cpufreq_transition,
697};
698
699static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
700{
701    cpufreq_host = host;
702    return cpufreq_register_notifier(&jz4740_mmc_cpufreq_nb,
703                     CPUFREQ_TRANSITION_NOTIFIER);
704}
705
706static inline void jz4740_mmc_cpufreq_unregister(void)
707{
708    cpufreq_unregister_notifier(&jz4740_mmc_cpufreq_nb,
709                    CPUFREQ_TRANSITION_NOTIFIER);
710}
711
712#else
713
714static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host)
715{
716    return 0;
717}
718
719static inline void jz4740_mmc_cpufreq_unregister(void)
720{
721}
722
723#endif
724
670725static const struct mmc_host_ops jz4740_mmc_ops = {
671726    .request = jz4740_mmc_request,
672727    .set_ios = jz4740_mmc_set_ios,
...... 
789844        goto err_free_host;
790845    }
791846
847    ret = jz4740_mmc_cpufreq_register(host);
848    if (ret) {
849        dev_err(&pdev->dev,
850            "Failed to register cpufreq transition notifier\n");
851        goto err_free_host;
852    }
853
792854    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
793855    host->base = devm_ioremap_resource(&pdev->dev, res);
794856    if (IS_ERR(host->base)) {
795857        ret = PTR_ERR(host->base);
796        goto err_free_host;
858        dev_err(&pdev->dev, "Failed to ioremap base memory\n");
859        goto err_cpufreq_unreg;
797860    }
798861
799862    ret = jz_gpio_bulk_request(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
800863    if (ret) {
801864        dev_err(&pdev->dev, "Failed to request mmc pins: %d\n", ret);
802        goto err_free_host;
865        goto err_cpufreq_unreg;
803866    }
804867
805868    ret = jz4740_mmc_request_gpios(mmc, pdev);
...... 
856919    jz4740_mmc_free_gpios(pdev);
857920err_gpio_bulk_free:
858921    jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
922err_cpufreq_unreg:
923    jz4740_mmc_cpufreq_unregister();
859924err_free_host:
860925    mmc_free_host(mmc);
861926
...... 
877942    jz4740_mmc_free_gpios(pdev);
878943    jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
879944
945    jz4740_mmc_cpufreq_unregister();
880946    mmc_free_host(host->mmc);
881947
882948    return 0;

Archive Download the corresponding diff file



interactive