diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-04-10 06:00:36 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-04-10 06:00:36 -0400 |
| commit | 38fc7839bae2db7a1321d9f6bfc7b5b3ccb59d2a (patch) | |
| tree | 743a51d973ed74fdc83053210b7ca3174fb339c4 /drivers/cpufreq | |
| parent | e5e02de0665ef2477e7a018193051387c6fe0fbc (diff) | |
| parent | 5acb972fed8bcfe6c38a4bdef4e74148eaad04b2 (diff) | |
Merge back earlier cpufreq material for v4.1.
Diffstat (limited to 'drivers/cpufreq')
| -rw-r--r-- | drivers/cpufreq/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/cpufreq/Kconfig.arm | 9 | ||||
| -rw-r--r-- | drivers/cpufreq/Kconfig.powerpc | 9 | ||||
| -rw-r--r-- | drivers/cpufreq/Makefile | 3 | ||||
| -rw-r--r-- | drivers/cpufreq/hisi-acpu-cpufreq.c | 42 | ||||
| -rw-r--r-- | drivers/cpufreq/powernv-cpufreq.c | 47 | ||||
| -rw-r--r-- | drivers/cpufreq/qoriq-cpufreq.c (renamed from drivers/cpufreq/ppc-corenet-cpufreq.c) | 161 |
7 files changed, 206 insertions, 73 deletions
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index a171fef2c2b6..659879a56dba 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig | |||
| @@ -293,5 +293,13 @@ config SH_CPU_FREQ | |||
| 293 | If unsure, say N. | 293 | If unsure, say N. |
| 294 | endif | 294 | endif |
| 295 | 295 | ||
| 296 | config QORIQ_CPUFREQ | ||
| 297 | tristate "CPU frequency scaling driver for Freescale QorIQ SoCs" | ||
| 298 | depends on OF && COMMON_CLK && (PPC_E500MC || ARM) | ||
| 299 | select CLK_QORIQ | ||
| 300 | help | ||
| 301 | This adds the CPUFreq driver support for Freescale QorIQ SoCs | ||
| 302 | which are capable of changing the CPU's frequency dynamically. | ||
| 303 | |||
| 296 | endif | 304 | endif |
| 297 | endmenu | 305 | endmenu |
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 1b06fc4640e2..4f3dbc8cf729 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm | |||
| @@ -108,6 +108,15 @@ config ARM_HIGHBANK_CPUFREQ | |||
| 108 | 108 | ||
| 109 | If in doubt, say N. | 109 | If in doubt, say N. |
| 110 | 110 | ||
| 111 | config ARM_HISI_ACPU_CPUFREQ | ||
| 112 | tristate "Hisilicon ACPU CPUfreq driver" | ||
| 113 | depends on ARCH_HISI && CPUFREQ_DT | ||
| 114 | select PM_OPP | ||
| 115 | help | ||
| 116 | This enables the hisilicon ACPU CPUfreq driver. | ||
| 117 | |||
| 118 | If in doubt, say N. | ||
| 119 | |||
| 111 | config ARM_IMX6Q_CPUFREQ | 120 | config ARM_IMX6Q_CPUFREQ |
| 112 | tristate "Freescale i.MX6 cpufreq support" | 121 | tristate "Freescale i.MX6 cpufreq support" |
| 113 | depends on ARCH_MXC | 122 | depends on ARCH_MXC |
diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc index 7ea24413cee6..3a0595b41eab 100644 --- a/drivers/cpufreq/Kconfig.powerpc +++ b/drivers/cpufreq/Kconfig.powerpc | |||
| @@ -23,15 +23,6 @@ config CPU_FREQ_MAPLE | |||
| 23 | This adds support for frequency switching on Maple 970FX | 23 | This adds support for frequency switching on Maple 970FX |
| 24 | Evaluation Board and compatible boards (IBM JS2x blades). | 24 | Evaluation Board and compatible boards (IBM JS2x blades). |
| 25 | 25 | ||
| 26 | config PPC_CORENET_CPUFREQ | ||
| 27 | tristate "CPU frequency scaling driver for Freescale E500MC SoCs" | ||
| 28 | depends on PPC_E500MC && OF && COMMON_CLK | ||
| 29 | select CLK_QORIQ | ||
| 30 | help | ||
| 31 | This adds the CPUFreq driver support for Freescale e500mc, | ||
| 32 | e5500 and e6500 series SoCs which are capable of changing | ||
| 33 | the CPU's frequency dynamically. | ||
| 34 | |||
| 35 | config CPU_FREQ_PMAC | 26 | config CPU_FREQ_PMAC |
| 36 | bool "Support for Apple PowerBooks" | 27 | bool "Support for Apple PowerBooks" |
| 37 | depends on ADB_PMU && PPC32 | 28 | depends on ADB_PMU && PPC32 |
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 82a1821471fd..cdce92ae2e8b 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile | |||
| @@ -59,6 +59,7 @@ arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ) += exynos4x12-cpufreq.o | |||
| 59 | arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o | 59 | arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o |
| 60 | obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o | 60 | obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o |
| 61 | obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o | 61 | obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o |
| 62 | obj-$(CONFIG_ARM_HISI_ACPU_CPUFREQ) += hisi-acpu-cpufreq.o | ||
| 62 | obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o | 63 | obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o |
| 63 | obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o | 64 | obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o |
| 64 | obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o | 65 | obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o |
| @@ -85,7 +86,7 @@ obj-$(CONFIG_CPU_FREQ_CBE) += ppc-cbe-cpufreq.o | |||
| 85 | ppc-cbe-cpufreq-y += ppc_cbe_cpufreq_pervasive.o ppc_cbe_cpufreq.o | 86 | ppc-cbe-cpufreq-y += ppc_cbe_cpufreq_pervasive.o ppc_cbe_cpufreq.o |
| 86 | obj-$(CONFIG_CPU_FREQ_CBE_PMI) += ppc_cbe_cpufreq_pmi.o | 87 | obj-$(CONFIG_CPU_FREQ_CBE_PMI) += ppc_cbe_cpufreq_pmi.o |
| 87 | obj-$(CONFIG_CPU_FREQ_MAPLE) += maple-cpufreq.o | 88 | obj-$(CONFIG_CPU_FREQ_MAPLE) += maple-cpufreq.o |
| 88 | obj-$(CONFIG_PPC_CORENET_CPUFREQ) += ppc-corenet-cpufreq.o | 89 | obj-$(CONFIG_QORIQ_CPUFREQ) += qoriq-cpufreq.o |
| 89 | obj-$(CONFIG_CPU_FREQ_PMAC) += pmac32-cpufreq.o | 90 | obj-$(CONFIG_CPU_FREQ_PMAC) += pmac32-cpufreq.o |
| 90 | obj-$(CONFIG_CPU_FREQ_PMAC64) += pmac64-cpufreq.o | 91 | obj-$(CONFIG_CPU_FREQ_PMAC64) += pmac64-cpufreq.o |
| 91 | obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += pasemi-cpufreq.o | 92 | obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += pasemi-cpufreq.o |
diff --git a/drivers/cpufreq/hisi-acpu-cpufreq.c b/drivers/cpufreq/hisi-acpu-cpufreq.c new file mode 100644 index 000000000000..026d5b2224de --- /dev/null +++ b/drivers/cpufreq/hisi-acpu-cpufreq.c | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | /* | ||
| 2 | * Hisilicon Platforms Using ACPU CPUFreq Support | ||
| 3 | * | ||
| 4 | * Copyright (c) 2015 Hisilicon Limited. | ||
| 5 | * Copyright (c) 2015 Linaro Limited. | ||
| 6 | * | ||
| 7 | * Leo Yan <leo.yan@linaro.org> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 14 | * kind, whether express or implied; without even the implied warranty | ||
| 15 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 20 | |||
| 21 | #include <linux/err.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/of.h> | ||
| 26 | #include <linux/platform_device.h> | ||
| 27 | |||
| 28 | static int __init hisi_acpu_cpufreq_driver_init(void) | ||
| 29 | { | ||
| 30 | struct platform_device *pdev; | ||
| 31 | |||
| 32 | if (!of_machine_is_compatible("hisilicon,hi6220")) | ||
| 33 | return -ENODEV; | ||
| 34 | |||
| 35 | pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0); | ||
| 36 | return PTR_ERR_OR_ZERO(pdev); | ||
| 37 | } | ||
| 38 | module_init(hisi_acpu_cpufreq_driver_init); | ||
| 39 | |||
| 40 | MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>"); | ||
| 41 | MODULE_DESCRIPTION("Hisilicon acpu cpufreq driver"); | ||
| 42 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 2dfd4fdb5a52..ebef0d8279c7 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c | |||
| @@ -34,9 +34,13 @@ | |||
| 34 | #include <asm/smp.h> /* Required for cpu_sibling_mask() in UP configs */ | 34 | #include <asm/smp.h> /* Required for cpu_sibling_mask() in UP configs */ |
| 35 | 35 | ||
| 36 | #define POWERNV_MAX_PSTATES 256 | 36 | #define POWERNV_MAX_PSTATES 256 |
| 37 | #define PMSR_PSAFE_ENABLE (1UL << 30) | ||
| 38 | #define PMSR_SPR_EM_DISABLE (1UL << 31) | ||
| 39 | #define PMSR_MAX(x) ((x >> 32) & 0xFF) | ||
| 40 | #define PMSR_LP(x) ((x >> 48) & 0xFF) | ||
| 37 | 41 | ||
| 38 | static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; | 42 | static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; |
| 39 | static bool rebooting; | 43 | static bool rebooting, throttled; |
| 40 | 44 | ||
| 41 | /* | 45 | /* |
| 42 | * Note: The set of pstates consists of contiguous integers, the | 46 | * Note: The set of pstates consists of contiguous integers, the |
| @@ -294,6 +298,44 @@ static inline unsigned int get_nominal_index(void) | |||
| 294 | return powernv_pstate_info.max - powernv_pstate_info.nominal; | 298 | return powernv_pstate_info.max - powernv_pstate_info.nominal; |
| 295 | } | 299 | } |
| 296 | 300 | ||
| 301 | static void powernv_cpufreq_throttle_check(unsigned int cpu) | ||
| 302 | { | ||
| 303 | unsigned long pmsr; | ||
| 304 | int pmsr_pmax, pmsr_lp; | ||
| 305 | |||
| 306 | pmsr = get_pmspr(SPRN_PMSR); | ||
| 307 | |||
| 308 | /* Check for Pmax Capping */ | ||
| 309 | pmsr_pmax = (s8)PMSR_MAX(pmsr); | ||
| 310 | if (pmsr_pmax != powernv_pstate_info.max) { | ||
| 311 | throttled = true; | ||
| 312 | pr_info("CPU %d Pmax is reduced to %d\n", cpu, pmsr_pmax); | ||
| 313 | pr_info("Max allowed Pstate is capped\n"); | ||
| 314 | } | ||
| 315 | |||
| 316 | /* | ||
| 317 | * Check for Psafe by reading LocalPstate | ||
| 318 | * or check if Psafe_mode_active is set in PMSR. | ||
| 319 | */ | ||
| 320 | pmsr_lp = (s8)PMSR_LP(pmsr); | ||
| 321 | if ((pmsr_lp < powernv_pstate_info.min) || | ||
| 322 | (pmsr & PMSR_PSAFE_ENABLE)) { | ||
| 323 | throttled = true; | ||
| 324 | pr_info("Pstate set to safe frequency\n"); | ||
| 325 | } | ||
| 326 | |||
| 327 | /* Check if SPR_EM_DISABLE is set in PMSR */ | ||
| 328 | if (pmsr & PMSR_SPR_EM_DISABLE) { | ||
| 329 | throttled = true; | ||
| 330 | pr_info("Frequency Control disabled from OS\n"); | ||
| 331 | } | ||
| 332 | |||
| 333 | if (throttled) { | ||
| 334 | pr_info("PMSR = %16lx\n", pmsr); | ||
| 335 | pr_crit("CPU Frequency could be throttled\n"); | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 297 | /* | 339 | /* |
| 298 | * powernv_cpufreq_target_index: Sets the frequency corresponding to | 340 | * powernv_cpufreq_target_index: Sets the frequency corresponding to |
| 299 | * the cpufreq table entry indexed by new_index on the cpus in the | 341 | * the cpufreq table entry indexed by new_index on the cpus in the |
| @@ -307,6 +349,9 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy, | |||
| 307 | if (unlikely(rebooting) && new_index != get_nominal_index()) | 349 | if (unlikely(rebooting) && new_index != get_nominal_index()) |
| 308 | return 0; | 350 | return 0; |
| 309 | 351 | ||
| 352 | if (!throttled) | ||
| 353 | powernv_cpufreq_throttle_check(smp_processor_id()); | ||
| 354 | |||
| 310 | freq_data.pstate_id = powernv_freqs[new_index].driver_data; | 355 | freq_data.pstate_id = powernv_freqs[new_index].driver_data; |
| 311 | 356 | ||
| 312 | /* | 357 | /* |
diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c index 7cb4b766cf94..9fd51c860308 100644 --- a/drivers/cpufreq/ppc-corenet-cpufreq.c +++ b/drivers/cpufreq/qoriq-cpufreq.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright 2013 Freescale Semiconductor, Inc. | 2 | * Copyright 2013 Freescale Semiconductor, Inc. |
| 3 | * | 3 | * |
| 4 | * CPU Frequency Scaling driver for Freescale PowerPC corenet SoCs. | 4 | * CPU Frequency Scaling driver for Freescale QorIQ SoCs. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
| @@ -20,12 +20,11 @@ | |||
| 20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
| 21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 22 | #include <linux/smp.h> | 22 | #include <linux/smp.h> |
| 23 | #include <sysdev/fsl_soc.h> | ||
| 24 | 23 | ||
| 25 | #include <asm/smp.h> /* for get_hard_smp_processor_id() in UP configs */ | 24 | #include <asm/smp.h> /* for get_hard_smp_processor_id() in UP configs */ |
| 26 | 25 | ||
| 27 | /** | 26 | /** |
| 28 | * struct cpu_data - per CPU data struct | 27 | * struct cpu_data |
| 29 | * @parent: the parent node of cpu clock | 28 | * @parent: the parent node of cpu clock |
| 30 | * @table: frequency table | 29 | * @table: frequency table |
| 31 | */ | 30 | */ |
| @@ -69,17 +68,78 @@ static const struct soc_data sdata[] = { | |||
| 69 | static u32 min_cpufreq; | 68 | static u32 min_cpufreq; |
| 70 | static const u32 *fmask; | 69 | static const u32 *fmask; |
| 71 | 70 | ||
| 72 | static DEFINE_PER_CPU(struct cpu_data *, cpu_data); | 71 | #if defined(CONFIG_ARM) |
| 72 | static int get_cpu_physical_id(int cpu) | ||
| 73 | { | ||
| 74 | return topology_core_id(cpu); | ||
| 75 | } | ||
| 76 | #else | ||
| 77 | static int get_cpu_physical_id(int cpu) | ||
| 78 | { | ||
| 79 | return get_hard_smp_processor_id(cpu); | ||
| 80 | } | ||
| 81 | #endif | ||
| 82 | |||
| 83 | static u32 get_bus_freq(void) | ||
| 84 | { | ||
| 85 | struct device_node *soc; | ||
| 86 | u32 sysfreq; | ||
| 87 | |||
| 88 | soc = of_find_node_by_type(NULL, "soc"); | ||
| 89 | if (!soc) | ||
| 90 | return 0; | ||
| 91 | |||
| 92 | if (of_property_read_u32(soc, "bus-frequency", &sysfreq)) | ||
| 93 | sysfreq = 0; | ||
| 94 | |||
| 95 | of_node_put(soc); | ||
| 73 | 96 | ||
| 74 | /* cpumask in a cluster */ | 97 | return sysfreq; |
| 75 | static DEFINE_PER_CPU(cpumask_var_t, cpu_mask); | 98 | } |
| 76 | 99 | ||
| 77 | #ifndef CONFIG_SMP | 100 | static struct device_node *cpu_to_clk_node(int cpu) |
| 78 | static inline const struct cpumask *cpu_core_mask(int cpu) | ||
| 79 | { | 101 | { |
| 80 | return cpumask_of(0); | 102 | struct device_node *np, *clk_np; |
| 103 | |||
| 104 | if (!cpu_present(cpu)) | ||
| 105 | return NULL; | ||
| 106 | |||
| 107 | np = of_get_cpu_node(cpu, NULL); | ||
| 108 | if (!np) | ||
| 109 | return NULL; | ||
| 110 | |||
| 111 | clk_np = of_parse_phandle(np, "clocks", 0); | ||
| 112 | if (!clk_np) | ||
| 113 | return NULL; | ||
| 114 | |||
| 115 | of_node_put(np); | ||
| 116 | |||
| 117 | return clk_np; | ||
| 118 | } | ||
| 119 | |||
| 120 | /* traverse cpu nodes to get cpu mask of sharing clock wire */ | ||
| 121 | static void set_affected_cpus(struct cpufreq_policy *policy) | ||
| 122 | { | ||
| 123 | struct device_node *np, *clk_np; | ||
| 124 | struct cpumask *dstp = policy->cpus; | ||
| 125 | int i; | ||
| 126 | |||
| 127 | np = cpu_to_clk_node(policy->cpu); | ||
| 128 | if (!np) | ||
| 129 | return; | ||
| 130 | |||
| 131 | for_each_present_cpu(i) { | ||
| 132 | clk_np = cpu_to_clk_node(i); | ||
| 133 | if (!clk_np) | ||
| 134 | continue; | ||
| 135 | |||
| 136 | if (clk_np == np) | ||
| 137 | cpumask_set_cpu(i, dstp); | ||
| 138 | |||
| 139 | of_node_put(clk_np); | ||
| 140 | } | ||
| 141 | of_node_put(np); | ||
| 81 | } | 142 | } |
| 82 | #endif | ||
| 83 | 143 | ||
| 84 | /* reduce the duplicated frequencies in frequency table */ | 144 | /* reduce the duplicated frequencies in frequency table */ |
| 85 | static void freq_table_redup(struct cpufreq_frequency_table *freq_table, | 145 | static void freq_table_redup(struct cpufreq_frequency_table *freq_table, |
| @@ -107,6 +167,7 @@ static void freq_table_sort(struct cpufreq_frequency_table *freq_table, | |||
| 107 | int i, j, ind; | 167 | int i, j, ind; |
| 108 | unsigned int freq, max_freq; | 168 | unsigned int freq, max_freq; |
| 109 | struct cpufreq_frequency_table table; | 169 | struct cpufreq_frequency_table table; |
| 170 | |||
| 110 | for (i = 0; i < count - 1; i++) { | 171 | for (i = 0; i < count - 1; i++) { |
| 111 | max_freq = freq_table[i].frequency; | 172 | max_freq = freq_table[i].frequency; |
| 112 | ind = i; | 173 | ind = i; |
| @@ -131,7 +192,7 @@ static void freq_table_sort(struct cpufreq_frequency_table *freq_table, | |||
| 131 | } | 192 | } |
| 132 | } | 193 | } |
| 133 | 194 | ||
| 134 | static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) | 195 | static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) |
| 135 | { | 196 | { |
| 136 | struct device_node *np; | 197 | struct device_node *np; |
| 137 | int i, count, ret; | 198 | int i, count, ret; |
| @@ -147,10 +208,8 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
| 147 | return -ENODEV; | 208 | return -ENODEV; |
| 148 | 209 | ||
| 149 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 210 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
| 150 | if (!data) { | 211 | if (!data) |
| 151 | pr_err("%s: no memory\n", __func__); | ||
| 152 | goto err_np; | 212 | goto err_np; |
| 153 | } | ||
| 154 | 213 | ||
| 155 | policy->clk = of_clk_get(np, 0); | 214 | policy->clk = of_clk_get(np, 0); |
| 156 | if (IS_ERR(policy->clk)) { | 215 | if (IS_ERR(policy->clk)) { |
| @@ -172,7 +231,7 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
| 172 | } | 231 | } |
| 173 | 232 | ||
| 174 | if (fmask) | 233 | if (fmask) |
| 175 | mask = fmask[get_hard_smp_processor_id(cpu)]; | 234 | mask = fmask[get_cpu_physical_id(cpu)]; |
| 176 | else | 235 | else |
| 177 | mask = 0x0; | 236 | mask = 0x0; |
| 178 | 237 | ||
| @@ -203,13 +262,12 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
| 203 | data->table = table; | 262 | data->table = table; |
| 204 | 263 | ||
| 205 | /* update ->cpus if we have cluster, no harm if not */ | 264 | /* update ->cpus if we have cluster, no harm if not */ |
| 206 | cpumask_copy(policy->cpus, per_cpu(cpu_mask, cpu)); | 265 | set_affected_cpus(policy); |
| 207 | for_each_cpu(i, per_cpu(cpu_mask, cpu)) | 266 | policy->driver_data = data; |
| 208 | per_cpu(cpu_data, i) = data; | ||
| 209 | 267 | ||
| 210 | /* Minimum transition latency is 12 platform clocks */ | 268 | /* Minimum transition latency is 12 platform clocks */ |
| 211 | u64temp = 12ULL * NSEC_PER_SEC; | 269 | u64temp = 12ULL * NSEC_PER_SEC; |
| 212 | do_div(u64temp, fsl_get_sys_freq()); | 270 | do_div(u64temp, get_bus_freq()); |
| 213 | policy->cpuinfo.transition_latency = u64temp + 1; | 271 | policy->cpuinfo.transition_latency = u64temp + 1; |
| 214 | 272 | ||
| 215 | of_node_put(np); | 273 | of_node_put(np); |
| @@ -221,7 +279,7 @@ err_nomem1: | |||
| 221 | err_node: | 279 | err_node: |
| 222 | of_node_put(data->parent); | 280 | of_node_put(data->parent); |
| 223 | err_nomem2: | 281 | err_nomem2: |
| 224 | per_cpu(cpu_data, cpu) = NULL; | 282 | policy->driver_data = NULL; |
| 225 | kfree(data); | 283 | kfree(data); |
| 226 | err_np: | 284 | err_np: |
| 227 | of_node_put(np); | 285 | of_node_put(np); |
| @@ -229,43 +287,40 @@ err_np: | |||
| 229 | return -ENODEV; | 287 | return -ENODEV; |
| 230 | } | 288 | } |
| 231 | 289 | ||
| 232 | static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy) | 290 | static int __exit qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy) |
| 233 | { | 291 | { |
| 234 | struct cpu_data *data = per_cpu(cpu_data, policy->cpu); | 292 | struct cpu_data *data = policy->driver_data; |
| 235 | unsigned int cpu; | ||
| 236 | 293 | ||
| 237 | of_node_put(data->parent); | 294 | of_node_put(data->parent); |
| 238 | kfree(data->table); | 295 | kfree(data->table); |
| 239 | kfree(data); | 296 | kfree(data); |
| 240 | 297 | policy->driver_data = NULL; | |
| 241 | for_each_cpu(cpu, per_cpu(cpu_mask, policy->cpu)) | ||
| 242 | per_cpu(cpu_data, cpu) = NULL; | ||
| 243 | 298 | ||
| 244 | return 0; | 299 | return 0; |
| 245 | } | 300 | } |
| 246 | 301 | ||
| 247 | static int corenet_cpufreq_target(struct cpufreq_policy *policy, | 302 | static int qoriq_cpufreq_target(struct cpufreq_policy *policy, |
| 248 | unsigned int index) | 303 | unsigned int index) |
| 249 | { | 304 | { |
| 250 | struct clk *parent; | 305 | struct clk *parent; |
| 251 | struct cpu_data *data = per_cpu(cpu_data, policy->cpu); | 306 | struct cpu_data *data = policy->driver_data; |
| 252 | 307 | ||
| 253 | parent = of_clk_get(data->parent, data->table[index].driver_data); | 308 | parent = of_clk_get(data->parent, data->table[index].driver_data); |
| 254 | return clk_set_parent(policy->clk, parent); | 309 | return clk_set_parent(policy->clk, parent); |
| 255 | } | 310 | } |
| 256 | 311 | ||
| 257 | static struct cpufreq_driver ppc_corenet_cpufreq_driver = { | 312 | static struct cpufreq_driver qoriq_cpufreq_driver = { |
| 258 | .name = "ppc_cpufreq", | 313 | .name = "qoriq_cpufreq", |
| 259 | .flags = CPUFREQ_CONST_LOOPS, | 314 | .flags = CPUFREQ_CONST_LOOPS, |
| 260 | .init = corenet_cpufreq_cpu_init, | 315 | .init = qoriq_cpufreq_cpu_init, |
| 261 | .exit = __exit_p(corenet_cpufreq_cpu_exit), | 316 | .exit = __exit_p(qoriq_cpufreq_cpu_exit), |
| 262 | .verify = cpufreq_generic_frequency_table_verify, | 317 | .verify = cpufreq_generic_frequency_table_verify, |
| 263 | .target_index = corenet_cpufreq_target, | 318 | .target_index = qoriq_cpufreq_target, |
| 264 | .get = cpufreq_generic_get, | 319 | .get = cpufreq_generic_get, |
| 265 | .attr = cpufreq_generic_attr, | 320 | .attr = cpufreq_generic_attr, |
| 266 | }; | 321 | }; |
| 267 | 322 | ||
| 268 | static const struct of_device_id node_matches[] __initdata = { | 323 | static const struct of_device_id node_matches[] __initconst = { |
| 269 | { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], }, | 324 | { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], }, |
| 270 | { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], }, | 325 | { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], }, |
| 271 | { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], }, | 326 | { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], }, |
| @@ -275,61 +330,43 @@ static const struct of_device_id node_matches[] __initdata = { | |||
| 275 | {} | 330 | {} |
| 276 | }; | 331 | }; |
| 277 | 332 | ||
| 278 | static int __init ppc_corenet_cpufreq_init(void) | 333 | static int __init qoriq_cpufreq_init(void) |
| 279 | { | 334 | { |
| 280 | int ret; | 335 | int ret; |
| 281 | struct device_node *np; | 336 | struct device_node *np; |
| 282 | const struct of_device_id *match; | 337 | const struct of_device_id *match; |
| 283 | const struct soc_data *data; | 338 | const struct soc_data *data; |
| 284 | unsigned int cpu; | ||
| 285 | 339 | ||
| 286 | np = of_find_matching_node(NULL, node_matches); | 340 | np = of_find_matching_node(NULL, node_matches); |
| 287 | if (!np) | 341 | if (!np) |
| 288 | return -ENODEV; | 342 | return -ENODEV; |
| 289 | 343 | ||
| 290 | for_each_possible_cpu(cpu) { | ||
| 291 | if (!alloc_cpumask_var(&per_cpu(cpu_mask, cpu), GFP_KERNEL)) | ||
| 292 | goto err_mask; | ||
| 293 | cpumask_copy(per_cpu(cpu_mask, cpu), cpu_core_mask(cpu)); | ||
| 294 | } | ||
| 295 | |||
| 296 | match = of_match_node(node_matches, np); | 344 | match = of_match_node(node_matches, np); |
| 297 | data = match->data; | 345 | data = match->data; |
| 298 | if (data) { | 346 | if (data) { |
| 299 | if (data->flag) | 347 | if (data->flag) |
| 300 | fmask = data->freq_mask; | 348 | fmask = data->freq_mask; |
| 301 | min_cpufreq = fsl_get_sys_freq(); | 349 | min_cpufreq = get_bus_freq(); |
| 302 | } else { | 350 | } else { |
| 303 | min_cpufreq = fsl_get_sys_freq() / 2; | 351 | min_cpufreq = get_bus_freq() / 2; |
| 304 | } | 352 | } |
| 305 | 353 | ||
| 306 | of_node_put(np); | 354 | of_node_put(np); |
| 307 | 355 | ||
| 308 | ret = cpufreq_register_driver(&ppc_corenet_cpufreq_driver); | 356 | ret = cpufreq_register_driver(&qoriq_cpufreq_driver); |
| 309 | if (!ret) | 357 | if (!ret) |
| 310 | pr_info("Freescale PowerPC corenet CPU frequency scaling driver\n"); | 358 | pr_info("Freescale QorIQ CPU frequency scaling driver\n"); |
| 311 | 359 | ||
| 312 | return ret; | 360 | return ret; |
| 313 | |||
| 314 | err_mask: | ||
| 315 | for_each_possible_cpu(cpu) | ||
| 316 | free_cpumask_var(per_cpu(cpu_mask, cpu)); | ||
| 317 | |||
| 318 | return -ENOMEM; | ||
| 319 | } | 361 | } |
| 320 | module_init(ppc_corenet_cpufreq_init); | 362 | module_init(qoriq_cpufreq_init); |
| 321 | 363 | ||
| 322 | static void __exit ppc_corenet_cpufreq_exit(void) | 364 | static void __exit qoriq_cpufreq_exit(void) |
| 323 | { | 365 | { |
| 324 | unsigned int cpu; | 366 | cpufreq_unregister_driver(&qoriq_cpufreq_driver); |
| 325 | |||
| 326 | for_each_possible_cpu(cpu) | ||
| 327 | free_cpumask_var(per_cpu(cpu_mask, cpu)); | ||
| 328 | |||
| 329 | cpufreq_unregister_driver(&ppc_corenet_cpufreq_driver); | ||
| 330 | } | 367 | } |
| 331 | module_exit(ppc_corenet_cpufreq_exit); | 368 | module_exit(qoriq_cpufreq_exit); |
| 332 | 369 | ||
| 333 | MODULE_LICENSE("GPL"); | 370 | MODULE_LICENSE("GPL"); |
| 334 | MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>"); | 371 | MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>"); |
| 335 | MODULE_DESCRIPTION("cpufreq driver for Freescale e500mc series SoCs"); | 372 | MODULE_DESCRIPTION("cpufreq driver for Freescale QorIQ series SoCs"); |
