soc: rockchip: opp_select: Implement rockchip_get_read_margin()

In order to get target read margin and scmi clk earlier,
and it will also be used in later submissions.

Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
Change-Id: I75bd79dc4963fa0dcc73d7c66a696e1cc0c177b7
This commit is contained in:
Finley Xiao
2022-02-17 11:03:43 +08:00
committed by Tao Huang
parent 686e5857b5
commit f5f2d23805
9 changed files with 104 additions and 103 deletions

View File

@@ -185,26 +185,11 @@ out:
static int rk3588_cpu_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
unsigned long volt)
u32 rm)
{
bool is_found = false;
u32 rm;
int i;
if (!opp_info->volt_rm_tbl)
return 0;
for (i = 0; opp_info->volt_rm_tbl[i].rm != VOLT_RM_TABLE_END; i++) {
if (volt >= opp_info->volt_rm_tbl[i].volt) {
rm = opp_info->volt_rm_tbl[i].rm;
is_found = true;
break;
}
}
if (!is_found)
return 0;
if (rm == opp_info->current_rm)
if (rm == opp_info->current_rm || rm == UINT_MAX)
return 0;
dev_dbg(dev, "set rm to %d\n", rm);
@@ -345,12 +330,10 @@ static int rockchip_cpufreq_set_volt(struct device *dev,
static int rockchip_cpufreq_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
unsigned long volt)
u32 rm)
{
if (opp_info->data && opp_info->data->set_read_margin) {
opp_info->data->set_read_margin(dev, opp_info, volt);
opp_info->volt_rm = volt;
}
if (opp_info->data && opp_info->data->set_read_margin)
opp_info->data->set_read_margin(dev, opp_info, rm);
return 0;
}
@@ -379,12 +362,15 @@ static int cpu_opp_helper(struct dev_pm_set_opp_data *data)
struct rockchip_opp_info *opp_info;
unsigned long old_freq = data->old_opp.rate;
unsigned long new_freq = data->new_opp.rate;
u32 target_rm = UINT_MAX;
int ret = 0;
cluster = rockchip_cluster_info_lookup(dev->id);
if (!cluster)
return -EINVAL;
opp_info = &cluster->opp_info;
rockchip_get_read_margin(dev, opp_info, new_supply_vdd->u_volt,
&target_rm);
/* Scaling up? Scale voltage before frequency */
if (new_freq >= old_freq) {
@@ -403,8 +389,7 @@ static int cpu_opp_helper(struct dev_pm_set_opp_data *data)
"vdd");
if (ret)
goto restore_voltage;
rockchip_cpufreq_set_read_margin(dev, opp_info,
new_supply_vdd->u_volt);
rockchip_cpufreq_set_read_margin(dev, opp_info, target_rm);
}
/* Change frequency */
@@ -418,8 +403,7 @@ static int cpu_opp_helper(struct dev_pm_set_opp_data *data)
/* Scaling down? Scale voltage after frequency */
if (new_freq < old_freq) {
rockchip_cpufreq_set_read_margin(dev, opp_info,
new_supply_vdd->u_volt);
rockchip_cpufreq_set_read_margin(dev, opp_info, target_rm);
ret = rockchip_cpufreq_set_volt(dev, vdd_reg, new_supply_vdd,
"vdd");
if (ret)
@@ -437,8 +421,9 @@ restore_freq:
dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
__func__, old_freq);
restore_rm:
rockchip_cpufreq_set_read_margin(dev, opp_info,
old_supply_vdd->u_volt);
rockchip_get_read_margin(dev, opp_info, old_supply_vdd->u_volt,
&target_rm);
rockchip_cpufreq_set_read_margin(dev, opp_info, target_rm);
restore_voltage:
rockchip_cpufreq_set_volt(dev, mem_reg, old_supply_mem, "mem");
rockchip_cpufreq_set_volt(dev, vdd_reg, old_supply_vdd, "vdd");
@@ -487,6 +472,7 @@ static int rockchip_cpufreq_cluster_init(int cpu, struct cluster_info *cluster)
rockchip_get_opp_data(rockchip_cpufreq_of_match, opp_info);
if (opp_info->data && opp_info->data->set_read_margin) {
opp_info->current_rm = UINT_MAX;
opp_info->target_rm = UINT_MAX;
opp_info->grf = syscon_regmap_lookup_by_phandle(np,
"rockchip,grf");
if (IS_ERR(opp_info->grf))

View File

@@ -74,7 +74,7 @@ static unsigned long get_voltage(struct kbase_device *kbdev, unsigned long freq)
opp = dev_pm_opp_find_freq_exact(kbdev->dev, freq, true);
if (IS_ERR_OR_NULL(opp))
if (IS_ERR(opp))
dev_err(kbdev->dev, "Failed to get opp (%ld)\n", PTR_ERR(opp));
else {
voltage = dev_pm_opp_get_voltage(opp);
@@ -129,13 +129,12 @@ void kbase_devfreq_opp_translate(struct kbase_device *kbdev, unsigned long freq,
static int kbase_devfreq_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
unsigned long volt,
u32 rm,
bool is_set_rm)
{
if (opp_info->data && opp_info->data->set_read_margin) {
if (is_set_rm)
opp_info->data->set_read_margin(dev, opp_info, volt);
opp_info->volt_rm = volt;
opp_info->data->set_read_margin(dev, opp_info, rm);
}
return 0;
@@ -157,11 +156,12 @@ int kbase_devfreq_opp_helper(struct dev_pm_set_opp_data *data)
unsigned long new_freq = data->new_opp.rate;
bool is_set_rm = true;
bool is_set_clk = true;
u32 target_rm = UINT_MAX;
int ret = 0;
if (!pm_runtime_active(dev)) {
is_set_rm = false;
if (kbdev->scmi_clk)
if (opp_info->scmi_clk)
is_set_clk = false;
}
@@ -170,6 +170,8 @@ int kbase_devfreq_opp_helper(struct dev_pm_set_opp_data *data)
dev_err(dev, "failed to enable opp clks\n");
return ret;
}
rockchip_get_read_margin(dev, opp_info, new_supply_vdd->u_volt,
&target_rm);
/* Scaling up? Scale voltage before frequency */
if (new_freq >= old_freq) {
@@ -187,8 +189,7 @@ int kbase_devfreq_opp_helper(struct dev_pm_set_opp_data *data)
new_supply_vdd->u_volt);
goto restore_voltage;
}
kbase_devfreq_set_read_margin(dev, opp_info,
new_supply_vdd->u_volt,
kbase_devfreq_set_read_margin(dev, opp_info, target_rm,
is_set_rm);
}
@@ -201,8 +202,7 @@ int kbase_devfreq_opp_helper(struct dev_pm_set_opp_data *data)
/* Scaling down? Scale voltage after frequency */
if (new_freq < old_freq) {
kbase_devfreq_set_read_margin(dev, opp_info,
new_supply_vdd->u_volt,
kbase_devfreq_set_read_margin(dev, opp_info, target_rm,
is_set_rm);
ret = regulator_set_voltage(vdd_reg, new_supply_vdd->u_volt,
INT_MAX);
@@ -228,8 +228,9 @@ restore_freq:
if (is_set_clk && clk_set_rate(clk, old_freq))
dev_err(dev, "failed to restore old-freq %lu Hz\n", old_freq);
restore_rm:
kbase_devfreq_set_read_margin(dev, opp_info, old_supply_vdd->u_volt,
is_set_rm);
rockchip_get_read_margin(dev, opp_info, old_supply_vdd->u_volt,
&target_rm);
kbase_devfreq_set_read_margin(dev, opp_info, target_rm, is_set_rm);
restore_voltage:
regulator_set_voltage(mem_reg, old_supply_mem->u_volt, INT_MAX);
regulator_set_voltage(vdd_reg, old_supply_vdd->u_volt, INT_MAX);
@@ -693,7 +694,7 @@ int kbase_devfreq_init(struct kbase_device *kbdev)
kbdev->current_freqs[i] = 0;
}
if (strstr(__clk_get_name(kbdev->clocks[0]), "scmi"))
kbdev->scmi_clk = kbdev->clocks[0];
kbdev->opp_info.scmi_clk = kbdev->clocks[0];
kbdev->current_nominal_freq = kbdev->current_freqs[0];
opp = devfreq_recommended_opp(kbdev->dev, &kbdev->current_nominal_freq, 0);

View File

@@ -982,7 +982,6 @@ struct kbase_device {
} irqs[3];
struct clk *clocks[BASE_MAX_NR_CLOCKS_REGULATORS];
struct clk *scmi_clk;
unsigned int nr_clocks;
#if IS_ENABLED(CONFIG_REGULATOR)
struct regulator *regulators[BASE_MAX_NR_CLOCKS_REGULATORS];

View File

@@ -202,13 +202,14 @@ static int rk_pm_callback_runtime_on(struct kbase_device *kbdev)
dev_err(kbdev->dev, "failed to enable opp clks\n");
return ret;
}
if (kbdev->scmi_clk) {
if (clk_set_rate(kbdev->scmi_clk, kbdev->current_nominal_freq))
if (opp_info->scmi_clk) {
if (clk_set_rate(opp_info->scmi_clk,
kbdev->current_nominal_freq))
dev_err(kbdev->dev, "failed to restore clk rate\n");
}
if (opp_info->data && opp_info->data->set_read_margin)
opp_info->data->set_read_margin(kbdev->dev, opp_info,
opp_info->volt_rm);
opp_info->target_rm);
clk_bulk_disable_unprepare(opp_info->num_clks, opp_info->clks);
return 0;
@@ -218,8 +219,8 @@ static void rk_pm_callback_runtime_off(struct kbase_device *kbdev)
{
struct rockchip_opp_info *opp_info = &kbdev->opp_info;
if (kbdev->scmi_clk) {
if (clk_set_rate(kbdev->scmi_clk, POWER_DOWN_FREQ))
if (opp_info->scmi_clk) {
if (clk_set_rate(opp_info->scmi_clk, POWER_DOWN_FREQ))
dev_err(kbdev->dev, "failed to set power down rate\n");
}
opp_info->current_rm = UINT_MAX;
@@ -500,26 +501,14 @@ static void kbase_platform_rk_remove_sysfs_files(struct device *dev)
static int rk3588_gpu_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
unsigned long volt)
u32 rm)
{
bool is_found = false;
int i, ret = 0;
u32 rm, val;
int ret = 0;
u32 val;
if (!opp_info->grf || !opp_info->volt_rm_tbl)
return 0;
for (i = 0; opp_info->volt_rm_tbl[i].rm != VOLT_RM_TABLE_END; i++) {
if (volt >= opp_info->volt_rm_tbl[i].volt) {
rm = opp_info->volt_rm_tbl[i].rm;
is_found = true;
break;
}
}
if (!is_found)
return 0;
if (rm == opp_info->current_rm)
if (rm == opp_info->current_rm || rm == UINT_MAX)
return 0;
dev_dbg(dev, "set rm to %d\n", rm);

View File

@@ -105,7 +105,6 @@ struct rknpu_device {
struct device *genpd_dev_npu0;
struct device *genpd_dev_npu1;
struct device *genpd_dev_npu2;
struct clk *scmi_clk;
bool multiple_domains;
};

View File

@@ -513,12 +513,10 @@ static struct monitor_dev_profile npu_mdevp = {
static int rknpu_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
unsigned long volt)
u32 rm)
{
if (opp_info->data && opp_info->data->set_read_margin) {
opp_info->data->set_read_margin(dev, opp_info, volt);
opp_info->volt_rm = volt;
}
if (opp_info->data && opp_info->data->set_read_margin)
opp_info->data->set_read_margin(dev, opp_info, rm);
return 0;
}
@@ -537,6 +535,7 @@ static int npu_opp_helper(struct dev_pm_set_opp_data *data)
struct rockchip_opp_info *opp_info = &rknpu_dev->opp_info;
unsigned long old_freq = data->old_opp.rate;
unsigned long new_freq = data->new_opp.rate;
u32 target_rm = UINT_MAX;
int ret = 0;
ret = clk_bulk_prepare_enable(opp_info->num_clks, opp_info->clks);
@@ -544,6 +543,8 @@ static int npu_opp_helper(struct dev_pm_set_opp_data *data)
LOG_DEV_ERROR(dev, "failed to enable opp clks\n");
return ret;
}
rockchip_get_read_margin(dev, opp_info, new_supply_vdd->u_volt,
&target_rm);
/* Scaling up? Scale voltage before frequency */
if (new_freq >= old_freq) {
@@ -563,7 +564,7 @@ static int npu_opp_helper(struct dev_pm_set_opp_data *data)
new_supply_vdd->u_volt);
goto restore_voltage;
}
rknpu_set_read_margin(dev, opp_info, new_supply_vdd->u_volt);
rknpu_set_read_margin(dev, opp_info, target_rm);
}
/* Change frequency */
@@ -577,7 +578,7 @@ static int npu_opp_helper(struct dev_pm_set_opp_data *data)
/* Scaling down? Scale voltage after frequency */
if (new_freq < old_freq) {
rknpu_set_read_margin(dev, opp_info, new_supply_vdd->u_volt);
rknpu_set_read_margin(dev, opp_info, target_rm);
ret = regulator_set_voltage(vdd_reg, new_supply_vdd->u_volt,
INT_MAX);
if (ret) {
@@ -605,7 +606,9 @@ restore_freq:
LOG_DEV_ERROR(dev, "failed to restore old-freq %lu Hz\n",
old_freq);
restore_rm:
rknpu_set_read_margin(dev, opp_info, old_supply_vdd->u_volt);
rockchip_get_read_margin(dev, opp_info, old_supply_vdd->u_volt,
&target_rm);
rknpu_set_read_margin(dev, opp_info, target_rm);
restore_voltage:
regulator_set_voltage(mem_reg, old_supply_mem->u_volt, INT_MAX);
regulator_set_voltage(vdd_reg, old_supply_vdd->u_volt, INT_MAX);
@@ -685,26 +688,15 @@ static struct devfreq_cooling_power npu_cooling_power = {
static int rk3588_npu_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
unsigned long volt)
u32 rm)
{
bool is_found = false;
u32 rm = 0, offset = 0, val = 0;
u32 offset = 0, val = 0;
int i, ret = 0;
if (!opp_info->grf || !opp_info->volt_rm_tbl)
return 0;
for (i = 0; opp_info->volt_rm_tbl[i].rm != VOLT_RM_TABLE_END; i++) {
if (volt >= opp_info->volt_rm_tbl[i].volt) {
rm = opp_info->volt_rm_tbl[i].rm;
is_found = true;
break;
}
}
if (!is_found)
return 0;
if (rm == opp_info->current_rm)
if (rm == opp_info->current_rm || rm == UINT_MAX)
return 0;
LOG_DEV_DEBUG(dev, "set rm to %d\n", rm);
@@ -933,7 +925,7 @@ static int rknpu_probe(struct platform_device *pdev)
rknpu_dev->num_clks = devm_clk_bulk_get_all(dev, &rknpu_dev->clks);
if (strstr(__clk_get_name(rknpu_dev->clks[0].clk), "scmi"))
rknpu_dev->scmi_clk = rknpu_dev->clks[0].clk;
rknpu_dev->opp_info.scmi_clk = rknpu_dev->clks[0].clk;
#ifndef FPGA_PLATFORM
rknpu_dev->vdd = devm_regulator_get_optional(dev, "rknpu");
@@ -1085,8 +1077,8 @@ static int rknpu_runtime_suspend(struct device *dev)
struct rknpu_device *rknpu_dev = dev_get_drvdata(dev);
struct rockchip_opp_info *opp_info = &rknpu_dev->opp_info;
if (rknpu_dev->scmi_clk) {
if (clk_set_rate(rknpu_dev->scmi_clk, POWER_DOWN_FREQ))
if (opp_info->scmi_clk) {
if (clk_set_rate(opp_info->scmi_clk, POWER_DOWN_FREQ))
LOG_DEV_ERROR(dev, "failed to restore clk rate\n");
}
opp_info->current_rm = UINT_MAX;
@@ -1109,14 +1101,14 @@ static int rknpu_runtime_resume(struct device *dev)
return ret;
}
if (rknpu_dev->scmi_clk) {
if (clk_set_rate(rknpu_dev->scmi_clk, rknpu_dev->current_freq))
if (opp_info->scmi_clk) {
if (clk_set_rate(opp_info->scmi_clk, rknpu_dev->current_freq))
LOG_DEV_ERROR(dev, "failed to set power down rate\n");
}
if (opp_info->data && opp_info->data->set_read_margin)
opp_info->data->set_read_margin(dev, opp_info,
opp_info->volt_rm);
opp_info->target_rm);
clk_bulk_disable_unprepare(opp_info->num_clks, opp_info->clks);

View File

@@ -1143,6 +1143,27 @@ out_np:
}
EXPORT_SYMBOL(rockchip_adjust_power_scale);
int rockchip_get_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
unsigned long volt, u32 *target_rm)
{
int i;
if (!opp_info || !opp_info->volt_rm_tbl)
return 0;
for (i = 0; opp_info->volt_rm_tbl[i].rm != VOLT_RM_TABLE_END; i++) {
if (volt >= opp_info->volt_rm_tbl[i].volt) {
opp_info->target_rm = opp_info->volt_rm_tbl[i].rm;
break;
}
}
*target_rm = opp_info->target_rm;
return 0;
}
EXPORT_SYMBOL(rockchip_get_read_margin);
int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info,
char *lkg_name, char *reg_name)
{

View File

@@ -1092,13 +1092,12 @@ EXPORT_SYMBOL(rockchip_monitor_volt_adjust_unlock);
static int rockchip_monitor_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
unsigned long volt)
u32 rm)
{
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;
opp_info->data->set_read_margin(dev, opp_info, rm);
}
return 0;
@@ -1114,6 +1113,7 @@ int rockchip_monitor_check_rate_volt(struct monitor_dev_info *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;
int ret = 0;
if (!info->regulators || !info->clk)
@@ -1168,6 +1168,8 @@ int rockchip_monitor_check_rate_volt(struct monitor_dev_info *info,
if (!new_volt || (info->regulator_count > 1 && !new_mem_volt))
goto unlock;
rockchip_get_read_margin(dev, opp_info, new_volt, &target_rm);
dev_dbg(dev, "%s: %lu Hz --> %lu Hz\n", __func__, old_rate, new_rate);
if (new_rate >= old_rate) {
if (info->regulator_count > 1) {
@@ -1185,7 +1187,7 @@ int rockchip_monitor_check_rate_volt(struct monitor_dev_info *info,
__func__, new_volt);
goto restore_voltage;
}
rockchip_monitor_set_read_margin(dev, opp_info, new_volt);
rockchip_monitor_set_read_margin(dev, opp_info, target_rm);
if (new_rate == old_rate)
goto unlock;
}
@@ -1197,7 +1199,7 @@ int rockchip_monitor_check_rate_volt(struct monitor_dev_info *info,
}
if (new_rate < old_rate) {
rockchip_monitor_set_read_margin(dev, opp_info, new_volt);
rockchip_monitor_set_read_margin(dev, opp_info, target_rm);
ret = regulator_set_voltage(vdd_reg, new_volt,
INT_MAX);
if (ret) {
@@ -1222,7 +1224,8 @@ restore_freq:
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, old_volt);
rockchip_get_read_margin(dev, opp_info, old_volt, &target_rm);
rockchip_monitor_set_read_margin(dev, opp_info, target_rm);
restore_voltage:
if (info->regulator_count > 1)
regulator_set_voltage(mem_reg, old_mem_volt, INT_MAX);

View File

@@ -20,7 +20,7 @@ struct rockchip_opp_data {
int *bin, int *process);
int (*set_read_margin)(struct device *dev,
struct rockchip_opp_info *opp_info,
unsigned long volt);
u32 rm);
};
struct rockchip_opp_info {
@@ -29,9 +29,10 @@ struct rockchip_opp_info {
struct regmap *grf;
struct regmap *dsu_grf;
struct clk_bulk_data *clks;
struct clk *scmi_clk;
int num_clks;
unsigned long volt_rm;
u32 current_rm;
u32 target_rm;
};
#if IS_ENABLED(CONFIG_ROCKCHIP_OPP)
@@ -60,6 +61,9 @@ void rockchip_get_scale_volt_sel(struct device *dev, char *lkg_name,
struct opp_table *rockchip_set_opp_prop_name(struct device *dev, int process,
int volt_sel);
int rockchip_adjust_power_scale(struct device *dev, int scale);
int rockchip_get_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
unsigned long volt, u32 *target_rm);
int rockchip_init_opp_table(struct device *dev,
struct rockchip_opp_info *info,
char *lkg_name, char *reg_name);
@@ -67,7 +71,7 @@ int rockchip_init_opp_table(struct device *dev,
static inline int rockchip_of_get_leakage(struct device *dev, char *lkg_name,
int *leakage)
{
return -ENOTSUPP;
return -EOPNOTSUPP;
}
static inline void rockchip_of_get_lkg_sel(struct device *dev,
@@ -133,19 +137,26 @@ static inline struct opp_table *rockchip_set_opp_prop_name(struct device *dev,
int process,
int volt_sel)
{
return ERR_PTR(-ENOTSUPP);
return ERR_PTR(-EOPNOTSUPP);
}
static inline int rockchip_adjust_power_scale(struct device *dev, int scale)
{
return -ENOTSUPP;
return -EOPNOTSUPP;
}
static inline int rockchip_get_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
unsigned long volt, u32 *target_rm)
{
return -EOPNOTSUPP;
}
static inline int rockchip_init_opp_table(struct device *dev,
struct rockchip_opp_info *info,
char *lkg_name, char *reg_name)
{
return -ENOTSUPP;
return -EOPNOTSUPP;
}
#endif /* CONFIG_ROCKCHIP_OPP */