mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
soc: rockchip_system_monitor: Avoid crash when set rate and read margin
1. only update voltage when low temperature. 2. set memory read margin only when pd is on. Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com> Change-Id: I7a0ae4af45b86c7a08c6ffadccb71a0db3fb44e5
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_opp.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>
|
||||
@@ -819,7 +820,7 @@ static void rockchip_low_temp_adjust(struct monitor_dev_info *info,
|
||||
info->is_low_temp = is_low;
|
||||
|
||||
if (devp->update_volt)
|
||||
devp->update_volt(info);
|
||||
devp->update_volt(info, false);
|
||||
}
|
||||
|
||||
static void rockchip_high_temp_adjust(struct monitor_dev_info *info,
|
||||
@@ -1071,13 +1072,18 @@ static int rockchip_monitor_set_read_margin(struct device *dev,
|
||||
struct rockchip_opp_info *opp_info,
|
||||
unsigned long volt)
|
||||
{
|
||||
if (opp_info && opp_info->data->set_read_margin)
|
||||
return opp_info->data->set_read_margin(dev, opp_info, volt);
|
||||
|
||||
if (opp_info && opp_info->data && opp_info->data->set_read_margin) {
|
||||
if (pm_runtime_active(dev))
|
||||
opp_info->data->set_read_margin(dev, opp_info, volt);
|
||||
opp_info->volt_rm = volt;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rockchip_monitor_check_rate_volt(struct monitor_dev_info *info)
|
||||
int rockchip_monitor_check_rate_volt(struct monitor_dev_info *info,
|
||||
bool is_set_clk)
|
||||
{
|
||||
struct device *dev = info->dev;
|
||||
struct regulator *vdd_reg = NULL;
|
||||
@@ -1128,7 +1134,6 @@ int rockchip_monitor_check_rate_volt(struct monitor_dev_info *info)
|
||||
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 &&
|
||||
@@ -1163,8 +1168,7 @@ int rockchip_monitor_check_rate_volt(struct monitor_dev_info *info)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(info->clk, new_rate);
|
||||
if (ret) {
|
||||
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;
|
||||
@@ -1192,11 +1196,11 @@ int rockchip_monitor_check_rate_volt(struct monitor_dev_info *info)
|
||||
goto disable_clk;
|
||||
|
||||
restore_freq:
|
||||
if (clk_set_rate(info->clk, old_rate))
|
||||
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_monitor_set_read_margin(dev, opp_info, new_volt);
|
||||
rockchip_monitor_set_read_margin(dev, opp_info, old_volt);
|
||||
restore_voltage:
|
||||
if (info->regulator_count > 1)
|
||||
regulator_set_voltage(mem_reg, old_mem_volt, INT_MAX);
|
||||
@@ -1230,14 +1234,14 @@ rockchip_system_monitor_register(struct device *dev,
|
||||
|
||||
rockchip_system_monitor_parse_supplies(dev, info);
|
||||
if (monitor_device_parse_dt(dev, info)) {
|
||||
rockchip_monitor_check_rate_volt(info);
|
||||
rockchip_monitor_check_rate_volt(info, true);
|
||||
kfree(info);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
rockchip_system_monitor_early_regulator_init(info);
|
||||
rockchip_system_monitor_wide_temp_init(info);
|
||||
rockchip_monitor_check_rate_volt(info);
|
||||
rockchip_monitor_check_rate_volt(info, true);
|
||||
devp->is_checked = true;
|
||||
rockchip_system_monitor_freq_qos_requset(info);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ struct rockchip_opp_info {
|
||||
struct regmap *grf;
|
||||
struct clk_bulk_data *clks;
|
||||
int num_clks;
|
||||
unsigned long volt_rm;
|
||||
u32 current_rm;
|
||||
};
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ struct monitor_dev_profile {
|
||||
bool is_checked;
|
||||
int (*low_temp_adjust)(struct monitor_dev_info *info, bool is_low);
|
||||
int (*high_temp_adjust)(struct monitor_dev_info *info, bool is_low);
|
||||
int (*update_volt)(struct monitor_dev_info *info);
|
||||
int (*update_volt)(struct monitor_dev_info *info, bool is_set_clk);
|
||||
struct cpumask allowed_cpus;
|
||||
struct rockchip_opp_info *opp_info;
|
||||
};
|
||||
@@ -133,7 +133,8 @@ int rockchip_monitor_cpu_high_temp_adjust(struct monitor_dev_info *info,
|
||||
bool is_high);
|
||||
void rockchip_monitor_volt_adjust_lock(struct monitor_dev_info *info);
|
||||
void rockchip_monitor_volt_adjust_unlock(struct monitor_dev_info *info);
|
||||
int rockchip_monitor_check_rate_volt(struct monitor_dev_info *info);
|
||||
int rockchip_monitor_check_rate_volt(struct monitor_dev_info *info,
|
||||
bool is_set_clk);
|
||||
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,
|
||||
@@ -176,7 +177,7 @@ rockchip_monitor_volt_adjust_unlock(struct monitor_dev_info *info)
|
||||
}
|
||||
|
||||
static inline int
|
||||
rockchip_monitor_check_rate_volt(struct monitor_dev_info *info)
|
||||
rockchip_monitor_check_rate_volt(struct monitor_dev_info *info, bool is_set_clk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user