Re: [PATCH v3 4/4] scsi: ufs-mediatek: gate ref-clk during Auto-Hibern8

From: Alim Akhtar
Date: Sun Feb 02 2020 - 09:37:22 EST


Hello Stanley

On Wed, Jan 29, 2020 at 1:10 PM Stanley Chu <stanley.chu@xxxxxxxxxxxx> 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@xxxxxxxxxxxx>

Reviewed-by: Alim Akhtar <alim.akhtar@xxxxxxxxxxx>
> ---
> 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



--
Regards,
Alim