On Fri, Jan 17, 2020 at 9:44 AM Stanley Chu <stanley.chu@xxxxxxxxxxxx> wrote: > > In MediaTek Chipsets, UniPro link and ufshci can enter proprietary > low-power mode while link is in hibern8 state. > > Signed-off-by: Stanley Chu <stanley.chu@xxxxxxxxxxxx> > --- Reviewed-by: Alim Akhtar <alim.akhtar@xxxxxxxxxxx> > drivers/scsi/ufs/ufs-mediatek.c | 53 +++++++++++++++++++++++++++++++++ > 1 file changed, 53 insertions(+) > > diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c > index d5194d0c4ef5..f32f3f34f6d0 100644 > --- a/drivers/scsi/ufs/ufs-mediatek.c > +++ b/drivers/scsi/ufs/ufs-mediatek.c > @@ -382,11 +382,60 @@ static void ufs_mtk_device_reset(struct ufs_hba *hba) > dev_info(hba->dev, "device reset done\n"); > } > > +static int ufs_mtk_link_set_hpm(struct ufs_hba *hba) > +{ > + int err; > + > + err = ufshcd_hba_enable(hba); > + if (err) > + return err; > + > + err = ufshcd_dme_set(hba, > + UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), > + 0); > + if (err) > + return err; > + > + err = ufshcd_uic_hibern8_exit(hba); > + if (!err) > + ufshcd_set_link_active(hba); > + else > + return err; > + > + err = ufshcd_make_hba_operational(hba); > + if (err) > + return err; > + > + return 0; > +} > + > +static int ufs_mtk_link_set_lpm(struct ufs_hba *hba) > +{ > + int err; > + > + err = ufshcd_dme_set(hba, > + UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), > + 1); > + if (err) { > + /* Resume UniPro state for following error recovery */ > + ufshcd_dme_set(hba, > + UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), > + 0); > + return err; > + } > + > + return 0; > +} > + > static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) > { > + int err; > struct ufs_mtk_host *host = ufshcd_get_variant(hba); > > if (ufshcd_is_link_hibern8(hba)) { > + err = ufs_mtk_link_set_lpm(hba); > + if (err) > + return -EAGAIN; > phy_power_off(host->mphy); > ufs_mtk_setup_ref_clk(hba, false); > } > @@ -397,10 +446,14 @@ static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) > static int ufs_mtk_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) > { > struct ufs_mtk_host *host = ufshcd_get_variant(hba); > + int err; > > if (ufshcd_is_link_hibern8(hba)) { > ufs_mtk_setup_ref_clk(hba, true); > phy_power_on(host->mphy); > + err = ufs_mtk_link_set_hpm(hba); > + if (err) > + return err; > } > > return 0; > -- > 2.18.0 -- Regards, Alim