diff options
-rw-r--r-- | drivers/cpufreq/rockchip-cpufreq.c | 44 | ||||
-rw-r--r-- | drivers/devfreq/rockchip_dmc.c | 19 | ||||
-rw-r--r-- | drivers/soc/rockchip/rockchip_system_monitor.c | 88 | ||||
-rw-r--r-- | include/soc/rockchip/rockchip_system_monitor.h | 4 |
4 files changed, 77 insertions, 78 deletions
diff --git a/drivers/cpufreq/rockchip-cpufreq.c b/drivers/cpufreq/rockchip-cpufreq.c index 3e1b253f5414..c206b7cf0205 100644 --- a/drivers/cpufreq/rockchip-cpufreq.c +++ b/drivers/cpufreq/rockchip-cpufreq.c @@ -24,7 +24,6 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_opp.h> -#include <linux/reboot.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> #include <linux/soc/rockchip/pvtm.h> @@ -35,7 +34,6 @@ #include "../clk/rockchip/clk.h" #define LEAKAGE_INVALID 0xff -#define REBOOT_FREQ 816000 /* kHz */ struct cluster_info { struct list_head list_head; @@ -48,7 +46,6 @@ struct cluster_info { int scale; int process; bool offline; - bool rebooting; bool freq_limit; bool is_check_init; }; @@ -300,9 +297,6 @@ static int rockchip_cpufreq_cluster_init(int cpu, struct cluster_info *cluster) goto np_err; } - if (of_property_read_u32(np, "rockchip,reboot-freq", - &cluster->reboot_freq)) - cluster->reboot_freq = REBOOT_FREQ; of_property_read_u32(np, "rockchip,threshold-freq", &cluster->threshold_freq); cluster->freq_limit = of_property_read_bool(np, "rockchip,freq-limit"); @@ -364,27 +358,6 @@ static struct notifier_block rockchip_hotcpu_nb = { .notifier_call = rockchip_hotcpu_notifier, }; -static int rockchip_reboot_notifier(struct notifier_block *nb, - unsigned long action, void *ptr) -{ - int cpu; - struct cluster_info *cluster; - - list_for_each_entry(cluster, &cluster_info_list, list_head) { - cpu = cpumask_first_and(&cluster->cpus, cpu_online_mask); - if (cpu >= nr_cpu_ids) - continue; - cluster->rebooting = true; - cpufreq_update_policy(cpu); - } - - return NOTIFY_OK; -} - -static struct notifier_block rockchip_reboot_nb = { - .notifier_call = rockchip_reboot_notifier, -}; - static int rockchip_cpufreq_policy_notifier(struct notifier_block *nb, unsigned long event, void *data) { @@ -399,20 +372,8 @@ static int rockchip_cpufreq_policy_notifier(struct notifier_block *nb, if (!cluster) return NOTIFY_DONE; - if (cluster->scale_rate) { - if (cluster->scale_rate < policy->max) - policy->max = cluster->scale_rate; - } - - if (cluster->rebooting) { - if (cluster->reboot_freq < policy->max) - policy->max = cluster->reboot_freq; - policy->min = policy->max; - pr_info("cpu%d limit freq=%d min=%d max=%d\n", - policy->cpu, cluster->reboot_freq, - policy->min, policy->max); - return NOTIFY_OK; - } + if (cluster->scale_rate && cluster->scale_rate < policy->max) + cpufreq_verify_within_limits(policy, 0, cluster->scale_rate); return NOTIFY_OK; } @@ -552,7 +513,6 @@ static int __init rockchip_cpufreq_driver_init(void) } register_hotcpu_notifier(&rockchip_hotcpu_nb); - register_reboot_notifier(&rockchip_reboot_nb); cpufreq_register_notifier(&rockchip_cpufreq_policy_nb, CPUFREQ_POLICY_NOTIFIER); diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index b49ed67590fb..4148b8a47bbb 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -36,7 +36,6 @@ #include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/pm_qos.h> -#include <linux/reboot.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/rockchip/rockchip_sip.h> @@ -1117,7 +1116,6 @@ struct rockchip_dmcfreq { struct dram_timing *timing; struct regulator *vdd_center; struct notifier_block status_nb; - struct notifier_block reboot_nb; struct notifier_block fb_nb; struct list_head video_info_list; struct freq_map_table *vop_bw_tbl; @@ -2780,6 +2778,7 @@ static int rockchip_dmcfreq_system_status_notifier(struct notifier_block *nb, } if (dmcfreq->reboot_rate && (status & SYS_STATUS_REBOOT)) { + devfreq_monitor_stop(dmcfreq->devfreq); target_rate = dmcfreq->reboot_rate; goto next; } @@ -2831,17 +2830,6 @@ next: return NOTIFY_OK; } -static int rockchip_dmcfreq_reboot_notifier(struct notifier_block *nb, - unsigned long action, void *ptr) -{ - struct rockchip_dmcfreq *dmcfreq = reboot_to_dmcfreq(nb); - - devfreq_monitor_stop(dmcfreq->devfreq); - rockchip_set_system_status(SYS_STATUS_REBOOT); - - return NOTIFY_OK; -} - static int rockchip_dmcfreq_fb_notifier(struct notifier_block *nb, unsigned long action, void *ptr) { @@ -3423,11 +3411,6 @@ static void rockchip_dmcfreq_register_notifier(struct rockchip_dmcfreq *dmcfreq) if (ret) dev_err(dmcfreq->dev, "failed to register system_status nb\n"); - dmcfreq->reboot_nb.notifier_call = rockchip_dmcfreq_reboot_notifier; - ret = register_reboot_notifier(&dmcfreq->reboot_nb); - if (ret) - dev_err(dmcfreq->dev, "failed to register reboot nb\n"); - dmcfreq->fb_nb.notifier_call = rockchip_dmcfreq_fb_notifier; ret = fb_register_client(&dmcfreq->fb_nb); if (ret) diff --git a/drivers/soc/rockchip/rockchip_system_monitor.c b/drivers/soc/rockchip/rockchip_system_monitor.c index 0b54b4bf588f..550f70cd42e9 100644 --- a/drivers/soc/rockchip/rockchip_system_monitor.c +++ b/drivers/soc/rockchip/rockchip_system_monitor.c @@ -15,6 +15,7 @@ #include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/uaccess.h> +#include <linux/reboot.h> #include <linux/slab.h> #include <linux/suspend.h> #include <linux/thermal.h> @@ -25,6 +26,7 @@ #include "../../base/power/opp/opp.h" #include "../../devfreq/governor.h" +#define CPU_REBOOT_FREQ 816000 /* kHz */ #define VIDEO_1080P_SIZE (1920 * 1080) #define THERMAL_POLLING_DELAY 200 /* milliseconds */ @@ -585,6 +587,19 @@ err: return ret; } +static int monitor_device_parse_status_config(struct device_node *np, + struct monitor_dev_info *info) +{ + int ret; + + ret = of_property_read_u32(np, "rockchip,video-4k-freq", + &info->video_4k_freq); + ret &= of_property_read_u32(np, "rockchip,reboot-freq", + &info->reboot_freq); + + return ret; +} + static int rockchip_get_temp_freq_table(struct device_node *np, char *porp_name, struct temp_freq_table **freq_table) @@ -629,7 +644,7 @@ static int monitor_device_parse_dt(struct device *dev, struct device_node *np; int ret = 0; bool is_wide_temp_en = false; - bool is_4k_limit_en = false; + bool is_status_limit_en = false; bool is_temp_freq_en = false; np = of_parse_phandle(dev->of_node, "operating-points-v2", 0); @@ -638,13 +653,12 @@ static int monitor_device_parse_dt(struct device *dev, if (!monitor_device_parse_wide_temp_config(np, info)) is_wide_temp_en = true; - if (!of_property_read_u32(np, "rockchip,video-4k-freq", - &info->video_4k_freq)) - is_4k_limit_en = true; + if (!monitor_device_parse_status_config(np, info)) + is_status_limit_en = true; if (!rockchip_get_temp_freq_table(np, "rockchip,temp-freq-table", &info->temp_freq_table)) is_temp_freq_en = true; - if (is_wide_temp_en || is_4k_limit_en || is_temp_freq_en) + if (is_wide_temp_en || is_status_limit_en || is_temp_freq_en) ret = 0; else ret = -EINVAL; @@ -1199,24 +1213,42 @@ static void rockchip_system_monitor_thermal_check(struct work_struct *work) rockchip_system_monitor_thermal_update(); } +static void rockchip_system_status_cpu_limit_freq(struct monitor_dev_info *info, + unsigned long status) +{ + unsigned int target_freq = 0; + bool is_freq_fixed = false; + int cpu; + + if (status & SYS_STATUS_REBOOT) { + if (!info->reboot_freq) + info->reboot_freq = CPU_REBOOT_FREQ; + info->status_min_limit = info->reboot_freq; + info->status_max_limit = info->reboot_freq; + info->is_status_freq_fixed = true; + goto next; + } + + if (info->video_4k_freq && (status & SYS_STATUS_VIDEO_4K)) + target_freq = info->video_4k_freq; + if (target_freq == info->status_max_limit && + info->is_status_freq_fixed == is_freq_fixed) + return; + info->status_max_limit = target_freq; + info->is_status_freq_fixed = is_freq_fixed; +next: + cpu = cpumask_any(&info->devp->allowed_cpus); + cpufreq_update_policy(cpu); +} + static void rockchip_system_status_limit_freq(unsigned long status) { struct monitor_dev_info *info; - unsigned int target_freq, cpu; down_read(&mdev_list_sem); list_for_each_entry(info, &monitor_dev_list, node) { - if (info->devp->type != MONITOR_TPYE_CPU) - continue; - if (status & SYS_STATUS_VIDEO_4K) - target_freq = info->video_4k_freq; - else - target_freq = 0; - if (target_freq != info->status_max_limit) { - info->status_max_limit = target_freq; - cpu = cpumask_any(&info->devp->allowed_cpus); - cpufreq_update_policy(cpu); - } + if (info->devp->type == MONITOR_TPYE_CPU) + rockchip_system_status_cpu_limit_freq(info, status); } up_read(&mdev_list_sem); } @@ -1302,8 +1334,14 @@ static int rockchip_monitor_cpufreq_policy_notifier(struct notifier_block *nb, limit_freq > info->status_max_limit) limit_freq = info->status_max_limit; - if (limit_freq < policy->max) + if (info->is_status_freq_fixed) { + cpufreq_verify_within_limits(policy, limit_freq, + limit_freq); + dev_info(info->dev, "min=%u, max=%u\n", policy->min, + policy->max); + } else if (limit_freq < policy->max) { cpufreq_verify_within_limits(policy, 0, limit_freq); + } } up_read(&mdev_list_sem); @@ -1314,6 +1352,18 @@ static struct notifier_block rockchip_monitor_cpufreq_policy_nb = { .notifier_call = rockchip_monitor_cpufreq_policy_notifier, }; +static int rockchip_monitor_reboot_notifier(struct notifier_block *nb, + unsigned long action, void *ptr) +{ + rockchip_set_system_status(SYS_STATUS_REBOOT); + + return NOTIFY_OK; +} + +static struct notifier_block rockchip_monitor_reboot_nb = { + .notifier_call = rockchip_monitor_reboot_notifier, +}; + static int rockchip_system_monitor_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1352,6 +1402,8 @@ static int rockchip_system_monitor_probe(struct platform_device *pdev) cpufreq_register_notifier(&rockchip_monitor_cpufreq_policy_nb, CPUFREQ_POLICY_NOTIFIER); + register_reboot_notifier(&rockchip_monitor_reboot_nb); + return 0; } diff --git a/include/soc/rockchip/rockchip_system_monitor.h b/include/soc/rockchip/rockchip_system_monitor.h index d6356a84d874..2c2b74e4a883 100644 --- a/include/soc/rockchip/rockchip_system_monitor.h +++ b/include/soc/rockchip/rockchip_system_monitor.h @@ -56,6 +56,7 @@ struct temp_opp_table { * @wide_temp_limit: Target maximum frequency when low or high temperature, * in Hz * @video_4k_freq: Maximum frequency when paly 4k video, in KHz + * @reboot_freq: Limit maximum and minimum frequency when reboot, in KHz * @status_min_limit: Minimum frequency of some status frequency, in KHz * @status_max_limit: Minimum frequency of all status frequency, in KHz * @freq_table: Optional list of frequencies in descending order @@ -67,6 +68,7 @@ struct temp_opp_table { * @is_high_temp: True if current temperature greater than high_temp * @is_low_temp_enabled: True if device node contains low temperature * configuration + * @is_status_freq_fixed: True if enter into some status */ struct monitor_dev_info { struct device *dev; @@ -83,6 +85,7 @@ struct monitor_dev_info { unsigned long high_temp_max_volt; unsigned long wide_temp_limit; unsigned int video_4k_freq; + unsigned int reboot_freq; unsigned int status_min_limit; unsigned int status_max_limit; unsigned long *freq_table; @@ -93,6 +96,7 @@ struct monitor_dev_info { bool is_low_temp; bool is_high_temp; bool is_low_temp_enabled; + bool is_status_freq_fixed; }; struct monitor_dev_profile { |