From b99f359494641eff1c32048a517bc510e0b9bf84 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 11 Jun 2019 14:33:15 +0800 Subject: [PATCH] soc: rockchip: Add rockchip system monitor support Change-Id: I4cb7fafcb33fda0212b5ad1f6eebd44503556336 Signed-off-by: Finley Xiao --- drivers/soc/rockchip/Kconfig | 6 + drivers/soc/rockchip/Makefile | 2 +- .../soc/rockchip/rockchip_system_monitor.c | 163 +++++++++--------- .../soc/rockchip/rockchip_system_monitor.h | 5 +- 4 files changed, 90 insertions(+), 86 deletions(-) diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig index 7134bf24ddc4..7daa570fbbff 100644 --- a/drivers/soc/rockchip/Kconfig +++ b/drivers/soc/rockchip/Kconfig @@ -78,4 +78,10 @@ config ROCKCHIP_SUSPEND_MODE help Say Y here if you want to set the suspend mode to the ATF. +config ROCKCHIP_SYSTEM_MONITOR + bool "Rockchip system monitor support" + default y + help + Say y here to enable rockchip system monitor support. + endif diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile index 5f543da93daa..d5eef424632d 100644 --- a/drivers/soc/rockchip/Makefile +++ b/drivers/soc/rockchip/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_ROCKCHIP_IPA) += rockchip_ipa.o obj-$(CONFIG_ROCKCHIP_OPP) += rockchip_opp_select.o obj-$(CONFIG_ROCKCHIP_PVTM) += rockchip_pvtm.o obj-$(CONFIG_ROCKCHIP_SUSPEND_MODE) += rockchip_pm_config.o +obj-$(CONFIG_ROCKCHIP_SYSTEM_MONITOR) += rockchip_system_monitor.o obj-y += rk_vendor_storage.o -obj-y += rockchip-system-status.o obj-$(CONFIG_RK_FLASH) += flash_vendor_storage.o diff --git a/drivers/soc/rockchip/rockchip_system_monitor.c b/drivers/soc/rockchip/rockchip_system_monitor.c index b81c5469d683..e20796cca0c2 100644 --- a/drivers/soc/rockchip/rockchip_system_monitor.c +++ b/drivers/soc/rockchip/rockchip_system_monitor.c @@ -24,7 +24,7 @@ #include #include -#include "../../base/power/opp/opp.h" +#include "../../opp/opp.h" #include "../../devfreq/governor.h" #define CPU_REBOOT_FREQ 816000 /* kHz */ @@ -446,77 +446,70 @@ static int rockchip_get_low_temp_volt(struct monitor_dev_info *info, static int rockchip_init_temp_opp_table(struct monitor_dev_info *info) { struct device *dev = info->dev; + struct opp_table *opp_table; struct dev_pm_opp *opp; int delta_volt = 0; - int i, max_count, ret = 0; - unsigned long rate; + int i = 0, max_count; + unsigned long low_limit = 0, high_limit = 0; bool reach_max_volt = false; bool reach_high_temp_max_volt = false; max_count = dev_pm_opp_get_opp_count(dev); - if (max_count <= 0) { - ret = max_count ? max_count : -ENODATA; - goto out; - } + if (max_count <= 0) + return max_count ? max_count : -ENODATA; info->opp_table = kzalloc(sizeof(*info->opp_table) * max_count, GFP_KERNEL); - if (!info->opp_table) { - ret = -ENOMEM; - goto out; + if (!info->opp_table) + return -ENOMEM; + + opp_table = dev_pm_opp_get_opp_table(dev); + if (!opp_table) { + kfree(info->opp_table); + return -ENOMEM; } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) - rcu_read_lock(); -#endif - for (i = 0, rate = 0; i < max_count; i++, rate++) { - /* find next rate */ - opp = dev_pm_opp_find_freq_ceil(dev, &rate); - if (IS_ERR(opp)) { - ret = PTR_ERR(opp); - kfree(info->opp_table); - goto unlock; - } + mutex_lock(&opp_table->lock); + list_for_each_entry(opp, &opp_table->opp_list, node) { info->opp_table[i].rate = opp->rate; - info->opp_table[i].volt = opp->u_volt; - info->opp_table[i].max_volt = opp->u_volt_max; + info->opp_table[i].volt = opp->supplies[0].u_volt; + info->opp_table[i].max_volt = opp->supplies[0].u_volt_max; - if (opp->u_volt <= info->high_temp_max_volt) { + if (opp->supplies[0].u_volt <= info->high_temp_max_volt) { if (!reach_high_temp_max_volt) - info->high_limit = opp->rate; - if (opp->u_volt == info->high_temp_max_volt) + high_limit = opp->rate; + if (opp->supplies[0].u_volt == info->high_temp_max_volt) reach_high_temp_max_volt = true; } if (rockchip_get_low_temp_volt(info, opp->rate, &delta_volt)) delta_volt = 0; - if ((opp->u_volt + delta_volt) <= info->max_volt) { + if ((opp->supplies[0].u_volt + delta_volt) <= info->max_volt) { info->opp_table[i].low_temp_volt = - opp->u_volt + delta_volt; + opp->supplies[0].u_volt + delta_volt; if (info->opp_table[i].low_temp_volt < info->low_temp_min_volt) info->opp_table[i].low_temp_volt = info->low_temp_min_volt; if (!reach_max_volt) - info->low_limit = opp->rate; + low_limit = opp->rate; if (info->opp_table[i].low_temp_volt == info->max_volt) reach_max_volt = true; } else { info->opp_table[i].low_temp_volt = info->max_volt; } + if (low_limit && low_limit != opp->rate) + 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", info->opp_table[i].rate, info->opp_table[i].volt, info->opp_table[i].low_temp_volt); + i++; } - if (info->low_limit == opp->rate) - info->low_limit = 0; - if (info->high_limit == opp->rate) - info->high_limit = 0; -unlock: -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) - rcu_read_unlock(); -#endif -out: - return ret; + mutex_unlock(&opp_table->lock); + + dev_pm_opp_put_opp_table(opp_table); + + return 0; } static int monitor_device_parse_wide_temp_config(struct device_node *np, @@ -771,44 +764,37 @@ static int rockchip_adjust_low_temp_opp_volt(struct monitor_dev_info *info, bool is_low_temp) { struct device *dev = info->dev; + struct opp_table *opp_table; struct dev_pm_opp *opp; - unsigned long rate; - int i, count, ret = 0; + int i = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) - rcu_read_lock(); -#endif - count = dev_pm_opp_get_opp_count(dev); - if (count <= 0) { - ret = count ? count : -ENODATA; - goto out; - } + opp_table = dev_pm_opp_get_opp_table(dev); + if (!opp_table) + return -ENOMEM; - for (i = 0, rate = 0; i < count; i++, rate++) { - /* find next rate */ - opp = dev_pm_opp_find_freq_ceil(dev, &rate); - if (IS_ERR(opp)) { - ret = PTR_ERR(opp); - goto out; - } + mutex_lock(&opp_table->lock); + list_for_each_entry(opp, &opp_table->opp_list, node) { if (is_low_temp) { - if (opp->u_volt_max < info->opp_table[i].low_temp_volt) - opp->u_volt_max = + if (opp->supplies[0].u_volt_max < + info->opp_table[i].low_temp_volt) + opp->supplies[0].u_volt_max = info->opp_table[i].low_temp_volt; - opp->u_volt = info->opp_table[i].low_temp_volt; - opp->u_volt_min = opp->u_volt; + opp->supplies[0].u_volt = + info->opp_table[i].low_temp_volt; + opp->supplies[0].u_volt_min = opp->supplies[0].u_volt; } else { - opp->u_volt_min = info->opp_table[i].volt; - opp->u_volt = opp->u_volt_min; - opp->u_volt_max = info->opp_table[i].max_volt; + 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; } + i++; } + mutex_unlock(&opp_table->lock); -out: -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) - rcu_read_unlock(); -#endif - return ret; + dev_pm_opp_put_opp_table(opp_table); + + return 0; } static void rockchip_low_temp_adjust(struct monitor_dev_info *info, @@ -841,8 +827,19 @@ static void rockchip_high_temp_adjust(struct monitor_dev_info *info, info->is_high_temp = is_high; } -int rockchip_monitor_suspend_low_temp_adjust(struct monitor_dev_info *info) +int rockchip_monitor_suspend_low_temp_adjust(int cpu) { + struct monitor_dev_info *info = NULL, *tmp; + + list_for_each_entry(tmp, &monitor_dev_list, node) { + if (tmp->devp->type != MONITOR_TPYE_CPU) + continue; + if (cpumask_test_cpu(cpu, &tmp->devp->allowed_cpus)) { + info = tmp; + break; + } + } + if (!info || !info->is_low_temp_enabled) return 0; @@ -921,11 +918,15 @@ static int system_monitor_devfreq_notifier_call(struct notifier_block *nb, static int monitor_set_freq_table(struct device *dev, struct monitor_dev_info *info) { + struct opp_table *opp_table; struct dev_pm_opp *opp; - unsigned long freq, *freq_table; - unsigned int i; + unsigned long *freq_table; int count; + opp_table = dev_pm_opp_get_opp_table(dev); + if (!opp_table) + return -ENOMEM; + /* Initialize the freq_table from OPP table */ count = dev_pm_opp_get_opp_count(dev); if (count <= 0) @@ -938,18 +939,16 @@ static int monitor_set_freq_table(struct device *dev, return -ENOMEM; } - rcu_read_lock(); - for (i = 0, freq = ULONG_MAX; i < info->max_state; i++, freq--) { - opp = dev_pm_opp_find_freq_floor(dev, &freq); - if (IS_ERR(opp)) { - kfree(freq_table); - info->max_state = 0; - rcu_read_unlock(); - return PTR_ERR(opp); + mutex_lock(&opp_table->lock); + list_for_each_entry(opp, &opp_table->opp_list, node) { + if (opp->available) { + count--; + freq_table[count] = opp->rate; } - freq_table[i] = freq; } - rcu_read_unlock(); + mutex_unlock(&opp_table->lock); + + dev_pm_opp_put_opp_table(opp_table); info->freq_table = freq_table; diff --git a/include/soc/rockchip/rockchip_system_monitor.h b/include/soc/rockchip/rockchip_system_monitor.h index 2c2b74e4a883..f60c07955580 100644 --- a/include/soc/rockchip/rockchip_system_monitor.h +++ b/include/soc/rockchip/rockchip_system_monitor.h @@ -120,7 +120,7 @@ int rockchip_monitor_dev_low_temp_adjust(struct monitor_dev_info *info, bool is_low); int rockchip_monitor_dev_high_temp_adjust(struct monitor_dev_info *info, bool is_high); -int rockchip_monitor_suspend_low_temp_adjust(struct monitor_dev_info *info); +int rockchip_monitor_suspend_low_temp_adjust(int cpu); int rockchip_system_monitor_adjust_cdev_state(struct thermal_cooling_device *cdev, int temp, unsigned long *state); @@ -163,8 +163,7 @@ rockchip_monitor_dev_high_temp_adjust(struct monitor_dev_info *info, return 0; }; -static inline int -rockchip_monitor_suspend_low_temp_adjust(struct monitor_dev_info *info) +static inline int rockchip_monitor_suspend_low_temp_adjust(in cpu) { return 0; };