diff options
author | Stanley Chu <stanley.chu@mediatek.com> | 2019-12-30 13:32:26 +0800 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2020-01-02 21:57:44 -0500 |
commit | b0d077ed389cb75b95396886517664c2500b0c10 (patch) | |
tree | 2e4c05454413f22be74a98eeebe57b9ba6efe259 /drivers/scsi/ufs/ufs-mediatek.c | |
parent | fef093ff7e9654eec77e79b8170485241f01d027 (diff) |
scsi: ufs-mediatek: add device reset implementation
Add device reset vops implementation in MediaTek UFS driver.
Cc: Alim Akhtar <alim.akhtar@samsung.com>
Cc: Avri Altman <avri.altman@wdc.com>
Cc: Bart Van Assche <bvanassche@acm.org>
Cc: Bean Huo <beanhuo@micron.com>
Cc: Can Guo <cang@codeaurora.org>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Link: https://lore.kernel.org/r/1577683950-1702-3-git-send-email-stanley.chu@mediatek.com
Reviewed-by: Avri Altman <avri.altman@wdc.com>
Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/ufs/ufs-mediatek.c')
-rw-r--r-- | drivers/scsi/ufs/ufs-mediatek.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 83e28edc3ac5..37e2c91fc452 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -6,16 +6,25 @@ * Peter Wang <peter.wang@mediatek.com> */ +#include <linux/arm-smccc.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/phy/phy.h> #include <linux/platform_device.h> +#include <linux/soc/mediatek/mtk_sip_svc.h> #include "ufshcd.h" #include "ufshcd-pltfrm.h" #include "unipro.h" #include "ufs-mediatek.h" +#define ufs_mtk_smc(cmd, val, res) \ + arm_smccc_smc(MTK_SIP_UFS_CONTROL, \ + cmd, val, 0, 0, 0, 0, 0, &(res)) + +#define ufs_mtk_device_reset_ctrl(high, res) \ + ufs_mtk_smc(UFS_MTK_SIP_DEVICE_RESET, high, res) + static void ufs_mtk_cfg_unipro_cg(struct ufs_hba *hba, bool enable) { u32 tmp; @@ -269,6 +278,29 @@ static int ufs_mtk_link_startup_notify(struct ufs_hba *hba, return ret; } +static void ufs_mtk_device_reset(struct ufs_hba *hba) +{ + struct arm_smccc_res res; + + ufs_mtk_device_reset_ctrl(0, res); + + /* + * The reset signal is active low. UFS devices 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 at least 10us. + */ + usleep_range(10, 15); + + ufs_mtk_device_reset_ctrl(1, res); + + /* Some devices may need time to respond to rst_n */ + usleep_range(10000, 15000); + + dev_info(hba->dev, "device reset done\n"); +} + static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); @@ -303,6 +335,7 @@ static struct ufs_hba_variant_ops ufs_hba_mtk_vops = { .pwr_change_notify = ufs_mtk_pwr_change_notify, .suspend = ufs_mtk_suspend, .resume = ufs_mtk_resume, + .device_reset = ufs_mtk_device_reset, }; /** |