Skip to content

Commit

Permalink
scsi: ufs: ufs-mediatek: Introduce workaround for power mode change
Browse files Browse the repository at this point in the history
Some MediaTek SoC chips need special flow for power mode change, especially
for chips supporting HS-G5.

Enable the workaround by setting the host-specific capability.

Link: https://lore.kernel.org/r/[email protected]
Reviewed-by: Stanley Chu <[email protected]>
Signed-off-by: CC Chou <[email protected]>
Signed-off-by: Eddie Huang <[email protected]>
Signed-off-by: Dennis Yu <[email protected]>
Signed-off-by: Peter Wang <[email protected]>
Signed-off-by: Stanley Chu <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
  • Loading branch information
CC Chou authored and martinkpetersen committed Jun 17, 2022
1 parent d81c4c6 commit 3f9b6ce
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 2 deletions.
60 changes: 58 additions & 2 deletions drivers/ufs/host/ufs-mediatek.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ static bool ufs_mtk_is_broken_vcc(struct ufs_hba *hba)
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);
}

static void ufs_mtk_cfg_unipro_cg(struct ufs_hba *hba, bool enable)
{
u32 tmp;
Expand Down Expand Up @@ -579,6 +586,9 @@ static void ufs_mtk_init_host_caps(struct ufs_hba *hba)
if (of_property_read_bool(np, "mediatek,ufs-broken-vcc"))
host->caps |= UFS_MTK_CAP_BROKEN_VCC;

if (of_property_read_bool(np, "mediatek,ufs-pmc-via-fastauto"))
host->caps |= UFS_MTK_CAP_PMC_VIA_FASTAUTO;

dev_info(hba->dev, "caps: 0x%x", host->caps);
}

Expand Down Expand Up @@ -754,6 +764,26 @@ static int ufs_mtk_init(struct ufs_hba *hba)
return err;
}

static bool ufs_mtk_pmc_via_fastauto(struct ufs_hba *hba,
struct ufs_pa_layer_attr *dev_req_params)
{
if (!ufs_mtk_is_pmc_via_fastauto(hba))
return false;

if (dev_req_params->hs_rate == hba->pwr_info.hs_rate)
return false;

if (dev_req_params->pwr_tx != FAST_MODE &&
dev_req_params->gear_tx < UFS_HS_G4)
return false;

if (dev_req_params->pwr_rx != FAST_MODE &&
dev_req_params->gear_rx < UFS_HS_G4)
return false;

return true;
}

static int ufs_mtk_pre_pwr_change(struct ufs_hba *hba,
struct ufs_pa_layer_attr *dev_max_params,
struct ufs_pa_layer_attr *dev_req_params)
Expand All @@ -763,8 +793,8 @@ static int ufs_mtk_pre_pwr_change(struct ufs_hba *hba,
int ret;

ufshcd_init_pwr_dev_param(&host_cap);
host_cap.hs_rx_gear = UFS_HS_G4;
host_cap.hs_tx_gear = UFS_HS_G4;
host_cap.hs_rx_gear = UFS_HS_G5;
host_cap.hs_tx_gear = UFS_HS_G5;

ret = ufshcd_get_pwr_dev_param(&host_cap,
dev_max_params,
Expand All @@ -774,6 +804,32 @@ static int ufs_mtk_pre_pwr_change(struct ufs_hba *hba,
__func__);
}

if (ufs_mtk_pmc_via_fastauto(hba, dev_req_params)) {
ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXTERMINATION), true);
ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXGEAR), UFS_HS_G1);

ufshcd_dme_set(hba, UIC_ARG_MIB(PA_RXTERMINATION), true);
ufshcd_dme_set(hba, UIC_ARG_MIB(PA_RXGEAR), UFS_HS_G1);

ufshcd_dme_set(hba, UIC_ARG_MIB(PA_ACTIVETXDATALANES),
dev_req_params->lane_tx);
ufshcd_dme_set(hba, UIC_ARG_MIB(PA_ACTIVERXDATALANES),
dev_req_params->lane_rx);
ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HSSERIES),
dev_req_params->hs_rate);

ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXHSADAPTTYPE),
PA_NO_ADAPT);

ret = ufshcd_uic_change_pwr_mode(hba,
FASTAUTO_MODE << 4 | FASTAUTO_MODE);

if (ret) {
dev_err(hba->dev, "%s: HSG1B FASTAUTO failed ret=%d\n",
__func__, ret);
}
}

if (host->hw_ver.major >= 3) {
ret = ufshcd_dme_configure_adapt(hba,
dev_req_params->gear_tx,
Expand Down
1 change: 1 addition & 0 deletions drivers/ufs/host/ufs-mediatek.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ enum ufs_mtk_host_caps {
UFS_MTK_CAP_VA09_PWR_CTRL = 1 << 1,
UFS_MTK_CAP_DISABLE_AH8 = 1 << 2,
UFS_MTK_CAP_BROKEN_VCC = 1 << 3,
UFS_MTK_CAP_PMC_VIA_FASTAUTO = 1 << 6,
};

struct ufs_mtk_crypt_cfg {
Expand Down
1 change: 1 addition & 0 deletions include/ufs/unipro.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ enum ufs_hs_gear_tag {
UFS_HS_G2, /* HS Gear 2 */
UFS_HS_G3, /* HS Gear 3 */
UFS_HS_G4, /* HS Gear 4 */
UFS_HS_G5 /* HS Gear 5 */
};

enum ufs_unipro_ver {
Expand Down

0 comments on commit 3f9b6ce

Please sign in to comment.