1
0

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

Merge ARM cpufreq updates for 6.14 from Viresh Kumar:

"- Extended support for more SoCs in apple cpufreq driver (Hector Martin
   and Nick Chan).

 - Add new cpufreq driver for Airoha SoCs (Christian Marangi).

 - Fix using cpufreq-dt as module (Andreas Kemnade).

 - Minor fixes for Sparc, scmi, and Qcom drivers (Ethan Carter Edwards,
   Sibi Sankar and Manivannan Sadhasivam)."

* tag 'cpufreq-arm-updates-6.14' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
  cpufreq: airoha: Add EN7581 CPUFreq SMCCC driver
  cpufreq: sparc: change kzalloc to kcalloc
  cpufreq: qcom: Implement clk_ops::determine_rate() for qcom_cpufreq* clocks
  cpufreq: qcom: Fix qcom_cpufreq_hw_recalc_rate() to query LUT if LMh IRQ is not available
  cpufreq: apple-soc: Add Apple A7-A8X SoC cpufreq support
  cpufreq: apple-soc: Set fallback transition latency to APPLE_DVFS_TRANSITION_TIMEOUT
  cpufreq: apple-soc: Increase cluster switch timeout to 400us
  cpufreq: apple-soc: Use 32-bit read for status register
  cpufreq: apple-soc: Allow per-SoC configuration of APPLE_DVFS_CMD_PS1
  cpufreq: apple-soc: Drop setting the PS2 field on M2+
  dt-bindings: cpufreq: apple,cluster-cpufreq: Add A7-A11, T2 compatibles
  dt-bindings: cpufreq: Document support for Airoha EN7581 CPUFreq
  cpufreq: fix using cpufreq-dt as module
  cpufreq: scmi: Register for limit change notifications
This commit is contained in:
Rafael J. Wysocki
2025-01-20 12:53:59 +01:00
12 changed files with 344 additions and 27 deletions

View File

@@ -0,0 +1,55 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/cpufreq/airoha,en7581-cpufreq.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Airoha EN7581 CPUFreq
maintainers:
- Christian Marangi <ansuelsmth@gmail.com>
description: |
On newer Airoha SoC, CPU Frequency is scaled indirectly with SMC commands
to ATF.
A virtual clock is exposed. This virtual clock is a get-only clock and
is used to expose the current global CPU clock. The frequency info comes
by the output of the SMC command that reports the clock in MHz.
The SMC sets the CPU clock by providing an index, this is modelled as
performance states in a power domain.
CPUs can't be individually scaled as the CPU frequency is shared across
all CPUs and is global.
properties:
compatible:
const: airoha,en7581-cpufreq
'#clock-cells':
const: 0
'#power-domain-cells':
const: 0
operating-points-v2: true
required:
- compatible
- '#clock-cells'
- '#power-domain-cells'
- operating-points-v2
additionalProperties: false
examples:
- |
performance-domain {
compatible = "airoha,en7581-cpufreq";
operating-points-v2 = <&cpu_smcc_opp_table>;
#power-domain-cells = <0>;
#clock-cells = <0>;
};

View File

@@ -24,9 +24,17 @@ properties:
- apple,t8112-cluster-cpufreq
- const: apple,cluster-cpufreq
- items:
- const: apple,t6000-cluster-cpufreq
- enum:
- apple,s8000-cluster-cpufreq
- apple,t8010-cluster-cpufreq
- apple,t8015-cluster-cpufreq
- apple,t6000-cluster-cpufreq
- const: apple,t8103-cluster-cpufreq
- const: apple,cluster-cpufreq
- items:
- const: apple,t7000-cluster-cpufreq
- const: apple,s5l8960x-cluster-cpufreq
- const: apple,s5l8960x-cluster-cpufreq
reg:
maxItems: 1

View File

@@ -232,7 +232,7 @@ config CPUFREQ_VIRT
If in doubt, say N.
config CPUFREQ_DT_PLATDEV
tristate "Generic DT based cpufreq platdev driver"
bool "Generic DT based cpufreq platdev driver"
depends on OF
help
This adds a generic DT based cpufreq platdev driver for frequency

View File

