mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
scsi: ufs: Add workaround to bypass cfgready signal for UFS gear4
The tx_cfg_rdy signal from PHY to Controller to indicate EOB(END OF BURST) runs using TX CFG clock which is half the Uniproclk freq. But it is observed that tx_cfg_rdyn signal is getting sampled in controller using Uniproclk (300 MHz) instead of TX CFG clock (150 MHz) and hence FSM in controller is going into unwanted state when only one of tx_cfg_rdyn_0 and tx_cfg_rdyn_1 is 0 around sampling clock edge. To workaround this issue, control should bypass the Cfgready signal(TX_CFGREADY and RX_CFGREDY) because controller stills wait for another signal tx_savestatusn which will serve same purpose. Change-Id: I2f32542682571ba6e7b1266393dfb1168dc68658 Signed-off-by: Nitin Rawat <nitirawa@codeaurora.org>
This commit is contained in:
parent
d8534164bb
commit
977028c755
2 changed files with 85 additions and 3 deletions
|
|
@ -81,7 +81,7 @@ static int ufs_qcom_init_sysfs(struct ufs_hba *hba);
|
|||
static int ufs_qcom_update_qos_constraints(struct qos_cpu_group *qcg,
|
||||
enum constraint type);
|
||||
static int ufs_qcom_unvote_qos_all(struct ufs_hba *hba);
|
||||
|
||||
static void ufs_qcom_parse_g4_workaround_flag(struct ufs_qcom_host *host);
|
||||
static int ufs_qcom_get_pwr_dev_param(struct ufs_qcom_dev_params *qcom_param,
|
||||
struct ufs_pa_layer_attr *dev_max,
|
||||
struct ufs_pa_layer_attr *agreed_pwr)
|
||||
|
|
@ -813,6 +813,61 @@ static int ufs_qcom_set_dme_vs_core_clk_ctrl_max_freq_mode(struct ufs_hba *hba)
|
|||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufs_qcom_bypass_cfgready_signal - Tunes PA_VS_CONFIG_REG1 and
|
||||
* PA_VS_CONFIG_REG2 vendor specific attributes of local unipro
|
||||
* to bypass CFGREADY signal on Config interface between UFS
|
||||
* controller and PHY.
|
||||
*
|
||||
* The issue is related to config signals sampling from PHY
|
||||
* to controller. The PHY signals which are driven by 150MHz
|
||||
* clock and sampled by 300MHz instead of 150MHZ.
|
||||
*
|
||||
* The issue will be seen when only one of tx_cfg_rdyn_0
|
||||
* and tx_cfg_rdyn_1 is 0 around sampling clock edge and
|
||||
* if timing is not met as timing margin for some devices is
|
||||
* very less in one of the corner.
|
||||
*
|
||||
* To workaround this issue, controller should bypass the Cfgready
|
||||
* signal(TX_CFGREADY and RX_CFGREDY) because controller still wait
|
||||
* for another signal tx_savestatusn which will serve same purpose.
|
||||
*
|
||||
* The corresponding HW CR: 'QCTDD06985523' UFS HSG4 test fails
|
||||
* in SDF MAX GLS is linked to this issue.
|
||||
*/
|
||||
static int ufs_qcom_bypass_cfgready_signal(struct ufs_hba *hba)
|
||||
{
|
||||
int err = 0;
|
||||
u32 pa_vs_config_reg1;
|
||||
u32 pa_vs_config_reg2;
|
||||
u32 mask;
|
||||
|
||||
err = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_VS_CONFIG_REG1),
|
||||
&pa_vs_config_reg1);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_VS_CONFIG_REG1),
|
||||
(pa_vs_config_reg1 | BIT_TX_EOB_COND));
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_VS_CONFIG_REG2),
|
||||
&pa_vs_config_reg2);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
mask = (BIT_RX_EOB_COND | BIT_LINKCFG_WAIT_LL1_RX_CFG_RDY |
|
||||
H8_ENTER_COND_MASK);
|
||||
pa_vs_config_reg2 = (pa_vs_config_reg2 & ~mask) |
|
||||
(0x2 << H8_ENTER_COND_OFFSET);
|
||||
|
||||
err = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_VS_CONFIG_REG2),
|
||||
(pa_vs_config_reg2));
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ufs_qcom_link_startup_notify(struct ufs_hba *hba,
|
||||
enum ufs_notify_change_status status)
|
||||
{
|
||||
|
|
@ -853,6 +908,9 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba,
|
|||
err = ufshcd_disable_host_tx_lcc(hba);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (host->bypass_g4_cfgready)
|
||||
err = ufs_qcom_bypass_cfgready_signal(hba);
|
||||
break;
|
||||
case POST_CHANGE:
|
||||
ufs_qcom_link_startup_post_change(hba);
|
||||
|
|
@ -2602,6 +2660,7 @@ static int ufs_qcom_init(struct ufs_hba *hba)
|
|||
|
||||
ufs_qcom_parse_pm_level(hba);
|
||||
ufs_qcom_parse_limits(host);
|
||||
ufs_qcom_parse_g4_workaround_flag(host);
|
||||
ufs_qcom_parse_lpm(host);
|
||||
if (host->disable_lpm)
|
||||
pm_runtime_forbid(host->hba->dev);
|
||||
|
|
@ -3180,6 +3239,20 @@ static void ufs_qcom_parse_limits(struct ufs_qcom_host *host)
|
|||
of_property_read_u32(np, "limit-phy-submode", &host->limit_phy_submode);
|
||||
}
|
||||
|
||||
/*
|
||||
* ufs_qcom_parse_g4_workaround_flag - read bypass-g4-cfgready entry from DT
|
||||
*/
|
||||
static void ufs_qcom_parse_g4_workaround_flag(struct ufs_qcom_host *host)
|
||||
{
|
||||
struct device_node *np = host->hba->dev->of_node;
|
||||
const char *str = "bypass-g4-cfgready";
|
||||
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
host->bypass_g4_cfgready = of_property_read_bool(np, str);
|
||||
}
|
||||
|
||||
/*
|
||||
* ufs_qcom_parse_lpm - read from DTS whether LPM modes should be disabled.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -168,8 +168,16 @@ enum ufs_qcom_phy_init_type {
|
|||
|
||||
/* QUniPro Vendor specific attributes */
|
||||
#define PA_VS_CONFIG_REG1 0x9000
|
||||
#define SAVECONFIGTIME_MODE_MASK 0x6000
|
||||
#define DME_VS_CORE_CLK_CTRL 0xD002
|
||||
#define BIT_TX_EOB_COND BIT(23)
|
||||
#define PA_VS_CONFIG_REG2 0x9005
|
||||
#define H8_ENTER_COND_OFFSET 0x6
|
||||
#define H8_ENTER_COND_MASK GENMASK(6, 7)
|
||||
#define BIT_RX_EOB_COND BIT(5)
|
||||
#define BIT_LINKCFG_WAIT_LL1_RX_CFG_RDY BIT(26)
|
||||
#define SAVECONFIGTIME_MODE_MASK 0x6000
|
||||
#define DME_VS_CORE_CLK_CTRL 0xD002
|
||||
|
||||
|
||||
/* bit and mask definitions for DME_VS_CORE_CLK_CTRL attribute */
|
||||
#define DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT BIT(8)
|
||||
#define DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK 0xFF
|
||||
|
|
@ -367,6 +375,7 @@ struct ufs_qcom_host {
|
|||
atomic_t scale_up;
|
||||
atomic_t clks_on;
|
||||
struct ufs_qcom_qos_req *ufs_qos;
|
||||
bool bypass_g4_cfgready;
|
||||
};
|
||||
|
||||
static inline u32
|
||||
|
|
|
|||
Loading…
Reference in a new issue