]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
scsi: ufs: host: mediatek: Support FDE (AES) clock scaling
authorPeter Wang <peter.wang@mediatek.com>
Tue, 22 Jul 2025 03:07:24 +0000 (11:07 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 25 Jul 2025 02:20:10 +0000 (22:20 -0400)
Add support for scaling the FDE (AES) clock to achieve higher
performance, particularly for HS-G5:

 1. Parse DTS settings for FDE min/max mux.

 2. Scale up the FDE clock when required for enhanced performance.

These changes ensure that the FDE clock can be dynamically adjusted based
on performance needs, leveraging DTS configurations.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Link: https://lore.kernel.org/r/20250722030841.1998783-10-peter.wang@mediatek.com
Reviewed-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/ufs/host/ufs-mediatek.c
drivers/ufs/host/ufs-mediatek.h

index a0c53d796a60267ad85175d0d471adbd8ef41208..91a2f3428b9f7b28b6b3ddf308455123a8de1fad 100644 (file)
@@ -953,9 +953,23 @@ static void ufs_mtk_init_clocks(struct ufs_hba *hba)
                        host->mclk.ufs_sel_min_clki = clki;
                        clk_disable_unprepare(clki->clk);
                        list_del(&clki->list);
+               } else if (!strcmp(clki->name, "ufs_fde")) {
+                       host->mclk.ufs_fde_clki = clki;
+               } else if (!strcmp(clki->name, "ufs_fde_max_src")) {
+                       host->mclk.ufs_fde_max_clki = clki;
+                       clk_disable_unprepare(clki->clk);
+                       list_del(&clki->list);
+               } else if (!strcmp(clki->name, "ufs_fde_min_src")) {
+                       host->mclk.ufs_fde_min_clki = clki;
+                       clk_disable_unprepare(clki->clk);
+                       list_del(&clki->list);
                }
        }
 
+       list_for_each_entry(clki, head, list) {
+               dev_info(hba->dev, "clk \"%s\" present", clki->name);
+       }
+
        if (!ufs_mtk_is_clk_scale_ready(hba)) {
                hba->caps &= ~UFSHCD_CAP_CLK_SCALING;
                dev_info(hba->dev,
@@ -1758,14 +1772,16 @@ 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 ufs_clk_info *fde_clki = mclk->ufs_fde_clki;
        struct regulator *reg;
        int volt, ret = 0;
        bool clk_bind_vcore = false;
+       bool clk_fde_scale = false;
 
        if (!hba->clk_scaling.is_initialized)
                return;
 
-       if (!clki)
+       if (!clki || !fde_clki)
                return;
 
        reg = host->mclk.reg_vcore;
@@ -1773,6 +1789,9 @@ static void _ufs_mtk_clk_scale(struct ufs_hba *hba, bool scale_up)
        if (reg && volt != 0)
                clk_bind_vcore = true;
 
+       if (mclk->ufs_fde_max_clki && mclk->ufs_fde_min_clki)
+               clk_fde_scale = true;
+
        ret = clk_prepare_enable(clki->clk);
        if (ret) {
                dev_info(hba->dev,
@@ -1780,6 +1799,15 @@ static void _ufs_mtk_clk_scale(struct ufs_hba *hba, bool scale_up)
                return;
        }
 
+       if (clk_fde_scale) {
+               ret = clk_prepare_enable(fde_clki->clk);
+               if (ret) {
+                       dev_info(hba->dev,
+                                "fde clk_prepare_enable() fail, ret: %d\n", ret);
+                       return;
+               }
+       }
+
        if (scale_up) {
                if (clk_bind_vcore) {
                        ret = regulator_set_voltage(reg, volt, INT_MAX);
@@ -1795,7 +1823,28 @@ static void _ufs_mtk_clk_scale(struct ufs_hba *hba, bool scale_up)
                        dev_info(hba->dev, "Failed to set clk mux, ret = %d\n",
                                ret);
                }
+
+               if (clk_fde_scale) {
+                       ret = clk_set_parent(fde_clki->clk,
+                               mclk->ufs_fde_max_clki->clk);
+                       if (ret) {
+                               dev_info(hba->dev,
+                                       "Failed to set fde clk mux, ret = %d\n",
+                                       ret);
+                       }
+               }
        } else {
+               if (clk_fde_scale) {
+                       ret = clk_set_parent(fde_clki->clk,
+                               mclk->ufs_fde_min_clki->clk);
+                       if (ret) {
+                               dev_info(hba->dev,
+                                       "Failed to set fde clk mux, ret = %d\n",
+                                       ret);
+                               goto out;
+                       }
+               }
+
                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",
@@ -1814,6 +1863,9 @@ static void _ufs_mtk_clk_scale(struct ufs_hba *hba, bool scale_up)
 
 out:
        clk_disable_unprepare(clki->clk);
+
+       if (clk_fde_scale)
+               clk_disable_unprepare(fde_clki->clk);
 }
 
 /**
index 0b25ce5aa8368c09c28dfefbddca3304ff5aa37f..e46dc5fa209dd913e72b9b34c20e42889d62b1c4 100644 (file)
@@ -149,6 +149,9 @@ 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 ufs_clk_info *ufs_fde_clki; /* Mux */
+       struct ufs_clk_info *ufs_fde_max_clki; /* Max src */
+       struct ufs_clk_info *ufs_fde_min_clki; /* Min src */
        struct regulator *reg_vcore;
        int vcore_volt;
 };