@@ -15,6 +15,14 @@ config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM
To compile this driver as a module, choose M here: the
module will be called sun50i-cpufreq-nvmem.
config ARM_AIROHA_SOC_CPUFREQ
tristate "Airoha EN7581 SoC CPUFreq support"
depends on ARCH_AIROHA || COMPILE_TEST
select PM_OPP
default ARCH_AIROHA
help
This adds the CPUFreq driver for Airoha EN7581 SoCs.
config ARM_APPLE_SOC_CPUFREQ
tristate "Apple Silicon SoC CPUFreq support"
depends on ARCH_APPLE || (COMPILE_TEST && 64BIT)

View File

@@ -53,6 +53,7 @@ obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY) += amd_freq_sensitivity.o
##################################################################################
# ARM SoC drivers
obj-$(CONFIG_ARM_AIROHA_SOC_CPUFREQ) += airoha-cpufreq.o
obj-$(CONFIG_ARM_APPLE_SOC_CPUFREQ) += apple-soc-cpufreq.o
obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
obj-$(CONFIG_ARM_ARMADA_8K_CPUFREQ) += armada-8k-cpufreq.o

View File

@@ -0,0 +1,152 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/bitfield.h>
#include <linux/cpufreq.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include "cpufreq-dt.h"
struct airoha_cpufreq_priv {
int opp_token;
struct dev_pm_domain_list *pd_list;
struct platform_device *cpufreq_dt;
};
static struct platform_device *cpufreq_pdev;
/* NOP function to disable OPP from setting clock */
static int airoha_cpufreq_config_clks_nop(struct device *dev,
struct opp_table *opp_table,
struct dev_pm_opp *opp,
void *data, bool scaling_down)
{
return 0;
}
static const char * const airoha_cpufreq_clk_names[] = { "cpu", NULL };
static const char * const airoha_cpufreq_pd_names[] = { "perf" };
static int airoha_cpufreq_probe(struct platform_device *pdev)
{
const struct dev_pm_domain_attach_data attach_data = {
.pd_names = airoha_cpufreq_pd_names,
.num_pd_names = ARRAY_SIZE(airoha_cpufreq_pd_names),
.pd_flags = PD_FLAG_DEV_LINK_ON | PD_FLAG_REQUIRED_OPP,
};
struct dev_pm_opp_config config = {
.clk_names = airoha_cpufreq_clk_names,
.config_clks = airoha_cpufreq_config_clks_nop,
};
struct platform_device *cpufreq_dt;
struct airoha_cpufreq_priv *priv;
struct device *dev = &pdev->dev;
struct device *cpu_dev;
int ret;
/* CPUs refer to the same OPP table */
cpu_dev = get_cpu_device(0);
if (!cpu_dev)
return -ENODEV;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
/* Set OPP table conf with NOP config_clks */
priv->opp_token = dev_pm_opp_set_config(cpu_dev, &config);
if (priv->opp_token < 0)
return dev_err_probe(dev, priv->opp_token, "Failed to set OPP config\n");
/* Attach PM for OPP */
ret = dev_pm_domain_attach_list(cpu_dev, &attach_data,
&priv->pd_list);
if (ret)
goto clear_opp_config;
cpufreq_dt = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
ret = PTR_ERR_OR_ZERO(cpufreq_dt);
if (ret) {
dev_err(dev, "failed to create cpufreq-dt device: %d\n", ret);
goto detach_pm;
}
priv->cpufreq_dt = cpufreq_dt;
platform_set_drvdata(pdev, priv);
return 0;
detach_pm:
dev_pm_domain_detach_list(priv->pd_list);
clear_opp_config:
dev_pm_opp_clear_config(priv->opp_token);
return ret;
}
static void airoha_cpufreq_remove(struct platform_device *pdev)
{
struct airoha_cpufreq_priv *priv = platform_get_drvdata(pdev);
platform_device_unregister(priv->cpufreq_dt);
dev_pm_domain_detach_list(priv->pd_list);
dev_pm_opp_clear_config(priv->opp_token);
}
static struct platform_driver airoha_cpufreq_driver = {
.probe = airoha_cpufreq_probe,
.remove = airoha_cpufreq_remove,
.driver = {
.name = "airoha-cpufreq",
},
};
static const struct of_device_id airoha_cpufreq_match_list[] __initconst = {
{ .compatible = "airoha,en7581" },
{},
};
MODULE_DEVICE_TABLE(of, airoha_cpufreq_match_list);
static int __init airoha_cpufreq_init(void)
{
struct device_node *np = of_find_node_by_path("/");
const struct of_device_id *match;
int ret;
if (!np)
return -ENODEV;
match = of_match_node(airoha_cpufreq_match_list, np);
of_node_put(np);
if (!match)
return -ENODEV;
ret = platform_driver_register(&airoha_cpufreq_driver);
if (unlikely(ret < 0))
return ret;
cpufreq_pdev = platform_device_register_data(NULL, "airoha-cpufreq",
-1, match, sizeof(*match));
ret = PTR_ERR_OR_ZERO(cpufreq_pdev);
if (ret)
platform_driver_unregister(&airoha_cpufreq_driver);
return ret;
}
module_init(airoha_cpufreq_init);
static void __exit airoha_cpufreq_exit(void)
{
platform_device_unregister(cpufreq_pdev);
platform_driver_unregister(&airoha_cpufreq_driver);
}
module_exit(airoha_cpufreq_exit);
MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
MODULE_DESCRIPTION("CPUfreq driver for Airoha SoCs");
MODULE_LICENSE("GPL");

