Skip to content

Commit 31a20e9

Browse files
ptr324martinkpetersen
authored andcommitted
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Chun-Hung Wu <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent ff40f31 commit 31a20e9

File tree

2 files changed

+112
-20
lines changed

2 files changed

+112
-20
lines changed

drivers/ufs/host/ufs-mediatek.c

Lines changed: 109 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,9 @@ static void ufs_mtk_init_clocks(struct ufs_hba *hba)
933933
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
934934
struct list_head *head = &hba->clk_list_head;
935935
struct ufs_clk_info *clki, *clki_tmp;
936+
struct device *dev = hba->dev;
937+
struct regulator *reg;
938+
u32 volt;
936939

937940
/*
938941
* 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)
958961
dev_info(hba->dev,
959962
"%s: Clk-scaling not ready. Feature disabled.",
960963
__func__);
964+
return;
965+
}
966+
967+
/*
968+
* Default get vcore if dts have these settings.
969+
* No matter clock scaling support or not. (may disable by customer)
970+
*/
971+
reg = devm_regulator_get_optional(dev, "dvfsrc-vcore");
972+
if (IS_ERR(reg)) {
973+
dev_info(dev, "failed to get dvfsrc-vcore: %ld",
974+
PTR_ERR(reg));
975+
return;
976+
}
977+
978+
if (of_property_read_u32(dev->of_node, "clk-scale-up-vcore-min",
979+
&volt)) {
980+
dev_info(dev, "failed to get clk-scale-up-vcore-min");
981+
return;
982+
}
983+
984+
host->mclk.reg_vcore = reg;
985+
host->mclk.vcore_volt = volt;
986+
987+
/* If default boot is max gear, request vcore */
988+
if (reg && volt && host->clk_scale_up) {
989+
if (regulator_set_voltage(reg, volt, INT_MAX)) {
990+
dev_info(hba->dev,
991+
"Failed to set vcore to %d\n", volt);
992+
}
961993
}
962994
}
963995

@@ -1126,6 +1158,7 @@ static int ufs_mtk_init(struct ufs_hba *hba)
11261158

11271159
/* Enable clk scaling*/
11281160
hba->caps |= UFSHCD_CAP_CLK_SCALING;
1161+
host->clk_scale_up = true; /* default is max freq */
11291162

11301163
/* Set runtime pm delay to replace default */
11311164
shost->rpm_autosuspend_delay = MTK_RPM_AUTOSUSPEND_DELAY_MS;
@@ -1720,24 +1753,25 @@ static void ufs_mtk_config_scaling_param(struct ufs_hba *hba,
17201753
hba->vps->ondemand_data.downdifferential = 20;
17211754
}
17221755

1723-
/**
1724-
* ufs_mtk_clk_scale - Internal clk scaling operation
1725-
*
1726-
* MTK platform supports clk scaling by switching parent of ufs_sel(mux).
1727-
* The ufs_sel downstream to ufs_ck which feeds directly to UFS hardware.
1728-
* Max and min clocks rate of ufs_sel defined in dts should match rate of
1729-
* "ufs_sel_max_src" and "ufs_sel_min_src" respectively.
1730-
* This prevent changing rate of pll clock that is shared between modules.
1731-
*
1732-
* @hba: per adapter instance
1733-
* @scale_up: True for scaling up and false for scaling down
1734-
*/
1735-
static void ufs_mtk_clk_scale(struct ufs_hba *hba, bool scale_up)
1756+
static void _ufs_mtk_clk_scale(struct ufs_hba *hba, bool scale_up)
17361757
{
17371758
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
17381759
struct ufs_mtk_clk *mclk = &host->mclk;
17391760
struct ufs_clk_info *clki = mclk->ufs_sel_clki;
1740-
int ret = 0;
1761+
struct regulator *reg;
1762+
int volt, ret = 0;
1763+
bool clk_bind_vcore = false;
1764+
1765+
if (!hba->clk_scaling.is_initialized)
1766+
return;
1767+
1768+
if (!clki)
1769+
return;
1770+
1771+
reg = host->mclk.reg_vcore;
1772+
volt = host->mclk.vcore_volt;
1773+
if (reg && volt != 0)
1774+
clk_bind_vcore = true;
17411775

17421776
ret = clk_prepare_enable(clki->clk);
17431777
if (ret) {
@@ -1747,20 +1781,75 @@ static void ufs_mtk_clk_scale(struct ufs_hba *hba, bool scale_up)
17471781
}
17481782

17491783
if (scale_up) {
1784+
if (clk_bind_vcore) {
1785+
ret = regulator_set_voltage(reg, volt, INT_MAX);
1786+
if (ret) {
1787+
dev_info(hba->dev,
1788+
"Failed to set vcore to %d\n", volt);
1789+
goto out;
1790+
}
1791+
}
1792+
17501793
ret = clk_set_parent(clki->clk, mclk->ufs_sel_max_clki->clk);
1751-
clki->curr_freq = clki->max_freq;
1794+
if (ret) {
1795+
dev_info(hba->dev, "Failed to set clk mux, ret = %d\n",
1796+
ret);
1797+
}
17521798
} else {
17531799
ret = clk_set_parent(clki->clk, mclk->ufs_sel_min_clki->clk);
1754-
clki->curr_freq = clki->min_freq;
1755-
}
1800+
if (ret) {
1801+
dev_info(hba->dev, "Failed to set clk mux, ret = %d\n",
1802+
ret);
1803+
goto out;
1804+
}
17561805

1757-
if (ret) {
1758-
dev_info(hba->dev,
1759-
"Failed to set ufs_sel_clki, ret: %d\n", ret);
1806+
if (clk_bind_vcore) {
1807+
ret = regulator_set_voltage(reg, 0, INT_MAX);
1808+
if (ret) {
1809+
dev_info(hba->dev,
1810+
"failed to set vcore to MIN\n");
1811+
}
1812+
}
17601813
}
17611814

1815+
out:
17621816
clk_disable_unprepare(clki->clk);
1817+
}
1818+
1819+
/**
1820+
* ufs_mtk_clk_scale - Internal clk scaling operation
1821+
*
1822+
* MTK platform supports clk scaling by switching parent of ufs_sel(mux).
1823+
* The ufs_sel downstream to ufs_ck which feeds directly to UFS hardware.
1824+
* Max and min clocks rate of ufs_sel defined in dts should match rate of
1825+
* "ufs_sel_max_src" and "ufs_sel_min_src" respectively.
1826+
* This prevent changing rate of pll clock that is shared between modules.
1827+
*
1828+
* @hba: per adapter instance
1829+
* @scale_up: True for scaling up and false for scaling down
1830+
*/
1831+
static void ufs_mtk_clk_scale(struct ufs_hba *hba, bool scale_up)
1832+
{
1833+
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
1834+
struct ufs_mtk_clk *mclk = &host->mclk;
1835+
struct ufs_clk_info *clki = mclk->ufs_sel_clki;
1836+
1837+
if (host->clk_scale_up == scale_up)
1838+
goto out;
1839+
1840+
if (scale_up)
1841+
_ufs_mtk_clk_scale(hba, true);
1842+
else
1843+
_ufs_mtk_clk_scale(hba, false);
17631844

1845+
host->clk_scale_up = scale_up;
1846+
1847+
/* Must always set before clk_set_rate() */
1848+
if (scale_up)
1849+
clki->curr_freq = clki->max_freq;
1850+
else
1851+
clki->curr_freq = clki->min_freq;
1852+
out:
17641853
trace_ufs_mtk_clk_scale(clki->name, scale_up, clk_get_rate(clki->clk));
17651854
}
17661855

drivers/ufs/host/ufs-mediatek.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ struct ufs_mtk_clk {
149149
struct ufs_clk_info *ufs_sel_clki; /* Mux */
150150
struct ufs_clk_info *ufs_sel_max_clki; /* Max src */
151151
struct ufs_clk_info *ufs_sel_min_clki; /* Min src */
152+
struct regulator *reg_vcore;
153+
int vcore_volt;
152154
};
153155

154156
struct ufs_mtk_hw_ver {
@@ -178,6 +180,7 @@ struct ufs_mtk_host {
178180
bool mphy_powered_on;
179181
bool unipro_lpm;
180182
bool ref_clk_enabled;
183+
bool clk_scale_up;
181184
u16 ref_clk_ungating_wait_us;
182185
u16 ref_clk_gating_wait_us;
183186
u32 ip_ver;

0 commit comments

Comments
 (0)