mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 00:53:34 +02:00
scsi: ufs: host: mediatek: Support clock scaling with Vcore binding
Add support for clock scaling with Vcore binding: 1. Parse the DTS setting for Vcore voltage. 2. Set the Vcore voltage to the DTS-specified value before scaling up. 3. Reset the Vcore voltage to the default setting after scaling down. These changes ensure that the Vcore voltage is appropriately managed during clock scaling operations to maintain system stability and performance. Signed-off-by: Peter Wang <peter.wang@mediatek.com> Link: https://lore.kernel.org/r/20250722030841.1998783-9-peter.wang@mediatek.com Reviewed-by: Chun-Hung Wu <chun-hung.wu@mediatek.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
ff40f31216
commit
31a20e9f7c
|
|
@ -933,6 +933,9 @@ static void ufs_mtk_init_clocks(struct ufs_hba *hba)
|
|||
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
|
||||
struct list_head *head = &hba->clk_list_head;
|
||||
struct ufs_clk_info *clki, *clki_tmp;
|
||||
struct device *dev = hba->dev;
|
||||
struct regulator *reg;
|
||||
u32 volt;
|
||||
|
||||
/*
|
||||
* Find private clocks and store them in struct ufs_mtk_clk.
|
||||
|
|
@ -958,6 +961,35 @@ static void ufs_mtk_init_clocks(struct ufs_hba *hba)
|
|||
dev_info(hba->dev,
|
||||
"%s: Clk-scaling not ready. Feature disabled.",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default get vcore if dts have these settings.
|
||||
* No matter clock scaling support or not. (may disable by customer)
|
||||
*/
|
||||
reg = devm_regulator_get_optional(dev, "dvfsrc-vcore");
|
||||
if (IS_ERR(reg)) {
|
||||
dev_info(dev, "failed to get dvfsrc-vcore: %ld",
|
||||
PTR_ERR(reg));
|
||||
return;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(dev->of_node, "clk-scale-up-vcore-min",
|
||||
&volt)) {
|
||||
dev_info(dev, "failed to get clk-scale-up-vcore-min");
|
||||
return;
|
||||
}
|
||||
|
||||
host->mclk.reg_vcore = reg;
|
||||
host->mclk.vcore_volt = volt;
|
||||
|
||||
/* If default boot is max gear, request vcore */
|
||||
if (reg && volt && host->clk_scale_up) {
|
||||
if (regulator_set_voltage(reg, volt, INT_MAX)) {
|
||||
dev_info(hba->dev,
|
||||
"Failed to set vcore to %d\n", volt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1126,6 +1158,7 @@ static int ufs_mtk_init(struct ufs_hba *hba)
|
|||
|
||||
/* Enable clk scaling*/
|
||||
hba->caps |= UFSHCD_CAP_CLK_SCALING;
|
||||
host->clk_scale_up = true; /* default is max freq */
|
||||
|
||||
/* Set runtime pm delay to replace default */
|
||||
shost->rpm_autosuspend_delay = MTK_RPM_AUTOSUSPEND_DELAY_MS;
|
||||
|
|
@ -1720,6 +1753,69 @@ static void ufs_mtk_config_scaling_param(struct ufs_hba *hba,
|
|||
hba->vps->ondemand_data.downdifferential = 20;
|
||||
}
|
||||
|
||||
static void _ufs_mtk_clk_scale(struct ufs_hba *hba, bool scale_up)
|
||||
{
|
||||
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
|
||||
struct ufs_mtk_clk *mclk = &host->mclk;
|
||||
struct ufs_clk_info *clki = mclk->ufs_sel_clki;
|
||||
struct regulator *reg;
|
||||
int volt, ret = 0;
|
||||
bool clk_bind_vcore = false;
|
||||
|
||||
if (!hba->clk_scaling.is_initialized)
|
||||
return;
|
||||
|
||||
if (!clki)
|
||||
return;
|
||||
|
||||
reg = host->mclk.reg_vcore;
|
||||
volt = host->mclk.vcore_volt;
|
||||
if (reg && volt != 0)
|
||||
clk_bind_vcore = true;
|
||||
|
||||
ret = clk_prepare_enable(clki->clk);
|
||||
if (ret) {
|
||||
dev_info(hba->dev,
|
||||
"clk_prepare_enable() fail, ret: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (scale_up) {
|
||||
if (clk_bind_vcore) {
|
||||
ret = regulator_set_voltage(reg, volt, INT_MAX);
|
||||
if (ret) {
|
||||
dev_info(hba->dev,
|
||||
"Failed to set vcore to %d\n", volt);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_set_parent(clki->clk, mclk->ufs_sel_max_clki->clk);
|
||||
if (ret) {
|
||||
dev_info(hba->dev, "Failed to set clk mux, ret = %d\n",
|
||||
ret);
|
||||
}
|
||||
} else {
|
||||
ret = clk_set_parent(clki->clk, mclk->ufs_sel_min_clki->clk);
|
||||
if (ret) {
|
||||
dev_info(hba->dev, "Failed to set clk mux, ret = %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (clk_bind_vcore) {
|
||||
ret = regulator_set_voltage(reg, 0, INT_MAX);
|
||||
if (ret) {
|
||||
dev_info(hba->dev,
|
||||
"failed to set vcore to MIN\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
clk_disable_unprepare(clki->clk);
|
||||
}
|
||||
|
||||
/**
|
||||
* ufs_mtk_clk_scale - Internal clk scaling operation
|
||||
*
|
||||
|
|
@ -1737,30 +1833,23 @@ static void ufs_mtk_clk_scale(struct ufs_hba *hba, bool scale_up)
|
|||
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
|
||||
struct ufs_mtk_clk *mclk = &host->mclk;
|
||||
struct ufs_clk_info *clki = mclk->ufs_sel_clki;
|
||||
int ret = 0;
|
||||
|
||||
ret = clk_prepare_enable(clki->clk);
|
||||
if (ret) {
|
||||
dev_info(hba->dev,
|
||||
"clk_prepare_enable() fail, ret: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
if (host->clk_scale_up == scale_up)
|
||||
goto out;
|
||||
|
||||
if (scale_up) {
|
||||
ret = clk_set_parent(clki->clk, mclk->ufs_sel_max_clki->clk);
|
||||
if (scale_up)
|
||||
_ufs_mtk_clk_scale(hba, true);
|
||||
else
|
||||
_ufs_mtk_clk_scale(hba, false);
|
||||
|
||||
host->clk_scale_up = scale_up;
|
||||
|
||||
/* Must always set before clk_set_rate() */
|
||||
if (scale_up)
|
||||
clki->curr_freq = clki->max_freq;
|
||||
} else {
|
||||
ret = clk_set_parent(clki->clk, mclk->ufs_sel_min_clki->clk);
|
||||
else
|
||||
clki->curr_freq = clki->min_freq;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
dev_info(hba->dev,
|
||||
"Failed to set ufs_sel_clki, ret: %d\n", ret);
|
||||
}
|
||||
|
||||
clk_disable_unprepare(clki->clk);
|
||||
|
||||
out:
|
||||
trace_ufs_mtk_clk_scale(clki->name, scale_up, clk_get_rate(clki->clk));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,8 @@ struct ufs_mtk_clk {
|
|||
struct ufs_clk_info *ufs_sel_clki; /* Mux */
|
||||
struct ufs_clk_info *ufs_sel_max_clki; /* Max src */
|
||||
struct ufs_clk_info *ufs_sel_min_clki; /* Min src */
|
||||
struct regulator *reg_vcore;
|
||||
int vcore_volt;
|
||||
};
|
||||
|
||||
struct ufs_mtk_hw_ver {
|
||||
|
|
@ -178,6 +180,7 @@ struct ufs_mtk_host {
|
|||
bool mphy_powered_on;
|
||||
bool unipro_lpm;
|
||||
bool ref_clk_enabled;
|
||||
bool clk_scale_up;
|
||||
u16 ref_clk_ungating_wait_us;
|
||||
u16 ref_clk_gating_wait_us;
|
||||
u32 ip_ver;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user