Date: | 2011-06-19 10:57:18 (12 years 5 months ago) |
---|---|
Author: | Maarten ter Huurne |
Commit: | c56a3cefe8e50e1607c9193267eb7b38946879a3 |
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 | ||
---|---|---|
23 | 23 | #include <linux/delay.h> |
24 | 24 | #include <linux/scatterlist.h> |
25 | 25 | #include <linux/clk.h> |
26 | #include <linux/cpufreq.h> | |
26 | 27 | |
27 | 28 | #include <linux/bitops.h> |
28 | 29 | #include <linux/gpio.h> |
... | ... | |
685 | 686 | jz4740_mmc_set_irq_enabled(host, JZ_MMC_IRQ_SDIO, enable); |
686 | 687 | } |
687 | 688 | |
689 | #ifdef CONFIG_CPU_FREQ | |
690 | ||
691 | static struct jz4740_mmc_host *cpufreq_host; | |
692 | ||
693 | static 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 | ||
715 | static struct notifier_block jz4740_mmc_cpufreq_nb = { | |
716 | .notifier_call = jz4740_mmc_cpufreq_transition, | |
717 | }; | |
718 | ||
719 | static 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 | ||
726 | static 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 | ||
734 | static inline int jz4740_mmc_cpufreq_register(struct jz4740_mmc_host *host) | |
735 | { | |
736 | return 0; | |
737 | } | |
738 | ||
739 | static inline void jz4740_mmc_cpufreq_unregister(void) | |
740 | { | |
741 | } | |
742 | ||
743 | #endif | |
744 | ||
688 | 745 | static const struct mmc_host_ops jz4740_mmc_ops = { |
689 | 746 | .request = jz4740_mmc_request, |
690 | 747 | .set_ios = jz4740_mmc_set_ios, |
... | ... | |
834 | 891 | goto err_free_host; |
835 | 892 | } |
836 | 893 | |
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 | ||
837 | 901 | host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
838 | 902 | if (!host->mem) { |
839 | 903 | ret = -ENOENT; |
840 | 904 | dev_err(&pdev->dev, "Failed to get base platform memory\n"); |
841 | goto err_clk_put; | |
905 | goto err_cpufreq_unreg; | |
842 | 906 | } |
843 | 907 | |
844 | 908 | host->mem = request_mem_region(host->mem->start, |
... | ... | |
846 | 910 | if (!host->mem) { |
847 | 911 | ret = -EBUSY; |
848 | 912 | dev_err(&pdev->dev, "Failed to request base memory region\n"); |
849 | goto err_clk_put; | |
913 | goto err_cpufreq_unreg; | |
850 | 914 | } |
851 | 915 | |
852 | 916 | host->base = ioremap_nocache(host->mem->start, resource_size(host->mem)); |
... | ... | |
929 | 993 | iounmap(host->base); |
930 | 994 | err_release_mem_region: |
931 | 995 | release_mem_region(host->mem->start, resource_size(host->mem)); |
996 | err_cpufreq_unreg: | |
997 | jz4740_mmc_cpufreq_unregister(); | |
932 | 998 | err_clk_put: |
933 | 999 | clk_put(host->clk); |
934 | 1000 | err_free_host: |
... | ... | |
958 | 1024 | iounmap(host->base); |
959 | 1025 | release_mem_region(host->mem->start, resource_size(host->mem)); |
960 | 1026 | |
1027 | jz4740_mmc_cpufreq_unregister(); | |
961 | 1028 | clk_put(host->clk); |
962 | 1029 | |
963 | 1030 | platform_set_drvdata(pdev, NULL); |
Branches:
ben-wpan
ben-wpan-stefan
5396a9238205f20f811ea57898980d3ca82df0b6
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9