diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2020-08-04 12:44:53 +0200 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2020-08-04 12:44:53 +0200 |
commit | 9ac1fb156a40b88fddb2e2b8c36e127b0d01fb8e (patch) | |
tree | bfef415d401765990b7021e9fc45ba1a629453aa /drivers/cpufreq/cppc_cpufreq.c | |
parent | 4daca379c703ff55edc065e8e5173dcfeecf0148 (diff) | |
parent | f259eab3ea0e7ed73db91f6358274dd3a9a27d79 (diff) | |
download | lwn-9ac1fb156a40b88fddb2e2b8c36e127b0d01fb8e.tar.gz lwn-9ac1fb156a40b88fddb2e2b8c36e127b0d01fb8e.zip |
Merge branch 'cpufreq/arm/linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm
Pull ARM cpufreq driver changes for v5.9-rc1 from Viresh Kumar:
"Here are the details:
- Adaptive voltage scaling (AVS) support and minor cleanups for
brcmstb driver (Florian Fainelli and Markus Mayer).
- A new tegra driver and cleanup for the existing one (Sumit Gupta and
Jon Hunter).
- Bandwidth level support for Qcom driver along with OPP changes (Sibi
Sankar).
- Cleanups to sti, cpufreq-dt, ap806, CPPC drivers (Viresh Kumar, Lee
Jones, Ivan Kokshaysky, Sven Auhagen, and Xin Hao).
- Make schedutil default governor for ARM (Valentin Schneider).
- Fix dependency issues for imx (Walter Lozano).
- Cleanup around cached_resolved_idx in cpufreq core (Viresh Kumar)."
* 'cpufreq/arm/linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
cpufreq: make schedutil the default for arm and arm64
cpufreq: cached_resolved_idx can not be negative
cpufreq: Add Tegra194 cpufreq driver
dt-bindings: arm: Add NVIDIA Tegra194 CPU Complex binding
cpufreq: imx: Select NVMEM_IMX_OCOTP
cpufreq: sti-cpufreq: Fix some formatting and misspelling issues
cpufreq: tegra186: Simplify probe return path
cpufreq: CPPC: Reuse caps variable in few routines
cpufreq: ap806: fix cpufreq driver needs ap cpu clk
cpufreq: cppc: Reorder code and remove apply_hisi_workaround variable
cpufreq: dt: fix oops on armada37xx
cpufreq: brcmstb-avs-cpufreq: send S2_ENTER / S2_EXIT commands to AVS
cpufreq: brcmstb-avs-cpufreq: Support polling AVS firmware
cpufreq: brcmstb-avs-cpufreq: more flexible interface for __issue_avs_command()
cpufreq: qcom: Disable fast switch when scaling DDR/L3
cpufreq: qcom: Update the bandwidth levels on frequency change
OPP: Add and export helper to set bandwidth
cpufreq: blacklist SC7180 in cpufreq-dt-platdev
cpufreq: blacklist SDM845 in cpufreq-dt-platdev
Diffstat (limited to 'drivers/cpufreq/cppc_cpufreq.c')
-rw-r--r-- | drivers/cpufreq/cppc_cpufreq.c | 95 |
1 files changed, 44 insertions, 51 deletions
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 257d726a4456..f29e8d0553a8 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -45,8 +45,6 @@ struct cppc_workaround_oem_info { u32 oem_revision; }; -static bool apply_hisi_workaround; - static struct cppc_workaround_oem_info wa_info[] = { { .oem_id = "HISI ", @@ -59,50 +57,6 @@ static struct cppc_workaround_oem_info wa_info[] = { } }; -static unsigned int cppc_cpufreq_perf_to_khz(struct cppc_cpudata *cpu, - unsigned int perf); - -/* - * HISI platform does not support delivered performance counter and - * 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 *cpudata = all_cpu_data[cpunum]; - u64 desired_perf; - int ret; - - ret = cppc_get_desired_perf(cpunum, &desired_perf); - if (ret < 0) - return -EIO; - - return cppc_cpufreq_perf_to_khz(cpudata, desired_perf); -} - -static void cppc_check_hisi_workaround(void) -{ - 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); 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) { - apply_hisi_workaround = true; - break; - } - } - - acpi_put_table(tbl); -} - /* Callback function used to retrieve the max frequency from DMI */ static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private) { @@ -161,7 +115,7 @@ static unsigned int cppc_cpufreq_perf_to_khz(struct cppc_cpudata *cpu, if (!max_khz) max_khz = cppc_get_dmi_max_khz(); mul = max_khz; - div = cpu->perf_caps.highest_perf; + div = caps->highest_perf; } return (u64)perf * mul / div; } @@ -184,7 +138,7 @@ static unsigned int cppc_cpufreq_khz_to_perf(struct cppc_cpudata *cpu, } else { if (!max_khz) max_khz = cppc_get_dmi_max_khz(); - mul = cpu->perf_caps.highest_perf; + mul = caps->highest_perf; div = max_khz; } @@ -402,9 +356,6 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpunum) struct cppc_cpudata *cpu = all_cpu_data[cpunum]; int ret; - if (apply_hisi_workaround) - return hisi_cppc_cpufreq_get_rate(cpunum); - ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t0); if (ret) return ret; @@ -455,6 +406,48 @@ static struct cpufreq_driver cppc_cpufreq_driver = { .name = "cppc_cpufreq", }; +/* + * HISI platform does not support delivered performance counter and + * 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 *cpudata = all_cpu_data[cpunum]; + u64 desired_perf; + int ret; + + ret = cppc_get_desired_perf(cpunum, &desired_perf); + if (ret < 0) + return -EIO; + + return cppc_cpufreq_perf_to_khz(cpudata, desired_perf); +} + +static void cppc_check_hisi_workaround(void) +{ + 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); 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) { + /* Overwrite the get() callback */ + cppc_cpufreq_driver.get = hisi_cppc_cpufreq_get_rate; + break; + } + } + + acpi_put_table(tbl); +} + static int __init cppc_cpufreq_init(void) { int i, ret = 0; |