[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20221222141001.54849-20-manivannan.sadhasivam@linaro.org>
Date: Thu, 22 Dec 2022 19:39:57 +0530
From: Manivannan Sadhasivam <manivannan.sadhasivam@...aro.org>
To: martin.petersen@...cle.com, jejb@...ux.ibm.com,
andersson@...nel.org, vkoul@...nel.org
Cc: quic_cang@...cinc.com, quic_asutoshd@...cinc.com,
linux-arm-msm@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-phy@...ts.infradead.org, linux-scsi@...r.kernel.org,
dmitry.baryshkov@...aro.org, ahalaney@...hat.com,
abel.vesa@...aro.org, alim.akhtar@...sung.com, avri.altman@....com,
bvanassche@....org,
Manivannan Sadhasivam <manivannan.sadhasivam@...aro.org>
Subject: [PATCH v5 19/23] scsi: ufs: core: Add support for reinitializing the UFS device
Some platforms like Qcom, requires the UFS device to be reinitialized
after switching to maximum gear speed. So add support for that in UFS
core by introducing a new quirk (UFSHCD_CAP_REINIT_AFTER_MAX_GEAR_SWITCH)
and doing the reinitialization, if the quirk is enabled by the controller
driver.
Suggested-by: Can Guo <quic_cang@...cinc.com>
Tested-by: Andrew Halaney <ahalaney@...hat.com> # Qdrive3/sa8540p-ride
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@...aro.org>
---
drivers/ufs/core/ufshcd.c | 63 +++++++++++++++++++++++++++++----------
include/ufs/ufshcd.h | 6 ++++
2 files changed, 53 insertions(+), 16 deletions(-)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index bda61be5f035..fe4720bf0d67 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -8161,27 +8161,18 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
return ret;
}
-/**
- * ufshcd_probe_hba - probe hba to detect device and initialize it
- * @hba: per-adapter instance
- * @init_dev_params: whether or not to call ufshcd_device_params_init().
- *
- * Execute link-startup and verify device initialization
- */
-static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
+static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params)
{
int ret;
- unsigned long flags;
- ktime_t start = ktime_get();
hba->ufshcd_state = UFSHCD_STATE_RESET;
ret = ufshcd_link_startup(hba);
if (ret)
- goto out;
+ return ret;
if (hba->quirks & UFSHCD_QUIRK_SKIP_PH_CONFIGURATION)
- goto out;
+ return ret;
/* Debug counters initialization */
ufshcd_clear_dbg_ufs_stats(hba);
@@ -8192,12 +8183,12 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
/* Verify device initialization by sending NOP OUT UPIU */
ret = ufshcd_verify_dev_init(hba);
if (ret)
- goto out;
+ return ret;
/* Initiate UFS initialization, and waiting until completion */
ret = ufshcd_complete_dev_init(hba);
if (ret)
- goto out;
+ return ret;
/*
* Initialize UFS device parameters used by driver, these
@@ -8206,7 +8197,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
if (init_dev_params) {
ret = ufshcd_device_params_init(hba);
if (ret)
- goto out;
+ return ret;
}
ufshcd_tune_unipro_params(hba);
@@ -8227,11 +8218,51 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
if (ret) {
dev_err(hba->dev, "%s: Failed setting power mode, err = %d\n",
__func__, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * ufshcd_probe_hba - probe hba to detect device and initialize it
+ * @hba: per-adapter instance
+ * @init_dev_params: whether or not to call ufshcd_device_params_init().
+ *
+ * Execute link-startup and verify device initialization
+ */
+static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
+{
+ ktime_t start = ktime_get();
+ unsigned long flags;
+ int ret;
+
+ ret = ufshcd_device_init(hba, init_dev_params);
+ if (ret)
+ goto out;
+
+ if (hba->quirks & UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH) {
+ /* Reset the device and controller before doing reinit */
+ ufshcd_device_reset(hba);
+ ufshcd_hba_stop(hba);
+ ufshcd_vops_reinit_notify(hba);
+ ret = ufshcd_hba_enable(hba);
+ if (ret) {
+ dev_err(hba->dev, "Host controller enable failed\n");
+ ufshcd_print_evt_hist(hba);
+ ufshcd_print_host_state(hba);
goto out;
}
- ufshcd_print_pwr_info(hba);
+
+ /* Reinit the device */
+ ret = ufshcd_device_init(hba, init_dev_params);
+ if (ret)
+ goto out;
}
+ ufshcd_print_pwr_info(hba);
+
/*
* bActiveICCLevel is volatile for UFS device (as per latest v2.1 spec)
* and for removable UFS card as well, hence always set the parameter.
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index 0a0b435f5c17..68bd822b9c22 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -595,6 +595,12 @@ enum ufshcd_quirks {
* auto-hibernate capability but it's FASTAUTO only.
*/
UFSHCD_QUIRK_HIBERN_FASTAUTO = 1 << 18,
+
+ /*
+ * This quirk needs to be enabled if the host controller needs
+ * to reinit the device after switching to maximum gear.
+ */
+ UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH = 1 << 19,
};
enum ufshcd_caps {
--
2.25.1
Powered by blists - more mailing lists