soc: rockchip: opp_select: Implement rockchip_set_read_margin()

Add common APIs to set read margin and set intermediate rate.

Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
Change-Id: I8fb1d16f4ca1a9ec0ba80019197a73e56391c14c
This commit is contained in:
Finley Xiao
2022-02-18 22:18:19 +08:00
committed by Tao Huang
parent f5f2d23805
commit f3a5053707
2 changed files with 103 additions and 0 deletions

View File

@@ -1164,6 +1164,69 @@ int rockchip_get_read_margin(struct device *dev,
}
EXPORT_SYMBOL(rockchip_get_read_margin);
int rockchip_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info, u32 rm,
bool is_set_rm)
{
if (!is_set_rm || !opp_info)
return 0;
if (!opp_info || !opp_info->volt_rm_tbl)
return 0;
if (!opp_info->data || !opp_info->data->set_read_margin)
return 0;
if (rm == opp_info->current_rm)
return 0;
return opp_info->data->set_read_margin(dev, opp_info, rm);
}
EXPORT_SYMBOL(rockchip_set_read_margin);
int rockchip_set_intermediate_rate(struct device *dev,
struct rockchip_opp_info *opp_info,
struct clk *clk, unsigned long old_freq,
unsigned long new_freq, bool is_scaling_up,
bool is_set_clk)
{
if (!is_set_clk)
return 0;
if (!opp_info || !opp_info->volt_rm_tbl)
return 0;
if (!opp_info->data || !opp_info->data->set_read_margin)
return 0;
if (opp_info->target_rm == opp_info->current_rm)
return 0;
/*
* There is no need to set intermediate rate if the new voltage
* and the current voltage are high voltage.
*/
if ((opp_info->target_rm < opp_info->low_rm) &&
(opp_info->current_rm < opp_info->low_rm))
return 0;
if (is_scaling_up) {
/*
* If scaling up and the current frequency is less than
* or equal to intermediate threshold frequency, there is
* no need to set intermediate rate.
*/
if (opp_info->intermediate_threshold_freq &&
old_freq <= opp_info->intermediate_threshold_freq)
return 0;
return clk_set_rate(clk, new_freq | OPP_SCALING_UP_INTER);
}
/*
* If scaling down and the new frequency is less than or equal to
* intermediate threshold frequency , there is no need to set
* intermediate rate and set the new frequency directly.
*/
if (opp_info->intermediate_threshold_freq &&
new_freq <= opp_info->intermediate_threshold_freq)
return clk_set_rate(clk, new_freq);
return clk_set_rate(clk, new_freq | OPP_SCALING_DOWN_INTER);
}
EXPORT_SYMBOL(rockchip_set_intermediate_rate);
int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info,
char *lkg_name, char *reg_name)
{
@@ -1171,6 +1234,7 @@ int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info,
int bin = -EINVAL, process = -EINVAL;
int scale = 0, volt_sel = -EINVAL;
int ret = 0, num_clks = 0, i;
u32 freq;
/* Get OPP descriptor node */
np = of_parse_phandle(dev->of_node, "operating-points-v2", 0);
@@ -1207,6 +1271,11 @@ int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info,
info->grf = NULL;
rockchip_get_volt_rm_table(dev, np, "volt-mem-read-margin",
&info->volt_rm_tbl);
of_property_read_u32(np, "low-volt-mem-read-margin",
&info->low_rm);
if (!of_property_read_u32(np, "intermediate-threshold-freq",
&freq))
info->intermediate_threshold_freq = freq * 1000;
}
if (info->data && info->data->get_soc_info)
info->data->get_soc_info(dev, np, &bin, &process);

View File

@@ -8,6 +8,12 @@
#define VOLT_RM_TABLE_END ~1
#define OPP_INTERMEDIATE_MASK 0x3f
#define OPP_INTERMEDIATE_RATE 0x01
#define OPP_SCALING_UP_RATE 0x02
#define OPP_SCALING_UP_INTER (OPP_INTERMEDIATE_RATE | OPP_SCALING_UP_RATE)
#define OPP_SCALING_DOWN_INTER OPP_INTERMEDIATE_RATE
struct rockchip_opp_info;
struct volt_rm_table {
@@ -30,7 +36,11 @@ struct rockchip_opp_info {
struct regmap *dsu_grf;
struct clk_bulk_data *clks;
struct clk *scmi_clk;
/* The threshold frequency for set intermediate rate */
unsigned long intermediate_threshold_freq;
int num_clks;
/* The read margin for low voltage */
u32 low_rm;
u32 current_rm;
u32 target_rm;
};
@@ -64,6 +74,14 @@ 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_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info, u32 rm,
bool is_set_rm);
int rockchip_set_intermediate_rate(struct device *dev,
struct rockchip_opp_info *opp_info,
struct clk *clk, unsigned long old_freq,
unsigned long new_freq, bool is_scaling_up,
bool is_set_clk);
int rockchip_init_opp_table(struct device *dev,
struct rockchip_opp_info *info,
char *lkg_name, char *reg_name);
@@ -151,6 +169,22 @@ static inline int rockchip_get_read_margin(struct device *dev,
{
return -EOPNOTSUPP;
}
static inline int rockchip_set_read_margin(struct device *dev,
struct rockchip_opp_info *opp_info,
u32 rm, bool is_set_rm)
{
return -EOPNOTSUPP;
}
static inline int
rockchip_set_intermediate_rate(struct device *dev,
struct rockchip_opp_info *opp_info,
struct clk *clk, unsigned long old_freq,
unsigned long new_freq, bool is_scaling_up,
bool is_set_clk)
{
return -EOPNOTSUPP;
}
static inline int rockchip_init_opp_table(struct device *dev,
struct rockchip_opp_info *info,