@@ -54,6 +54,8 @@ Optional properties:
PHY reset from the UFS controller.
- resets : reset node register
- reset-names : describe reset node register, the "rst" corresponds to reset the whole UFS IP.
+- reset-gpios : A phandle and gpio specifier denoting the GPIO connected
+ to the RESET pin of the UFS memory device.
Note: If above properties are not defined it can be assumed that the supply
regulators or clocks are always on.
@@ -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"
@@ -1140,6 +1141,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;
@@ -1545,6 +1555,31 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
usleep_range(1000, 1100);
}
+/**
+ * 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
*
@@ -1565,6 +1600,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,
};
/**
@@ -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
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>. Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> --- Changes since v3: - Renamed device-reset-gpios to just reset-gpios. - Explicitly bail on !host->device_reset, to not rely on passing NULL to gpiod_set_value_cansleep() .../devicetree/bindings/ufs/ufshcd-pltfrm.txt | 2 ++ drivers/scsi/ufs/ufs-qcom.c | 36 +++++++++++++++++++ drivers/scsi/ufs/ufs-qcom.h | 4 +++ 3 files changed, 42 insertions(+) -- 2.18.0