Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp1770389imu; Thu, 17 Jan 2019 03:02:41 -0800 (PST) X-Google-Smtp-Source: ALg8bN6pfCQzkoFAmQm5iyyHxv8wSkLRFy5HLsHDUTOaEnNig/p5uFj64jxHMCpn8MDFh9KKy5SF X-Received: by 2002:a17:902:4681:: with SMTP id p1mr14860219pld.184.1547722960994; Thu, 17 Jan 2019 03:02:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1547722960; cv=none; d=google.com; s=arc-20160816; b=ItBP4c5P2ZzmX1bHXOXOZyInl6qrkIDGT9XatwueIB3DonUnad7Jgy8svBbSzLq34I iIG5E8wwScrsE2GGIU+Yauppij/mJ5N81ENJEA2KpZ6L/dy5vQiwV2UwpwLwcF7nj/jn c9qtTpMxNHd4s9OKZbOj3FfGVw3RdjjXL0ZN63xGVsoVwO3nsSTxs0+CWYvYD3nSpUZQ iUBoeaDJ6+8iQNiZ5YnV+MoDuQWN99IUiObTifM7UF49h6htZrIAePTKHA/HDlypLIyQ 5uaRocbcMVfhHRJvfqa+SXlAS3W7bGpW9gGZQt808fB4nak4wRJEoZQqfnALWp2u2hgC S7+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:message-id:date:subject:cc :to:from; bh=NhRuMVa5B5hVHQIHdTOdQ3J74p8Fr7hYICqngTWA66c=; b=uKdQUD8OVlxokjmmrkxDaY6Mgq5dyNAxGys59yaCnfgam94M4gemVICGsascYCgmj9 Ct/BRgpJhz9vLAVXps6N3ab5Cnhxxf3I/GWLPonTKS2nVP2q0IgigcyP9pFq5jpgvwxR yrvWmuG4KjZkbKsqwnlvLtUDTOGrdTmSZVTYY6kPlPQuIPkDPPdj8pX7EYXs+oNCmoXd magqxOWYYd2vFoJrYFXMxLR7wwyZyIKRt4dmeCb95GkZkDPc5xlSjwbUyI026mc9ZHKK jvSnczm5F0hVl2yNq3wdCxuVO2A7cFNcBkU770vGalUbthLb/qma9H7cPa8tou9lUOYd 3mTQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 76si1430035pfw.66.2019.01.17.03.02.23; Thu, 17 Jan 2019 03:02:40 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728828AbfAQLAu (ORCPT + 99 others); Thu, 17 Jan 2019 06:00:50 -0500 Received: from szxga04-in.huawei.com ([45.249.212.190]:2185 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728460AbfAQLAu (ORCPT ); Thu, 17 Jan 2019 06:00:50 -0500 Received: from DGGEMS401-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id C7AD4237E2186A6AD862; Thu, 17 Jan 2019 19:00:46 +0800 (CST) Received: from linux-ibm.site (10.175.102.37) by DGGEMS401-HUB.china.huawei.com (10.3.19.201) with Microsoft SMTP Server id 14.3.408.0; Thu, 17 Jan 2019 19:00:39 +0800 From: Xiongfeng Wang To: , , , CC: , , , , Subject: [RFC PATCH] cpufreq / cppc: Work around for Hisilicon CPPC cpufreq Date: Thu, 17 Jan 2019 19:00:11 +0800 Message-ID: <1547722811-18052-1-git-send-email-wangxiongfeng2@huawei.com> X-Mailer: git-send-email 1.7.12.4 MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.175.102.37] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hisilicon chips do not support delivered performance counter register and reference performance counter register. But the platform can calculate the real performance using its own method. This patch provide a workaround for this problem, and other platforms can also use this workaround framework. We reuse the desired performance register to store the real performance calculated by the platform. After the platform finished the frequency adjust, it gets the real performance and writes it into desired performance register. OS can use it to calculate the real frequency. Signed-off-by: Xiongfeng Wang --- drivers/acpi/cppc_acpi.c | 29 ++++++++++++++++++++ drivers/cpufreq/Kconfig.arm | 7 +++++ drivers/cpufreq/cppc_cpufreq.c | 62 ++++++++++++++++++++++++++++++++++++++++++ include/acpi/cppc_acpi.h | 4 +++ 4 files changed, 102 insertions(+) diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 217a782..0cdaf7e 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -1050,6 +1050,35 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) return ret_val; } +#ifdef CONFIG_HISILICON_CPPC_CPUFREQ_WORKAROUND +/* + * We reuse the desired performance register to store the real performance + * calculated by the platform. + */ +u64 hisi_cppc_get_real_perf(unsigned int cpunum) +{ + int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum); + struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum); + struct cpc_register_resource *desired_reg; + u64 desired_perf; + int ret; + + /* + * Make sure the platform has finished the frequency adjust + * and wrote the real performance in desired performance register + */ + ret = check_pcc_chan(pcc_ss_id, false); + if (ret) + return 0; + + desired_reg = &cpc_desc->cpc_regs[DESIRED_PERF]; + cpc_read(cpunum, desired_reg, &desired_perf); + + return desired_perf; +} +EXPORT_SYMBOL_GPL(hisi_cppc_get_real_perf); +#endif + /** * cppc_get_perf_caps - Get a CPUs performance capabilities. * @cpunum: CPU from which to get capabilities info. diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 688f102..236bd07 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -18,6 +18,13 @@ config ACPI_CPPC_CPUFREQ If in doubt, say N. +config HISILICON_CPPC_CPUFREQ_WORKAROUND + bool "Workaround for Hisilicon CPPC Cpufreq" + default y + depends on ACPI_CPPC_CPUFREQ && ARM64 + help + This option enables a workaround for Hisilicon CPPC Cpufreq. + config ARM_ARMADA_37XX_CPUFREQ tristate "Armada 37xx CPUFreq support" depends on ARCH_MVEBU && CPUFREQ_DT diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index fd25c21c..b910e84 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -33,6 +33,13 @@ /* Offest in the DMI processor structure for the max frequency */ #define DMI_PROCESSOR_MAX_SPEED 0x14 +struct cppc_get_rate_workaround_info { + char oem_id[ACPI_OEM_ID_SIZE +1]; + char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; + u32 oem_revision; + unsigned int (*get)(unsigned int cpu); +}; + /* * These structs contain information parsed from per CPU * ACPI _CPC structures. @@ -357,6 +364,59 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpunum) .name = "cppc_cpufreq", }; +#ifdef CONFIG_HISILICON_CPPC_CPUFREQ_WORKAROUND +/* + * When the platform does not support delivered performance counter or + * reference performance counter, it can calculate the performance using the + * platform specific mechanism. We reuse the desired performance register to + * store the real performance calculated by the platform. + */ +static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpunum) +{ + struct cppc_cpudata *cpu = all_cpu_data[cpunum]; + u64 desired_perf = hisi_cppc_get_real_perf(cpunum); + + return cppc_cpufreq_perf_to_khz(cpu, desired_perf); +} +#endif + +static struct cppc_get_rate_workaround_info wa_info[] = { +#ifdef CONFIG_HISILICON_CPPC_CPUFREQ_WORKAROUND + { + .oem_id = "HISI ", + .oem_table_id = "HIP07 ", + .oem_revision = 0, + .get = hisi_cppc_cpufreq_get_rate, + }, + { + .oem_id = "HISI ", + .oem_table_id = "HIP08 ", + .oem_revision = 0, + .get = hisi_cppc_cpufreq_get_rate, + }, +#endif + {}, +}; + +static void cppc_check_get_rate_workaround(struct cpufreq_driver *cppc_cpufreq_driver) +{ + struct acpi_table_header *tbl; + acpi_status status = AE_OK; + int i; + + status = acpi_get_table(ACPI_SIG_PCCT, 0, &tbl); + if (ACPI_FAILURE(status) || !tbl) + return; + + for (i = 0; i < ARRAY_SIZE(wa_info) - 1; i++) { + if (!memcmp(wa_info[i].oem_id, tbl->oem_id, ACPI_OEM_ID_SIZE) && + !memcmp(wa_info[i].oem_table_id, tbl->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) && + wa_info[i].oem_revision == tbl->oem_revision) { + cppc_cpufreq_driver->get = wa_info[i].get; + return; + } + } +} static int __init cppc_cpufreq_init(void) { int i, ret = 0; @@ -386,6 +446,8 @@ static int __init cppc_cpufreq_init(void) goto out; } + cppc_check_get_rate_workaround(&cppc_cpufreq_driver); + ret = cpufreq_register_driver(&cppc_cpufreq_driver); if (ret) goto out; diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h index 4f34734..be7400b 100644 --- a/include/acpi/cppc_acpi.h +++ b/include/acpi/cppc_acpi.h @@ -146,4 +146,8 @@ struct cppc_cpudata { extern int cpc_read_ffh(int cpunum, struct cpc_reg *reg, u64 *val); extern int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val); +#ifdef CONFIG_HISILICON_CPPC_CPUFREQ_WORKAROUND +u64 hisi_cppc_get_real_perf(unsigned int cpunum); +#endif + #endif /* _CPPC_ACPI_H*/ -- 1.7.12.4