From patchwork Tue Dec 13 06:25:26 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Zhao X-Patchwork-Id: 5619 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 426D223E0E for ; Tue, 13 Dec 2011 06:26:01 +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 33013A18293 for ; Tue, 13 Dec 2011 06:26:01 +0000 (UTC) Received: by mail-bw0-f52.google.com with SMTP id 17so8656841bke.11 for ; Mon, 12 Dec 2011 22:26:01 -0800 (PST) Received: by 10.205.129.137 with SMTP id hi9mr3707722bkc.90.1323757561018; Mon, 12 Dec 2011 22:26:01 -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 hg2cs70751bkc; Mon, 12 Dec 2011 22:26:00 -0800 (PST) Received: by 10.180.4.37 with SMTP id h5mr25238702wih.45.1323757559592; Mon, 12 Dec 2011 22:25:59 -0800 (PST) Received: from DB3EHSOBE002.bigfish.com (db3ehsobe002.messaging.microsoft.com. [213.199.154.140]) by mx.google.com with ESMTPS id z3si13026843wid.36.2011.12.12.22.25.59 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 12 Dec 2011 22:25:59 -0800 (PST) Received-SPF: neutral (google.com: 213.199.154.140 is neither permitted nor denied by best guess record for domain of richard.zhao@linaro.org) client-ip=213.199.154.140; Authentication-Results: mx.google.com; spf=neutral (google.com: 213.199.154.140 is neither permitted nor denied by best guess record for domain of richard.zhao@linaro.org) smtp.mail=richard.zhao@linaro.org Received: from mail83-db3-R.bigfish.com (10.3.81.246) by DB3EHSOBE002.bigfish.com (10.3.84.22) with Microsoft SMTP Server id 14.1.225.23; Tue, 13 Dec 2011 06:25:55 +0000 Received: from mail83-db3 (localhost [127.0.0.1]) by mail83-db3-R.bigfish.com (Postfix) with ESMTP id B302F2002BA; Tue, 13 Dec 2011 06:25:55 +0000 (UTC) X-SpamScore: 0 X-BigFish: VS0(zzzz1202hzz8275dhz2dh87h2a8h668h839h) 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-DOMAIN-IP-MATCH: fail Received: from mail83-db3 (localhost.localdomain [127.0.0.1]) by mail83-db3 (MessageSwitch) id 1323757555534026_25305; Tue, 13 Dec 2011 06:25:55 +0000 (UTC) Received: from DB3EHSMHS012.bigfish.com (unknown [10.3.81.241]) by mail83-db3.bigfish.com (Postfix) with ESMTP id 7388E3C0042; Tue, 13 Dec 2011 06:25:55 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by DB3EHSMHS012.bigfish.com (10.3.87.112) with Microsoft SMTP Server (TLS) id 14.1.225.23; Tue, 13 Dec 2011 06:25:55 +0000 Received: from az33smr01.freescale.net (10.64.34.199) by 039-SN1MMR1-002.039d.mgd.msft.net (10.84.1.15) with Microsoft SMTP Server id 14.1.355.3; Tue, 13 Dec 2011 00:25:56 -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 pBD6PjOL010279; Tue, 13 Dec 2011 00:25:54 -0600 (CST) From: Richard Zhao To: CC: , , , , , Subject: [PATCH V2 3/7] arm/imx: cpufreq: add multi-core support Date: Tue, 13 Dec 2011 14:25:26 +0800 Message-ID: <1323757530-19402-4-git-send-email-richard.zhao@linaro.org> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1323757530-19402-1-git-send-email-richard.zhao@linaro.org> References: <1323757530-19402-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 adbff70..85d037f 100644 --- a/arch/arm/plat-mxc/cpufreq.c +++ b/arch/arm/plat-mxc/cpufreq.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,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; @@ -59,17 +61,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; } @@ -77,23 +73,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; } @@ -105,7 +127,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) @@ -117,37 +139,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; @@ -174,7 +204,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; }