From patchwork Mon Dec 12 03:42:27 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Zhao X-Patchwork-Id: 5581 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id D8E9A23E03 for ; Mon, 12 Dec 2011 03:42:54 +0000 (UTC) Received: from mail-bw0-f52.google.com (mail-bw0-f52.google.com [209.85.214.52]) by fiordland.canonical.com (Postfix) with ESMTP id C90DAA18566 for ; Mon, 12 Dec 2011 03:42:54 +0000 (UTC) Received: by mail-bw0-f52.google.com with SMTP id 17so6647003bke.11 for ; Sun, 11 Dec 2011 19:42:54 -0800 (PST) Received: by 10.204.156.208 with SMTP id y16mr8872195bkw.72.1323661374621; Sun, 11 Dec 2011 19:42:54 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.205.129.2 with SMTP id hg2cs36492bkc; Sun, 11 Dec 2011 19:42:54 -0800 (PST) Received: by 10.68.72.99 with SMTP id c3mr29591065pbv.122.1323661371728; Sun, 11 Dec 2011 19:42:51 -0800 (PST) Received: from TX2EHSOBE002.bigfish.com (tx2ehsobe001.messaging.microsoft.com. [65.55.88.11]) by mx.google.com with ESMTPS id k1si21697474pbh.235.2011.12.11.19.42.50 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 11 Dec 2011 19:42:51 -0800 (PST) Received-SPF: neutral (google.com: 65.55.88.11 is neither permitted nor denied by best guess record for domain of richard.zhao@linaro.org) client-ip=65.55.88.11; Authentication-Results: mx.google.com; spf=neutral (google.com: 65.55.88.11 is neither permitted nor denied by best guess record for domain of richard.zhao@linaro.org) smtp.mail=richard.zhao@linaro.org Received: from mail96-tx2-R.bigfish.com (10.9.14.245) by TX2EHSOBE002.bigfish.com (10.9.40.22) with Microsoft SMTP Server id 14.1.225.23; Mon, 12 Dec 2011 03:42:48 +0000 Received: from mail96-tx2 (localhost [127.0.0.1]) by mail96-tx2-R.bigfish.com (Postfix) with ESMTP id 85AED3603B7; Mon, 12 Dec 2011 03:42:48 +0000 (UTC) X-SpamScore: 0 X-BigFish: VS0(zzzz1202hzz8275dhz2dh87h2a8h668h839h61h) X-Spam-TCS-SCL: 0:0 X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-FB-SS: 0, X-FB-DOMAIN-IP-MATCH: fail Received: from mail96-tx2 (localhost.localdomain [127.0.0.1]) by mail96-tx2 (MessageSwitch) id 1323661367958313_13418; Mon, 12 Dec 2011 03:42:47 +0000 (UTC) Received: from TX2EHSMHS018.bigfish.com (unknown [10.9.14.242]) by mail96-tx2.bigfish.com (Postfix) with ESMTP id DA7D5320043; Mon, 12 Dec 2011 03:42:47 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by TX2EHSMHS018.bigfish.com (10.9.99.118) with Microsoft SMTP Server (TLS) id 14.1.225.23; Mon, 12 Dec 2011 03:42:49 +0000 Received: from az33smr01.freescale.net (10.64.34.199) by 039-SN1MMR1-003.039d.mgd.msft.net (10.84.1.16) with Microsoft SMTP Server id 14.1.355.3; Sun, 11 Dec 2011 21:42:48 -0600 Received: from b20223-02.ap.freescale.net (b20223-02.ap.freescale.net [10.192.242.124]) by az33smr01.freescale.net (8.13.1/8.13.0) with ESMTP id pBC3geqE019860; Sun, 11 Dec 2011 21:42:46 -0600 (CST) From: Richard Zhao To: CC: , , , , , Richard Zhao Subject: [PATCH 2/7] arm/imx: cpufreq: add multi-core support Date: Mon, 12 Dec 2011 11:42:27 +0800 Message-ID: <1323661352-10291-3-git-send-email-richard.zhao@linaro.org> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1323661352-10291-1-git-send-email-richard.zhao@linaro.org> References: <1323661352-10291-1-git-send-email-richard.zhao@linaro.org> MIME-Version: 1.0 X-OriginatorOrg: sigmatel.com Signed-off-by: Richard Zhao --- arch/arm/plat-mxc/cpufreq.c | 99 ++++++++++++++++++++++++++++-------------- 1 files changed, 66 insertions(+), 33 deletions(-) diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c index 74aac96..122b21a 100644 --- a/arch/arm/plat-mxc/cpufreq.c +++ b/arch/arm/plat-mxc/cpufreq.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,7 @@ static int cpu_freq_khz_min; static int cpu_freq_khz_max; static struct clk *cpu_clk; +static DEFINE_MUTEX(cpu_lock); static struct cpufreq_frequency_table *imx_freq_table; static int cpu_op_nr; @@ -58,17 +60,11 @@ static int set_cpu_freq(int freq) static int mxc_verify_speed(struct cpufreq_policy *policy) { - if (policy->cpu != 0) - return -EINVAL; - return cpufreq_frequency_table_verify(policy, imx_freq_table); } static unsigned int mxc_get_speed(unsigned int cpu) { - if (cpu) - return 0; - return clk_get_rate(cpu_clk) / 1000; } @@ -76,23 +72,49 @@ static int mxc_set_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation) { struct cpufreq_freqs freqs; - int freq_Hz; + int freq_Hz, cpu; int ret = 0; unsigned int index; + mutex_lock(&cpu_lock); + cpufreq_frequency_table_target(policy, imx_freq_table, target_freq, relation, &index); freq_Hz = imx_freq_table[index].frequency * 1000; freqs.old = clk_get_rate(cpu_clk) / 1000; - freqs.new = freq_Hz / 1000; - freqs.cpu = 0; + freqs.new = clk_round_rate(cpu_clk, freq_Hz); + freqs.new = (freqs.new ? freqs.new : freq_Hz) / 1000; freqs.flags = 0; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + if (freqs.old == freqs.new) { + mutex_unlock(&cpu_lock); + return 0; + } + + for_each_possible_cpu(cpu) { + freqs.cpu = cpu; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } ret = set_cpu_freq(freq_Hz); - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); +#ifdef CONFIG_SMP + /* loops_per_jiffy is not updated by the cpufreq core for SMP systems. + * So update it for all CPUs. + */ + for_each_possible_cpu(cpu) + per_cpu(cpu_data, cpu).loops_per_jiffy = + cpufreq_scale(per_cpu(cpu_data, cpu).loops_per_jiffy, + freqs.old, freqs.new); +#endif + + for_each_possible_cpu(cpu) { + freqs.cpu = cpu; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } + + mutex_unlock(&cpu_lock); return ret; } @@ -104,7 +126,7 @@ static int __init mxc_cpufreq_init(struct cpufreq_policy *policy) printk(KERN_INFO "i.MXC CPU frequency driver\n"); - if (policy->cpu != 0) + if (policy->cpu >= num_possible_cpus()) return -EINVAL; if (!get_cpu_op) @@ -116,37 +138,45 @@ static int __init mxc_cpufreq_init(struct cpufreq_policy *policy) return PTR_ERR(cpu_clk); } - cpu_op_tbl = get_cpu_op(&cpu_op_nr); + mutex_lock(&cpu_lock); + if (!imx_freq_table) { + cpu_op_tbl = get_cpu_op(&cpu_op_nr); - cpu_freq_khz_min = cpu_op_tbl[0].cpu_rate / 1000; - cpu_freq_khz_max = cpu_op_tbl[0].cpu_rate / 1000; + cpu_freq_khz_min = cpu_op_tbl[0].cpu_rate / 1000; + cpu_freq_khz_max = cpu_op_tbl[0].cpu_rate / 1000; - imx_freq_table = kmalloc( - sizeof(struct cpufreq_frequency_table) * (cpu_op_nr + 1), - GFP_KERNEL); - if (!imx_freq_table) { - ret = -ENOMEM; - goto err1; - } + imx_freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) + * (cpu_op_nr + 1), GFP_KERNEL); + if (!imx_freq_table) { + ret = -ENOMEM; + mutex_unlock(&cpu_lock); + goto err1; + } - for (i = 0; i < cpu_op_nr; i++) { - imx_freq_table[i].index = i; - imx_freq_table[i].frequency = cpu_op_tbl[i].cpu_rate / 1000; + for (i = 0; i < cpu_op_nr; i++) { + imx_freq_table[i].index = i; + imx_freq_table[i].frequency = + cpu_op_tbl[i].cpu_rate / 1000; - if ((cpu_op_tbl[i].cpu_rate / 1000) < cpu_freq_khz_min) - cpu_freq_khz_min = cpu_op_tbl[i].cpu_rate / 1000; + if ((cpu_op_tbl[i].cpu_rate / 1000) < cpu_freq_khz_min) + cpu_freq_khz_min = + cpu_op_tbl[i].cpu_rate / 1000; - if ((cpu_op_tbl[i].cpu_rate / 1000) > cpu_freq_khz_max) - cpu_freq_khz_max = cpu_op_tbl[i].cpu_rate / 1000; - } + if ((cpu_op_tbl[i].cpu_rate / 1000) > cpu_freq_khz_max) + cpu_freq_khz_max = + cpu_op_tbl[i].cpu_rate / 1000; + } - imx_freq_table[i].index = i; - imx_freq_table[i].frequency = CPUFREQ_TABLE_END; + imx_freq_table[i].index = i; + imx_freq_table[i].frequency = CPUFREQ_TABLE_END; + } + mutex_unlock(&cpu_lock); policy->cur = clk_get_rate(cpu_clk) / 1000; policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min; policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max; - + policy->shared_type = CPUFREQ_SHARED_TYPE_ANY; + cpumask_setall(policy->cpus); /* Manual states, that PLL stabilizes in two CLK32 periods */ policy->cpuinfo.transition_latency = 2 * NANOSECOND / CLK32_FREQ; @@ -173,7 +203,10 @@ static int mxc_cpufreq_exit(struct cpufreq_policy *policy) set_cpu_freq(cpu_freq_khz_max * 1000); clk_put(cpu_clk); + mutex_lock(&cpu_lock); kfree(imx_freq_table); + imx_freq_table = NULL; + mutex_unlock(&cpu_lock); return 0; }