mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 14:19:09 -04:00
Merge "scsi: ufs: Add workaround to bypass cfgready signal for UFS gear4"
This commit is contained in:
commit
8a6bfe1047
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