diff options
-rw-r--r-- | drivers/cpufreq/Kconfig.arm | 8 | ||||
-rw-r--r-- | drivers/cpufreq/Kconfig.powerpc | 14 | ||||
-rw-r--r-- | drivers/cpufreq/Makefile | 2 | ||||
-rw-r--r-- | drivers/cpufreq/qoriq-cpufreq.c (renamed from drivers/cpufreq/ppc-corenet-cpufreq.c) | 165 |
4 files changed, 118 insertions, 71 deletions
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 0fa204b..553a50c 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -235,3 +235,11 @@ config ARM_TEGRA_CPUFREQ default y help This adds the CPUFreq driver support for TEGRA SOCs. + +config QORIQ_CPUFREQ + tristate "CPU frequency scaling driver for Freescale QorIQ SoCs" + depends on OF && COMMON_CLK + select CLK_QORIQ + help + This adds the CPUFreq driver support for Freescale QorIQ SoCs + which are capable of changing the CPU's frequency dynamically. diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc index e859a1d..1527a79 100644 --- a/drivers/cpufreq/Kconfig.powerpc +++ b/drivers/cpufreq/Kconfig.powerpc @@ -35,15 +35,13 @@ config MPC85xx_CPUFREQ have a JOG feature, which provides a dynamic mechanism to lower or raise the CPU core clock at runtime. -config PPC_CORENET_CPUFREQ - tristate "CPU frequency scaling driver for Freescale E500MC SoCs" - depends on PPC_E500MC && OF && COMMON_CLK - select CPU_FREQ_TABLE - select CLK_PPC_CORENET +config QORIQ_CPUFREQ + tristate "CPU frequency scaling driver for Freescale QorIQ SoCs" + depends on OF && COMMON_CLK + select CLK_QORIQ help - This adds the CPUFreq driver support for Freescale e500mc, - e5500 and e6500 series SoCs which are capable of changing - the CPU's frequency dynamically. + This adds the CPUFreq driver support for Freescale QorIQ SoCs + which are capable of changing the CPU's frequency dynamically. config CPU_FREQ_PMAC bool "Support for Apple PowerBooks" diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index cc1b57d..708f794 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -84,7 +84,7 @@ obj-$(CONFIG_CPU_FREQ_CBE) += ppc-cbe-cpufreq.o ppc-cbe-cpufreq-y += ppc_cbe_cpufreq_pervasive.o ppc_cbe_cpufreq.o obj-$(CONFIG_CPU_FREQ_CBE_PMI) += ppc_cbe_cpufreq_pmi.o obj-$(CONFIG_CPU_FREQ_MAPLE) += maple-cpufreq.o -obj-$(CONFIG_PPC_CORENET_CPUFREQ) += ppc-corenet-cpufreq.o +obj-$(CONFIG_QORIQ_CPUFREQ) += qoriq-cpufreq.o obj-$(CONFIG_MPC85xx_CPUFREQ) += mpc85xx-cpufreq.o obj-$(CONFIG_CPU_FREQ_PMAC) += pmac32-cpufreq.o obj-$(CONFIG_CPU_FREQ_PMAC64) += pmac64-cpufreq.o diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c index 8500627..9d0aa19 100644 --- a/drivers/cpufreq/ppc-corenet-cpufreq.c +++ b/drivers/cpufreq/qoriq-cpufreq.c @@ -1,7 +1,7 @@ /* * Copyright 2013 Freescale Semiconductor, Inc. * - * CPU Frequency Scaling driver for Freescale PowerPC corenet SoCs. + * CPU Frequency Scaling driver for Freescale QorIQ SoCs. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,7 +13,6 @@ #include <linux/clk.h> #include <linux/cpufreq.h> #include <linux/errno.h> -#include <sysdev/fsl_soc.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> @@ -73,17 +72,7 @@ static const u32 *fmask; static DEFINE_MUTEX(cpufreq_lock); static DEFINE_PER_CPU(struct cpu_data *, cpu_data); -/* cpumask in a cluster */ -static DEFINE_PER_CPU(cpumask_var_t, cpu_mask); - -#ifndef CONFIG_SMP -static inline const struct cpumask *cpu_core_mask(int cpu) -{ - return cpumask_of(0); -} -#endif - -static unsigned int corenet_cpufreq_get_speed(unsigned int cpu) +static unsigned int qoriq_cpufreq_get_speed(unsigned int cpu) { struct cpu_data *data = per_cpu(cpu_data, cpu); @@ -140,7 +129,80 @@ static void freq_table_sort(struct cpufreq_frequency_table *freq_table, } } -static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) +#if defined(CONFIG_ARM) +static int get_cpu_physical_id(int cpu) +{ + return topology_core_id(cpu); +} +#else +static int get_cpu_physical_id(int cpu) +{ + return get_hard_smp_processor_id(cpu); +} +#endif + +static u32 get_bus_freq(void) +{ + struct device_node *soc; + u32 sysfreq; + + soc = of_find_node_by_type(NULL, "soc"); + if (!soc) + return 0; + + if (of_property_read_u32(soc, "bus-frequency", &sysfreq)) + sysfreq = 0; + + of_node_put(soc); + + return sysfreq; +} + +static struct device_node *cpu_to_clk_node(int cpu) +{ + struct device_node *np, *clk_np; + + if (!cpu_present(cpu)) + return NULL; + + np = of_get_cpu_node(cpu, NULL); + if (!np) + return NULL; + + clk_np = of_parse_phandle(np, "clocks", 0); + if (!clk_np) + return NULL; + + of_node_put(np); + + return clk_np; +} + +/* traverse cpu nodes to get cpu mask of sharing clock wire */ +static void set_affected_cpus(struct cpufreq_policy *policy) +{ + struct device_node *np, *clk_np; + struct cpumask *dstp = policy->cpus; + int i; + + np = cpu_to_clk_node(policy->cpu); + if (!np) + return; + + for_each_present_cpu(i) { + clk_np = cpu_to_clk_node(i); + if (!clk_np) + continue; + + if (clk_np == np) + cpumask_set_cpu(i, dstp); + + of_node_put(clk_np); + } + of_node_put(np); +} + +static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) { struct device_node *np; int i, count, ret; @@ -181,7 +243,7 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) } if (fmask) - mask = fmask[get_hard_smp_processor_id(cpu)]; + mask = fmask[get_cpu_physical_id(cpu)]; else mask = 0x0; @@ -213,15 +275,15 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy) per_cpu(cpu_data, cpu) = data; /* update ->cpus if we have cluster, no harm if not */ - cpumask_copy(policy->cpus, per_cpu(cpu_mask, cpu)); - for_each_cpu(i, per_cpu(cpu_mask, cpu)) + set_affected_cpus(policy); + for_each_cpu(i, policy->cpus) per_cpu(cpu_data, i) = data; /* Minimum transition latency is 12 platform clocks */ u64temp = 12ULL * NSEC_PER_SEC; - do_div(u64temp, fsl_get_sys_freq()); + do_div(u64temp, get_bus_freq()); policy->cpuinfo.transition_latency = u64temp + 1; - policy->cur = corenet_cpufreq_get_speed(policy->cpu); + policy->cur = qoriq_cpufreq_get_speed(policy->cpu); cpufreq_frequency_table_get_attr(table, cpu); of_node_put(np); @@ -241,23 +303,19 @@ err_np: return -ENODEV; } -static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy) +static int __exit qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy) { struct cpu_data *data = per_cpu(cpu_data, policy->cpu); - unsigned int cpu; cpufreq_frequency_table_put_attr(policy->cpu); of_node_put(data->parent); kfree(data->table); kfree(data); - for_each_cpu(cpu, per_cpu(cpu_mask, policy->cpu)) - per_cpu(cpu_data, cpu) = NULL; - return 0; } -static int corenet_cpufreq_verify(struct cpufreq_policy *policy) +static int qoriq_cpufreq_verify(struct cpufreq_policy *policy) { struct cpufreq_frequency_table *table = per_cpu(cpu_data, policy->cpu)->table; @@ -265,7 +323,7 @@ static int corenet_cpufreq_verify(struct cpufreq_policy *policy) return cpufreq_frequency_table_verify(policy, table); } -static int corenet_cpufreq_target(struct cpufreq_policy *policy, +static int qoriq_cpufreq_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { struct cpufreq_freqs freqs; @@ -297,20 +355,20 @@ static int corenet_cpufreq_target(struct cpufreq_policy *policy, return ret; } -static struct freq_attr *corenet_cpufreq_attr[] = { +static struct freq_attr *qoriq_cpufreq_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, NULL, }; -static struct cpufreq_driver ppc_corenet_cpufreq_driver = { - .name = "ppc_cpufreq", +static struct cpufreq_driver qoriq_cpufreq_driver = { + .name = "qoriq_cpufreq", .flags = CPUFREQ_CONST_LOOPS, - .init = corenet_cpufreq_cpu_init, - .exit = __exit_p(corenet_cpufreq_cpu_exit), - .verify = corenet_cpufreq_verify, - .target = corenet_cpufreq_target, - .get = corenet_cpufreq_get_speed, - .attr = corenet_cpufreq_attr, + .init = qoriq_cpufreq_cpu_init, + .exit = __exit_p(qoriq_cpufreq_cpu_exit), + .verify = qoriq_cpufreq_verify, + .target = qoriq_cpufreq_target, + .get = qoriq_cpufreq_get_speed, + .attr = qoriq_cpufreq_attr, }; static const struct of_device_id node_matches[] __initdata = { @@ -320,63 +378,46 @@ static const struct of_device_id node_matches[] __initdata = { { .compatible = "fsl,p4080-clockgen", .data = &sdata[2], }, { .compatible = "fsl,p5040-clockgen", .data = &sdata[2], }, { .compatible = "fsl,qoriq-clockgen-2.0", }, + { .compatible = "fsl,ls1021a-clockgen", }, {} }; -static int __init ppc_corenet_cpufreq_init(void) +static int __init qoriq_cpufreq_init(void) { int ret; struct device_node *np; const struct of_device_id *match; const struct soc_data *data; - unsigned int cpu; np = of_find_matching_node(NULL, node_matches); if (!np) return -ENODEV; - for_each_possible_cpu(cpu) { - if (!alloc_cpumask_var(&per_cpu(cpu_mask, cpu), GFP_KERNEL)) - goto err_mask; - cpumask_copy(per_cpu(cpu_mask, cpu), cpu_core_mask(cpu)); - } - match = of_match_node(node_matches, np); data = match->data; if (data) { if (data->flag) fmask = data->freq_mask; - min_cpufreq = fsl_get_sys_freq(); + min_cpufreq = get_bus_freq(); } else { - min_cpufreq = fsl_get_sys_freq() / 2; + min_cpufreq = get_bus_freq() / 2; } of_node_put(np); - ret = cpufreq_register_driver(&ppc_corenet_cpufreq_driver); + ret = cpufreq_register_driver(&qoriq_cpufreq_driver); if (!ret) - pr_info("Freescale PowerPC corenet CPU frequency scaling driver\n"); + pr_info("Freescale PowerPC qoriq CPU frequency scaling driver\n"); return ret; - -err_mask: - for_each_possible_cpu(cpu) - free_cpumask_var(per_cpu(cpu_mask, cpu)); - - return -ENOMEM; } -module_init(ppc_corenet_cpufreq_init); +module_init(qoriq_cpufreq_init); -static void __exit ppc_corenet_cpufreq_exit(void) +static void __exit qoriq_cpufreq_exit(void) { - unsigned int cpu; - - for_each_possible_cpu(cpu) - free_cpumask_var(per_cpu(cpu_mask, cpu)); - - cpufreq_unregister_driver(&ppc_corenet_cpufreq_driver); + cpufreq_unregister_driver(&qoriq_cpufreq_driver); } -module_exit(ppc_corenet_cpufreq_exit); +module_exit(qoriq_cpufreq_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>"); |