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>
This commit is contained in:
parent
d8d9f7931a
commit
b8416b2fed
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -1542,6 +1552,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
|
||||
*
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue