From 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 07:44:59 +0000
Subject: [PATCH] gmac get mac form eeprom

---
 kernel/drivers/soc/rockchip/rockchip_system_monitor.c | 1081 ++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 722 insertions(+), 359 deletions(-)

diff --git a/kernel/drivers/soc/rockchip/rockchip_system_monitor.c b/kernel/drivers/soc/rockchip/rockchip_system_monitor.c
index 8a84d02..c2fbb66 100644
--- a/kernel/drivers/soc/rockchip/rockchip_system_monitor.c
+++ b/kernel/drivers/soc/rockchip/rockchip_system_monitor.c
@@ -4,9 +4,10 @@
  * Author: Finley Xiao <finley.xiao@rock-chips.com>
  */
 
-#include <dt-bindings/soc/rockchip-system-status.h>
+#include <linux/clk-provider.h>
 #include <linux/cpu.h>
 #include <linux/cpufreq.h>
+#include <linux/devfreq.h>
 #include <linux/device.h>
 #include <linux/fb.h>
 #include <linux/module.h>
@@ -15,26 +16,32 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_opp.h>
-#include <linux/uaccess.h>
+#include <linux/pm_qos.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/coupler.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
 #include <linux/reboot.h>
+#include <linux/rockchip/rockchip_sip.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
 #include <linux/thermal.h>
+#include <linux/uaccess.h>
 #include <linux/version.h>
+#include <linux/delay.h>
+#include <soc/rockchip/rockchip_opp_select.h>
 #include <soc/rockchip/rockchip_system_monitor.h>
 #include <soc/rockchip/rockchip-system-status.h>
 
-#include "../../opp/opp.h"
-#include "../../devfreq/governor.h"
-
 #include "../../gpu/drm/rockchip/ebc-dev/ebc_dev.h"
+#include "../../opp/opp.h"
+#include "../../regulator/internal.h"
+#include "../../thermal/thermal_core.h"
 
 #define CPU_REBOOT_FREQ		816000 /* kHz */
 #define VIDEO_1080P_SIZE	(1920 * 1080)
 #define THERMAL_POLLING_DELAY	200 /* milliseconds */
-
-#define devfreq_nb_to_monitor(nb) container_of(nb, struct monitor_dev_info, \
-					       devfreq_nb)
 
 struct video_info {
 	unsigned int width;
@@ -64,6 +71,7 @@
 
 	struct thermal_zone_device *tz;
 	struct delayed_work thermal_work;
+	int last_temp;
 	int offline_cpus_temp;
 	int temp_hysteresis;
 	unsigned int delay;
@@ -84,6 +92,7 @@
 static struct system_monitor *system_monitor;
 static atomic_t monitor_in_suspend;
 
+static BLOCKING_NOTIFIER_HEAD(system_monitor_notifier_list);
 static BLOCKING_NOTIFIER_HEAD(system_status_notifier_list);
 
 int rockchip_register_system_status_notifier(struct notifier_block *nb)
@@ -173,9 +182,9 @@
 		return -EINVAL;
 	}
 
-	return __compat_only_sysfs_link_entry_to_kobj(&dev->kobj,
-						      system_monitor->kobj,
-						      "system_status");
+	return compat_only_sysfs_link_entry_to_kobj(&dev->kobj,
+						    system_monitor->kobj,
+						    "system_status", NULL);
 }
 EXPORT_SYMBOL(rockchip_add_system_status_interface);
 
@@ -237,34 +246,6 @@
 	return video_info;
 }
 
-static struct video_info *rockchip_find_video_info(const char *buf)
-{
-	struct video_info *info, *video_info;
-
-	video_info = rockchip_parse_video_info(buf);
-
-	if (!video_info)
-		return NULL;
-
-	mutex_lock(&video_info_mutex);
-	list_for_each_entry(info, &video_info_list, node) {
-		if (info->width == video_info->width &&
-		    info->height == video_info->height &&
-		    info->ishevc == video_info->ishevc &&
-		    info->videoFramerate == video_info->videoFramerate &&
-		    info->streamBitrate == video_info->streamBitrate) {
-			mutex_unlock(&video_info_mutex);
-			kfree(video_info);
-			return info;
-		}
-	}
-
-	mutex_unlock(&video_info_mutex);
-	kfree(video_info);
-
-	return NULL;
-}
-
 static void rockchip_add_video_info(struct video_info *video_info)
 {
 	if (video_info) {
@@ -276,18 +257,32 @@
 
 static void rockchip_del_video_info(struct video_info *video_info)
 {
-	if (video_info) {
-		mutex_lock(&video_info_mutex);
-		list_del(&video_info->node);
-		mutex_unlock(&video_info_mutex);
-		kfree(video_info);
+	struct video_info *info, *tmp;
+
+	if (!video_info)
+		return;
+
+	mutex_lock(&video_info_mutex);
+	list_for_each_entry_safe(info, tmp, &video_info_list, node) {
+		if (info->width == video_info->width &&
+		    info->height == video_info->height &&
+		    info->ishevc == video_info->ishevc &&
+		    info->videoFramerate == video_info->videoFramerate &&
+		    info->streamBitrate == video_info->streamBitrate) {
+			list_del(&info->node);
+			kfree(info);
+			break;
+		}
 	}
+	kfree(video_info);
+	mutex_unlock(&video_info_mutex);
 }
 
 static void rockchip_update_video_info(void)
 {
 	struct video_info *video_info;
 	unsigned int max_res = 0, max_stream_bitrate = 0, res = 0;
+	unsigned int max_video_framerate = 0;
 
 	mutex_lock(&video_info_mutex);
 	if (list_empty(&video_info_list)) {
@@ -302,6 +297,8 @@
 			max_res = res;
 		if (video_info->streamBitrate > max_stream_bitrate)
 			max_stream_bitrate = video_info->streamBitrate;
+		if (video_info->videoFramerate > max_video_framerate)
+			max_video_framerate = video_info->videoFramerate;
 	}
 	mutex_unlock(&video_info_mutex);
 
@@ -310,8 +307,9 @@
 	} else {
 		if (max_stream_bitrate == 10)
 			rockchip_set_system_status(SYS_STATUS_VIDEO_4K_10B);
-		else
-			rockchip_set_system_status(SYS_STATUS_VIDEO_4K);
+		if (max_video_framerate == 60)
+			rockchip_set_system_status(SYS_STATUS_VIDEO_4K_60P);
+		rockchip_set_system_status(SYS_STATUS_VIDEO_4K);
 	}
 }
 
@@ -325,7 +323,7 @@
 	switch (buf[0]) {
 	case '0':
 		/* clear video flag */
-		video_info = rockchip_find_video_info(buf);
+		video_info = rockchip_parse_video_info(buf);
 		if (video_info) {
 			rockchip_del_video_info(video_info);
 			rockchip_update_video_info();
@@ -354,6 +352,14 @@
 	case 'n':
 		/* clear performance flag */
 		rockchip_clear_system_status(SYS_STATUS_PERFORMANCE);
+		break;
+	case 'S':
+		/* set video svep flag */
+		rockchip_set_system_status(SYS_STATUS_VIDEO_SVEP);
+		break;
+	case 's':
+		/* clear video svep flag */
+		rockchip_clear_system_status(SYS_STATUS_VIDEO_SVEP);
 		break;
 	default:
 		break;
@@ -492,8 +498,11 @@
 	int delta_volt = 0;
 	int i = 0, max_count;
 	unsigned long low_limit = 0, high_limit = 0;
+	unsigned long low_limit_mem = 0, high_limit_mem = 0;
 	bool reach_max_volt = false;
+	bool reach_max_mem_volt = false;
 	bool reach_high_temp_max_volt = false;
+	bool reach_high_temp_max_mem_volt = false;
 
 	max_count = dev_pm_opp_get_opp_count(dev);
 	if (max_count <= 0)
@@ -511,6 +520,8 @@
 	}
 	mutex_lock(&opp_table->lock);
 	list_for_each_entry(opp, &opp_table->opp_list, node) {
+		if (!opp->available)
+			continue;
 		info->opp_table[i].rate = opp->rate;
 		info->opp_table[i].volt = opp->supplies[0].u_volt;
 		info->opp_table[i].max_volt = opp->supplies[0].u_volt_max;
@@ -542,9 +553,48 @@
 			info->low_limit = low_limit;
 		if (high_limit && high_limit != opp->rate)
 			info->high_limit = high_limit;
-		dev_dbg(dev, "rate=%lu, volt=%lu, low_temp_volt=%lu\n",
+
+		if (opp_table->regulator_count > 1) {
+			info->opp_table[i].mem_volt = opp->supplies[1].u_volt;
+			info->opp_table[i].max_mem_volt = opp->supplies[1].u_volt_max;
+
+			if (opp->supplies[1].u_volt <= info->high_temp_max_volt) {
+				if (!reach_high_temp_max_mem_volt)
+					high_limit_mem = opp->rate;
+				if (opp->supplies[1].u_volt == info->high_temp_max_volt)
+					reach_high_temp_max_mem_volt = true;
+			}
+
+			if ((opp->supplies[1].u_volt + delta_volt) <= info->max_volt) {
+				info->opp_table[i].low_temp_mem_volt =
+					opp->supplies[1].u_volt + delta_volt;
+				if (info->opp_table[i].low_temp_mem_volt <
+				    info->low_temp_min_volt)
+					info->opp_table[i].low_temp_mem_volt =
+						info->low_temp_min_volt;
+				if (!reach_max_mem_volt)
+					low_limit_mem = opp->rate;
+				if (info->opp_table[i].low_temp_mem_volt == info->max_volt)
+					reach_max_mem_volt = true;
+			} else {
+				info->opp_table[i].low_temp_mem_volt = info->max_volt;
+			}
+
+			if (low_limit_mem && low_limit_mem != opp->rate) {
+				if (info->low_limit > low_limit_mem)
+					info->low_limit = low_limit_mem;
+			}
+			if (high_limit_mem && high_limit_mem != opp->rate) {
+				if (info->high_limit > high_limit_mem)
+					info->high_limit = high_limit_mem;
+			}
+		}
+
+		dev_dbg(dev, "rate=%lu, volt=%lu %lu low_temp_volt=%lu %lu\n",
 			info->opp_table[i].rate, info->opp_table[i].volt,
-			info->opp_table[i].low_temp_volt);
+			info->opp_table[i].mem_volt,
+			info->opp_table[i].low_temp_volt,
+			info->opp_table[i].low_temp_mem_volt);
 		i++;
 	}
 	mutex_unlock(&opp_table->lock);
@@ -586,9 +636,12 @@
 	else
 		info->high_temp_max_volt = value;
 	rockchip_init_temp_opp_table(info);
-	if (rockchip_get_temp_freq_table(np, "rockchip,high-temp-limit-table",
-					 &info->high_limit_table)) {
-		info->high_limit_table = NULL;
+	rockchip_get_temp_freq_table(np, "rockchip,temp-freq-table",
+				     &info->high_limit_table);
+	if (!info->high_limit_table)
+		rockchip_get_temp_freq_table(np, "rockchip,high-temp-limit-table",
+					     &info->high_limit_table);
+	if (!info->high_limit_table) {
 		if (!of_property_read_u32(np, "rockchip,high-temp-max-freq",
 					  &value)) {
 			high_temp_max_freq = value * 1000;
@@ -640,7 +693,7 @@
 				   &info->video_4k_freq);
 	ret &= of_property_read_u32(np, "rockchip,reboot-freq",
 				    &info->reboot_freq);
-	if (info->devp->type == MONITOR_TPYE_CPU) {
+	if (info->devp->type == MONITOR_TYPE_CPU) {
 		if (!info->reboot_freq) {
 			info->reboot_freq = CPU_REBOOT_FREQ;
 			ret = 0;
@@ -650,66 +703,70 @@
 	return ret;
 }
 
+static int monitor_device_parse_early_min_volt(struct device_node *np,
+					       struct monitor_dev_info *info)
+{
+	return of_property_read_u32(np, "rockchip,early-min-microvolt",
+				    &info->early_min_volt);
+}
+
+static int monitor_device_parse_read_margin(struct device_node *np,
+					    struct monitor_dev_info *info)
+{
+	if (of_property_read_bool(np, "volt-mem-read-margin"))
+		return 0;
+	return -EINVAL;
+}
+
+static int monitor_device_parse_scmi_clk(struct device_node *np,
+					 struct monitor_dev_info *info)
+{
+	struct clk *clk;
+
+	clk = clk_get(info->dev, NULL);
+	if (strstr(__clk_get_name(clk), "scmi"))
+		return 0;
+	return -EINVAL;
+}
+
 static int monitor_device_parse_dt(struct device *dev,
 				   struct monitor_dev_info *info)
 {
 	struct device_node *np;
-	int ret = 0;
-	bool is_wide_temp_en = false;
-	bool is_status_limit_en = false;
-	bool is_temp_freq_en = false;
+	int ret;
 
 	np = of_parse_phandle(dev->of_node, "operating-points-v2", 0);
 	if (!np)
 		return -EINVAL;
 
-	if (!monitor_device_parse_wide_temp_config(np, info))
-		is_wide_temp_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_status_limit_en || is_temp_freq_en)
-		ret = 0;
-	else
-		ret = -EINVAL;
+	of_property_read_u32(np, "rockchip,init-freq", &info->init_freq);
+
+	ret = monitor_device_parse_wide_temp_config(np, info);
+	ret &= monitor_device_parse_status_config(np, info);
+	ret &= monitor_device_parse_early_min_volt(np, info);
+	ret &= monitor_device_parse_read_margin(np, info);
+	ret &= monitor_device_parse_scmi_clk(np, info);
 
 	of_node_put(np);
 
 	return ret;
 }
 
-int rockchip_monitor_opp_set_rate(struct monitor_dev_info *info,
-				  unsigned long target_freq)
-{
-	int ret = 0;
-
-	mutex_lock(&info->volt_adjust_mutex);
-	ret = dev_pm_opp_set_rate(info->dev, target_freq);
-	mutex_unlock(&info->volt_adjust_mutex);
-
-	return ret;
-}
-EXPORT_SYMBOL(rockchip_monitor_opp_set_rate);
-
 int rockchip_monitor_cpu_low_temp_adjust(struct monitor_dev_info *info,
 					 bool is_low)
 {
-	struct device *dev = info->dev;
-	unsigned int cpu = cpumask_any(&info->devp->allowed_cpus);
+	if (!info->low_limit)
+		return 0;
 
-	if (info->low_limit) {
-		if (is_low)
-			info->wide_temp_limit = info->low_limit;
-		else
-			info->wide_temp_limit = 0;
-		cpufreq_update_policy(cpu);
-	}
+	if (!freq_qos_request_active(&info->max_temp_freq_req))
+		return 0;
 
-	mutex_lock(&info->volt_adjust_mutex);
-	dev_pm_opp_check_rate_volt(dev, false);
-	mutex_unlock(&info->volt_adjust_mutex);
+	if (is_low)
+		freq_qos_update_request(&info->max_temp_freq_req,
+					info->low_limit / 1000);
+	else
+		freq_qos_update_request(&info->max_temp_freq_req,
+					FREQ_QOS_MAX_DEFAULT_VALUE);
 
 	return 0;
 }
@@ -718,53 +775,44 @@
 int rockchip_monitor_cpu_high_temp_adjust(struct monitor_dev_info *info,
 					  bool is_high)
 {
-	unsigned int cpu = cpumask_any(&info->devp->allowed_cpus);
+	if (!info->high_limit)
+		return 0;
+
+	if (!freq_qos_request_active(&info->max_temp_freq_req))
+		return 0;
 
 	if (info->high_limit_table) {
-		info->wide_temp_limit = info->high_limit;
-		cpufreq_update_policy(cpu);
-	} else {
-		if (info->high_limit) {
-			if (is_high)
-				info->wide_temp_limit = info->high_limit;
-			else
-				info->wide_temp_limit = 0;
-			cpufreq_update_policy(cpu);
-		}
+		freq_qos_update_request(&info->max_temp_freq_req,
+					info->high_limit / 1000);
+		return 0;
 	}
+
+	if (is_high)
+		freq_qos_update_request(&info->max_temp_freq_req,
+					info->high_limit / 1000);
+	else
+		freq_qos_update_request(&info->max_temp_freq_req,
+					FREQ_QOS_MAX_DEFAULT_VALUE);
 
 	return 0;
 }
 EXPORT_SYMBOL(rockchip_monitor_cpu_high_temp_adjust);
 
-static int rockchip_monitor_update_devfreq(struct devfreq *df)
-{
-	int ret = 0;
-
-#ifdef CONFIG_PM_DEVFREQ
-	mutex_lock(&df->lock);
-	ret = update_devfreq(df);
-	mutex_unlock(&df->lock);
-#endif
-	return ret;
-};
-
 int rockchip_monitor_dev_low_temp_adjust(struct monitor_dev_info *info,
 					 bool is_low)
 {
-	struct devfreq *df;
+	if (!dev_pm_qos_request_active(&info->dev_max_freq_req))
+		return 0;
 
-	if (info->low_limit) {
-		if (is_low)
-			info->wide_temp_limit = info->low_limit;
-		else
-			info->wide_temp_limit = 0;
-	}
+	if (!info->low_limit)
+		return 0;
 
-	if (info->devp && info->devp->data) {
-		df = (struct devfreq *)info->devp->data;
-		rockchip_monitor_update_devfreq(df);
-	}
+	if (is_low)
+		dev_pm_qos_update_request(&info->dev_max_freq_req,
+					  info->low_limit / 1000);
+	else
+		dev_pm_qos_update_request(&info->dev_max_freq_req,
+					  PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
 
 	return 0;
 }
@@ -773,26 +821,24 @@
 int rockchip_monitor_dev_high_temp_adjust(struct monitor_dev_info *info,
 					  bool is_high)
 {
-	struct devfreq *df;
+	if (!dev_pm_qos_request_active(&info->dev_max_freq_req))
+		return 0;
+
+	if (!info->high_limit)
+		return 0;
 
 	if (info->high_limit_table) {
-		info->wide_temp_limit = info->high_limit;
-		if (info->devp && info->devp->data) {
-			df = (struct devfreq *)info->devp->data;
-			rockchip_monitor_update_devfreq(df);
-		}
-	} else {
-		if (info->high_limit) {
-			if (is_high)
-				info->wide_temp_limit = info->high_limit;
-			else
-				info->wide_temp_limit = 0;
-			if (info->devp && info->devp->data) {
-				df = (struct devfreq *)info->devp->data;
-				rockchip_monitor_update_devfreq(df);
-			}
-		}
+		dev_pm_qos_update_request(&info->dev_max_freq_req,
+					  info->high_limit / 1000);
+		return 0;
 	}
+
+	if (is_high)
+		dev_pm_qos_update_request(&info->dev_max_freq_req,
+					  info->high_limit / 1000);
+	else
+		dev_pm_qos_update_request(&info->dev_max_freq_req,
+					  PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
 
 	return 0;
 }
@@ -812,6 +858,8 @@
 
 	mutex_lock(&opp_table->lock);
 	list_for_each_entry(opp, &opp_table->opp_list, node) {
+		if (!opp->available)
+			continue;
 		if (is_low_temp) {
 			if (opp->supplies[0].u_volt_max <
 			    info->opp_table[i].low_temp_volt)
@@ -820,11 +868,29 @@
 			opp->supplies[0].u_volt =
 				info->opp_table[i].low_temp_volt;
 			opp->supplies[0].u_volt_min = opp->supplies[0].u_volt;
+			if (opp_table->regulator_count > 1) {
+				if (opp->supplies[1].u_volt_max <
+				    info->opp_table[i].low_temp_mem_volt)
+					opp->supplies[1].u_volt_max =
+						info->opp_table[i].low_temp_mem_volt;
+				opp->supplies[1].u_volt =
+					info->opp_table[i].low_temp_mem_volt;
+				opp->supplies[1].u_volt_min =
+					opp->supplies[1].u_volt;
+			}
 		} else {
 			opp->supplies[0].u_volt_min = info->opp_table[i].volt;
 			opp->supplies[0].u_volt = opp->supplies[0].u_volt_min;
 			opp->supplies[0].u_volt_max =
 				info->opp_table[i].max_volt;
+			if (opp_table->regulator_count > 1) {
+				opp->supplies[1].u_volt_min =
+					info->opp_table[i].mem_volt;
+				opp->supplies[1].u_volt =
+					opp->supplies[1].u_volt_min;
+				opp->supplies[1].u_volt_max =
+					info->opp_table[i].max_mem_volt;
+			}
 		}
 		i++;
 	}
@@ -839,6 +905,7 @@
 				     bool is_low)
 {
 	struct monitor_dev_profile *devp = info->devp;
+	struct arm_smccc_res res;
 	int ret = 0;
 
 	dev_dbg(info->dev, "low_temp %d\n", is_low);
@@ -850,6 +917,20 @@
 		ret = devp->low_temp_adjust(info, is_low);
 	if (!ret)
 		info->is_low_temp = is_low;
+
+	if (devp->update_volt)
+		devp->update_volt(info);
+
+	if (devp->opp_info && devp->opp_info->pvtpll_low_temp) {
+		res = sip_smc_pvtpll_config(PVTPLL_LOW_TEMP,
+					    devp->opp_info->pvtpll_clk_id,
+					    is_low, 0, 0, 0, 0);
+		if (res.a0)
+			dev_err(info->dev,
+				"%s: error cfg id=%u low temp %d (%d)\n",
+				__func__, devp->opp_info->pvtpll_clk_id,
+				is_low, (int)res.a0);
+	}
 }
 
 static void rockchip_high_temp_adjust(struct monitor_dev_info *info,
@@ -858,12 +939,14 @@
 	struct monitor_dev_profile *devp = info->devp;
 	int ret = 0;
 
+	if (!devp->high_temp_adjust)
+		return;
+
 	if (info->high_limit_table) {
 		devp->high_temp_adjust(info, is_high);
 	} else {
 		dev_dbg(info->dev, "high_temp %d\n", is_high);
-		if (devp->high_temp_adjust)
-			ret = devp->high_temp_adjust(info, is_high);
+		ret = devp->high_temp_adjust(info, is_high);
 		if (!ret)
 			info->is_high_temp = is_high;
 	}
@@ -874,7 +957,7 @@
 	struct monitor_dev_info *info = NULL, *tmp;
 
 	list_for_each_entry(tmp, &monitor_dev_list, node) {
-		if (tmp->devp->type != MONITOR_TPYE_CPU)
+		if (tmp->devp->type != MONITOR_TYPE_CPU)
 			continue;
 		if (cpumask_test_cpu(cpu, &tmp->devp->allowed_cpus)) {
 			info = tmp;
@@ -941,6 +1024,11 @@
 {
 	int ret, temp;
 
+	if (!info->opp_table)
+		return;
+	if (!system_monitor->tz)
+		return;
+
 	/*
 	 * set the init state to low temperature that the voltage will be enough
 	 * when cpu up at low temperature.
@@ -948,7 +1036,6 @@
 	if (!info->is_low_temp) {
 		if (info->opp_table)
 			rockchip_adjust_low_temp_opp_volt(info, true);
-		info->wide_temp_limit = info->low_limit;
 		info->is_low_temp = true;
 	}
 
@@ -963,150 +1050,386 @@
 		if (info->opp_table)
 			rockchip_adjust_low_temp_opp_volt(info, false);
 		info->is_low_temp = false;
-
-		info->wide_temp_limit = info->high_limit;
 		info->is_high_temp = true;
 	} else if (temp > (info->low_temp + info->temp_hysteresis)) {
 		if (info->opp_table)
 			rockchip_adjust_low_temp_opp_volt(info, false);
 		info->is_low_temp = false;
-		info->wide_temp_limit = 0;
 	}
 }
 
-static int system_monitor_devfreq_notifier_call(struct notifier_block *nb,
-						unsigned long event,
-						void *data)
+static const char *get_rdev_name(struct regulator_dev *rdev)
 {
-	struct monitor_dev_info *info = devfreq_nb_to_monitor(nb);
-	struct devfreq_policy *policy = data;
-
-	if (event != DEVFREQ_ADJUST)
-		return NOTIFY_DONE;
-
-	if (info->wide_temp_limit && info->wide_temp_limit < policy->max)
-		devfreq_verify_within_limits(policy, 0, info->wide_temp_limit);
-
-	return NOTIFY_OK;
+	if (rdev->constraints && rdev->constraints->name)
+		return rdev->constraints->name;
+	else if (rdev->desc->name)
+		return rdev->desc->name;
+	else
+		return "";
 }
 
-static int monitor_set_freq_table(struct device *dev,
-				  struct monitor_dev_info *info)
+static void
+rockchip_system_monitor_early_regulator_init(struct monitor_dev_info *info)
 {
-	struct opp_table *opp_table;
-	struct dev_pm_opp *opp;
-	unsigned long *freq_table;
-	int count;
+	struct regulator *reg;
+	struct regulator_dev *rdev;
 
-	opp_table = dev_pm_opp_get_opp_table(dev);
-	if (!opp_table)
-		return -ENOMEM;
+	if (!info->early_min_volt || !info->regulators)
+		return;
 
-	/* Initialize the freq_table from OPP table */
-	count = dev_pm_opp_get_opp_count(dev);
-	if (count <= 0)
-		return -EINVAL;
-
-	info->max_state = count;
-	freq_table = kcalloc(count, sizeof(*info->freq_table), GFP_KERNEL);
-	if (!freq_table) {
-		info->max_state = 0;
-		return -ENOMEM;
+	rdev = info->regulators[0]->rdev;
+	reg = regulator_get(NULL, get_rdev_name(rdev));
+	if (!IS_ERR_OR_NULL(reg)) {
+		info->early_reg = reg;
+		reg->voltage[PM_SUSPEND_ON].min_uV = info->early_min_volt;
+		reg->voltage[PM_SUSPEND_ON].max_uV = rdev->constraints->max_uV;
 	}
+}
 
-	mutex_lock(&opp_table->lock);
-	list_for_each_entry(opp, &opp_table->opp_list, node) {
-		if (opp->available) {
-			count--;
-			freq_table[count] = opp->rate;
+static int
+rockchip_system_monitor_freq_qos_requset(struct monitor_dev_info *info)
+{
+	struct devfreq *devfreq;
+	struct cpufreq_policy *policy;
+	int max_default_value = FREQ_QOS_MAX_DEFAULT_VALUE;
+	int ret;
+
+	if (!info->devp->data)
+		return 0;
+
+	if (info->is_low_temp && info->low_limit)
+		max_default_value = info->low_limit / 1000;
+	else if (info->is_high_temp && info->high_limit)
+		max_default_value = info->high_limit / 1000;
+
+	if (info->devp->type == MONITOR_TYPE_CPU) {
+		policy = (struct cpufreq_policy *)info->devp->data;
+		ret = freq_qos_add_request(&policy->constraints,
+					   &info->max_temp_freq_req,
+					   FREQ_QOS_MAX,
+					   max_default_value);
+		if (ret < 0) {
+			dev_info(info->dev,
+				 "failed to add temp freq constraint\n");
+			return ret;
+		}
+		ret = freq_qos_add_request(&policy->constraints,
+					   &info->min_sta_freq_req,
+					   FREQ_QOS_MIN,
+					   FREQ_QOS_MIN_DEFAULT_VALUE);
+		if (ret < 0) {
+			dev_info(info->dev,
+				 "failed to add sta freq constraint\n");
+			freq_qos_remove_request(&info->max_temp_freq_req);
+			return ret;
+		}
+		ret = freq_qos_add_request(&policy->constraints,
+					   &info->max_sta_freq_req,
+					   FREQ_QOS_MAX,
+					   FREQ_QOS_MAX_DEFAULT_VALUE);
+		if (ret < 0) {
+			dev_info(info->dev,
+				 "failed to add sta freq constraint\n");
+			freq_qos_remove_request(&info->max_temp_freq_req);
+			freq_qos_remove_request(&info->min_sta_freq_req);
+			return ret;
+		}
+	} else if (info->devp->type == MONITOR_TYPE_DEV) {
+		devfreq = (struct devfreq *)info->devp->data;
+		ret = dev_pm_qos_add_request(devfreq->dev.parent,
+					     &info->dev_max_freq_req,
+					     DEV_PM_QOS_MAX_FREQUENCY,
+					     max_default_value);
+		if (ret < 0) {
+			dev_info(info->dev, "failed to add freq constraint\n");
+			return ret;
 		}
 	}
-	mutex_unlock(&opp_table->lock);
+
+	return 0;
+}
+
+static int rockchip_system_monitor_parse_supplies(struct device *dev,
+						  struct monitor_dev_info *info)
+{
+	struct opp_table *opp_table;
+	struct dev_pm_set_opp_data *data;
+	int len, count;
+
+	opp_table = dev_pm_opp_get_opp_table(dev);
+	if (IS_ERR(opp_table))
+		return PTR_ERR(opp_table);
+
+	if (opp_table->clk)
+		info->clk = opp_table->clk;
+	if (opp_table->regulators)
+		info->regulators = opp_table->regulators;
+	info->regulator_count = opp_table->regulator_count;
+
+	if (opp_table->regulators && info->devp->set_opp) {
+		count = opp_table->regulator_count;
+		/* space for set_opp_data */
+		len = sizeof(*data);
+		/* space for old_opp.supplies and new_opp.supplies */
+		len += 2 * sizeof(struct dev_pm_opp_supply) * count;
+		data = kzalloc(len, GFP_KERNEL);
+		if (!data)
+			return -ENOMEM;
+		data->old_opp.supplies = (void *)(data + 1);
+		data->new_opp.supplies = data->old_opp.supplies + count;
+		info->set_opp_data = data;
+	}
 
 	dev_pm_opp_put_opp_table(opp_table);
 
-	info->freq_table = freq_table;
+	return 0;
+}
+
+void rockchip_monitor_volt_adjust_lock(struct monitor_dev_info *info)
+{
+	if (info)
+		mutex_lock(&info->volt_adjust_mutex);
+}
+EXPORT_SYMBOL(rockchip_monitor_volt_adjust_lock);
+
+void rockchip_monitor_volt_adjust_unlock(struct monitor_dev_info *info)
+{
+	if (info)
+		mutex_unlock(&info->volt_adjust_mutex);
+}
+EXPORT_SYMBOL(rockchip_monitor_volt_adjust_unlock);
+
+static int rockchip_monitor_enable_opp_clk(struct device *dev,
+					   struct rockchip_opp_info *opp_info)
+{
+	int ret = 0;
+
+	if (!opp_info)
+		return 0;
+
+	ret = clk_bulk_prepare_enable(opp_info->num_clks, opp_info->clks);
+	if (ret) {
+		dev_err(dev, "failed to enable opp clks\n");
+		return ret;
+	}
 
 	return 0;
 }
 
-static unsigned long monitor_freq_to_state(struct monitor_dev_info *info,
-					   unsigned long freq)
+static void rockchip_monitor_disable_opp_clk(struct device *dev,
+					     struct rockchip_opp_info *opp_info)
 {
-	unsigned long i = 0;
+	if (!opp_info)
+		return;
 
-	if (!info->freq_table) {
-		dev_info(info->dev, "failed to get freq_table");
-		return 0;
-	}
-
-	for (i = 0; i < info->max_state; i++) {
-		if (freq >= info->freq_table[i])
-			return i;
-	}
-
-	return info->max_state - 1;
+	clk_bulk_disable_unprepare(opp_info->num_clks, opp_info->clks);
 }
 
-static int monitor_temp_to_state(struct monitor_dev_info *info,
-				 int temp, unsigned long *state)
+static int rockchip_monitor_set_opp(struct monitor_dev_info *info,
+				    unsigned long old_freq,
+				    unsigned long freq,
+				    struct dev_pm_opp_supply *old_supply,
+				    struct dev_pm_opp_supply *new_supply)
 {
-	unsigned long target_state, target_freq = 0;
-	int i;
+	struct dev_pm_set_opp_data *data;
+	int size;
 
-	if (temp == THERMAL_TEMP_INVALID)
+	data = info->set_opp_data;
+	data->regulators = info->regulators;
+	data->regulator_count = info->regulator_count;
+	data->clk = info->clk;
+	data->dev = info->dev;
+
+	data->old_opp.rate = old_freq;
+	size = sizeof(*old_supply) * info->regulator_count;
+	if (!old_supply)
+		memset(data->old_opp.supplies, 0, size);
+	else
+		memcpy(data->old_opp.supplies, old_supply, size);
+
+	data->new_opp.rate = freq;
+	memcpy(data->new_opp.supplies, new_supply, size);
+
+	return info->devp->set_opp(data);
+}
+
+int rockchip_monitor_check_rate_volt(struct monitor_dev_info *info)
+{
+	struct device *dev = info->dev;
+	struct regulator *vdd_reg = NULL;
+	struct regulator *mem_reg = NULL;
+	struct rockchip_opp_info *opp_info = info->devp->opp_info;
+	struct dev_pm_opp *opp;
+	unsigned long old_rate, new_rate, new_volt, new_mem_volt;
+	int old_volt, old_mem_volt;
+	u32 target_rm = UINT_MAX;
+	bool is_set_clk = true;
+	bool is_set_rm = false;
+	int ret = 0;
+
+	if (!info->regulators || !info->clk)
 		return 0;
-	if (info->temp_freq_table) {
-		for (i = 0; info->temp_freq_table[i].freq != UINT_MAX; i++) {
-			if (temp > info->temp_freq_table[i].temp)
-				target_freq = info->temp_freq_table[i].freq;
+
+	mutex_lock(&info->volt_adjust_mutex);
+
+	vdd_reg = info->regulators[0];
+	old_rate = clk_get_rate(info->clk);
+	old_volt = regulator_get_voltage(vdd_reg);
+	if (info->regulator_count > 1) {
+		mem_reg = info->regulators[1];
+		old_mem_volt = regulator_get_voltage(mem_reg);
+	}
+
+	if (info->init_freq) {
+		new_rate = info->init_freq * 1000;
+		info->init_freq = 0;
+	} else {
+		new_rate = old_rate;
+	}
+	opp = dev_pm_opp_find_freq_ceil(dev, &new_rate);
+	if (IS_ERR(opp)) {
+		opp = dev_pm_opp_find_freq_floor(dev, &new_rate);
+		if (IS_ERR(opp)) {
+			ret = PTR_ERR(opp);
+			goto unlock;
 		}
-		if (target_freq)
-			*state = monitor_freq_to_state(info,
-						       target_freq * 1000);
-		else
-			*state = 0;
+	}
+	new_volt = opp->supplies[0].u_volt;
+	if (info->regulator_count > 1)
+		new_mem_volt = opp->supplies[1].u_volt;
+	dev_pm_opp_put(opp);
+
+	if (old_rate == new_rate) {
+		if (info->regulator_count > 1) {
+			if (old_volt == new_volt &&
+			    new_mem_volt == old_mem_volt)
+				goto unlock;
+		} else if (old_volt == new_volt) {
+			goto unlock;
+		}
+	}
+	if (!new_volt || (info->regulator_count > 1 && !new_mem_volt))
+		goto unlock;
+
+	if (info->devp->set_opp) {
+		ret = rockchip_monitor_set_opp(info, old_rate, new_rate,
+					       NULL, opp->supplies);
+		goto unlock;
 	}
 
-	if (info->status_min_limit) {
-		target_freq = info->status_min_limit * 1000;
-		target_state = monitor_freq_to_state(info, target_freq);
-		if (*state > target_state)
-			*state = target_state;
+	if (opp_info && opp_info->data && opp_info->data->set_read_margin) {
+		is_set_rm = true;
+		if (info->devp->type == MONITOR_TYPE_DEV) {
+			if (!pm_runtime_active(dev)) {
+				is_set_rm = false;
+				if (opp_info->scmi_clk)
+					is_set_clk = false;
+			}
+		}
 	}
+	rockchip_monitor_enable_opp_clk(dev, opp_info);
+	rockchip_get_read_margin(dev, opp_info, new_volt, &target_rm);
 
-	return 0;
+	dev_dbg(dev, "%s: %lu Hz --> %lu Hz\n", __func__, old_rate, new_rate);
+	if (new_rate >= old_rate) {
+		rockchip_set_intermediate_rate(dev, opp_info, info->clk,
+					       old_rate, new_rate,
+					       true, is_set_clk);
+
+		if (old_volt > new_volt) {
+			ret = regulator_set_voltage(vdd_reg, new_volt, INT_MAX);
+			if (ret) {
+				dev_err(dev, "%s: failed to set volt: %lu\n",
+					__func__, new_volt);
+				goto restore_voltage;
+			}
+		}
+		if (info->regulator_count > 1) {
+			ret = regulator_set_voltage(mem_reg, new_mem_volt,
+						    INT_MAX);
+			if (ret) {
+				dev_err(dev, "%s: failed to set volt: %lu\n",
+					__func__, new_mem_volt);
+				goto restore_voltage;
+			}
+		}
+		if (old_volt <= new_volt) {
+			ret = regulator_set_voltage(vdd_reg, new_volt, INT_MAX);
+			if (ret) {
+				dev_err(dev, "%s: failed to set volt: %lu\n",
+					__func__, new_volt);
+				goto restore_voltage;
+			}
+		}
+		rockchip_set_read_margin(dev, opp_info, target_rm, is_set_rm);
+		if (is_set_clk && clk_set_rate(info->clk, new_rate)) {
+			dev_err(dev, "%s: failed to set clock rate: %lu\n",
+				__func__, new_rate);
+			goto restore_rm;
+		}
+	} else {
+		rockchip_set_intermediate_rate(dev, opp_info, info->clk,
+					       old_rate, new_rate,
+					       false, is_set_clk);
+		rockchip_set_read_margin(dev, opp_info, target_rm, is_set_rm);
+		if (is_set_clk && clk_set_rate(info->clk, new_rate)) {
+			dev_err(dev, "%s: failed to set clock rate: %lu\n",
+				__func__, new_rate);
+			goto restore_rm;
+		}
+		ret = regulator_set_voltage(vdd_reg, new_volt,
+					    INT_MAX);
+		if (ret) {
+			dev_err(dev, "%s: failed to set volt: %lu\n",
+				__func__, new_volt);
+			goto restore_freq;
+		}
+		if (info->regulator_count > 1) {
+			ret = regulator_set_voltage(mem_reg, new_mem_volt,
+						    INT_MAX);
+			if (ret) {
+				dev_err(dev, "%s: failed to set volt: %lu\n",
+					__func__, new_mem_volt);
+				goto restore_freq;
+			}
+		}
+	}
+	goto disable_clk;
+
+restore_freq:
+	if (is_set_clk && clk_set_rate(info->clk, old_rate))
+		dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
+			__func__, old_rate);
+restore_rm:
+	rockchip_get_read_margin(dev, opp_info, old_volt, &target_rm);
+	rockchip_set_read_margin(dev, opp_info, target_rm, is_set_rm);
+restore_voltage:
+	if (old_volt <= new_volt)
+		regulator_set_voltage(vdd_reg, old_volt, INT_MAX);
+	if (info->regulator_count > 1)
+		regulator_set_voltage(mem_reg, old_mem_volt, INT_MAX);
+	if (old_volt > new_volt)
+		regulator_set_voltage(vdd_reg, old_volt, INT_MAX);
+disable_clk:
+	rockchip_monitor_disable_opp_clk(dev, opp_info);
+unlock:
+	mutex_unlock(&info->volt_adjust_mutex);
+
+	return ret;
 }
-
-int
-rockchip_system_monitor_adjust_cdev_state(struct thermal_cooling_device *cdev,
-					  int temp, unsigned long *state)
-{
-	struct monitor_dev_info *info;
-
-	down_read(&mdev_list_sem);
-	list_for_each_entry(info, &monitor_dev_list, node) {
-		if (cdev->np != info->dev->of_node)
-			continue;
-		monitor_temp_to_state(info, temp, state);
-		break;
-	}
-	up_read(&mdev_list_sem);
-
-	return 0;
-}
-EXPORT_SYMBOL(rockchip_system_monitor_adjust_cdev_state);
+EXPORT_SYMBOL(rockchip_monitor_check_rate_volt);
 
 struct monitor_dev_info *
 rockchip_system_monitor_register(struct device *dev,
 				 struct monitor_dev_profile *devp)
 {
 	struct monitor_dev_info *info;
-	struct devfreq *devfreq;
-	int ret;
 
 	if (!system_monitor)
 		return ERR_PTR(-ENOMEM);
+
+	if (!devp)
+		return ERR_PTR(-EINVAL);
 
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
@@ -1114,39 +1437,33 @@
 	info->dev = dev;
 	info->devp = devp;
 
-	ret = monitor_device_parse_dt(dev, info);
-	if (ret)
-		goto free_info;
+	mutex_init(&info->volt_adjust_mutex);
 
-	monitor_set_freq_table(dev, info);
-
-	if (info->devp->type == MONITOR_TPYE_DEV) {
-		info->devfreq_nb.notifier_call =
-			system_monitor_devfreq_notifier_call;
-		devfreq = (struct devfreq *)info->devp->data;
-		devm_devfreq_register_notifier(dev, devfreq, &info->devfreq_nb,
-					       DEVFREQ_POLICY_NOTIFIER);
+	rockchip_system_monitor_parse_supplies(dev, info);
+	if (monitor_device_parse_dt(dev, info)) {
+		rockchip_monitor_check_rate_volt(info);
+		devp->is_checked = true;
+		kfree(info->set_opp_data);
+		kfree(info);
+		return ERR_PTR(-EINVAL);
 	}
 
+	rockchip_system_monitor_early_regulator_init(info);
 	rockchip_system_monitor_wide_temp_init(info);
-	mutex_init(&info->volt_adjust_mutex);
+	rockchip_monitor_check_rate_volt(info);
+	devp->is_checked = true;
+	rockchip_system_monitor_freq_qos_requset(info);
 
 	down_write(&mdev_list_sem);
 	list_add(&info->node, &monitor_dev_list);
 	up_write(&mdev_list_sem);
 
 	return info;
-
-free_info:
-	kfree(info);
-	return ERR_PTR(-EINVAL);
 }
 EXPORT_SYMBOL(rockchip_system_monitor_register);
 
 void rockchip_system_monitor_unregister(struct monitor_dev_info *info)
 {
-	struct devfreq *devfreq;
-
 	if (!info)
 		return;
 
@@ -1154,18 +1471,59 @@
 	list_del(&info->node);
 	up_write(&mdev_list_sem);
 
-	devfreq = (struct devfreq *)info->devp->data;
-	if (info->devp->type == MONITOR_TPYE_DEV)
-		devm_devfreq_unregister_notifier(info->dev, devfreq,
-						 &info->devfreq_nb,
-						 DEVFREQ_TRANSITION_NOTIFIER);
+	if (info->devp->type == MONITOR_TYPE_CPU) {
+		if (freq_qos_request_active(&info->max_temp_freq_req))
+			freq_qos_remove_request(&info->max_temp_freq_req);
+		if (freq_qos_request_active(&info->min_sta_freq_req))
+			freq_qos_remove_request(&info->min_sta_freq_req);
+		if (freq_qos_request_active(&info->max_sta_freq_req))
+			freq_qos_remove_request(&info->max_sta_freq_req);
+	} else {
+		if (dev_pm_qos_request_active(&info->dev_max_freq_req))
+			dev_pm_qos_remove_request(&info->dev_max_freq_req);
+	}
 
 	kfree(info->low_temp_adjust_table);
 	kfree(info->opp_table);
-	kfree(info->freq_table);
+	kfree(info->set_opp_data);
 	kfree(info);
 }
 EXPORT_SYMBOL(rockchip_system_monitor_unregister);
+
+int rockchip_system_monitor_register_notifier(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&system_monitor_notifier_list, nb);
+}
+EXPORT_SYMBOL(rockchip_system_monitor_register_notifier);
+
+void rockchip_system_monitor_unregister_notifier(struct notifier_block *nb)
+{
+	blocking_notifier_chain_unregister(&system_monitor_notifier_list, nb);
+}
+EXPORT_SYMBOL(rockchip_system_monitor_unregister_notifier);
+
+static int rockchip_system_monitor_temp_notify(int temp)
+{
+	struct system_monitor_event_data event_data;
+	int ret;
+
+	event_data.temp = temp;
+	ret = blocking_notifier_call_chain(&system_monitor_notifier_list,
+					   SYSTEM_MONITOR_CHANGE_TEMP,
+					   (void *)&event_data);
+
+	return notifier_to_errno(ret);
+}
+
+static int notify_dummy(struct thermal_zone_device *tz, int trip)
+{
+	return 0;
+}
+
+static struct thermal_governor thermal_gov_dummy = {
+	.name		= "dummy",
+	.throttle	= notify_dummy,
+};
 
 static int rockchip_system_monitor_parse_dt(struct system_monitor *monitor)
 {
@@ -1173,7 +1531,7 @@
 	const char *tz_name, *buf = NULL;
 
 	if (of_property_read_string(np, "rockchip,video-4k-offline-cpus", &buf))
-		cpumask_clear(&system_monitor->video_4k_offline_cpus);
+		cpumask_clear(&monitor->video_4k_offline_cpus);
 	else
 		cpulist_parse(buf, &monitor->video_4k_offline_cpus);
 
@@ -1199,6 +1557,13 @@
 		system_monitor->offline_cpus_temp = INT_MAX;
 	of_property_read_u32(np, "rockchip,temp-hysteresis",
 			     &system_monitor->temp_hysteresis);
+
+	if (of_find_property(np, "rockchip,thermal-governor-dummy", NULL)) {
+		if (monitor->tz->governor->unbind_from_tz)
+			monitor->tz->governor->unbind_from_tz(monitor->tz);
+		monitor->tz->governor = &thermal_gov_dummy;
+	}
+
 out:
 	return 0;
 }
@@ -1224,7 +1589,7 @@
 	cpumask_copy(&system_monitor->offline_cpus, &offline_cpus);
 	for_each_cpu(cpu, &system_monitor->offline_cpus) {
 		if (cpu_online(cpu))
-			cpu_down(cpu);
+			remove_cpu(cpu);
 	}
 
 	cpumask_clear(&online_cpus);
@@ -1234,7 +1599,7 @@
 	if (cpumask_empty(&online_cpus))
 		goto out;
 	for_each_cpu(cpu, &online_cpus)
-		cpu_up(cpu);
+		add_cpu(cpu);
 
 out:
 	mutex_unlock(&cpu_on_off_mutex);
@@ -1266,7 +1631,6 @@
 {
 	int temp, ret;
 	struct monitor_dev_info *info;
-	static int last_temp = INT_MAX;
 
 	ret = thermal_zone_get_temp(system_monitor->tz, &temp);
 	if (ret || temp == THERMAL_TEMP_INVALID)
@@ -1274,9 +1638,12 @@
 
 	dev_dbg(system_monitor->dev, "temperature=%d\n", temp);
 
-	if (temp < last_temp && last_temp - temp <= 2000)
+	if (temp < system_monitor->last_temp &&
+	    system_monitor->last_temp - temp <= 2000)
 		goto out;
-	last_temp = temp;
+	system_monitor->last_temp = temp;
+
+	rockchip_system_monitor_temp_notify(temp);
 
 	down_read(&mdev_list_sem);
 	list_for_each_entry(info, &monitor_dev_list, node)
@@ -1302,26 +1669,32 @@
 						  unsigned long status)
 {
 	unsigned int target_freq = 0;
-	bool is_freq_fixed = false;
-	int cpu;
+
+	if (!freq_qos_request_active(&info->min_sta_freq_req))
+		return;
+	if (!freq_qos_request_active(&info->max_sta_freq_req))
+		return;
 
 	if (status & SYS_STATUS_REBOOT) {
-		info->status_min_limit = info->reboot_freq;
-		info->status_max_limit = info->reboot_freq;
-		info->is_status_freq_fixed = true;
-		goto next;
+		freq_qos_update_request(&info->max_sta_freq_req,
+					info->reboot_freq);
+		freq_qos_update_request(&info->min_sta_freq_req,
+					info->reboot_freq);
+		return;
 	}
 
 	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)
+
+	if (target_freq == info->status_max_limit)
 		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);
+	if (info->status_max_limit)
+		freq_qos_update_request(&info->max_sta_freq_req,
+					info->status_max_limit);
+	else
+		freq_qos_update_request(&info->max_sta_freq_req,
+					FREQ_QOS_MAX_DEFAULT_VALUE);
 }
 
 static void rockchip_system_status_limit_freq(unsigned long status)
@@ -1330,7 +1703,7 @@
 
 	down_read(&mdev_list_sem);
 	list_for_each_entry(info, &monitor_dev_list, node) {
-		if (info->devp->type == MONITOR_TPYE_CPU)
+		if (info->devp->type == MONITOR_TYPE_CPU)
 			rockchip_system_status_cpu_limit_freq(info, status);
 	}
 	up_read(&mdev_list_sem);
@@ -1364,6 +1737,26 @@
 	return NOTIFY_OK;
 }
 
+static int rockchip_system_monitor_set_cpu_uevent_suppress(bool is_suppress)
+{
+	struct monitor_dev_info *info;
+	struct cpufreq_policy *policy;
+
+	list_for_each_entry(info, &monitor_dev_list, node) {
+		if (info->devp->type != MONITOR_TYPE_CPU)
+			continue;
+		policy = (struct cpufreq_policy *)info->devp->data;
+		if (!policy || !policy->cdev)
+			continue;
+		if (is_suppress)
+			dev_set_uevent_suppress(&policy->cdev->device, 1);
+		else
+			dev_set_uevent_suppress(&policy->cdev->device, 0);
+	}
+
+	return 0;
+}
+
 static int monitor_pm_notify(struct notifier_block *nb,
 			     unsigned long mode, void *_unused)
 {
@@ -1372,6 +1765,7 @@
 	case PM_RESTORE_PREPARE:
 	case PM_SUSPEND_PREPARE:
 		atomic_set(&monitor_in_suspend, 1);
+		rockchip_system_monitor_set_cpu_uevent_suppress(true);
 		break;
 	case PM_POST_HIBERNATION:
 	case PM_POST_RESTORE:
@@ -1379,6 +1773,8 @@
 		if (system_monitor->tz)
 			rockchip_system_monitor_thermal_update();
 		atomic_set(&monitor_in_suspend, 0);
+		rockchip_system_monitor_set_cpu_uevent_suppress(false);
+		system_monitor->last_temp = INT_MAX;
 		break;
 	default:
 		break;
@@ -1388,51 +1784,6 @@
 
 static struct notifier_block monitor_pm_nb = {
 	.notifier_call = monitor_pm_notify,
-};
-
-static int rockchip_monitor_cpufreq_policy_notifier(struct notifier_block *nb,
-						    unsigned long event,
-						    void *data)
-{
-	struct monitor_dev_info *info;
-	struct cpufreq_policy *policy = data;
-	int cpu = policy->cpu;
-	unsigned int limit_freq = UINT_MAX;
-
-	if (event != CPUFREQ_ADJUST)
-		return NOTIFY_OK;
-
-	down_read(&mdev_list_sem);
-	list_for_each_entry(info, &monitor_dev_list, node) {
-		if (info->devp->type != MONITOR_TPYE_CPU)
-			continue;
-		if (!cpumask_test_cpu(cpu, &info->devp->allowed_cpus))
-			continue;
-
-		if (info->wide_temp_limit) {
-			if (limit_freq > info->wide_temp_limit / 1000)
-				limit_freq = info->wide_temp_limit / 1000;
-		}
-		if (info->status_max_limit &&
-		    limit_freq > info->status_max_limit)
-			limit_freq = info->status_max_limit;
-
-		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);
-
-	return NOTIFY_OK;
-}
-
-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,
@@ -1454,24 +1805,15 @@
 {
 	struct fb_event *event = ptr;
 
-	switch (action) {
-	case FB_EARLY_EVENT_BLANK:
-		switch (*((int *)event->data)) {
-		case FB_BLANK_UNBLANK:
-			rockchip_clear_system_status(SYS_STATUS_SUSPEND);
-			break;
-		default:
-			break;
-		}
+	if (action != FB_EVENT_BLANK)
+		return NOTIFY_OK;
+
+	switch (*((int *)event->data)) {
+	case FB_BLANK_UNBLANK:
+		rockchip_clear_system_status(SYS_STATUS_SUSPEND);
 		break;
-	case FB_EVENT_BLANK:
-		switch (*((int *)event->data)) {
-		case FB_BLANK_POWERDOWN:
-			rockchip_set_system_status(SYS_STATUS_SUSPEND);
-			break;
-		default:
-			break;
-		}
+	case FB_BLANK_POWERDOWN:
+		rockchip_set_system_status(SYS_STATUS_SUSPEND);
 		break;
 	default:
 		break;
@@ -1494,12 +1836,6 @@
 	case EBC_OFF:
 		rockchip_set_system_status(SYS_STATUS_LOW_POWER);
 		break;
-	case EBC_FB_BLANK:
-		rockchip_set_system_status(SYS_STATUS_SUSPEND);
-		break;
-	case EBC_FB_UNBLANK:
-		rockchip_clear_system_status(SYS_STATUS_SUSPEND);
-		break;
 	default:
 		break;
 	}
@@ -1510,6 +1846,32 @@
 static struct notifier_block rockchip_monitor_ebc_nb = {
 	.notifier_call = rockchip_eink_devfs_notifier,
 };
+
+static void system_monitor_early_min_volt_function(struct work_struct *work)
+{
+	struct monitor_dev_info *info;
+	struct regulator_dev *rdev;
+	int min_uV, max_uV;
+	int ret;
+
+	down_read(&mdev_list_sem);
+	list_for_each_entry(info, &monitor_dev_list, node) {
+		if (!info->early_min_volt || !info->early_reg)
+			continue;
+		rdev = info->early_reg->rdev;
+		min_uV = rdev->constraints->min_uV;
+		max_uV = rdev->constraints->max_uV;
+		ret = regulator_set_voltage(info->early_reg, min_uV, max_uV);
+		if (ret)
+			dev_err(&rdev->dev,
+				"%s: failed to set volt\n", __func__);
+		regulator_put(info->early_reg);
+	}
+	up_read(&mdev_list_sem);
+}
+
+static DECLARE_DELAYED_WORK(system_monitor_early_min_volt_work,
+			    system_monitor_early_min_volt_function);
 
 static int rockchip_system_monitor_probe(struct platform_device *pdev)
 {
@@ -1532,6 +1894,7 @@
 
 	rockchip_system_monitor_parse_dt(system_monitor);
 	if (system_monitor->tz) {
+		system_monitor->last_temp = INT_MAX;
 		INIT_DELAYED_WORK(&system_monitor->thermal_work,
 				  rockchip_system_monitor_thermal_check);
 		mod_delayed_work(system_freezable_wq,
@@ -1546,9 +1909,6 @@
 	if (register_pm_notifier(&monitor_pm_nb))
 		dev_err(dev, "failed to register suspend notifier\n");
 
-	cpufreq_register_notifier(&rockchip_monitor_cpufreq_policy_nb,
-				  CPUFREQ_POLICY_NOTIFIER);
-
 	register_reboot_notifier(&rockchip_monitor_reboot_nb);
 
 	if (fb_register_client(&rockchip_monitor_fb_nb))
@@ -1556,6 +1916,9 @@
 
 	ebc_register_notifier(&rockchip_monitor_ebc_nb);
 
+	schedule_delayed_work(&system_monitor_early_min_volt_work,
+			      msecs_to_jiffies(30000));
+
 	dev_info(dev, "system monitor probe\n");
 
 	return 0;

--
Gitblit v1.6.2