diff --git a/arch/arm64/boot/dts/rockchip/px30-android.dtsi b/arch/arm64/boot/dts/rockchip/px30-android.dtsi index 71d4cc489ff1..f2884e8e991d 100644 --- a/arch/arm64/boot/dts/rockchip/px30-android.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-android.dtsi @@ -72,7 +72,7 @@ }; &cpu0_opp_table { - rockchip,avs-enable = <1>; + rockchip,avs = <1>; }; &display_subsystem { diff --git a/arch/arm64/boot/dts/rockchip/rk3368-android.dtsi b/arch/arm64/boot/dts/rockchip/rk3368-android.dtsi index b7a8ab6971f4..4976c72d6c34 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-android.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368-android.dtsi @@ -174,7 +174,7 @@ }; &cluster1_opp { - rockchip,avs-enable = <1>; + rockchip,avs = <1>; }; &display_subsystem { diff --git a/drivers/cpufreq/rockchip-cpufreq.c b/drivers/cpufreq/rockchip-cpufreq.c index 85474d487465..cd8bcdac0e45 100644 --- a/drivers/cpufreq/rockchip-cpufreq.c +++ b/drivers/cpufreq/rockchip-cpufreq.c @@ -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; } diff --git a/drivers/soc/rockchip/rockchip_opp_select.c b/drivers/soc/rockchip/rockchip_opp_select.c index 88e746b687a5..27999746fe3b 100644 --- a/drivers/soc/rockchip/rockchip_opp_select.c +++ b/drivers/soc/rockchip/rockchip_opp_select.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-2.0+ */ #include +#include #include #include #include @@ -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: diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index e1eb0967feef..24b9e4e137b4 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -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; }