CPUFreq arm updates for 7.2

- Add cpufreq scaling support for Qualcomm Shikra SoC (Taniya Das, and
   Imran Shaik).
 
 - Minor fixes for cpufreq drivers (Krzysztof Kozlowski, Akashdeep Kaur,
   Hans Zhang, Guangshuo Li, and Xueqin Luo).
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEx73Crsp7f6M6scA70rkcPK6BEhwFAmomWYMACgkQ0rkcPK6B
 EhypdRAAnIHddDVfbl8mqMSVENcQrMBAgdSw4Foh6DcOfP2Nxu9+KSPR3xbFbNsy
 AxHc8M/merdjsHcuvA/03D/BgCzcpI80mb70k0u88LDneH7KbWbRMZ4nHFVzBui1
 CUV/LZ17q8RRlNCNKySAZAK+jGeLMh4KIGK15RCZn0hv+KsinFQkKyER7EgqZANA
 7TydPpwoQZakTh+YDJb27l2Cls/JXWZABuQbNtJIo1/SRBGnNQVpn+bEaYxhdeta
 G5OJrBw3i6fV0xfOEGQfwRy9qGr308qFvJEqoIJs0A/uBcY47TsYEYu/XHZfI5+C
 k8froLZIuClrHNEn+rAzS5n0PJTrp+bKaYMKCT31dDeOEB5KRMU0e/2Cj20dbjrz
 HB/2qufhhwR3C8W5N3l8POWvJJFUVABDO6N8vgOkp2qQYPdZmxKviTMcgKOYe0CA
 Z4DszH6DlwT9etP4lS4gv5rt8JmIdxFxSOrL6tYT2wVbpkA63H8wXIlKnob8wm5K
 CrQvUhSoxPqoHcKRd6RCSeOBDguVcpos9vgp8I6Mzdh4dVNvZRkKerJIJq+SBffw
 /SQhuBeireFMmDxoXb2nbKbQ05CNP4LM3AK35CLwu3Gz3Hm1o4m+IuoCmyZJkKAM
 pXcPQCZ2Es60sfkDXKLNSepQ3ux7d++TFIt0FcviyYTXICWnVVk=
 =hVKd
 -----END PGP SIGNATURE-----

Merge tag 'cpufreq-arm-updates-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm

Pull CPUFreq Arm updates for 7.2 from Viresh Kumar:

"- Add cpufreq scaling support for Qualcomm Shikra SoC (Taniya Das, and
   Imran Shaik).

 - Minor fixes for cpufreq drivers (Krzysztof Kozlowski, Akashdeep Kaur,
   Hans Zhang, Guangshuo Li, and Xueqin Luo)."

* tag 'cpufreq-arm-updates-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
  cpufreq: ti: Add EPROBE_DEFER for K3 SoCs
  cpufreq: qcom: Add cpufreq scaling support for Qualcomm Shikra SoC
  dt-bindings: cpufreq: Document Qualcomm Shikra SoC EPSS
  cpufreq: cppc: mask Desired_Excursion when autonomous selection is enabled
  cpufreq: qcom-cpufreq-hw: Fix possible double free
  cpufreq: apple-soc: Use FIELD_MODIFY()
  cpufreq/amd-pstate: Use FIELD_MODIFY()
  cpufreq: qcom: Unify user-visible "Qualcomm" name
This commit is contained in:
Rafael J. Wysocki 2026-06-08 14:55:31 +02:00
commit 11efcfc295
7 changed files with 167 additions and 26 deletions

View File

