summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/cpufreq/rockchip-cpufreq.c44
-rw-r--r--drivers/devfreq/rockchip_dmc.c19
-rw-r--r--drivers/soc/rockchip/rockchip_system_monitor.c88
-rw-r--r--include/soc/rockchip/rockchip_system_monitor.h4
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 {