From 9d4ff08fa405324401e2efe0409eca6457929cc2 Mon Sep 17 00:00:00 2001 From: Asutosh Das Date: Tue, 28 Jan 2020 02:27:33 -0800 Subject: [PATCH] scsi: ufs: Fix phy init sequence Phy init is assumed to be done during powerup sequence. The phy init is now being invoked during clock init as well. At this point in initialization the phy mode and submode is not yet set. So the phy initialization puts the phy in a weird state. It also increments the counters that prevent re-init and re-power-on of the phy. Thus, when the phy init is invoked during powerup sequence, it just returns thus leading to failures during controller enable. This patch fixes this by removing the phy init during clock init. The ufs device reset traditionally uses pinctrl. This patch moves it to gpio based reset. Change-Id: Id9205185b042e4f11fc4132419a179ba81af7226 Signed-off-by: Asutosh Das Signed-off-by: Bao D Nguyen Signed-off-by: Can Guo --- drivers/scsi/ufs/ufs-qcom.c | 8 ---- drivers/scsi/ufs/ufshcd-pltfrm.c | 1 - drivers/scsi/ufs/ufshcd-qti.c | 69 +------------------------------- drivers/scsi/ufs/ufshcd.h | 1 - 4 files changed, 2 insertions(+), 77 deletions(-) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 84ea7fc78fd8..b7cac5384c67 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1562,10 +1562,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, return 0; if (on && (status == POST_CHANGE)) { - if (!host->is_phy_pwr_on) { - phy_power_on(host->generic_phy); - host->is_phy_pwr_on = true; - } /* enable the device ref clock for HS mode*/ if (ufshcd_is_hs_mode(&hba->pwr_info)) ufs_qcom_dev_ref_clk_ctrl(host, true); @@ -1580,10 +1576,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, /* disable device ref_clk */ ufs_qcom_dev_ref_clk_ctrl(host, false); /* powering off PHY during aggressive clk gating */ - if (host->is_phy_pwr_on) { - phy_power_off(host->generic_phy); - host->is_phy_pwr_on = false; - } } diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index 8d40dc918f4e..5e48e6029257 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -151,7 +151,6 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name, return -ENOMEM; vreg->name = kstrdup(name, GFP_KERNEL); - snprintf(prop_name, MAX_PROP_SIZE, "%s-max-microamp", name); if (of_property_read_u32(np, prop_name, &vreg->max_uA)) { dev_info(dev, "%s: unable to find %s\n", __func__, prop_name); diff --git a/drivers/scsi/ufs/ufshcd-qti.c b/drivers/scsi/ufs/ufshcd-qti.c index 5130bf1b60f2..000c15092b04 100644 --- a/drivers/scsi/ufs/ufshcd-qti.c +++ b/drivers/scsi/ufs/ufshcd-qti.c @@ -463,63 +463,6 @@ void ufshcd_scsi_block_requests(struct ufs_hba *hba) } EXPORT_SYMBOL(ufshcd_scsi_block_requests); -static int ufshcd_device_reset_ctrl(struct ufs_hba *hba, bool ctrl) -{ - int ret = 0; - - if (!hba->pctrl) - return 0; - - /* Assert reset if ctrl == true */ - if (ctrl) - ret = pinctrl_select_state(hba->pctrl, - pinctrl_lookup_state(hba->pctrl, "dev-reset-assert")); - else - ret = pinctrl_select_state(hba->pctrl, - pinctrl_lookup_state(hba->pctrl, "dev-reset-deassert")); - - if (ret < 0) - dev_err(hba->dev, "%s: %s failed with err %d\n", - __func__, ctrl ? "Assert" : "Deassert", ret); - - return ret; -} - -static inline int ufshcd_assert_device_reset(struct ufs_hba *hba) -{ - return ufshcd_device_reset_ctrl(hba, true); -} - -static inline int ufshcd_deassert_device_reset(struct ufs_hba *hba) -{ - return ufshcd_device_reset_ctrl(hba, false); -} - -static int ufshcd_reset_device(struct ufs_hba *hba) -{ - int ret; - - /* reset the connected UFS device */ - ret = ufshcd_assert_device_reset(hba); - if (ret) - goto out; - /* - * The reset signal is active low. - * The UFS device shall detect more than or equal to 1us of positive - * or negative RST_n pulse width. - * To be on safe side, keep the reset low for atleast 10us. - */ - usleep_range(10, 15); - - ret = ufshcd_deassert_device_reset(hba); - if (ret) - goto out; - /* same as assert, wait for atleast 10us after deassert */ - usleep_range(10, 15); -out: - return ret; -} - static void ufshcd_add_cmd_upiu_trace(struct ufs_hba *hba, unsigned int tag, const char *str) { @@ -7466,12 +7409,7 @@ out: static int ufshcd_detect_device(struct ufs_hba *hba) { - int err = 0; - - err = ufshcd_reset_device(hba); - if (err) - dev_warn(hba->dev, "%s: device reset failed. err %d\n", - __func__, err); + ufshcd_vops_device_reset(hba); return ufshcd_host_reset_and_restore(hba); } @@ -9987,10 +9925,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) } /* reset connected UFS device */ - err = ufshcd_reset_device(hba); - if (err) - dev_warn(hba->dev, "%s: device reset failed. err %d\n", - __func__, err); + ufshcd_vops_device_reset(hba); /* Init crypto */ err = ufshcd_hba_init_crypto(hba); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 38aba68b086d..d6a89cb8d8f9 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -919,7 +919,6 @@ struct ufs_hba { /* Allow standalone Hibern8 enter on idle */ #define UFSHCD_CAP_HIBERN8_ENTER_ON_IDLE (1 << 5) struct rw_semaphore lock; - struct pinctrl *pctrl; /* Bitmask for enabling debug prints */ u32 ufshcd_dbg_print; /* If set, don't gate device ref_clk during clock gating */