Message ID | 20200129073902.5786-5-stanley.chu@mediatek.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | MediaTek UFS vendor implemenation part III and Auto-Hibern8 fix | expand |
Hello Stanley On Wed, Jan 29, 2020 at 1:10 PM Stanley Chu <stanley.chu@mediatek.com> wrote: > > In current UFS driver design, hba->uic_link_state will not > be changed after link enters Hibern8 state by Auto-Hibern8 mechanism. > In this case, reference clock gating will be skipped unless special > handling is implemented in vendor's callbacks. > > Support reference clock gating during Auto-Hibern8 period in > MediaTek Chipsets: If link state is already in Hibern8 while > Auto-Hibern8 feature is enabled, gate reference clock in > setup_clocks callback. > > Signed-off-by: Stanley Chu <stanley.chu@mediatek.com> Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com> > --- > drivers/scsi/ufs/ufs-mediatek.c | 38 +++++++++++++++++++++++---------- > drivers/scsi/ufs/ufs-mediatek.h | 12 +++++++++++ > 2 files changed, 39 insertions(+), 11 deletions(-) > > diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c > index d78897a14905..0ce08872d671 100644 > --- a/drivers/scsi/ufs/ufs-mediatek.c > +++ b/drivers/scsi/ufs/ufs-mediatek.c > @@ -143,6 +143,17 @@ static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on) > return 0; > } > > +static u32 ufs_mtk_link_get_state(struct ufs_hba *hba) > +{ > + u32 val; > + > + ufshcd_writel(hba, 0x20, REG_UFS_DEBUG_SEL); > + val = ufshcd_readl(hba, REG_UFS_PROBE); > + val = val >> 28; > + > + return val; > +} > + > /** > * ufs_mtk_setup_clocks - enables/disable clocks > * @hba: host controller instance > @@ -155,7 +166,7 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, > enum ufs_notify_change_status status) > { > struct ufs_mtk_host *host = ufshcd_get_variant(hba); > - int ret = -EINVAL; > + int ret = 0; > > /* > * In case ufs_mtk_init() is not yet done, simply ignore. > @@ -165,19 +176,24 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, > if (!host) > return 0; > > - switch (status) { > - case PRE_CHANGE: > - if (!on && !ufshcd_is_link_active(hba)) { > + if (!on && status == PRE_CHANGE) { > + if (!ufshcd_is_link_active(hba)) { > ufs_mtk_setup_ref_clk(hba, on); > ret = phy_power_off(host->mphy); > + } else { > + /* > + * Gate ref-clk if link state is in Hibern8 > + * triggered by Auto-Hibern8. > + */ > + if (!ufshcd_can_hibern8_during_gating(hba) && > + ufshcd_is_auto_hibern8_enabled(hba) && > + ufs_mtk_link_get_state(hba) == > + VS_LINK_HIBERN8) > + ufs_mtk_setup_ref_clk(hba, on); > } > - break; > - case POST_CHANGE: > - if (on) { > - ret = phy_power_on(host->mphy); > - ufs_mtk_setup_ref_clk(hba, on); > - } > - break; > + } else if (on && status == POST_CHANGE) { > + ret = phy_power_on(host->mphy); > + ufs_mtk_setup_ref_clk(hba, on); > } > > return ret; > diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h > index fccdd979d6fb..492414e5f481 100644 > --- a/drivers/scsi/ufs/ufs-mediatek.h > +++ b/drivers/scsi/ufs/ufs-mediatek.h > @@ -53,6 +53,18 @@ > #define VS_SAVEPOWERCONTROL 0xD0A6 > #define VS_UNIPROPOWERDOWNCONTROL 0xD0A8 > > +/* > + * Vendor specific link state > + */ > +enum { > + VS_LINK_DISABLED = 0, > + VS_LINK_DOWN = 1, > + VS_LINK_UP = 2, > + VS_LINK_HIBERN8 = 3, > + VS_LINK_LOST = 4, > + VS_LINK_CFG = 5, > +}; > + > /* > * SiP commands > */ > -- > 2.18.0
diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index d78897a14905..0ce08872d671 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -143,6 +143,17 @@ static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on) return 0; } +static u32 ufs_mtk_link_get_state(struct ufs_hba *hba) +{ + u32 val; + + ufshcd_writel(hba, 0x20, REG_UFS_DEBUG_SEL); + val = ufshcd_readl(hba, REG_UFS_PROBE); + val = val >> 28; + + return val; +} + /** * ufs_mtk_setup_clocks - enables/disable clocks * @hba: host controller instance @@ -155,7 +166,7 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, enum ufs_notify_change_status status) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); - int ret = -EINVAL; + int ret = 0; /* * In case ufs_mtk_init() is not yet done, simply ignore. @@ -165,19 +176,24 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, if (!host) return 0; - switch (status) { - case PRE_CHANGE: - if (!on && !ufshcd_is_link_active(hba)) { + if (!on && status == PRE_CHANGE) { + if (!ufshcd_is_link_active(hba)) { ufs_mtk_setup_ref_clk(hba, on); ret = phy_power_off(host->mphy); + } else { + /* + * Gate ref-clk if link state is in Hibern8 + * triggered by Auto-Hibern8. + */ + if (!ufshcd_can_hibern8_during_gating(hba) && + ufshcd_is_auto_hibern8_enabled(hba) && + ufs_mtk_link_get_state(hba) == + VS_LINK_HIBERN8) + ufs_mtk_setup_ref_clk(hba, on); } - break; - case POST_CHANGE: - if (on) { - ret = phy_power_on(host->mphy); - ufs_mtk_setup_ref_clk(hba, on); - } - break; + } else if (on && status == POST_CHANGE) { + ret = phy_power_on(host->mphy); + ufs_mtk_setup_ref_clk(hba, on); } return ret; diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h index fccdd979d6fb..492414e5f481 100644 --- a/drivers/scsi/ufs/ufs-mediatek.h +++ b/drivers/scsi/ufs/ufs-mediatek.h @@ -53,6 +53,18 @@ #define VS_SAVEPOWERCONTROL 0xD0A6 #define VS_UNIPROPOWERDOWNCONTROL 0xD0A8 +/* + * Vendor specific link state + */ +enum { + VS_LINK_DISABLED = 0, + VS_LINK_DOWN = 1, + VS_LINK_UP = 2, + VS_LINK_HIBERN8 = 3, + VS_LINK_LOST = 4, + VS_LINK_CFG = 5, +}; + /* * SiP commands */
In current UFS driver design, hba->uic_link_state will not be changed after link enters Hibern8 state by Auto-Hibern8 mechanism. In this case, reference clock gating will be skipped unless special handling is implemented in vendor's callbacks. Support reference clock gating during Auto-Hibern8 period in MediaTek Chipsets: If link state is already in Hibern8 while Auto-Hibern8 feature is enabled, gate reference clock in setup_clocks callback. Signed-off-by: Stanley Chu <stanley.chu@mediatek.com> --- drivers/scsi/ufs/ufs-mediatek.c | 38 +++++++++++++++++++++++---------- drivers/scsi/ufs/ufs-mediatek.h | 12 +++++++++++ 2 files changed, 39 insertions(+), 11 deletions(-)