mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
CPUFreq arm updates for 7.0
- Update cpufreq-dt-platdev list for tegra, qcom, TI (Aaron Kling, Dhruva Gole, and Konrad Dybcio). - Minor improvements to the cpufreq / cpumask rust implementation (Alexandre Courbot, Alice Ryhl, Tamir Duberstein, and Yilin Chen). - Add support for AM62L3 SoC to ti-cpufreq driver (Dhruva Gole). - Update FIE arch_freq_scale in ticks for non-PCC regs (Jie Zhan). - Other minor cleanups / improvements (Felix Gu, Juan Martinez, Luca Weiss, and Sergey Shtylyov). -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEx73Crsp7f6M6scA70rkcPK6BEhwFAml4YIcACgkQ0rkcPK6B Ehx6hQ//Y8GoICqNQe6IrVQ6b9eJLB/YOP7vPyZuwc0iqT9YWXrMou5xlnmNW/IY zj0Wo3l3fidp6eDOo7f21mXALF9yt8kElKq411Oqcg4WVWyAXc9p6ODpWZp/G2/h JcmusAkwFPul0XE0QJmlJ54KqtsyjoSWQHtrPzOO54mJEhOL4dWQwqhWP046ed7T FVkNRLb7ysY3+weNuAg45SbVJ3FT/a7f8XbdGd5DAz96efbqTyFt+znhfsd3Xti+ sF75Mq1AEN0Vnfb8ZP4MZUCe7zeVdOVfLFqXXiW/qJOdbRgoD6k2uAOIt2NAcYU/ sbv6UjaW0NE0oTvKbJ8CLE4IIJudjRgVNjyyGlKHdjBVgMQQk9vr7DIedGLghink VABcyerIqhPFGkBkY0IXkLSmhNtKWoLN9w7sMeCwhE34l63Bnie3Sg9JLikRxaXK 6BAm3+8BiG30tg4WL1LX8UyssnMlUGvvOD9TCP4jOfLQeAk8wWgQ1D+CwWCB5o5j jtDwPTOCIN9UQT46lYS+kkqzwf4YTFVdA4c23Tod70gjrtm7Z1a7UzYNxoTGcGS3 VtrgVnlgPh3/I/95Qpsgoy5D1oeIz9znFoVv6ETPBINy4A4rAsYMA4DEASfM7tIY pNhbSTcbtDbp6Eo79hkh5J2ZGoJyTSthrX+irqOz+IQFp8fP9s4= =Zz3B -----END PGP SIGNATURE----- Merge tag 'cpufreq-arm-updates-7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm Pull CPUFreq Arm updates for 7.0 from Viresh Kumar: "- Update cpufreq-dt-platdev list for tegra, qcom, TI (Aaron Kling, Dhruva Gole, and Konrad Dybcio). - Minor improvements to the cpufreq / cpumask rust implementation (Alexandre Courbot, Alice Ryhl, Tamir Duberstein, and Yilin Chen). - Add support for AM62L3 SoC to ti-cpufreq driver (Dhruva Gole). - Update FIE arch_freq_scale in ticks for non-PCC regs (Jie Zhan). - Other minor cleanups / improvements (Felix Gu, Juan Martinez, Luca Weiss, and Sergey Shtylyov)." * tag 'cpufreq-arm-updates-7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm: cpufreq: scmi: Fix device_node reference leak in scmi_cpu_domain_id() cpufreq: ti-cpufreq: add support for AM62L3 SoC cpufreq: dt-platdev: Add ti,am62l3 to blocklist cpufreq/amd-pstate: Add comment explaining nominal_perf usage for performance policy cpufreq: scmi: correct SCMI explanation cpufreq: dt-platdev: Block the driver from probing on more QC platforms rust: cpumask: rename methods of Cpumask for clarity and consistency cpufreq: CPPC: Update FIE arch_freq_scale in ticks for non-PCC regs cpufreq: CPPC: Factor out cppc_fie_kworker_init() ACPI: CPPC: Factor out and export per-cpu cppc_perf_ctrs_in_pcc_cpu() rust: cpufreq: replace `kernel::c_str!` with C-Strings cpufreq: Add Tegra186 and Tegra194 to cpufreq-dt-platdev blocklist dt-bindings: cpufreq: qcom-hw: document Milos CPUFREQ Hardware rust: cpufreq: add __rust_helper to helpers rust: cpufreq: always inline functions using build_assert with arguments
This commit is contained in:
commit
b753c3204d
12 changed files with 165 additions and 67 deletions
|
|
@ -35,6 +35,7 @@ properties:
|
|||
- description: v2 of CPUFREQ HW (EPSS)
|
||||
items:
|
||||
- enum:
|
||||
- qcom,milos-cpufreq-epss
|
||||
- qcom,qcs8300-cpufreq-epss
|
||||
- qcom,qdu1000-cpufreq-epss
|
||||
- qcom,sa8255p-cpufreq-epss
|
||||
|
|
@ -169,6 +170,7 @@ allOf:
|
|||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,milos-cpufreq-epss
|
||||
- qcom,qcs8300-cpufreq-epss
|
||||
- qcom,sc7280-cpufreq-epss
|
||||
- qcom,sm8250-cpufreq-epss
|
||||
|
|
|
|||
|
|
@ -1423,6 +1423,32 @@ out_err:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_get_perf_caps);
|
||||
|
||||
/**
|
||||
* cppc_perf_ctrs_in_pcc_cpu - Check if any perf counters of a CPU are in PCC.
|
||||
* @cpu: CPU on which to check perf counters.
|
||||
*
|
||||
* Return: true if any of the counters are in PCC regions, false otherwise
|
||||
*/
|
||||
bool cppc_perf_ctrs_in_pcc_cpu(unsigned int cpu)
|
||||
{
|
||||
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
|
||||
struct cpc_register_resource *ref_perf_reg;
|
||||
|
||||
/*
|
||||
* If reference perf register is not supported then we should use the
|
||||
* nominal perf value
|
||||
*/
|
||||
ref_perf_reg = &cpc_desc->cpc_regs[REFERENCE_PERF];
|
||||
if (!CPC_SUPPORTED(ref_perf_reg))
|
||||
ref_perf_reg = &cpc_desc->cpc_regs[NOMINAL_PERF];
|
||||
|
||||
return CPC_IN_PCC(&cpc_desc->cpc_regs[DELIVERED_CTR]) ||
|
||||
CPC_IN_PCC(&cpc_desc->cpc_regs[REFERENCE_CTR]) ||
|
||||
CPC_IN_PCC(&cpc_desc->cpc_regs[CTR_WRAP_TIME]) ||
|
||||
CPC_IN_PCC(ref_perf_reg);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cppc_perf_ctrs_in_pcc_cpu);
|
||||
|
||||
/**
|
||||
* cppc_perf_ctrs_in_pcc - Check if any perf counters are in a PCC region.
|
||||
*
|
||||
|
|
@ -1437,27 +1463,7 @@ bool cppc_perf_ctrs_in_pcc(void)
|
|||
int cpu;
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
struct cpc_register_resource *ref_perf_reg;
|
||||
struct cpc_desc *cpc_desc;
|
||||
|
||||
cpc_desc = per_cpu(cpc_desc_ptr, cpu);
|
||||
|
||||
if (CPC_IN_PCC(&cpc_desc->cpc_regs[DELIVERED_CTR]) ||
|
||||
CPC_IN_PCC(&cpc_desc->cpc_regs[REFERENCE_CTR]) ||
|
||||
CPC_IN_PCC(&cpc_desc->cpc_regs[CTR_WRAP_TIME]))
|
||||
return true;
|
||||
|
||||
|
||||
ref_perf_reg = &cpc_desc->cpc_regs[REFERENCE_PERF];
|
||||
|
||||
/*
|
||||
* If reference perf register is not supported then we should
|
||||
* use the nominal perf value
|
||||
*/
|
||||
if (!CPC_SUPPORTED(ref_perf_reg))
|
||||
ref_perf_reg = &cpc_desc->cpc_regs[NOMINAL_PERF];
|
||||
|
||||
if (CPC_IN_PCC(ref_perf_reg))
|
||||
if (cppc_perf_ctrs_in_pcc_cpu(cpu))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -636,6 +636,19 @@ static void amd_pstate_update_min_max_limit(struct cpufreq_policy *policy)
|
|||
WRITE_ONCE(cpudata->max_limit_freq, policy->max);
|
||||
|
||||
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
|
||||
/*
|
||||
* For performance policy, set MinPerf to nominal_perf rather than
|
||||
* highest_perf or lowest_nonlinear_perf.
|
||||
*
|
||||
* Per commit 0c411b39e4f4c, using highest_perf was observed
|
||||
* to cause frequency throttling on power-limited platforms, leading to
|
||||
* performance regressions. Using lowest_nonlinear_perf would limit
|
||||
* performance too much for HPC workloads requiring high frequency
|
||||
* operation and minimal wakeup latency from idle states.
|
||||
*
|
||||
* nominal_perf therefore provides a balance by avoiding throttling
|
||||
* while still maintaining enough performance for HPC workloads.
|
||||
*/
|
||||
perf.min_limit_perf = min(perf.nominal_perf, perf.max_limit_perf);
|
||||
WRITE_ONCE(cpudata->min_limit_freq, min(cpudata->nominal_freq, cpudata->max_limit_freq));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -54,31 +54,24 @@ static int cppc_perf_from_fbctrs(struct cppc_perf_fb_ctrs *fb_ctrs_t0,
|
|||
struct cppc_perf_fb_ctrs *fb_ctrs_t1);
|
||||
|
||||
/**
|
||||
* cppc_scale_freq_workfn - CPPC arch_freq_scale updater for frequency invariance
|
||||
* @work: The work item.
|
||||
* __cppc_scale_freq_tick - CPPC arch_freq_scale updater for frequency invariance
|
||||
* @cppc_fi: per-cpu CPPC FIE data.
|
||||
*
|
||||
* The CPPC driver register itself with the topology core to provide its own
|
||||
* The CPPC driver registers itself with the topology core to provide its own
|
||||
* implementation (cppc_scale_freq_tick()) of topology_scale_freq_tick() which
|
||||
* gets called by the scheduler on every tick.
|
||||
*
|
||||
* Note that the arch specific counters have higher priority than CPPC counters,
|
||||
* if available, though the CPPC driver doesn't need to have any special
|
||||
* handling for that.
|
||||
*
|
||||
* On an invocation of cppc_scale_freq_tick(), we schedule an irq work (since we
|
||||
* reach here from hard-irq context), which then schedules a normal work item
|
||||
* and cppc_scale_freq_workfn() updates the per_cpu arch_freq_scale variable
|
||||
* based on the counter updates since the last tick.
|
||||
*/
|
||||
static void cppc_scale_freq_workfn(struct kthread_work *work)
|
||||
static void __cppc_scale_freq_tick(struct cppc_freq_invariance *cppc_fi)
|
||||
{
|
||||
struct cppc_freq_invariance *cppc_fi;
|
||||
struct cppc_perf_fb_ctrs fb_ctrs = {0};
|
||||
struct cppc_cpudata *cpu_data;
|
||||
unsigned long local_freq_scale;
|
||||
u64 perf;
|
||||
|
||||
cppc_fi = container_of(work, struct cppc_freq_invariance, work);
|
||||
cpu_data = cppc_fi->cpu_data;
|
||||
|
||||
if (cppc_get_perf_ctrs(cppc_fi->cpu, &fb_ctrs)) {
|
||||
|
|
@ -102,6 +95,24 @@ static void cppc_scale_freq_workfn(struct kthread_work *work)
|
|||
per_cpu(arch_freq_scale, cppc_fi->cpu) = local_freq_scale;
|
||||
}
|
||||
|
||||
static void cppc_scale_freq_tick(void)
|
||||
{
|
||||
__cppc_scale_freq_tick(&per_cpu(cppc_freq_inv, smp_processor_id()));
|
||||
}
|
||||
|
||||
static struct scale_freq_data cppc_sftd = {
|
||||
.source = SCALE_FREQ_SOURCE_CPPC,
|
||||
.set_freq_scale = cppc_scale_freq_tick,
|
||||
};
|
||||
|
||||
static void cppc_scale_freq_workfn(struct kthread_work *work)
|
||||
{
|
||||
struct cppc_freq_invariance *cppc_fi;
|
||||
|
||||
cppc_fi = container_of(work, struct cppc_freq_invariance, work);
|
||||
__cppc_scale_freq_tick(cppc_fi);
|
||||
}
|
||||
|
||||
static void cppc_irq_work(struct irq_work *irq_work)
|
||||
{
|
||||
struct cppc_freq_invariance *cppc_fi;
|
||||
|
|
@ -110,7 +121,14 @@ static void cppc_irq_work(struct irq_work *irq_work)
|
|||
kthread_queue_work(kworker_fie, &cppc_fi->work);
|
||||
}
|
||||
|
||||
static void cppc_scale_freq_tick(void)
|
||||
/*
|
||||
* Reading perf counters may sleep if the CPC regs are in PCC. Thus, we
|
||||
* schedule an irq work in scale_freq_tick (since we reach here from hard-irq
|
||||
* context), which then schedules a normal work item cppc_scale_freq_workfn()
|
||||
* that updates the per_cpu arch_freq_scale variable based on the counter
|
||||
* updates since the last tick.
|
||||
*/
|
||||
static void cppc_scale_freq_tick_pcc(void)
|
||||
{
|
||||
struct cppc_freq_invariance *cppc_fi = &per_cpu(cppc_freq_inv, smp_processor_id());
|
||||
|
||||
|
|
@ -121,13 +139,14 @@ static void cppc_scale_freq_tick(void)
|
|||
irq_work_queue(&cppc_fi->irq_work);
|
||||
}
|
||||
|
||||
static struct scale_freq_data cppc_sftd = {
|
||||
static struct scale_freq_data cppc_sftd_pcc = {
|
||||
.source = SCALE_FREQ_SOURCE_CPPC,
|
||||
.set_freq_scale = cppc_scale_freq_tick,
|
||||
.set_freq_scale = cppc_scale_freq_tick_pcc,
|
||||
};
|
||||
|
||||
static void cppc_cpufreq_cpu_fie_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct scale_freq_data *sftd = &cppc_sftd;
|
||||
struct cppc_freq_invariance *cppc_fi;
|
||||
int cpu, ret;
|
||||
|
||||
|
|
@ -138,8 +157,11 @@ static void cppc_cpufreq_cpu_fie_init(struct cpufreq_policy *policy)
|
|||
cppc_fi = &per_cpu(cppc_freq_inv, cpu);
|
||||
cppc_fi->cpu = cpu;
|
||||
cppc_fi->cpu_data = policy->driver_data;
|
||||
kthread_init_work(&cppc_fi->work, cppc_scale_freq_workfn);
|
||||
init_irq_work(&cppc_fi->irq_work, cppc_irq_work);
|
||||
if (cppc_perf_ctrs_in_pcc_cpu(cpu)) {
|
||||
kthread_init_work(&cppc_fi->work, cppc_scale_freq_workfn);
|
||||
init_irq_work(&cppc_fi->irq_work, cppc_irq_work);
|
||||
sftd = &cppc_sftd_pcc;
|
||||
}
|
||||
|
||||
ret = cppc_get_perf_ctrs(cpu, &cppc_fi->prev_perf_fb_ctrs);
|
||||
|
||||
|
|
@ -155,7 +177,7 @@ static void cppc_cpufreq_cpu_fie_init(struct cpufreq_policy *policy)
|
|||
}
|
||||
|
||||
/* Register for freq-invariance */
|
||||
topology_set_scale_freq_source(&cppc_sftd, policy->cpus);
|
||||
topology_set_scale_freq_source(sftd, policy->cpus);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -178,13 +200,15 @@ static void cppc_cpufreq_cpu_fie_exit(struct cpufreq_policy *policy)
|
|||
topology_clear_scale_freq_source(SCALE_FREQ_SOURCE_CPPC, policy->related_cpus);
|
||||
|
||||
for_each_cpu(cpu, policy->related_cpus) {
|
||||
if (!cppc_perf_ctrs_in_pcc_cpu(cpu))
|
||||
continue;
|
||||
cppc_fi = &per_cpu(cppc_freq_inv, cpu);
|
||||
irq_work_sync(&cppc_fi->irq_work);
|
||||
kthread_cancel_work_sync(&cppc_fi->work);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init cppc_freq_invariance_init(void)
|
||||
static void cppc_fie_kworker_init(void)
|
||||
{
|
||||
struct sched_attr attr = {
|
||||
.size = sizeof(struct sched_attr),
|
||||
|
|
@ -201,22 +225,12 @@ static void __init cppc_freq_invariance_init(void)
|
|||
};
|
||||
int ret;
|
||||
|
||||
if (fie_disabled != FIE_ENABLED && fie_disabled != FIE_DISABLED) {
|
||||
fie_disabled = FIE_ENABLED;
|
||||
if (cppc_perf_ctrs_in_pcc()) {
|
||||
pr_info("FIE not enabled on systems with registers in PCC\n");
|
||||
fie_disabled = FIE_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (fie_disabled)
|
||||
return;
|
||||
|
||||
kworker_fie = kthread_run_worker(0, "cppc_fie");
|
||||
if (IS_ERR(kworker_fie)) {
|
||||
pr_warn("%s: failed to create kworker_fie: %ld\n", __func__,
|
||||
PTR_ERR(kworker_fie));
|
||||
fie_disabled = FIE_DISABLED;
|
||||
kworker_fie = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -226,15 +240,33 @@ static void __init cppc_freq_invariance_init(void)
|
|||
ret);
|
||||
kthread_destroy_worker(kworker_fie);
|
||||
fie_disabled = FIE_DISABLED;
|
||||
kworker_fie = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init cppc_freq_invariance_init(void)
|
||||
{
|
||||
bool perf_ctrs_in_pcc = cppc_perf_ctrs_in_pcc();
|
||||
|
||||
if (fie_disabled == FIE_UNSET) {
|
||||
if (perf_ctrs_in_pcc) {
|
||||
pr_info("FIE not enabled on systems with registers in PCC\n");
|
||||
fie_disabled = FIE_DISABLED;
|
||||
} else {
|
||||
fie_disabled = FIE_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (fie_disabled || !perf_ctrs_in_pcc)
|
||||
return;
|
||||
|
||||
cppc_fie_kworker_init();
|
||||
}
|
||||
|
||||
static void cppc_freq_invariance_exit(void)
|
||||
{
|
||||
if (fie_disabled)
|
||||
return;
|
||||
|
||||
kthread_destroy_worker(kworker_fie);
|
||||
if (kworker_fie)
|
||||
kthread_destroy_worker(kworker_fie);
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -147,6 +147,8 @@ static const struct of_device_id blocklist[] __initconst = {
|
|||
{ .compatible = "nvidia,tegra30", },
|
||||
{ .compatible = "nvidia,tegra114", },
|
||||
{ .compatible = "nvidia,tegra124", },
|
||||
{ .compatible = "nvidia,tegra186", },
|
||||
{ .compatible = "nvidia,tegra194", },
|
||||
{ .compatible = "nvidia,tegra210", },
|
||||
{ .compatible = "nvidia,tegra234", },
|
||||
|
||||
|
|
@ -169,8 +171,11 @@ static const struct of_device_id blocklist[] __initconst = {
|
|||
{ .compatible = "qcom,sdm845", },
|
||||
{ .compatible = "qcom,sdx75", },
|
||||
{ .compatible = "qcom,sm6115", },
|
||||
{ .compatible = "qcom,sm6125", },
|
||||
{ .compatible = "qcom,sm6150", },
|
||||
{ .compatible = "qcom,sm6350", },
|
||||
{ .compatible = "qcom,sm6375", },
|
||||
{ .compatible = "qcom,sm7125", },
|
||||
{ .compatible = "qcom,sm7225", },
|
||||
{ .compatible = "qcom,sm7325", },
|
||||
{ .compatible = "qcom,sm8150", },
|
||||
|
|
@ -191,6 +196,7 @@ static const struct of_device_id blocklist[] __initconst = {
|
|||
{ .compatible = "ti,am625", },
|
||||
{ .compatible = "ti,am62a7", },
|
||||
{ .compatible = "ti,am62d2", },
|
||||
{ .compatible = "ti,am62l3", },
|
||||
{ .compatible = "ti,am62p5", },
|
||||
|
||||
{ .compatible = "qcom,ipq5332", },
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
//! Rust based implementation of the cpufreq-dt driver.
|
||||
|
||||
use kernel::{
|
||||
c_str,
|
||||
clk::Clk,
|
||||
cpu, cpufreq,
|
||||
cpumask::CpumaskVar,
|
||||
|
|
@ -52,7 +51,7 @@ impl opp::ConfigOps for CPUFreqDTDriver {}
|
|||
|
||||
#[vtable]
|
||||
impl cpufreq::Driver for CPUFreqDTDriver {
|
||||
const NAME: &'static CStr = c_str!("cpufreq-dt");
|
||||
const NAME: &'static CStr = c"cpufreq-dt";
|
||||
const FLAGS: u16 = cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpufreq::flags::IS_COOLING_DEV;
|
||||
const BOOST_ENABLED: bool = true;
|
||||
|
||||
|
|
@ -197,7 +196,7 @@ kernel::of_device_table!(
|
|||
OF_TABLE,
|
||||
MODULE_OF_TABLE,
|
||||
<CPUFreqDTDriver as platform::Driver>::IdInfo,
|
||||
[(of::DeviceId::new(c_str!("operating-points-v2")), ())]
|
||||
[(of::DeviceId::new(c"operating-points-v2"), ())]
|
||||
);
|
||||
|
||||
impl platform::Driver for CPUFreqDTDriver {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* System Control and Power Interface (SCMI) based CPUFreq Interface driver
|
||||
* System Control and Management Interface (SCMI) based CPUFreq Interface driver
|
||||
*
|
||||
* Copyright (C) 2018-2021 ARM Ltd.
|
||||
* Sudeep Holla <sudeep.holla@arm.com>
|
||||
|
|
@ -101,6 +101,7 @@ static int scmi_cpu_domain_id(struct device *cpu_dev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
of_node_put(domain_id.np);
|
||||
return domain_id.args[0];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,12 @@ enum {
|
|||
#define AM62A7_SUPPORT_R_MPU_OPP BIT(1)
|
||||
#define AM62A7_SUPPORT_V_MPU_OPP BIT(2)
|
||||
|
||||
#define AM62L3_EFUSE_E_MPU_OPP 5
|
||||
#define AM62L3_EFUSE_O_MPU_OPP 15
|
||||
|
||||
#define AM62L3_SUPPORT_E_MPU_OPP BIT(0)
|
||||
#define AM62L3_SUPPORT_O_MPU_OPP BIT(1)
|
||||
|
||||
#define AM62P5_EFUSE_O_MPU_OPP 15
|
||||
#define AM62P5_EFUSE_S_MPU_OPP 19
|
||||
#define AM62P5_EFUSE_T_MPU_OPP 20
|
||||
|
|
@ -213,6 +219,22 @@ static unsigned long am625_efuse_xlate(struct ti_cpufreq_data *opp_data,
|
|||
return calculated_efuse;
|
||||
}
|
||||
|
||||
static unsigned long am62l3_efuse_xlate(struct ti_cpufreq_data *opp_data,
|
||||
unsigned long efuse)
|
||||
{
|
||||
unsigned long calculated_efuse = AM62L3_SUPPORT_E_MPU_OPP;
|
||||
|
||||
switch (efuse) {
|
||||
case AM62L3_EFUSE_O_MPU_OPP:
|
||||
calculated_efuse |= AM62L3_SUPPORT_O_MPU_OPP;
|
||||
fallthrough;
|
||||
case AM62L3_EFUSE_E_MPU_OPP:
|
||||
calculated_efuse |= AM62L3_SUPPORT_E_MPU_OPP;
|
||||
}
|
||||
|
||||
return calculated_efuse;
|
||||
}
|
||||
|
||||
static struct ti_cpufreq_soc_data am3x_soc_data = {
|
||||
.efuse_xlate = amx3_efuse_xlate,
|
||||
.efuse_fallback = AM33XX_800M_ARM_MPU_MAX_FREQ,
|
||||
|
|
@ -313,8 +335,9 @@ static struct ti_cpufreq_soc_data am3517_soc_data = {
|
|||
static const struct soc_device_attribute k3_cpufreq_soc[] = {
|
||||
{ .family = "AM62X", },
|
||||
{ .family = "AM62AX", },
|
||||
{ .family = "AM62PX", },
|
||||
{ .family = "AM62DX", },
|
||||
{ .family = "AM62LX", },
|
||||
{ .family = "AM62PX", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
|
|
@ -335,6 +358,14 @@ static struct ti_cpufreq_soc_data am62a7_soc_data = {
|
|||
.multi_regulator = false,
|
||||
};
|
||||
|
||||
static struct ti_cpufreq_soc_data am62l3_soc_data = {
|
||||
.efuse_xlate = am62l3_efuse_xlate,
|
||||
.efuse_offset = 0x0,
|
||||
.efuse_mask = 0x07c0,
|
||||
.efuse_shift = 0x6,
|
||||
.multi_regulator = false,
|
||||
};
|
||||
|
||||
static struct ti_cpufreq_soc_data am62p5_soc_data = {
|
||||
.efuse_xlate = am62p5_efuse_xlate,
|
||||
.efuse_offset = 0x0,
|
||||
|
|
@ -463,6 +494,7 @@ static const struct of_device_id ti_cpufreq_of_match[] __maybe_unused = {
|
|||
{ .compatible = "ti,am625", .data = &am625_soc_data, },
|
||||
{ .compatible = "ti,am62a7", .data = &am62a7_soc_data, },
|
||||
{ .compatible = "ti,am62d2", .data = &am62a7_soc_data, },
|
||||
{ .compatible = "ti,am62l3", .data = &am62l3_soc_data, },
|
||||
{ .compatible = "ti,am62p5", .data = &am62p5_soc_data, },
|
||||
/* legacy */
|
||||
{ .compatible = "ti,omap3430", .data = &omap34xx_soc_data, },
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ extern int cppc_get_perf_ctrs(int cpu, struct cppc_perf_fb_ctrs *perf_fb_ctrs);
|
|||
extern int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls);
|
||||
extern int cppc_set_enable(int cpu, bool enable);
|
||||
extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps);
|
||||
extern bool cppc_perf_ctrs_in_pcc_cpu(unsigned int cpu);
|
||||
extern bool cppc_perf_ctrs_in_pcc(void);
|
||||
extern unsigned int cppc_perf_to_khz(struct cppc_perf_caps *caps, unsigned int perf);
|
||||
extern unsigned int cppc_khz_to_perf(struct cppc_perf_caps *caps, unsigned int freq);
|
||||
|
|
@ -204,6 +205,10 @@ static inline int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps)
|
|||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline bool cppc_perf_ctrs_in_pcc_cpu(unsigned int cpu)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline bool cppc_perf_ctrs_in_pcc(void)
|
||||
{
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
#include <linux/cpufreq.h>
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
void rust_helper_cpufreq_register_em_with_opp(struct cpufreq_policy *policy)
|
||||
__rust_helper void
|
||||
rust_helper_cpufreq_register_em_with_opp(struct cpufreq_policy *policy)
|
||||
{
|
||||
cpufreq_register_em_with_opp(policy);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -840,7 +840,6 @@ pub trait Driver {
|
|||
/// ```
|
||||
/// use kernel::{
|
||||
/// cpufreq,
|
||||
/// c_str,
|
||||
/// device::{Core, Device},
|
||||
/// macros::vtable,
|
||||
/// of, platform,
|
||||
|
|
@ -853,7 +852,7 @@ pub trait Driver {
|
|||
///
|
||||
/// #[vtable]
|
||||
/// impl cpufreq::Driver for SampleDriver {
|
||||
/// const NAME: &'static CStr = c_str!("cpufreq-sample");
|
||||
/// const NAME: &'static CStr = c"cpufreq-sample";
|
||||
/// const FLAGS: u16 = cpufreq::flags::NEED_INITIAL_FREQ_CHECK | cpufreq::flags::IS_COOLING_DEV;
|
||||
/// const BOOST_ENABLED: bool = true;
|
||||
///
|
||||
|
|
@ -1015,6 +1014,8 @@ impl<T: Driver> Registration<T> {
|
|||
..pin_init::zeroed()
|
||||
};
|
||||
|
||||
// Always inline to optimize out error path of `build_assert`.
|
||||
#[inline(always)]
|
||||
const fn copy_name(name: &'static CStr) -> [c_char; CPUFREQ_NAME_LEN] {
|
||||
let src = name.to_bytes_with_nul();
|
||||
let mut dst = [0; CPUFREQ_NAME_LEN];
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ use core::ops::{Deref, DerefMut};
|
|||
/// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: CpuId, clear_cpu: CpuId) {
|
||||
/// // SAFETY: The `ptr` is valid for writing and remains valid for the lifetime of the
|
||||
/// // returned reference.
|
||||
/// let mask = unsafe { Cpumask::as_mut_ref(ptr) };
|
||||
/// let mask = unsafe { Cpumask::from_raw_mut(ptr) };
|
||||
///
|
||||
/// mask.set(set_cpu);
|
||||
/// mask.clear(clear_cpu);
|
||||
|
|
@ -49,13 +49,13 @@ use core::ops::{Deref, DerefMut};
|
|||
pub struct Cpumask(Opaque<bindings::cpumask>);
|
||||
|
||||
impl Cpumask {
|
||||
/// Creates a mutable reference to an existing `struct cpumask` pointer.
|
||||
/// Creates a mutable reference from an existing `struct cpumask` pointer.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime
|
||||
/// of the returned reference.
|
||||
pub unsafe fn as_mut_ref<'a>(ptr: *mut bindings::cpumask) -> &'a mut Self {
|
||||
pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpumask) -> &'a mut Self {
|
||||
// SAFETY: Guaranteed by the safety requirements of the function.
|
||||
//
|
||||
// INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the
|
||||
|
|
@ -63,13 +63,13 @@ impl Cpumask {
|
|||
unsafe { &mut *ptr.cast() }
|
||||
}
|
||||
|
||||
/// Creates a reference to an existing `struct cpumask` pointer.
|
||||
/// Creates a reference from an existing `struct cpumask` pointer.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime
|
||||
/// of the returned reference.
|
||||
pub unsafe fn as_ref<'a>(ptr: *const bindings::cpumask) -> &'a Self {
|
||||
pub unsafe fn from_raw<'a>(ptr: *const bindings::cpumask) -> &'a Self {
|
||||
// SAFETY: Guaranteed by the safety requirements of the function.
|
||||
//
|
||||
// INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue