ufs: host: mediatek: Provide features and fixes in MediaTek platforms
[email protected]
maintainerv3 cover ufs: host: mediatek: Provide features and fixes in MediaTek platforms
From: Peter Wang <[email protected]>
This series fixes some defects and provide features in MediaTek UFS drivers.
Changes since v2:
1. Remove unnecessary parentheses in patch:
ufs: host: mediatek: Remove unnecessary boolean conversion and
parentheses
2. Fix comment or patch description in patch:
ufs: host: mediatek: Add DDR_EN setting
ufs: host: mediatek: Set IRQ affinity policy for MCQ mode
Peter Wang (7):
ufs: host: mediatek: Remove unnecessary boolean conversion and
parentheses
ufs: host: mediatek: Change ref-clk timeout policy
ufs: host: mediatek: Handle broken RTC based on DTS setting
ufs: host: mediatek: Set IRQ affinity policy for MCQ mode
ufs: host: mediatek: Add clock scaling query function
ufs: host: mediatek: Support clock scaling with Vcore binding
ufs: host: mediatek: Support FDE (AES) clock scaling
Naomi Chu (1):
ufs: host: mediatek: Add DDR_EN setting
Alice Chao (1):
ufs: host: mediatek: Add more UFSCHI hardware versions
drivers/ufs/host/ufs-mediatek.c | 329 ++++++++++++++++++++++++++++---- drivers/ufs/host/ufs-mediatek.h | 32 ++++ 2 files changed, 328 insertions(+), 33 deletions(-)
Signature · 1 line
2.45.2
[email protected]
maintainerPATCH v3 1/9 ufs: host: mediatek: Remove unnecessary boolean conversion and parentheses
From: Peter Wang <[email protected]>
This patch removes unnecessary boolean conversions and parentheses to ensure consistency with other usages in ufs-mediatek.c. The changes simplify the code by directly returning the result of bitwise operations without converting them to boolean values or using extra parentheses.
--- drivers/ufs/host/ufs-mediatek.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/ufs/host/ufs-mediatek.c +7 -7
@@ -96,49 +96,49 @@ static bool ufs_mtk_is_boost_crypt_enabled(struct ufs_hba *hba) {struct ufs_mtk_host *host =ufshcd_get_variant (hba); -return !!(host->caps &UFS_MTK_CAP_BOOST_CRYPT_ENGINE ); +return host->caps &UFS_MTK_CAP_BOOST_CRYPT_ENGINE ; }static bool ufs_mtk_is_va09_supported (struct ufs_hba *hba) {struct ufs_mtk_host *host =ufshcd_get_variant (hba); -return !!(host->caps &UFS_MTK_CAP_VA09_PWR_CTRL ); +return host->caps &UFS_MTK_CAP_VA09_PWR_CTRL ; }static bool ufs_mtk_is_broken_vcc (struct ufs_hba *hba) {struct ufs_mtk_host *host =ufshcd_get_variant (hba); -return !!(host->caps &UFS_MTK_CAP_BROKEN_VCC ); +return host->caps &UFS_MTK_CAP_BROKEN_VCC ; }static bool ufs_mtk_is_pmc_via_fastauto (struct ufs_hba *hba) {struct ufs_mtk_host *host =ufshcd_get_variant (hba); -return !!(host->caps &UFS_MTK_CAP_PMC_VIA_FASTAUTO ); +return host->caps &UFS_MTK_CAP_PMC_VIA_FASTAUTO ; }static bool ufs_mtk_is_tx_skew_fix (struct ufs_hba *hba) {struct ufs_mtk_host *host =ufshcd_get_variant (hba); -return (host->caps &UFS_MTK_CAP_TX_SKEW_FIX ); +return host->caps &UFS_MTK_CAP_TX_SKEW_FIX ; }static bool ufs_mtk_is_rtff_mtcmos (struct ufs_hba *hba) {struct ufs_mtk_host *host =ufshcd_get_variant (hba); -return (host->caps &UFS_MTK_CAP_RTFF_MTCMOS ); +return host->caps &UFS_MTK_CAP_RTFF_MTCMOS ; }static bool ufs_mtk_is_allow_vccqx_lpm (struct ufs_hba *hba) {struct ufs_mtk_host *host =ufshcd_get_variant (hba); -return (host->caps &UFS_MTK_CAP_ALLOW_VCCQX_LPM ); +return host->caps &UFS_MTK_CAP_ALLOW_VCCQX_LPM ; }static void ufs_mtk_cfg_unipro_cg (struct ufs_hba *hba,bool enable)
Signature · 1 line
2.45.2
Re: [PATCH v3 1/9] ufs: host: mediatek: Remove unnecessary boolean conversion and parentheses
Quoted 3 lines · On 7/21/25 1:35 AM, [email protected] wrote:
The changes
simplify the code by directly returning the result of bitwise operations without converting them to boolean values or using extra parentheses.
The code changes look good to me but the description of this patch does not. The conversion from unsigned int to boolean still happens with this patch applied. This patch converts an explicit conversion into an implicit conversion.
Thanks,
Bart.
Peter Wang (王信友)
maintainerRe: [PATCH v3 1/9] ufs: host: mediatek: Remove unnecessary boolean conversion and parentheses
Quoted 11 lines · Bart Van Assche
The code changes look good to me but the description of this patch does
not. The conversion from unsigned int to boolean still happens with this patch applied. This patch converts an explicit conversion into an
implicit conversion.Thanks,
Bart.
Hi Bart,
Okay, I will revise the commit message.
Thanks.
Peter
[email protected]
maintainerPATCH v3 2/9 ufs: host: mediatek: Add DDR_EN setting
In reply to [email protected]From: Naomi Chu <[email protected]>
On MT6989 and later platforms, control of DDR_EN has been switched from SPM to EMI. To prevent abnormal access to DRAM, it is necessary to wait for 'ddren_ack' or assert 'ddren_urgent' after sending 'ddren_req'.
This patch introduces the DDR_EN configuration in the UFS initialization flow, utilizing the assertion of 'ddren_urgent' to maintain performance.
--- drivers/ufs/host/ufs-mediatek.c | 7 +++++++ drivers/ufs/host/ufs-mediatek.h | 12 ++++++++++++ 2 files changed, 19 insertions(+)
drivers/ufs/host/ufs-mediatek.c +7 -0
@@ -267,6 +267,13 @@ static int ufs_mtk_hce_enable_notify(struct ufs_hba *hba,ufshcd_writel (hba,ufshcd_readl (hba,REG_UFS_XOUFS_CTRL ) |0x80 ,REG_UFS_XOUFS_CTRL ); + +/* DDR_EN setting */ +if (host->ip_ver >=IP_VER_MT6989 ) { +ufshcd_rmwl (hba,UFS_MASK (0x7FFF ,8 ), +0x453000 ,REG_UFS_MMIO_OPT_CTRL_0 ); + } + }return 0 ;
drivers/ufs/host/ufs-mediatek.h +12 -0
@@ -192,4 +192,16 @@ struct ufs_mtk_host {/* MTK RTT support number */ #define MTK_MAX_NUM_RTT 2 +/* UFSHCI MTK ip version value */ +enum { +/* UFSHCI 3.1 */ +IP_VER_MT6878 =0x10420200 , + +/* UFSHCI 4.0 */ +IP_VER_MT6897 =0x10440000 , +IP_VER_MT6989 =0x10450000 , + +IP_VER_NONE =0xFFFFFFFF +}; +#endif /* !_UFS_MEDIATEK_H */
Signature · 1 line
2.45.2
[email protected]
maintainerPATCH v3 3/9 ufs: host: mediatek: Change ref-clk timeout policy
In reply to [email protected]From: Peter Wang <[email protected]>
This patch updates the timeout policy for ref-clk control.
- If a clock-on operation times out, it is assumed that the clock is off. The system will notify TFA to perform clock-off settings.
- If a clock-off operation times out, it is assumed that the clock will eventually turn off. The 'ref_clk_enabled' flag is set directly.
--- drivers/ufs/host/ufs-mediatek.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/ufs/host/ufs-mediatek.c +10 -1
@@ -351,7 +351,16 @@ static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on)dev_err (hba->dev,"missing ack of refclk req, reg: 0x%x\n" , value); -ufs_mtk_ref_clk_notify (host->ref_clk_enabled,POST_CHANGE , res); +/* +* If clock on timeout, assume clock is off, notify tfa do clock +* off setting.(keep DIFN disable, release resource) +* If clock off timeout, assume clock will off finally, +* set ref_clk_enabled directly.(keep DIFN disable, keep resource) +*/ +if (on) +ufs_mtk_ref_clk_notify (false,POST_CHANGE , res); +else + host->ref_clk_enabled = false;return -ETIMEDOUT ;
Signature · 1 line
2.45.2
[email protected]
maintainerPATCH v3 4/9 ufs: host: mediatek: Handle broken RTC based on DTS setting
In reply to [email protected]From: Peter Wang <[email protected]>
This patch introduces a mechanism to handle broken RTC by checking the DTS setting. The configuration is specifically required for legacy platform.
--- drivers/ufs/host/ufs-mediatek.c | 8 +++++++- drivers/ufs/host/ufs-mediatek.h | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-)
drivers/ufs/host/ufs-mediatek.c +7 -1
@@ -679,6 +679,9 @@ static void ufs_mtk_init_host_caps(struct ufs_hba *hba)if (of_property_read_bool (np,"mediatek,ufs-rtff-mtcmos" )) host->caps |=UFS_MTK_CAP_RTFF_MTCMOS ; +if (of_property_read_bool (np,"mediatek,ufs-broken-rtc" )) + host->caps |=UFS_MTK_CAP_MCQ_BROKEN_RTC ; +dev_info (hba->dev,"caps: 0x%x" , host->caps); }
@@ -1035,8 +1038,11 @@ static int ufs_mtk_init(struct ufs_hba *hba) shost->rpm_autosuspend_delay =MTK_RPM_AUTOSUSPEND_DELAY_MS ; hba->quirks |=UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL ; + hba->quirks |=UFSHCD_QUIRK_MCQ_BROKEN_INTR ; - hba->quirks |=UFSHCD_QUIRK_MCQ_BROKEN_RTC ; +if (host->caps &UFS_MTK_CAP_MCQ_BROKEN_RTC ) + hba->quirks |=UFSHCD_QUIRK_MCQ_BROKEN_RTC ; + hba->vps->wb_flush_threshold =UFS_WB_BUF_REMAIN_PERCENT (80 );if (host->caps &UFS_MTK_CAP_DISABLE_AH8 )
drivers/ufs/host/ufs-mediatek.h +2 -0
@@ -133,6 +133,8 @@ enum ufs_mtk_host_caps {UFS_MTK_CAP_DISABLE_MCQ =1 <<8 ,/* Control MTCMOS with RTFF */ UFS_MTK_CAP_RTFF_MTCMOS =1 <<9 , + + UFS_MTK_CAP_MCQ_BROKEN_RTC = 1 << 10, }; struct ufs_mtk_crypt_cfg {
Signature · 1 line
2.45.2
[email protected]
maintainerPATCH v3 5/9 ufs: host: mediatek: Set IRQ affinity policy for MCQ mode
In reply to [email protected]From: Peter Wang <[email protected]>
This patch sets the IRQ affinity for MCQ mode to improve performance. Specifically, it migrates the IRQ from CPU0 to CPU3 to enhance IRQ handling efficiency.
Setting IRQ affinity directly from the kernel allows the configuration to take effect earlier, and provides greater security and consistency, especially important for systems with strict performanceor real-time requirements.
--- drivers/ufs/host/ufs-mediatek.c | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
drivers/ufs/host/ufs-mediatek.c +47 -0
@@ -798,6 +798,46 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on,return ret; } +static u32 ufs_mtk_mcq_get_irq (struct ufs_hba *hba,unsigned int cpu) +{ +struct ufs_mtk_host *host =ufshcd_get_variant (hba); +struct blk_mq_tag_set *tag_set = &hba->host->tag_set; +struct blk_mq_queue_map *map = &tag_set->map[HCTX_TYPE_DEFAULT ]; +unsigned int nr = map->nr_queues; +unsigned int q_index; + + q_index = map->mq_map[cpu]; +if (q_index > nr) { +dev_err (hba->dev,"hwq index %d exceed %d\n" , + q_index, nr); +return MTK_MCQ_INVALID_IRQ ; + } + +return host->mcq_intr_info[q_index].irq; +} + +static void ufs_mtk_mcq_set_irq_affinity (struct ufs_hba *hba,unsigned int cpu) +{ +unsigned int irq, _cpu; +int ret; + + irq =ufs_mtk_mcq_get_irq (hba, cpu); +if (irq ==MTK_MCQ_INVALID_IRQ ) { +dev_err (hba->dev,"invalid irq. unable to bind irq to cpu%d" , cpu); +return ; + } + +/* force migrate irq of cpu0 to cpu3 */ + _cpu = (cpu ==0 ) ?3 : cpu; + ret =irq_set_affinity (irq,cpumask_of (_cpu)); +if (ret) { +dev_err (hba->dev,"set irq %d affinity to CPU %d failed\n" , + irq, _cpu); +return ; + } +dev_info (hba->dev,"set irq %d affinity to CPU: %d\n" , irq, _cpu); +} +static void ufs_mtk_get_controller_version (struct ufs_hba *hba) {struct ufs_mtk_host *host =ufshcd_get_variant (hba);
@@ -1527,6 +1567,13 @@ static int ufs_mtk_apply_dev_quirks(struct ufs_hba *hba) {struct ufs_dev_info *dev_info = &hba->dev_info;u16 mid = dev_info->wmanufacturerid; +unsigned int cpu; + +if (hba->mcq_enabled) { +/* Iterate all cpus to set affinity for mcq irqs */ +for (cpu =0 ; cpu < nr_cpu_ids; cpu++) +ufs_mtk_mcq_set_irq_affinity (hba, cpu); + }if (mid ==UFS_VENDOR_SAMSUNG ) {ufshcd_dme_set (hba,UIC_ARG_MIB (PA_TACTIVATE ),6 );
Signature · 1 line
2.45.2
[email protected]
maintainerPATCH v3 6/9 ufs: host: mediatek: Add more UFSCHI hardware versions
In reply to [email protected]From: Alice Chao <[email protected]>
This patch introduces a function for version control to distinguish between new and old platforms. It updates the handling of hardware IP versions, ensuring correct version comparisons by adjusting the version format for specific projects.
--- drivers/ufs/host/ufs-mediatek.c | 47 ++++++++++++++++++++++++++++++++- drivers/ufs/host/ufs-mediatek.h | 12 +++++++++ 2 files changed, 58 insertions(+), 1 deletion(-)
drivers/ufs/host/ufs-mediatek.c +46 -1
@@ -838,6 +838,51 @@ static void ufs_mtk_mcq_set_irq_affinity(struct ufs_hba *hba, unsigned int cpu)dev_info (hba->dev,"set irq %d affinity to CPU: %d\n" , irq, _cpu); } +static bool ufs_mtk_is_legacy_chipset (struct ufs_hba *hba,u32 hw_ip_ver) +{ +bool is_legacy = false; + +switch (hw_ip_ver) { +case IP_LEGACY_VER_MT6893 : +case IP_LEGACY_VER_MT6781 : +/* can add other legacy chipset ID here accordingly */ + is_legacy = true; +break ; +default : +break ; + } +dev_info (hba->dev,"legacy IP version - 0x%x, is legacy : %d" , hw_ip_ver, is_legacy); + +return is_legacy; +} + +/* +* HW version format has been changed from 01MMmmmm to 1MMMmmmm, since +* project MT6878. In order to perform correct version comparison, +* version number is changed by SW for the following projects. +* IP_VER_MT6983 0x00360000 to 0x10360000 +* IP_VER_MT6897 0x01440000 to 0x10440000 +* IP_VER_MT6989 0x01450000 to 0x10450000 +* IP_VER_MT6991 0x01460000 to 0x10460000 +*/ +static void ufs_mtk_get_hw_ip_version (struct ufs_hba *hba) +{ +struct ufs_mtk_host *host =ufshcd_get_variant (hba); +u32 hw_ip_ver; + + hw_ip_ver =ufshcd_readl (hba,REG_UFS_MTK_IP_VER ); + +if (((hw_ip_ver & (0xFF <<24 )) == (0x1 <<24 )) || + ((hw_ip_ver & (0xFF <<24 )) ==0 )) { + hw_ip_ver &= ~(0xFF <<24 ); + hw_ip_ver |= (0x1 <<28 ); + } + + host->ip_ver = hw_ip_ver; + + host->legacy_ip_ver =ufs_mtk_is_legacy_chipset (hba, hw_ip_ver); +} +static void ufs_mtk_get_controller_version (struct ufs_hba *hba) {struct ufs_mtk_host *host =ufshcd_get_variant (hba);
@@ -1112,7 +1157,7 @@ static int ufs_mtk_init(struct ufs_hba *hba)ufs_mtk_setup_clocks (hba, true,POST_CHANGE ); - host->ip_ver =ufshcd_readl (hba,REG_UFS_MTK_IP_VER ); +ufs_mtk_get_hw_ip_version (hba); goto out;
drivers/ufs/host/ufs-mediatek.h +12 -0
@@ -181,6 +181,7 @@ struct ufs_mtk_host {u16 ref_clk_ungating_wait_us;u16 ref_clk_gating_wait_us;u32 ip_ver; +bool legacy_ip_ver;bool mcq_set_intr;bool is_mcq_intr_enabled;
@@ -197,13 +198,24 @@ struct ufs_mtk_host {/* UFSHCI MTK ip version value */ enum {/* UFSHCI 3.1 */ +IP_VER_MT6983 =0x10360000 ,IP_VER_MT6878 =0x10420200 ,/* UFSHCI 4.0 */ IP_VER_MT6897 =0x10440000 ,IP_VER_MT6989 =0x10450000 , +IP_VER_MT6899 =0x10450100 , +IP_VER_MT6991_A0 =0x10460000 , +IP_VER_MT6991_B0 =0x10470000 , +IP_VER_MT6993 =0x10480000 ,IP_VER_NONE =0xFFFFFFFF }; +enum ip_ver_legacy { +IP_LEGACY_VER_MT6781 =0x10380000 , +IP_LEGACY_VER_MT6879 =0x10360000 , +IP_LEGACY_VER_MT6893 =0x20160706 +}; +#endif /* !_UFS_MEDIATEK_H */
Signature · 1 line
2.45.2
[email protected]
maintainerPATCH v3 7/9 ufs: host: mediatek: Add clock scaling query function
In reply to [email protected]From: Peter Wang <[email protected]>
This patch introduces a clock scaling readiness query function to streamline the process of checking clock scaling parameters. This function simplifies the code by encapsulating the logic for determining if clock scaling is ready.
--- drivers/ufs/host/ufs-mediatek.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
drivers/ufs/host/ufs-mediatek.c +11 -3
@@ -141,6 +141,16 @@ static bool ufs_mtk_is_allow_vccqx_lpm(struct ufs_hba *hba)return host->caps &UFS_MTK_CAP_ALLOW_VCCQX_LPM ; } +static bool ufs_mtk_is_clk_scale_ready (struct ufs_hba *hba) +{ +struct ufs_mtk_host *host =ufshcd_get_variant (hba); +struct ufs_mtk_clk *mclk = &host->mclk; + +return mclk->ufs_sel_clki && + mclk->ufs_sel_max_clki && + mclk->ufs_sel_min_clki; +} +static void ufs_mtk_cfg_unipro_cg (struct ufs_hba *hba,bool enable) {u32 tmp;
@@ -922,7 +932,6 @@ 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_mtk_clk *mclk = &host->mclk;struct ufs_clk_info *clki, *clki_tmp;/*
@@ -944,8 +953,7 @@ static void ufs_mtk_init_clocks(struct ufs_hba *hba) } } -if (!mclk->ufs_sel_clki || !mclk->ufs_sel_max_clki || - !mclk->ufs_sel_min_clki) { +if (!ufs_mtk_is_clk_scale_ready (hba)) { hba->caps &= ~UFSHCD_CAP_CLK_SCALING ; dev_info(hba->dev, "%s: Clk-scaling not ready. Feature disabled.",
Signature · 1 line
2.45.2
[email protected]
maintainerPATCH v3 8/9 ufs: host: mediatek: Support clock scaling with Vcore binding
In reply to [email protected]From: Peter Wang <[email protected]>
This patch adds support for clock scaling with Vcore binding. It includes the following changes:
1. Parses the DTS setting for Vcore voltage.
2. Sets the Vcore voltage to the DTS-specified value before scaling up.
3. Resets 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.
--- drivers/ufs/host/ufs-mediatek.c | 129 +++++++++++++++++++++++++++----- drivers/ufs/host/ufs-mediatek.h | 3 + 2 files changed, 112 insertions(+), 20 deletions(-)
drivers/ufs/host/ufs-mediatek.c +109 -20
@@ -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,24 +1753,25 @@ static void ufs_mtk_config_scaling_param(struct ufs_hba *hba, hba->vps->ondemand_data.downdifferential =20 ; } -/** -* ufs_mtk_clk_scale - Internal clk scaling operation -* -* MTK platform supports clk scaling by switching parent of ufs_sel(mux). -* The ufs_sel downstream to ufs_ck which feeds directly to UFS hardware. -* Max and min clocks rate of ufs_sel defined in dts should match rate of -* "ufs_sel_max_src" and "ufs_sel_min_src" respectively. -* This prevent changing rate of pll clock that is shared between modules. -* -* @hba: per adapter instance -* @scale_up: True for scaling up and false for scaling down -*/ -static void ufs_mtk_clk_scale (struct ufs_hba *hba,bool scale_up) +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 ; +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) {
@@ -1747,20 +1781,75 @@ static void ufs_mtk_clk_scale(struct ufs_hba *hba, bool scale_up) }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); - clki->curr_freq = clki->max_freq; +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); - clki->curr_freq = clki->min_freq; - } +if (ret) { +dev_info (hba->dev,"Failed to set clk mux, ret = %d\n" , + ret); + goto out; + } -if (ret) { -dev_info (hba->dev, -"Failed to set ufs_sel_clki, ret: %d\n" , ret); +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 +* +* MTK platform supports clk scaling by switching parent of ufs_sel(mux). +* The ufs_sel downstream to ufs_ck which feeds directly to UFS hardware. +* Max and min clocks rate of ufs_sel defined in dts should match rate of +* "ufs_sel_max_src" and "ufs_sel_min_src" respectively. +* This prevent changing rate of pll clock that is shared between modules. +* +* @hba: per adapter instance +* @scale_up: True for scaling up and false for scaling down +*/ +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; + +if (host->clk_scale_up == scale_up) + goto out; + +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 + clki->curr_freq = clki->min_freq; +out:trace_ufs_mtk_clk_scale (clki->name, scale_up,clk_get_rate (clki->clk)); }
drivers/ufs/host/ufs-mediatek.h +3 -0
@@ -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;
Signature · 1 line
2.45.2
[email protected]
maintainerPATCH v3 9/9 ufs: host: mediatek: Support FDE (AES) clock scaling
In reply to [email protected]From: Peter Wang <[email protected]>
This patch adds support for scaling the FDE (AES) clock to achieve higher performance, particularly for HS-G5. The implementation includes:
1. Parsing DTS settings for FDE min/max mux.
2. Scaling 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.
--- drivers/ufs/host/ufs-mediatek.c | 54 ++++++++++++++++++++++++++++++++- drivers/ufs/host/ufs-mediatek.h | 3 ++ 2 files changed, 56 insertions(+), 1 deletion(-)
drivers/ufs/host/ufs-mediatek.c +53 -1
@@ -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); }/**
drivers/ufs/host/ufs-mediatek.h +3 -0
@@ -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; };
Signature · 1 line
2.45.2