From patchwork Wed Sep 9 20:27:05 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ashwin Chaugule X-Patchwork-Id: 53333 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f200.google.com (mail-lb0-f200.google.com [209.85.217.200]) by patches.linaro.org (Postfix) with ESMTPS id B0D9322B19 for ; Wed, 9 Sep 2015 20:27:29 +0000 (UTC) Received: by lbcjc2 with SMTP id jc2sf7253188lbc.0 for ; Wed, 09 Sep 2015 13:27:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:in-reply-to:references :x-original-sender:x-original-authentication-results:precedence :mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=H0jJHEBxbv7jfIsp0KfnE6zfflYEJohHIZWy9Cc7/kA=; b=b5Yf5Z25Wce8FB3Bnq6quAZrsBu6HfLc/9eFBDOBGjOBF1Nx3aHknJ54R8VzCS8RDV QdDGI0xulhT3nN5itL1ZN6JXpMps277wJdVG9MinTvwXIsdLtM3QRBM8mQ3QGj+jFaxj SaMA+R+v6tmH+RmegoFhddSaK0VG3Kjq0PUPmRWT7EB3//EObhtQqQHinCsQaxQa8Hs9 MfTWKglpRsPnHgXtMXs7Emq+rTZ/IiQ/173+7qlKcW9N0Ybc7wwvN7KSye52EazAJ/15 vpDGQTWQJGf2yS0qL5c4hwLu6iITeWlLbT6acbQPOpdDUO3j4QJOVTP28m3GprLg7PUy d01Q== X-Gm-Message-State: ALoCoQnGVQRxKKcLgwTtKNCUCAOzPxFljeSIPdsMdR8qK7Ur7UyP90bklzKf4voOHrX05rPo20EE X-Received: by 10.112.144.99 with SMTP id sl3mr8521804lbb.12.1441830448295; Wed, 09 Sep 2015 13:27:28 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.9.66 with SMTP id x2ls55266laa.107.gmail; Wed, 09 Sep 2015 13:27:28 -0700 (PDT) X-Received: by 10.152.43.198 with SMTP id y6mr30314881lal.41.1441830448137; Wed, 09 Sep 2015 13:27:28 -0700 (PDT) Received: from mail-la0-f41.google.com (mail-la0-f41.google.com. [209.85.215.41]) by mx.google.com with ESMTPS id j9si7811431lam.16.2015.09.09.13.27.28 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 09 Sep 2015 13:27:28 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.41 as permitted sender) client-ip=209.85.215.41; Received: by lamp12 with SMTP id p12so14395756lam.0 for ; Wed, 09 Sep 2015 13:27:28 -0700 (PDT) X-Received: by 10.152.161.232 with SMTP id xv8mr14540192lab.32.1441830448032; Wed, 09 Sep 2015 13:27:28 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.112.59.35 with SMTP id w3csp541950lbq; Wed, 9 Sep 2015 13:27:26 -0700 (PDT) X-Received: by 10.66.65.234 with SMTP id a10mr65259742pat.2.1441830442822; Wed, 09 Sep 2015 13:27:22 -0700 (PDT) Received: from mail-pa0-f47.google.com (mail-pa0-f47.google.com. [209.85.220.47]) by mx.google.com with ESMTPS id bu8si13435902pad.7.2015.09.09.13.27.21 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 09 Sep 2015 13:27:22 -0700 (PDT) Received-SPF: pass (google.com: domain of ashwin.chaugule@linaro.org designates 209.85.220.47 as permitted sender) client-ip=209.85.220.47; Received: by padhy16 with SMTP id hy16so19989673pad.1 for ; Wed, 09 Sep 2015 13:27:21 -0700 (PDT) X-Received: by 10.67.4.98 with SMTP id cd2mr64457764pad.43.1441830441891; Wed, 09 Sep 2015 13:27:21 -0700 (PDT) Received: from esagroth.qualcomm.com (rrcs-67-52-130-30.west.biz.rr.com. [67.52.130.30]) by smtp.gmail.com with ESMTPSA id md10sm7992049pdb.0.2015.09.09.13.27.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 09 Sep 2015 13:27:20 -0700 (PDT) From: Ashwin Chaugule To: rjw@rjwysocki.net Cc: sudeep.holla@arm.com, linux-pm@vger.kernel.org, linux-acpi@vger.kernel.org, linaro-acpi@lists.linaro.org, patches@linaro.org, viresh.kumar@linaro.org, rwells@codeaurora.org, Ashwin Chaugule Subject: [PATCH v9 2/5] CPPC: Add a CPUFreq driver for use with CPPC Date: Wed, 9 Sep 2015 16:27:05 -0400 Message-Id: <6d24b51b0387f4ef6cc4a2517ace2e5e9731d7be.1441830300.git.ashwin.chaugule@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: References: In-Reply-To: References: X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ashwin.chaugule@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.41 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , This driver utilizes the methods introduced in the previous patch - "ACPI: Introduce CPU performance controls using CPPC" and enables usage with existing CPUFreq governors. Signed-off-by: Ashwin Chaugule Reviewed-by: Al Stone --- drivers/cpufreq/Kconfig.arm | 17 +++++ drivers/cpufreq/Makefile | 2 + drivers/cpufreq/cppc_cpufreq.c | 169 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 188 insertions(+) create mode 100644 drivers/cpufreq/cppc_cpufreq.c diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index cc8a71c..e8bb41b 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -261,3 +261,20 @@ config ARM_PXA2xx_CPUFREQ This add the CPUFreq driver support for Intel PXA2xx SOCs. If in doubt, say N. + +config ACPI_CPPC_CPUFREQ + tristate "CPUFreq driver based on the ACPI CPPC spec" + depends on ACPI + select ACPI_CPPC_LIB + default n + help + This adds a CPUFreq driver which uses CPPC methods + as described in the ACPIv5.1 spec. CPPC stands for + Collaborative Processor Performance Controls. It + is based on an abstract continuous scale of CPU + performance values which allows the remote power + processor to flexibly optimize for power and + performance. CPPC relies on power management firmware + support for its operation. + + If in doubt, say N. diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 2169bf7..676660e 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -78,6 +78,8 @@ obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o obj-$(CONFIG_ARM_TEGRA_CPUFREQ) += tegra-cpufreq.o obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o +obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o + ################################################################################## # PowerPC platform drivers diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c new file mode 100644 index 0000000..2f6ed0b --- /dev/null +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -0,0 +1,169 @@ +/* + * CPPC (Collaborative Processor Performance Control) driver for + * interfacing with the CPUfreq layer and governors. See + * cppc_acpi.c for CPPC specific methods. + * + * (C) Copyright 2014, 2015 Linaro Ltd. + * Author: Ashwin Chaugule + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + */ + +#define pr_fmt(fmt) "CPPC Cpufreq:" fmt + +#include +#include +#include +#include +#include +#include + +#include + +/* + * These structs contain information parsed from per CPU + * ACPI _CPC structures. + * e.g. For each CPU the highest, lowest supported + * performance capabilities, desired performance level + * requested etc. + */ +static struct cpudata **all_cpu_data; + +static int cppc_cpufreq_set_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct cpudata *cpu; + struct cpufreq_freqs freqs; + int ret = 0; + + cpu = all_cpu_data[policy->cpu]; + + cpu->perf_ctrls.desired_perf = target_freq; + freqs.old = policy->cur; + freqs.new = target_freq; + + cpufreq_freq_transition_begin(policy, &freqs); + ret = cppc_set_perf(cpu->cpu, &cpu->perf_ctrls); + cpufreq_freq_transition_end(policy, &freqs, ret != 0); + + if (ret) { + pr_debug("Failed to set target on CPU:%d. ret:%d\n", + cpu->cpu, ret); + return -EFAULT; + } + + return ret; +} + +static int cppc_verify_policy(struct cpufreq_policy *policy) +{ + cpufreq_verify_within_cpu_limits(policy); + return 0; +} + +static void cppc_cpufreq_stop_cpu(struct cpufreq_policy *policy) +{ + int cpu_num = policy->cpu; + struct cpudata *cpu = all_cpu_data[cpu_num]; + int ret; + + pr_info("CPU %d exiting\n", cpu_num); + + cpu->perf_ctrls.desired_perf = cpu->perf_caps.lowest_perf; + + ret = cppc_set_perf(cpu_num, &cpu->perf_ctrls); + if (ret) + pr_err("Err setting perf value:%d on CPU:%d. ret:%d\n", + cpu->perf_caps.lowest_perf, cpu_num, ret); +} + +static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + struct cpudata *cpu; + int ret = 0; + + cpu = all_cpu_data[policy->cpu]; + + cpu->cpu = policy->cpu; + ret = cppc_get_perf_caps(policy->cpu, &cpu->perf_caps); + + if (ret) { + pr_err("Err reading CPU%d perf capabilities. ret:%d\n", + cpu->cpu, ret); + return -FAULT; + } + + policy->min = cpu->perf_caps.lowest_perf; + policy->max = cpu->perf_caps.highest_perf; + policy->cpuinfo.min_freq = policy->min; + policy->cpuinfo.max_freq = policy->max; + + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL || + policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + cpumask_copy(policy->cpus, cpu->shared_cpu_map); + + cpumask_set_cpu(policy->cpu, policy->cpus); + cpu->cur_policy = policy; + + pr_debug("Initialized on cpu:%d\n", cpu->cpu); + return ret; +} + +static struct cpufreq_driver cppc_cpufreq_driver = { + .flags = CPUFREQ_CONST_LOOPS, + .verify = cppc_verify_policy, + .target = cppc_cpufreq_set_target, + .init = cppc_cpufreq_cpu_init, + .stop_cpu = cppc_cpufreq_stop_cpu, + .name = "cppc_cpufreq", +}; + +static int __init cppc_cpufreq_init(void) +{ + int i, ret = 0; + struct cpudata *cpu; + + if (acpi_disabled) + return -ENODEV; + + all_cpu_data = vzalloc(sizeof(void *) * num_possible_cpus()); + if (!all_cpu_data) + return -ENOMEM; + + for_each_possible_cpu(i) { + all_cpu_data[i] = kzalloc(sizeof(struct cpudata), GFP_KERNEL); + if (!all_cpu_data[i]) + goto out; + + cpu = all_cpu_data[i]; + if (!zalloc_cpumask_var(&cpu->shared_cpu_map, GFP_KERNEL)) + goto out; + } + + ret = acpi_get_psd_map(all_cpu_data); + if (ret) { + pr_debug("Error parsing PSD data. Aborting cpufreq registration.\n"); + goto out; + } + + ret = cpufreq_register_driver(&cppc_cpufreq_driver); + if (ret) + goto out; + + pr_info("Registration completed.\n"); + return ret; + +out: + for_each_possible_cpu(i) + if (all_cpu_data[i]) + kfree(all_cpu_data[i]); + + vfree(all_cpu_data); + return -ENODEV; +} + +late_initcall(cppc_cpufreq_init);