View File

@@ -22,11 +22,14 @@
#include <linux/pm_opp.h>
#include <linux/slab.h>
#define APPLE_DVFS_CMD 0x20
#define APPLE_DVFS_CMD_BUSY BIT(31)
#define APPLE_DVFS_CMD_SET BIT(25)
#define APPLE_DVFS_CMD_PS2 GENMASK(16, 12)
#define APPLE_DVFS_CMD_PS1 GENMASK(4, 0)
#define APPLE_DVFS_CMD 0x20
#define APPLE_DVFS_CMD_BUSY BIT(31)
#define APPLE_DVFS_CMD_SET BIT(25)
#define APPLE_DVFS_CMD_PS1_S5L8960X GENMASK(24, 22)
#define APPLE_DVFS_CMD_PS1_S5L8960X_SHIFT 22
#define APPLE_DVFS_CMD_PS2 GENMASK(15, 12)
#define APPLE_DVFS_CMD_PS1 GENMASK(4, 0)
#define APPLE_DVFS_CMD_PS1_SHIFT 0
/* Same timebase as CPU counter (24MHz) */
#define APPLE_DVFS_LAST_CHG_TIME 0x38
@@ -35,6 +38,9 @@
* Apple ran out of bits and had to shift this in T8112...
*/
#define APPLE_DVFS_STATUS 0x50
#define APPLE_DVFS_STATUS_CUR_PS_S5L8960X GENMASK(5, 3)
#define APPLE_DVFS_STATUS_CUR_PS_SHIFT_S5L8960X 3
#define APPLE_DVFS_STATUS_TGT_PS_S5L8960X GENMASK(2, 0)
#define APPLE_DVFS_STATUS_CUR_PS_T8103 GENMASK(7, 4)
#define APPLE_DVFS_STATUS_CUR_PS_SHIFT_T8103 4
#define APPLE_DVFS_STATUS_TGT_PS_T8103 GENMASK(3, 0)
@@ -52,12 +58,15 @@
#define APPLE_DVFS_PLL_FACTOR_MULT GENMASK(31, 16)
#define APPLE_DVFS_PLL_FACTOR_DIV GENMASK(15, 0)
#define APPLE_DVFS_TRANSITION_TIMEOUT 100
#define APPLE_DVFS_TRANSITION_TIMEOUT 400
struct apple_soc_cpufreq_info {
bool has_ps2;
u64 max_pstate;
u64 cur_pstate_mask;
u64 cur_pstate_shift;
u64 ps1_mask;
u64 ps1_shift;
};
struct apple_cpu_priv {
@@ -68,24 +77,46 @@ struct apple_cpu_priv {
static struct cpufreq_driver apple_soc_cpufreq_driver;
static const struct apple_soc_cpufreq_info soc_s5l8960x_info = {
.has_ps2 = false,
.max_pstate = 7,
.cur_pstate_mask = APPLE_DVFS_STATUS_CUR_PS_S5L8960X,
.cur_pstate_shift = APPLE_DVFS_STATUS_CUR_PS_SHIFT_S5L8960X,
.ps1_mask = APPLE_DVFS_CMD_PS1_S5L8960X,
.ps1_shift = APPLE_DVFS_CMD_PS1_S5L8960X_SHIFT,
};
static const struct apple_soc_cpufreq_info soc_t8103_info = {
.has_ps2 = true,
.max_pstate = 15,
.cur_pstate_mask = APPLE_DVFS_STATUS_CUR_PS_T8103,
.cur_pstate_shift = APPLE_DVFS_STATUS_CUR_PS_SHIFT_T8103,
.ps1_mask = APPLE_DVFS_CMD_PS1,
.ps1_shift = APPLE_DVFS_CMD_PS1_SHIFT,
};
static const struct apple_soc_cpufreq_info soc_t8112_info = {
.has_ps2 = false,
.max_pstate = 31,
.cur_pstate_mask = APPLE_DVFS_STATUS_CUR_PS_T8112,
.cur_pstate_shift = APPLE_DVFS_STATUS_CUR_PS_SHIFT_T8112,
.ps1_mask = APPLE_DVFS_CMD_PS1,
.ps1_shift = APPLE_DVFS_CMD_PS1_SHIFT,
};
static const struct apple_soc_cpufreq_info soc_default_info = {
.has_ps2 = false,
.max_pstate = 15,
.cur_pstate_mask = 0, /* fallback */
.ps1_mask = APPLE_DVFS_CMD_PS1,
.ps1_shift = APPLE_DVFS_CMD_PS1_SHIFT,
};
static const struct of_device_id apple_soc_cpufreq_of_match[] __maybe_unused = {
{
.compatible = "apple,s5l8960x-cluster-cpufreq",
.data = &soc_s5l8960x_info,
},
{
.compatible = "apple,t8103-cluster-cpufreq",
.data = &soc_t8103_info,
@@ -109,7 +140,7 @@ static unsigned int apple_soc_cpufreq_get_rate(unsigned int cpu)
unsigned int pstate;
if (priv->info->cur_pstate_mask) {
u64 reg = readq_relaxed(priv->reg_base + APPLE_DVFS_STATUS);
u32 reg = readl_relaxed(priv->reg_base + APPLE_DVFS_STATUS);
pstate = (reg & priv->info->cur_pstate_mask) >> priv->info->cur_pstate_shift;
} else {
@@ -148,9 +179,12 @@ static int apple_soc_cpufreq_set_target(struct cpufreq_policy *policy,
return -EIO;
}
reg &= ~(APPLE_DVFS_CMD_PS1 | APPLE_DVFS_CMD_PS2);
reg |= FIELD_PREP(APPLE_DVFS_CMD_PS1, pstate);
reg |= FIELD_PREP(APPLE_DVFS_CMD_PS2, pstate);
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);
}
reg |= APPLE_DVFS_CMD_SET;
writeq_relaxed(reg, priv->reg_base + APPLE_DVFS_CMD);
@@ -275,7 +309,7 @@ static int apple_soc_cpufreq_init(struct cpufreq_policy *policy)
transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev);
if (!transition_latency)
transition_latency = CPUFREQ_ETERNAL;
transition_latency = APPLE_DVFS_TRANSITION_TIMEOUT * NSEC_PER_USEC;
policy->cpuinfo.transition_latency = transition_latency;
policy->dvfs_possible_from_any_cpu = true;

View File

@@ -103,6 +103,8 @@ static const struct of_device_id allowlist[] __initconst = {
* platforms using "operating-points-v2" property.
*/
static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "airoha,en7581", },
{ .compatible = "allwinner,sun50i-a100" },
{ .compatible = "allwinner,sun50i-h6", },
{ .compatible = "allwinner,sun50i-h616", },
@@ -235,5 +237,3 @@ create_pdev:
sizeof(struct cpufreq_dt_platform_data)));
}
core_initcall(cpufreq_dt_platdev_init);
MODULE_DESCRIPTION("Generic DT based cpufreq platdev driver");
MODULE_LICENSE("GPL");

