[RAMEN9610-14207][COMMON] scsi: ufs: UFS power recovery when probe fail.
authorJaeHun Jung <jh0801.jung@samsung.com>
Thu, 4 Apr 2019 13:12:59 +0000 (22:12 +0900)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:23:22 +0000 (20:23 +0300)
Check GPIO when UFS probe error case. And if gpio has abnormal state.
I will be retry.

Change-Id: I5d4028493d1e907d7b3ebd399fb8c7696675f3c8
Signed-off-by: JaeHun Jung <jh0801.jung@samsung.com>
drivers/scsi/ufs/ufs.h
drivers/scsi/ufs/ufshcd-pltfrm.c
drivers/scsi/ufs/ufshcd.c

index 6ae13f0b7b32b06b37c3253e9986de1a62159a84..3850b00428b934abd6f3650311e00d4555acf7bd 100644 (file)
@@ -550,6 +550,8 @@ struct ufs_vreg_info {
        struct ufs_vreg *vccq;
        struct ufs_vreg *vccq2;
        struct ufs_vreg *vdd_hba;
+       int ufs_power_gpio;
+       int ufs_reset_n_gpio;
 };
 
 struct ufs_dev_info {
index 1823ee64744f101aecfe7aa32945637dbb4dd330..a84594b1c7bb0b4b7bc26378866a05616b3c4a34 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_gpio.h>
 
 #include "ufshcd.h"
 #include "ufshcd-pltfrm.h"
@@ -213,6 +214,7 @@ static int ufshcd_parse_regulator_info(struct ufs_hba *hba)
 {
        int err;
        struct device *dev = hba->dev;
+       struct device_node *np = dev->of_node;
        struct ufs_vreg_info *info = &hba->vreg_info;
 
        err = ufshcd_populate_vreg(dev, "vdd-hba", &info->vdd_hba);
@@ -228,6 +230,14 @@ static int ufshcd_parse_regulator_info(struct ufs_hba *hba)
                goto out;
 
        err = ufshcd_populate_vreg(dev, "vccq2", &info->vccq2);
+       if (err)
+               goto out;
+
+       if (of_get_property(np, "ufs-power-gpio", NULL))
+               info->ufs_power_gpio = of_get_named_gpio(np, "ufs-power-gpio", 0);
+
+       if (of_get_property(np, "ufs-reset-n-gpio", NULL))
+               info->ufs_reset_n_gpio = of_get_named_gpio(np, "ufs-reset-n-gpio", 0);
 out:
        return err;
 }
index d788f02780e71fd6445dd074f59f9b9d35e76fdc..75601c6e113ac025bca9c728909f5f85dd0d1754 100644 (file)
@@ -46,6 +46,8 @@
 #include <scsi/ufs/ioctl.h>
 #include <linux/of.h>
 #include <linux/blkdev.h>
+#include <linux/gpio.h>
+
 #include "ufshcd.h"
 #include "ufs_quirks.h"
 #include "unipro.h"
@@ -251,6 +253,8 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
                                     enum ufs_dev_pwr_mode pwr_mode);
 static int ufshcd_send_request_sense(struct ufs_hba *hba,
                                struct scsi_device *sdp);
+static void ufshcd_vreg_set_lpm(struct ufs_hba *hba);
+static int ufshcd_vreg_set_hpm(struct ufs_hba *hba);
 static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
 {
        return tag >= 0 && tag < hba->nutrs;
@@ -5446,6 +5450,7 @@ out:
 static void ufshcd_err_handler(struct work_struct *work)
 {
        struct ufs_hba *hba;
+       struct ufs_vreg_info *info = &hba->vreg_info;
        struct exynos_ufs *ufs;
        unsigned long flags;
        u32 err_xfer = 0;
@@ -5470,6 +5475,12 @@ static void ufshcd_err_handler(struct work_struct *work)
        /* Dump debugging information to system memory */
        ufshcd_vops_dbg_register_dump(hba);
 
+       /* Dump UFS power & reset_n GPIO status */
+       if (gpio_is_valid(info->ufs_power_gpio))
+               dev_info(hba->dev, "%s: UFS power pin: 0x%08x\n", __func__, gpio_get_value(info->ufs_power_gpio));
+       if (gpio_is_valid(info->ufs_reset_n_gpio))
+               dev_info(hba->dev, "%s: RESET_N: 0x%08x\n", __func__, gpio_get_value(info->ufs_reset_n_gpio));
+
        spin_lock_irqsave(hba->host->host_lock, flags);
        if (hba->ufshcd_state == UFSHCD_STATE_RESET)
                goto out;
@@ -6734,19 +6745,36 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
 {
        struct ufs_dev_desc card = {0};
        struct ufs_pa_layer_attr *pwr_info = &hba->max_pwr_info.info;
+       struct ufs_vreg_info *info = &hba->vreg_info;
        int re_cnt = 0;
-       int ret;
+       int ret, link_startup_fail = 0;
        ktime_t start = ktime_get();
        unsigned long flags;
 
 retry:
+       /* For deivce power control when link startup fail. */
+       if (link_startup_fail) {
+               ufshcd_vreg_set_lpm(hba);
+               ret = ufshcd_vreg_set_hpm(hba);
+
+               if (gpio_is_valid(info->ufs_power_gpio))
+                       dev_info(hba->dev, "%s: UFS power pin: 0x%08x\n", __func__, gpio_get_value(info->ufs_power_gpio));
+               if (gpio_is_valid(info->ufs_reset_n_gpio))
+                       dev_info(hba->dev, "%s: RESET_N: 0x%08x\n", __func__, gpio_get_value(info->ufs_reset_n_gpio));
+               if (ret)
+                       goto out;
+       }
+
        ret = ufshcd_hba_enable(hba);
        if (ret)
                goto out;
 
        ret = ufshcd_link_startup(hba);
-       if (ret)
+       if (ret) {
+               link_startup_fail = 1;
                goto out;
+       }
+       link_startup_fail = 0;
 
        dev_info(hba->dev, "UFS link established\n");