Commit fd915c67 authored by Nitin Rawat's avatar Nitin Rawat Committed by Martin K. Petersen

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: default avatarNaveen Kumar Goud Arepalli <quic_narepall@quicinc.com>
Signed-off-by: default avatarNaveen Kumar Goud Arepalli <quic_narepall@quicinc.com>
Signed-off-by: default avatarNitin Rawat <quic_nitirawa@quicinc.com>
Link: https://lore.kernel.org/r/20230905052400.13935-6-quic_nitirawa@quicinc.comReviewed-by: default avatarCan Guo <quic_cang@quicinc.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 3091181b
......@@ -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);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment