mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 15:12:13 +02:00
scsi: ufs: qcom: Configure SYS1CLK_1US_REG for UFS V4 and above
SYS1CLK_1US represents the required number of system 1-clock cycles for one microsecond. UFS Host Controller V4.0 and above mandates to write SYS1CLK_1US_REG register and also these timer configuration needs to be called from clk scaling pre ops as per HPG. Refactor ufs_qcom_cfg_timers and add the below code support to align with HPG. a)Configure SYS1CLK_1US_REG for UFS V4 and above. b)Introduce a new argument is_pre_scale_up for ufs_qcom_cfg_timers to configure SYS1CLK_1US for max freq during prescale and link startup condition. c)Move ufs_qcom_cfg_timers from clk scaling post change ops to clk scaling pre change ops. Co-developed-by: Naveen Kumar Goud Arepalli <quic_narepall@quicinc.com> Signed-off-by: Naveen Kumar Goud Arepalli <quic_narepall@quicinc.com> Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com> Link: https://lore.kernel.org/r/20230905052400.13935-6-quic_nitirawa@quicinc.com Reviewed-by: Can Guo <quic_cang@quicinc.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
3091181bee
commit
fd915c67cd
|
|
@ -527,11 +527,20 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
|
|||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* ufs_qcom_cfg_timers - Configure ufs qcom cfg timers
|
||||
*
|
||||
* @hba: host controller instance
|
||||
* @gear: Current operating gear
|
||||
* @hs: current power mode
|
||||
* @rate: current operating rate (A or B)
|
||||
* @update_link_startup_timer: indicate if link_start ongoing
|
||||
* @is_pre_scale_up: flag to check if pre scale up condition.
|
||||
* Return: zero for success and non-zero in case of a failure.
|
||||
*/
|
||||
static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear,
|
||||
u32 hs, u32 rate, bool update_link_startup_timer)
|
||||
u32 hs, u32 rate, bool update_link_startup_timer,
|
||||
bool is_pre_scale_up)
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
struct ufs_clk_info *clki;
|
||||
|
|
@ -562,11 +571,14 @@ static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear,
|
|||
/*
|
||||
* The Qunipro controller does not use following registers:
|
||||
* SYS1CLK_1US_REG, TX_SYMBOL_CLK_1US_REG, CLK_NS_REG &
|
||||
* UFS_REG_PA_LINK_STARTUP_TIMER
|
||||
* But UTP controller uses SYS1CLK_1US_REG register for Interrupt
|
||||
* UFS_REG_PA_LINK_STARTUP_TIMER.
|
||||
* However UTP controller uses SYS1CLK_1US_REG register for Interrupt
|
||||
* Aggregation logic.
|
||||
*/
|
||||
if (ufs_qcom_cap_qunipro(host) && !ufshcd_is_intr_aggr_allowed(hba))
|
||||
* It is mandatory to write SYS1CLK_1US_REG register on UFS host
|
||||
* controller V4.0.0 onwards.
|
||||
*/
|
||||
if (host->hw_ver.major < 4 && ufs_qcom_cap_qunipro(host) &&
|
||||
!ufshcd_is_intr_aggr_allowed(hba))
|
||||
return 0;
|
||||
|
||||
if (gear == 0) {
|
||||
|
|
@ -575,8 +587,14 @@ static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear,
|
|||
}
|
||||
|
||||
list_for_each_entry(clki, &hba->clk_list_head, list) {
|
||||
if (!strcmp(clki->name, "core_clk"))
|
||||
core_clk_rate = clk_get_rate(clki->clk);
|
||||
if (!strcmp(clki->name, "core_clk")) {
|
||||
if (is_pre_scale_up)
|
||||
core_clk_rate = clki->max_freq;
|
||||
else
|
||||
core_clk_rate = clk_get_rate(clki->clk);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* If frequency is smaller than 1MHz, set to 1MHz */
|
||||
|
|
@ -678,7 +696,7 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba,
|
|||
switch (status) {
|
||||
case PRE_CHANGE:
|
||||
if (ufs_qcom_cfg_timers(hba, UFS_PWM_G1, SLOWAUTO_MODE,
|
||||
0, true)) {
|
||||
0, true, false)) {
|
||||
dev_err(hba->dev, "%s: ufs_qcom_cfg_timers() failed\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
|
|
@ -922,7 +940,7 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
|
|||
case POST_CHANGE:
|
||||
if (ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
|
||||
dev_req_params->pwr_rx,
|
||||
dev_req_params->hs_rate, false)) {
|
||||
dev_req_params->hs_rate, false, false)) {
|
||||
dev_err(hba->dev, "%s: ufs_qcom_cfg_timers() failed\n",
|
||||
__func__);
|
||||
/*
|
||||
|
|
@ -1418,10 +1436,22 @@ static int ufs_qcom_set_core_clk_ctrl(struct ufs_hba *hba, bool is_scale_up)
|
|||
static int ufs_qcom_clk_scale_up_pre_change(struct ufs_hba *hba)
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
struct ufs_pa_layer_attr *attr = &host->dev_req_params;
|
||||
int ret;
|
||||
|
||||
if (!ufs_qcom_cap_qunipro(host))
|
||||
return 0;
|
||||
|
||||
if (attr) {
|
||||
ret = ufs_qcom_cfg_timers(hba, attr->gear_rx,
|
||||
attr->pwr_rx, attr->hs_rate,
|
||||
false, true);
|
||||
if (ret) {
|
||||
dev_err(hba->dev, "%s ufs cfg timer failed\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/* set unipro core clock attributes and clear clock divider */
|
||||
return ufs_qcom_set_core_clk_ctrl(hba, true);
|
||||
}
|
||||
|
|
@ -1471,7 +1501,6 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba,
|
|||
bool scale_up, enum ufs_notify_change_status status)
|
||||
{
|
||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||
struct ufs_pa_layer_attr *dev_req_params = &host->dev_req_params;
|
||||
int err = 0;
|
||||
|
||||
/* check the host controller state before sending hibern8 cmd */
|
||||
|
|
@ -1501,11 +1530,6 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba,
|
|||
return err;
|
||||
}
|
||||
|
||||
ufs_qcom_cfg_timers(hba,
|
||||
dev_req_params->gear_rx,
|
||||
dev_req_params->pwr_rx,
|
||||
dev_req_params->hs_rate,
|
||||
false);
|
||||
ufs_qcom_icc_update_bw(host);
|
||||
ufshcd_uic_hibern8_exit(hba);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user