Date:2011-06-19 10:57:18 (11 years 3 months ago)
Author:Maarten ter Huurne
Commit:2429afa6b7317d2b68e4112ed68233adee5d1e85
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 (!host->base) {
795857        ret = -EBUSY;
796858        dev_err(&pdev->dev, "Failed to ioremap base memory\n");
797        goto err_free_host;
859        goto err_cpufreq_unreg;
798860    }
799861
800862    ret = jz_gpio_bulk_request(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
801863    if (ret) {
802864        dev_err(&pdev->dev, "Failed to request mmc pins: %d\n", ret);
803        goto err_free_host;
865        goto err_cpufreq_unreg;
804866    }
805867
806868    ret = jz4740_mmc_request_gpios(mmc, pdev);
...... 
857919    jz4740_mmc_free_gpios(pdev);
858920err_gpio_bulk_free:
859921    jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
922err_cpufreq_unreg:
923    jz4740_mmc_cpufreq_unregister();
860924err_free_host:
861925    mmc_free_host(mmc);
862926
...... 
878942    jz4740_mmc_free_gpios(pdev);
879943    jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host));
880944
945    jz4740_mmc_cpufreq_unregister();
881946    mmc_free_host(host->mmc);
882947
883948    return 0;

Archive Download the corresponding diff file



interactive