mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 21:07:02 +09:00
soc: rockchip: system_monitor: Add reboot notifier
Change-Id: Ic788ca9ba353c7d7c64e3e323698d8c23303eaa0 Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
@@ -1203,24 +1217,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);
|
||||
}
|
||||
@@ -1306,8 +1338,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);
|
||||
|
||||
@@ -1318,6 +1356,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;
|
||||
@@ -1356,6 +1406,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);
|
||||
|
||||
dev_info(dev, "system monitor probe\n");
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user