View File

@@ -143,14 +143,12 @@ static unsigned long qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data)
}
/* Get the frequency requested by the cpufreq core for the CPU */
static unsigned int qcom_cpufreq_get_freq(unsigned int cpu)
static unsigned int qcom_cpufreq_get_freq(struct cpufreq_policy *policy)
{
struct qcom_cpufreq_data *data;
const struct qcom_cpufreq_soc_data *soc_data;
struct cpufreq_policy *policy;
unsigned int index;
policy = cpufreq_cpu_get_raw(cpu);
if (!policy)
return 0;
@@ -163,12 +161,10 @@ static unsigned int qcom_cpufreq_get_freq(unsigned int cpu)
return policy->freq_table[index].frequency;
}
static unsigned int qcom_cpufreq_hw_get(unsigned int cpu)
static unsigned int __qcom_cpufreq_hw_get(struct cpufreq_policy *policy)
{
struct qcom_cpufreq_data *data;
struct cpufreq_policy *policy;
policy = cpufreq_cpu_get_raw(cpu);
if (!policy)
return 0;
@@ -177,7 +173,12 @@ static unsigned int qcom_cpufreq_hw_get(unsigned int cpu)
if (data->throttle_irq >= 0)
return qcom_lmh_get_throttle_freq(data) / HZ_PER_KHZ;
return qcom_cpufreq_get_freq(cpu);
return qcom_cpufreq_get_freq(policy);
}
static unsigned int qcom_cpufreq_hw_get(unsigned int cpu)
{
return __qcom_cpufreq_hw_get(cpufreq_cpu_get_raw(cpu));
}
static unsigned int qcom_cpufreq_hw_fast_switch(struct cpufreq_policy *policy,
@@ -363,7 +364,7 @@ static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data)
* If h/w throttled frequency is higher than what cpufreq has requested
* for, then stop polling and switch back to interrupt mechanism.
*/
if (throttled_freq >= qcom_cpufreq_get_freq(cpu))
if (throttled_freq >= qcom_cpufreq_get_freq(cpufreq_cpu_get_raw(cpu)))
enable_irq(data->throttle_irq);
else
mod_delayed_work(system_highpri_wq, &data->throttle_work,
@@ -441,7 +442,6 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index)
return data->throttle_irq;
data->cancel_throttle = false;
data->policy = policy;
mutex_init(&data->throttle_lock);
INIT_DEFERRABLE_WORK(&data->throttle_work, qcom_lmh_dcvs_poll);
@@ -552,6 +552,7 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
policy->driver_data = data;
policy->dvfs_possible_from_any_cpu = true;
data->policy = policy;
ret = qcom_cpufreq_hw_read_lut(cpu_dev, policy);
if (ret) {
@@ -622,11 +623,24 @@ static unsigned long qcom_cpufreq_hw_recalc_rate(struct clk_hw *hw, unsigned lon
{
struct qcom_cpufreq_data *data = container_of(hw, struct qcom_cpufreq_data, cpu_clk);
return qcom_lmh_get_throttle_freq(data);
return __qcom_cpufreq_hw_get(data->policy) * HZ_PER_KHZ;
}
/*
* Since we cannot determine the closest rate of the target rate, let's just
* return the actual rate at which the clock is running at. This is needed to
* make clk_set_rate() API work properly.
*/
static int qcom_cpufreq_hw_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
req->rate = qcom_cpufreq_hw_recalc_rate(hw, 0);
return 0;
}
static const struct clk_ops qcom_cpufreq_hw_clk_ops = {
.recalc_rate = qcom_cpufreq_hw_recalc_rate,
.determine_rate = qcom_cpufreq_hw_determine_rate,
};
static int qcom_cpufreq_hw_driver_probe(struct platform_device *pdev)

View File

@@ -16,6 +16,7 @@
#include <linux/export.h>
#include <linux/module.h>
#include <linux/pm_opp.h>
#include <linux/pm_qos.h>
#include <linux/slab.h>
#include <linux/scmi_protocol.h>
#include <linux/types.h>
@@ -26,6 +27,8 @@ struct scmi_data {
int nr_opp;
struct device *cpu_dev;
cpumask_var_t opp_shared_cpus;
struct notifier_block limit_notify_nb;
struct freq_qos_request limits_freq_req;
};
static struct scmi_protocol_handle *ph;
@@ -174,6 +177,22 @@ static struct freq_attr *scmi_cpufreq_hw_attr[] = {
NULL,
};
static int scmi_limit_notify_cb(struct notifier_block *nb, unsigned long event, void *data)
{
struct scmi_data *priv = container_of(nb, struct scmi_data, limit_notify_nb);
struct scmi_perf_limits_report *limit_notify = data;
unsigned int limit_freq_khz;
int ret;
limit_freq_khz = limit_notify->range_max_freq / HZ_PER_KHZ;
ret = freq_qos_update_request(&priv->limits_freq_req, limit_freq_khz);
if (ret < 0)
pr_warn("failed to update freq constraint: %d\n", ret);
return NOTIFY_OK;
}
static int scmi_cpufreq_init(struct cpufreq_policy *policy)
{
int ret, nr_opp, domain;
@@ -181,6 +200,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
struct device *cpu_dev;
struct scmi_data *priv;
struct cpufreq_frequency_table *freq_table;
struct scmi_device *sdev = cpufreq_get_driver_data();
cpu_dev = get_cpu_device(policy->cpu);
if (!cpu_dev) {
@@ -294,6 +314,23 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
}
}
ret = freq_qos_add_request(&policy->constraints, &priv->limits_freq_req, FREQ_QOS_MAX,
FREQ_QOS_MAX_DEFAULT_VALUE);
if (ret < 0) {
dev_err(cpu_dev, "failed to add qos limits request: %d\n", ret);
goto out_free_table;
}
priv->limit_notify_nb.notifier_call = scmi_limit_notify_cb;
ret = sdev->handle->notify_ops->event_notifier_register(sdev->handle, SCMI_PROTOCOL_PERF,
SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED,
&priv->domain_id,
&priv->limit_notify_nb);
if (ret)
dev_warn(&sdev->dev,
"failed to register for limits change notifier for domain %d\n",
priv->domain_id);
return 0;
out_free_table:
@@ -313,7 +350,13 @@ out_free_priv:
static void scmi_cpufreq_exit(struct cpufreq_policy *policy)
{
struct scmi_data *priv = policy->driver_data;
struct scmi_device *sdev = cpufreq_get_driver_data();
sdev->handle->notify_ops->event_notifier_unregister(sdev->handle, SCMI_PROTOCOL_PERF,
SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED,
&priv->domain_id,
&priv->limit_notify_nb);
freq_qos_remove_request(&priv->limits_freq_req);
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
free_cpumask_var(priv->opp_shared_cpus);
@@ -372,6 +415,8 @@ static int scmi_cpufreq_probe(struct scmi_device *sdev)
if (!handle)
return -ENODEV;
scmi_cpufreq_driver.driver_data = sdev;
perf_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_PERF, &ph);
if (IS_ERR(perf_ops))
return PTR_ERR(perf_ops);

View File

@@ -323,7 +323,7 @@ static int __init us2e_freq_init(void)
impl = ((ver >> 32) & 0xffff);
if (manuf == 0x17 && impl == 0x13) {
us2e_freq_table = kzalloc(NR_CPUS * sizeof(*us2e_freq_table),
us2e_freq_table = kcalloc(NR_CPUS, sizeof(*us2e_freq_table),
GFP_KERNEL);
if (!us2e_freq_table)
return -ENOMEM;

View File

@@ -171,7 +171,7 @@ static int __init us3_freq_init(void)
impl == CHEETAH_PLUS_IMPL ||
impl == JAGUAR_IMPL ||
impl == PANTHER_IMPL)) {
us3_freq_table = kzalloc(NR_CPUS * sizeof(*us3_freq_table),
us3_freq_table = kcalloc(NR_CPUS, sizeof(*us3_freq_table),
GFP_KERNEL);
if (!us3_freq_table)
return -ENOMEM;