summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorBjorn Andersson <bjorn.andersson@linaro.org>2019-08-28 12:17:55 -0700
committerMartin K. Petersen <martin.petersen@oracle.com>2019-09-07 16:36:03 -0400
commitb8416b2fedbf1cfe1c3645c627b2341d253880bd (patch)
treee2b085f6e9024efe16e13bee7bdd33018797a436 /drivers/scsi
parentd8d9f7931ac2698fc2b37d2db748c47122ee2a6f (diff)
downloadlinux-b8416b2fedbf1cfe1c3645c627b2341d253880bd.tar.bz2
scsi: ufs-qcom: Implement device_reset vops
The UFS_RESET pin on Qualcomm SoCs are controlled by TLMM and exposed through the GPIO framework. Acquire the device-reset GPIO and use this to implement the device_reset vops, to allow resetting the attached memory. Based on downstream support implemented by Subhash Jadavani <subhashj@codeaurora.org>. Link: https://lore.kernel.org/r/20190828191756.24312-3-bjorn.andersson@linaro.org Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> Acked-by: Rob Herring <robh@kernel.org> Acked-by: Avri Altman <Avri.Altman@wdc.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c36
-rw-r--r--drivers/scsi/ufs/ufs-qcom.h4
2 files changed, 40 insertions, 0 deletions
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 02cdcefb81ac..a5b71487a206 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -8,6 +8,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
+#include <linux/gpio/consumer.h>
#include <linux/reset-controller.h>
#include "ufshcd.h"
@@ -1137,6 +1138,15 @@ static int ufs_qcom_init(struct ufs_hba *hba)
}
}
+ host->device_reset = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(host->device_reset)) {
+ err = PTR_ERR(host->device_reset);
+ if (err != -EPROBE_DEFER)
+ dev_err(dev, "failed to acquire reset gpio: %d\n", err);
+ goto out_variant_clear;
+ }
+
err = ufs_qcom_bus_register(host);
if (err)
goto out_variant_clear;
@@ -1543,6 +1553,31 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
}
/**
+ * ufs_qcom_device_reset() - toggle the (optional) device reset line
+ * @hba: per-adapter instance
+ *
+ * Toggles the (optional) reset line to reset the attached device.
+ */
+static void ufs_qcom_device_reset(struct ufs_hba *hba)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+
+ /* reset gpio is optional */
+ if (!host->device_reset)
+ return;
+
+ /*
+ * The UFS device shall detect reset pulses of 1us, sleep for 10us to
+ * be on the safe side.
+ */
+ gpiod_set_value_cansleep(host->device_reset, 1);
+ usleep_range(10, 15);
+
+ gpiod_set_value_cansleep(host->device_reset, 0);
+ usleep_range(10, 15);
+}
+
+/**
* struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
*
* The variant operations configure the necessary controller and PHY
@@ -1562,6 +1597,7 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
.suspend = ufs_qcom_suspend,
.resume = ufs_qcom_resume,
.dbg_register_dump = ufs_qcom_dump_dbg_regs,
+ .device_reset = ufs_qcom_device_reset,
};
/**
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h
index 001915d1e0e4..d401f174bb70 100644
--- a/drivers/scsi/ufs/ufs-qcom.h
+++ b/drivers/scsi/ufs/ufs-qcom.h
@@ -195,6 +195,8 @@ struct ufs_qcom_testbus {
u8 select_minor;
};
+struct gpio_desc;
+
struct ufs_qcom_host {
/*
* Set this capability if host controller supports the QUniPro mode
@@ -232,6 +234,8 @@ struct ufs_qcom_host {
struct ufs_qcom_testbus testbus;
struct reset_controller_dev rcdev;
+
+ struct gpio_desc *device_reset;
};
static inline u32