[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)
committerhskang <hs1218.kang@samsung.com>
Fri, 5 Apr 2019 08:31:07 +0000 (17:31 +0900)
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 91410acaa9f1781004198cdd180bc285ef6d8613..17b32bc5219289627f7637b1fb5f42240d67b256 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"
@@ -202,6 +203,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);
@@ -217,6 +219,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 0b5ddcaced3106d5e1e99e58f8b2ce59dbc3fbce..ed0ee31db676b209f385ef43e932ddcad2220e9c 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"
@@ -249,6 +251,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;
@@ -5422,6 +5426,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;
@@ -5446,6 +5451,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;
@@ -6711,19 +6722,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");