@ -0,0 +1,96 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/cpufreq/qcom,shikra-epss.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Shikra SoC EPSS
maintainers:
- Imran Shaik <imran.shaik@oss.qualcomm.com>
- Taniya Das <taniya.das@oss.qualcomm.com>
description: |
EPSS is a hardware engine used by some Qualcomm SoCs to manage
frequency in hardware. It is capable of controlling frequency for
multiple clusters.
The Qualcomm Shikra SoC EPSS supports up to 12 frequency lookup table
(LUT) entries.
properties:
compatible:
enum:
- qcom,shikra-epss
reg:
items:
- description: Frequency domain 0 register region
- description: Frequency domain 1 register region
reg-names:
items:
- const: freq-domain0
- const: freq-domain1
clocks:
items:
- description: XO Clock
- description: GPLL0 Clock
clock-names:
items:
- const: xo
- const: alternate
interrupts:
items:
- description: IRQ line for DCVSH 0
- description: IRQ line for DCVSH 1
interrupt-names:
items:
- const: dcvsh-irq-0
- const: dcvsh-irq-1
'#freq-domain-cells':
const: 1
'#clock-cells':
const: 1
required:
- compatible
- reg
- clocks
- clock-names
- interrupts
- interrupt-names
- '#freq-domain-cells'
- '#clock-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmcc.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
soc {
#address-cells = <1>;
#size-cells = <1>;
cpufreq@fd91000 {
compatible = "qcom,shikra-epss";
reg = <0x0fd91000 0x1000>, <0x0fd92000 0x1000>;
reg-names = "freq-domain0", "freq-domain1";
clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&gpll0>;
clock-names = "xo", "alternate";
interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "dcvsh-irq-0", "dcvsh-irq-1";
#freq-domain-cells = <1>;
#clock-cells = <1>;
};
};
...

View File

@ -153,7 +153,7 @@ config ARM_QCOM_CPUFREQ_NVMEM
If in doubt, say N.
config ARM_QCOM_CPUFREQ_HW
tristate "QCOM CPUFreq HW driver"
tristate "Qualcomm CPUFreq HW driver"
depends on ARCH_QCOM || COMPILE_TEST
depends on COMMON_CLK
help

View File

