mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
soc: rockchip: opp_select: Add support to limit cpu frequency
Change-Id: I6ac41448bbb031b88cc89d5895068191bd2f2dc8 Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
This commit is contained in:
@@ -72,7 +72,7 @@
|
||||
};
|
||||
|
||||
&cpu0_opp_table {
|
||||
rockchip,avs-enable = <1>;
|
||||
rockchip,avs = <1>;
|
||||
};
|
||||
|
||||
&display_subsystem {
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
};
|
||||
|
||||
&cluster1_opp {
|
||||
rockchip,avs-enable = <1>;
|
||||
rockchip,avs = <1>;
|
||||
};
|
||||
|
||||
&display_subsystem {
|
||||
|
||||
@@ -41,6 +41,7 @@ struct cluster_info {
|
||||
cpumask_t cpus;
|
||||
unsigned int reboot_freq;
|
||||
unsigned int threshold_freq;
|
||||
unsigned int scale_rate;
|
||||
int volt_sel;
|
||||
int scale;
|
||||
int process;
|
||||
@@ -127,6 +128,25 @@ static struct cluster_info *rockchip_cluster_info_lookup(int cpu)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct cluster_info *rockchip_cluster_lookup_by_dev(struct device *dev)
|
||||
{
|
||||
struct cluster_info *cluster;
|
||||
struct device *cpu_dev;
|
||||
int cpu;
|
||||
|
||||
list_for_each_entry(cluster, &cluster_info_list, list_head) {
|
||||
for_each_cpu(cpu, &cluster->cpus) {
|
||||
cpu_dev = get_cpu_device(cpu);
|
||||
if (!cpu_dev)
|
||||
continue;
|
||||
if (cpu_dev == dev)
|
||||
return cluster;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int rockchip_cpufreq_get_scale(int cpu)
|
||||
{
|
||||
struct cluster_info *cluster;
|
||||
@@ -139,6 +159,19 @@ int rockchip_cpufreq_get_scale(int cpu)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rockchip_cpufreq_get_scale);
|
||||
|
||||
int rockchip_cpufreq_set_scale_rate(struct device *dev, unsigned long rate)
|
||||
{
|
||||
struct cluster_info *cluster;
|
||||
|
||||
cluster = rockchip_cluster_lookup_by_dev(dev);
|
||||
if (!cluster)
|
||||
return -EINVAL;
|
||||
cluster->scale_rate = rate / 1000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rockchip_cpufreq_set_scale_rate);
|
||||
|
||||
static int rockchip_cpufreq_cluster_init(int cpu, struct cluster_info *cluster)
|
||||
{
|
||||
struct device_node *np;
|
||||
@@ -274,6 +307,11 @@ static int rockchip_cpufreq_policy_notifier(struct notifier_block *nb,
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
if (cluster->scale_rate) {
|
||||
if (cluster->scale_rate < policy->max)
|
||||
policy->max = cluster->scale_rate;
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -677,7 +678,7 @@ int rockchip_adjust_power_scale(struct device *dev, int scale)
|
||||
struct device_node *np;
|
||||
struct clk *clk;
|
||||
int irdrop_scale = 0, opp_scale = 0;
|
||||
u32 target_scale, avs_enable = 0, avs_scale = 0;
|
||||
u32 target_scale, avs = 0, avs_scale = 0;
|
||||
long scale_rate = 0;
|
||||
int ret = 0;
|
||||
|
||||
@@ -686,14 +687,15 @@ int rockchip_adjust_power_scale(struct device *dev, int scale)
|
||||
dev_warn(dev, "OPP-v2 not supported\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
of_property_read_u32(np, "rockchip,avs-enable", &avs_enable);
|
||||
of_property_read_u32(np, "rockchip,avs-enable", &avs);
|
||||
of_property_read_u32(np, "rockchip,avs", &avs);
|
||||
of_property_read_u32(np, "rockchip,avs-scale", &avs_scale);
|
||||
|
||||
rockchip_adjust_opp_by_irdrop(dev, np, &irdrop_scale, &opp_scale);
|
||||
target_scale = max(irdrop_scale, scale);
|
||||
if (target_scale <= 0)
|
||||
return 0;
|
||||
dev_info(dev, "target-scale=%d\n", target_scale);
|
||||
dev_info(dev, "avs=%d, target-scale=%d\n", avs, target_scale);
|
||||
|
||||
clk = of_clk_get_by_name(np, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
@@ -701,7 +703,7 @@ int rockchip_adjust_power_scale(struct device *dev, int scale)
|
||||
goto np_err;
|
||||
}
|
||||
|
||||
if (avs_enable) {
|
||||
if (avs == 1) {
|
||||
ret = rockchip_pll_clk_adaptive_scaling(clk, target_scale);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to adaptive scaling\n");
|
||||
@@ -731,9 +733,15 @@ int rockchip_adjust_power_scale(struct device *dev, int scale)
|
||||
goto clk_err;
|
||||
}
|
||||
dev_info(dev, "scale_rate=%lu\n", scale_rate);
|
||||
ret = rockchip_adjust_opp_table(dev, scale_rate);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to adjust opp table\n");
|
||||
if (avs == 2) {
|
||||
ret = rockchip_cpufreq_set_scale_rate(dev, scale_rate);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to set cpu scale rate\n");
|
||||
} else {
|
||||
ret = rockchip_adjust_opp_table(dev, scale_rate);
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to adjust opp table\n");
|
||||
}
|
||||
}
|
||||
|
||||
clk_err:
|
||||
|
||||
@@ -698,6 +698,7 @@ unsigned long cpufreq_scale_max_freq_capacity(int cpu);
|
||||
#ifdef CONFIG_ARM_ROCKCHIP_CPUFREQ
|
||||
unsigned int rockchip_cpufreq_adjust_target(int cpu, unsigned int freq);
|
||||
int rockchip_cpufreq_get_scale(int cpu);
|
||||
int rockchip_cpufreq_set_scale_rate(struct device *dev, unsigned long rate);
|
||||
#else
|
||||
static inline unsigned int rockchip_cpufreq_adjust_target(int cpu,
|
||||
unsigned int freq)
|
||||
@@ -705,7 +706,13 @@ static inline unsigned int rockchip_cpufreq_adjust_target(int cpu,
|
||||
return freq;
|
||||
}
|
||||
|
||||
int rockchip_cpufreq_get_scale(int cpu)
|
||||
static inline int rockchip_cpufreq_get_scale(int cpu)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int rockchip_cpufreq_set_scale_rate(struct device *dev,
|
||||
unsigned long rate)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user