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

Pull CPUFreq Arm updates for 7.3 from Viresh Kumar:

"- Minor fixes / cleanups in cpufreq drivers (Dan Carpenter, Guru Das
   Srinagesh, Haoxiang Li, Karl Mehltretter, Sasha Finkelstein, and Pan
   Chuang).

 - Fix cpufreq table creation and bios_limits() callback in the Rust
   bindings (Priya Bala Govindasamy).

 - Add IPQ5210 support to qcom-nvmem driver (Varadarajan Narayanan)."

* tag 'cpufreq-arm-updates-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
  cpufreq: imx6q: fix out-of-bounds write when probed more than once
  cpufreq: imx6q: fix devres accumulation across driver rebind
  rust: cpufreq: Fix temporary write in Registration::bios_limit_callback
  rust: cpufreq: Add CPUFREQ_TABLE_END as last table entry in TableBuilder::to_table
  cpufreq: apple-soc: Calculate frequency as a 64-bit value
  cpufreq: spear: Fix an IS_ERR() vs NULL bug in spear1340_set_cpu_rate()
  cpufreq: brcmstb-avs: Remove redundant dev_err()
  rust: rcpufreq_dt: use vertical import style
  cpufreq: apple-soc: Fix OPP table cleanup
  cpufreq: qcom-nvmem: Add IPQ5210 support
This commit is contained in:
Rafael J. Wysocki
2026-08-06 13:25:02 +02:00
8 changed files with 58 additions and 41 deletions

View File

@@ -249,21 +249,19 @@ static int apple_soc_cpufreq_init(struct cpufreq_policy *policy)
return -ENODEV;
}
ret = dev_pm_opp_of_add_table(cpu_dev);
if (ret < 0) {
dev_err(cpu_dev, "%s: failed to add OPP table: %d\n", __func__, ret);
return ret;
}
priv = kzalloc_obj(*priv);
if (!priv)
return -ENOMEM;
ret = apple_soc_cpufreq_find_cluster(policy, &reg_base, &info);
if (ret) {
dev_err(cpu_dev, "%s: failed to get cluster info: %d\n", __func__, ret);
return ret;
goto out_free_priv;
}
ret = dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus);
if (ret) {
dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n", __func__, ret);
ret = dev_pm_opp_of_cpumask_add_table(policy->cpus);
if (ret < 0) {
dev_err(cpu_dev, "%s: failed to add OPP table: %d\n", __func__, ret);
goto out_iounmap;
}
@@ -271,24 +269,18 @@ static int apple_soc_cpufreq_init(struct cpufreq_policy *policy)
if (ret <= 0) {
dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
ret = -EPROBE_DEFER;
goto out_free_opp;
}
priv = kzalloc_obj(*priv);
if (!priv) {
ret = -ENOMEM;
goto out_free_opp;
goto out_free_table;
}
ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
if (ret) {
dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
goto out_free_priv;
goto out_free_table;
}
/* Get OPP levels (p-state indexes) and stash them in driver_data */
for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
unsigned long rate = freq_table[i].frequency * 1000 + 999;
unsigned long rate = freq_table[i].frequency * 1000UL + 999;
struct dev_pm_opp *opp = dev_pm_opp_find_freq_floor(cpu_dev, &rate);
if (IS_ERR(opp)) {
@@ -318,12 +310,12 @@ static int apple_soc_cpufreq_init(struct cpufreq_policy *policy)
out_free_cpufreq_table:
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
out_free_priv:
kfree(priv);
out_free_opp:
dev_pm_opp_remove_all_dynamic(cpu_dev);
out_free_table:
dev_pm_opp_of_cpumask_remove_table(policy->cpus);
out_iounmap:
iounmap(reg_base);
out_free_priv:
kfree(priv);
return ret;
}
@@ -332,7 +324,7 @@ static void apple_soc_cpufreq_exit(struct cpufreq_policy *policy)
struct apple_cpu_priv *priv = policy->driver_data;
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
dev_pm_opp_of_cpumask_remove_table(policy->cpus);
iounmap(priv->reg_base);
kfree(priv);
}

View File

@@ -584,11 +584,8 @@ static int brcm_avs_prepare_init(struct platform_device *pdev)
ret = devm_request_irq(dev, priv->host_irq, irq_handler,
IRQF_TRIGGER_RISING,
BRCM_AVS_HOST_INTR, priv);
if (ret && priv->host_irq >= 0) {
dev_err(dev, "IRQ request failed: %s (%d) -- %d\n",
BRCM_AVS_HOST_INTR, priv->host_irq, ret);
if (ret && priv->host_irq >= 0)
goto unmap_intr_base;
}
if (brcm_avs_is_firmware_loaded(priv))
return 0;

View File

@@ -200,6 +200,7 @@ static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "ti,am62l3", },
{ .compatible = "ti,am62p5", },
{ .compatible = "qcom,ipq5210", },
{ .compatible = "qcom,ipq5332", },
{ .compatible = "qcom,ipq5424", },
{ .compatible = "qcom,ipq6018", },

View File