@ -242,12 +242,10 @@ static int msr_update_perf(struct cpufreq_policy *policy, u8 min_perf,
value = prev = READ_ONCE(cpudata->cppc_req_cached);
value &= ~(AMD_CPPC_MAX_PERF_MASK | AMD_CPPC_MIN_PERF_MASK |
AMD_CPPC_DES_PERF_MASK | AMD_CPPC_EPP_PERF_MASK);
value |= FIELD_PREP(AMD_CPPC_MAX_PERF_MASK, max_perf);
value |= FIELD_PREP(AMD_CPPC_DES_PERF_MASK, des_perf);
value |= FIELD_PREP(AMD_CPPC_MIN_PERF_MASK, min_perf);
value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp);
FIELD_MODIFY(AMD_CPPC_MAX_PERF_MASK, &value, max_perf);
FIELD_MODIFY(AMD_CPPC_DES_PERF_MASK, &value, des_perf);
FIELD_MODIFY(AMD_CPPC_MIN_PERF_MASK, &value, min_perf);
FIELD_MODIFY(AMD_CPPC_EPP_PERF_MASK, &value, epp);
if (trace_amd_pstate_epp_perf_enabled()) {
union perf_cached perf = READ_ONCE(cpudata->perf);
@ -296,8 +294,7 @@ static int msr_set_epp(struct cpufreq_policy *policy, u8 epp)
int ret;
value = prev = READ_ONCE(cpudata->cppc_req_cached);
value &= ~AMD_CPPC_EPP_PERF_MASK;
value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp);
FIELD_MODIFY(AMD_CPPC_EPP_PERF_MASK, &value, epp);
if (trace_amd_pstate_epp_perf_enabled()) {
union perf_cached perf = cpudata->perf;
@ -437,8 +434,7 @@ static int shmem_set_epp(struct cpufreq_policy *policy, u8 epp)
}
value = READ_ONCE(cpudata->cppc_req_cached);
value &= ~AMD_CPPC_EPP_PERF_MASK;
value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp);
FIELD_MODIFY(AMD_CPPC_EPP_PERF_MASK, &value, epp);
WRITE_ONCE(cpudata->cppc_req_cached, value);
return ret;
@ -571,12 +567,10 @@ static int shmem_update_perf(struct cpufreq_policy *policy, u8 min_perf,
value = prev = READ_ONCE(cpudata->cppc_req_cached);
value &= ~(AMD_CPPC_MAX_PERF_MASK | AMD_CPPC_MIN_PERF_MASK |
AMD_CPPC_DES_PERF_MASK | AMD_CPPC_EPP_PERF_MASK);
value |= FIELD_PREP(AMD_CPPC_MAX_PERF_MASK, max_perf);
value |= FIELD_PREP(AMD_CPPC_DES_PERF_MASK, des_perf);
value |= FIELD_PREP(AMD_CPPC_MIN_PERF_MASK, min_perf);
value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp);
FIELD_MODIFY(AMD_CPPC_MAX_PERF_MASK, &value, max_perf);
FIELD_MODIFY(AMD_CPPC_DES_PERF_MASK, &value, des_perf);
FIELD_MODIFY(AMD_CPPC_MIN_PERF_MASK, &value, min_perf);
FIELD_MODIFY(AMD_CPPC_EPP_PERF_MASK, &value, epp);
if (trace_amd_pstate_epp_perf_enabled()) {
union perf_cached perf = READ_ONCE(cpudata->perf);

View File

@ -187,10 +187,8 @@ static int apple_soc_cpufreq_set_target(struct cpufreq_policy *policy,
reg &= ~priv->info->ps1_mask;
reg |= pstate << priv->info->ps1_shift;
if (priv->info->has_ps2) {
reg &= ~APPLE_DVFS_CMD_PS2;
reg |= FIELD_PREP(APPLE_DVFS_CMD_PS2, pstate);
}
if (priv->info->has_ps2)
FIELD_MODIFY(APPLE_DVFS_CMD_PS2, &reg, pstate);
reg |= APPLE_DVFS_CMD_SET;
writeq_relaxed(reg, priv->reg_base + APPLE_DVFS_CMD);

View File

@ -982,7 +982,34 @@ store_energy_performance_preference_val(struct cpufreq_policy *policy,
return count;
}
CPPC_CPUFREQ_ATTR_RW_U64(perf_limited, cppc_get_perf_limited,
static int cppc_get_perf_limited_filtered(int cpu, u64 *perf_limited)
{
struct cpufreq_policy *policy;
struct cppc_cpudata *cpu_data;
int ret;
ret = cppc_get_perf_limited(cpu, perf_limited);
if (ret)
return ret;
policy = cpufreq_cpu_get_raw(cpu);
if (!policy)
return -EINVAL;
cpu_data = policy->driver_data;
/*
* Desired Excursion is ignored when autonomous selection is
* enabled. Clear the bit to avoid exposing meaningless state
* to userspace.
*/
if (cpu_data && cpu_data->perf_ctrls.auto_sel)
*perf_limited &= ~CPPC_PERF_LIMITED_DESIRED_EXCURSION;
return 0;
}
CPPC_CPUFREQ_ATTR_RW_U64(perf_limited, cppc_get_perf_limited_filtered,
cppc_set_perf_limited)
cpufreq_freq_attr_ro(freqdomain_cpus);

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/bitfield.h>
@ -40,6 +41,7 @@ struct qcom_cpufreq_soc_data {
u32 reg_intr_clr;
u32 reg_current_vote;
u32 reg_perf_state;
u32 lut_max_entries;
u8 lut_row_size;
};
@ -156,7 +158,7 @@ static unsigned int qcom_cpufreq_get_freq(struct cpufreq_policy *policy)
soc_data = qcom_cpufreq.soc_data;
index = readl_relaxed(data->base + soc_data->reg_perf_state);
index = min(index, LUT_MAX_ENTRIES - 1);
index = min(index, soc_data->lut_max_entries - 1);
return policy->freq_table[index].frequency;
}
@ -211,7 +213,7 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev,
struct qcom_cpufreq_data *drv_data = policy->driver_data;
const struct qcom_cpufreq_soc_data *soc_data = qcom_cpufreq.soc_data;
table = kzalloc_objs(*table, LUT_MAX_ENTRIES + 1);
table = kzalloc_objs(*table, soc_data->lut_max_entries + 1);
if (!table)
return -ENOMEM;
@ -236,7 +238,7 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev,
icc_scaling_enabled = false;
}
for (i = 0; i < LUT_MAX_ENTRIES; i++) {
for (i = 0; i < soc_data->lut_max_entries; i++) {
data = readl_relaxed(drv_data->base + soc_data->reg_freq_lut +
i * soc_data->lut_row_size);
src = FIELD_GET(LUT_SRC, data);
@ -405,6 +407,7 @@ static const struct qcom_cpufreq_soc_data qcom_soc_data = {
.reg_current_vote = 0x704,
.reg_perf_state = 0x920,
.lut_row_size = 32,
.lut_max_entries = LUT_MAX_ENTRIES,
};
static const struct qcom_cpufreq_soc_data epss_soc_data = {
@ -416,11 +419,25 @@ static const struct qcom_cpufreq_soc_data epss_soc_data = {
.reg_intr_clr = 0x308,
.reg_perf_state = 0x320,
.lut_row_size = 4,
.lut_max_entries = LUT_MAX_ENTRIES,
};
static const struct qcom_cpufreq_soc_data shikra_epss_soc_data = {
.reg_enable = 0x0,
.reg_domain_state = 0x20,
.reg_dcvs_ctrl = 0xb0,
.reg_freq_lut = 0x100,
.reg_volt_lut = 0x200,
.reg_intr_clr = 0x308,
.reg_perf_state = 0x320,
.lut_row_size = 4,
.lut_max_entries = 12,
};
static const struct of_device_id qcom_cpufreq_hw_match[] = {
{ .compatible = "qcom,cpufreq-hw", .data = &qcom_soc_data },
{ .compatible = "qcom,cpufreq-epss", .data = &epss_soc_data },
{ .compatible = "qcom,shikra-epss", .data = &shikra_epss_soc_data },
{}
};
MODULE_DEVICE_TABLE(of, qcom_cpufreq_hw_match);
@ -578,7 +595,6 @@ static void qcom_cpufreq_hw_cpu_exit(struct cpufreq_policy *policy)
dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
qcom_cpufreq_hw_lmh_exit(data);
kfree(policy->freq_table);
kfree(data);
}
static void qcom_cpufreq_ready(struct cpufreq_policy *policy)

View File

@ -99,6 +99,7 @@ struct ti_cpufreq_soc_data {
unsigned long efuse_shift;
unsigned long rev_offset;
bool multi_regulator;
bool needs_k3_socinfo;
/* Backward compatibility hack: Might have missing syscon */
#define TI_QUIRK_SYSCON_MAY_BE_MISSING 0x1
/* Backward compatibility hack: new syscon size is 1 register wide */
@ -347,6 +348,7 @@ static struct ti_cpufreq_soc_data am625_soc_data = {
.efuse_mask = 0x07c0,
.efuse_shift = 0x6,
.multi_regulator = false,
.needs_k3_socinfo = true,
.quirks = TI_QUIRK_SYSCON_IS_SINGLE_REG,
};
@ -356,6 +358,7 @@ static struct ti_cpufreq_soc_data am62a7_soc_data = {
.efuse_mask = 0x07c0,
.efuse_shift = 0x6,
.multi_regulator = false,
.needs_k3_socinfo = true,
};
static struct ti_cpufreq_soc_data am62l3_soc_data = {
@ -364,6 +367,7 @@ static struct ti_cpufreq_soc_data am62l3_soc_data = {
.efuse_mask = 0x07c0,
.efuse_shift = 0x6,
.multi_regulator = false,
.needs_k3_socinfo = true,
};
static struct ti_cpufreq_soc_data am62p5_soc_data = {
@ -372,6 +376,7 @@ static struct ti_cpufreq_soc_data am62p5_soc_data = {
.efuse_mask = 0x07c0,
.efuse_shift = 0x6,
.multi_regulator = false,
.needs_k3_socinfo = true,
};
/**
@ -443,6 +448,11 @@ static int ti_cpufreq_get_rev(struct ti_cpufreq_data *opp_data,
goto done;
}
/* Defer if k3-socinfo hasn't registered the SoC device yet */
if (opp_data->soc_data->needs_k3_socinfo)
return dev_err_probe(opp_data->cpu_dev, -EPROBE_DEFER,
"SoC device not registered by k3-socinfo\n");
ret = regmap_read(opp_data->syscon, opp_data->soc_data->rev_offset,
&revision);
if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) {