@@ -55,7 +55,6 @@ static unsigned int max_freq;
static unsigned int transition_latency;
static u32 *imx6_soc_volt;
static u32 soc_opp_count;
static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
{
@@ -330,6 +329,7 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
const struct property *prop;
const __be32 *val;
u32 nr, i, j;
u32 soc_opp_count = 0;
cpu_dev = get_cpu_device(0);
if (!cpu_dev) {
@@ -400,7 +400,7 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
}
/* Make imx6_soc_volt array's size same as arm opp number */
imx6_soc_volt = devm_kcalloc(cpu_dev, num, sizeof(*imx6_soc_volt),
imx6_soc_volt = devm_kcalloc(&pdev->dev, num, sizeof(*imx6_soc_volt),
GFP_KERNEL);
if (imx6_soc_volt == NULL) {
ret = -ENOMEM;
@@ -485,6 +485,7 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
return 0;
free_freq_table:
imx6_soc_volt = NULL;
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
out_free_opp:
dev_pm_opp_of_remove_table(cpu_dev);
@@ -506,6 +507,7 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
static void imx6q_cpufreq_remove(struct platform_device *pdev)
{
cpufreq_unregister_driver(&imx6q_cpufreq_driver);
imx6_soc_volt = NULL;
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
dev_pm_opp_of_remove_table(cpu_dev);
regulator_put(arm_reg);

View File

@@ -200,6 +200,13 @@ static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
case QCOM_ID_IPQ9574:
drv->versions = 1 << (unsigned int)(*speedbin);
break;
case QCOM_ID_IPQ5200:
case QCOM_ID_IPQ5210:
case QCOM_ID_QCF2200:
case QCOM_ID_QCF3200:
case QCOM_ID_QCF3210:
drv->versions = (*speedbin == 0xcd) ? BIT(1) : BIT(0);
break;
case QCOM_ID_IPQ5424:
case QCOM_ID_IPQ5404:
drv->versions = (*speedbin == 0x3b) ? BIT(1) : BIT(0);
@@ -618,6 +625,7 @@ static const struct of_device_id qcom_cpufreq_match_list[] __initconst __maybe_u
{ .compatible = "qcom,msm8909", .data = &match_data_msm8909 },
{ .compatible = "qcom,msm8996", .data = &match_data_kryo },
{ .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
{ .compatible = "qcom,ipq5210", .data = &match_data_kryo },
{ .compatible = "qcom,ipq5332", .data = &match_data_kryo },
{ .compatible = "qcom,ipq5424", .data = &match_data_kryo },
{ .compatible = "qcom,ipq6018", .data = &match_data_ipq6018 },

View File

@@ -4,12 +4,19 @@
use kernel::{
clk::Clk,
cpu, cpufreq,
cpu,
cpufreq, //
cpumask::CpumaskVar,
device::{Core, Device},
device::{
Core,
Device, //
},
error::code::*,
macros::vtable,
module_platform_driver, of, opp, platform,
module_platform_driver,
of,
opp,
platform, //
prelude::*,
str::CString,
sync::Arc,

View File

@@ -79,9 +79,9 @@ static int spear1340_set_cpu_rate(struct clk *sys_pclk, unsigned long newfreq)
int ret = 0;
sys_clk = clk_get_parent(spear_cpufreq.clk);
if (IS_ERR(sys_clk)) {
if (!sys_clk) {
pr_err("failed to get cpu's parent (sys) clock\n");
return PTR_ERR(sys_clk);
return -EINVAL;
}
/* Set the rate of the source clock before changing the parent */

View File

@@ -361,23 +361,28 @@ pub fn new() -> Self {
}
}
/// Adds a new entry to the table.
pub fn add(&mut self, freq: Hertz, flags: u32, driver_data: u32) -> Result {
/// Adds a raw frequency-table entry.
fn push(&mut self, frequency: u32, flags: u32, driver_data: u32) -> Result {
// Adds the new entry at the end of the vector.
Ok(self.entries.push(
bindings::cpufreq_frequency_table {
flags,
driver_data,
frequency: freq.as_khz() as u32,
frequency,
},
GFP_KERNEL,
)?)
}
/// Adds a new entry to the table.
pub fn add(&mut self, freq: Hertz, flags: u32, driver_data: u32) -> Result {
self.push(freq.as_khz() as u32, flags, driver_data)
}
/// Consumes the [`TableBuilder`] and returns [`TableBox`].
pub fn to_table(mut self) -> Result<TableBox> {
// Add last entry to the table.
self.add(Hertz(c_ulong::MAX), 0, 0)?;
self.push(bindings::CPUFREQ_TABLE_END as u32, 0, 0)?;
TableBox::new(self.entries)
}
@@ -823,7 +828,9 @@ fn update_limits(_policy: &mut Policy) {
}
/// Driver's `bios_limit` callback.
fn bios_limit(_policy: &mut Policy, _limit: &mut u32) -> Result {
///
/// Returns HW/BIOS max frequency limitations for the CPU.
fn bios_limit(_policy: &mut Policy) -> Result<u32> {
build_error!(VTABLE_DEFAULT_ERROR)
}
@@ -1359,9 +1366,12 @@ impl<T: Driver> Registration<T> {
from_result(|| {
let mut policy = PolicyCpu::from_cpu(cpu_id)?;
let val = T::bios_limit(&mut policy)?;
// SAFETY: `limit` is guaranteed by the C code to be valid.
T::bios_limit(&mut policy, &mut (unsafe { *limit })).map(|()| 0)
unsafe {
*limit = val;
}
Ok(0)
})
}