drivers:ufs: fix hynix ufs bug with quirk on hi36xx SoC

Hynix ufs has deviations on hi36xx platform which will result
in ufs bursts transfer failures at a very low probability.

To fix the problem, the Hynix device must set the register
VS_DebugSaveConfigTime to 0x10, which will set time reference
for SaveConfigTime is 250 ns. The time reference for SaveConfigTime
is 40 ns by default.

Signed-off-by: fengbaopeng <fengbaopeng@hisilicon.com>
diff --git a/drivers/synopsys/ufs/dw_ufs.c b/drivers/synopsys/ufs/dw_ufs.c
index d8ed5b6..b0ea3e7 100644
--- a/drivers/synopsys/ufs/dw_ufs.c
+++ b/drivers/synopsys/ufs/dw_ufs.c
@@ -97,10 +97,21 @@
 	int result;
 	unsigned int data, tx_lanes, rx_lanes;
 	uintptr_t base;
+	unsigned int flags;
 
 	assert((params != NULL) && (params->reg_base != 0));
 
 	base = params->reg_base;
+	flags = params->flags;
+	if ((flags & UFS_FLAGS_VENDOR_SKHYNIX) != 0U) {
+		NOTICE("ufs: H**** device must set VS_DebugSaveConfigTime 0x10\n");
+		/* VS_DebugSaveConfigTime */
+		result = ufshc_dme_set(0xd0a0, 0x0, 0x10);
+		assert(result == 0);
+		/* sync length */
+		result = ufshc_dme_set(0x1556, 0x0, 0x48);
+		assert(result == 0);
+	}
 
 	result = ufshc_dme_get(PA_TACTIVATE_OFFSET, 0, &data);
 	assert(result == 0);
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index d513d0a..254866f 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -705,11 +705,27 @@
 	}
 }
 
+static void ufs_get_device_info(struct ufs_dev_desc *card_data)
+{
+	uint8_t desc_buf[DESC_DEVICE_MAX_SIZE];
+
+	ufs_query(QUERY_READ_DESC, DESC_TYPE_DEVICE, 0, 0,
+				(uintptr_t)desc_buf, DESC_DEVICE_MAX_SIZE);
+
+	/*
+	 * getting vendor (manufacturerID) and Bank Index in big endian
+	 * format
+	 */
+	card_data->wmanufacturerid = (uint16_t)((desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8) |
+				     (desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1]));
+}
+
 int ufs_init(const ufs_ops_t *ops, ufs_params_t *params)
 {
 	int result;
 	unsigned int data;
 	uic_cmd_t cmd;
+	struct ufs_dev_desc card = {0};
 
 	assert((params != NULL) &&
 	       (params->reg_base != 0) &&
@@ -750,10 +766,17 @@
 		ops->phy_init(&ufs_params);
 		result = ufshc_link_startup(ufs_params.reg_base);
 		assert(result == 0);
+
+		ufs_enum();
+
+		ufs_get_device_info(&card);
+		if (card.wmanufacturerid == UFS_VENDOR_SKHYNIX) {
+			ufs_params.flags |= UFS_FLAGS_VENDOR_SKHYNIX;
+		}
+
 		ops->phy_set_pwr_mode(&ufs_params);
 	}
 
-	ufs_enum();
 	(void)result;
 	return 0;
 }
diff --git a/include/drivers/ufs.h b/include/drivers/ufs.h
index 3a4f1c7..88dedc5 100644
--- a/include/drivers/ufs.h
+++ b/include/drivers/ufs.h
@@ -7,6 +7,8 @@
 #ifndef __UFS_H__
 #define __UFS_H__
 
+#include <utils_def.h>
+
 /* register map of UFSHCI */
 /* Controller Capabilities */
 #define CAP				0x00
@@ -214,6 +216,9 @@
 #define DESC_TYPE_INTERCONNECT		0x04
 #define DESC_TYPE_STRING		0x05
 
+#define DESC_DEVICE_MAX_SIZE		0x1F
+#define DEVICE_DESC_PARAM_MANF_ID	0x18
+
 #define ATTR_CUR_PWR_MODE		0x02	/* bCurrentPowerMode */
 #define ATTR_ACTIVECC			0x03	/* bActiveICCLevel */
 
@@ -246,8 +251,22 @@
 
 #define FLAG_DEVICE_INIT		0x01
 
+#define UFS_VENDOR_SKHYNIX		U(0x1AD)
+
+#define MAX_MODEL_LEN 16
+/**
+ * ufs_dev_desc - ufs device details from the device descriptor
+ * @wmanufacturerid: card details
+ * @model: card model
+ */
+struct ufs_dev_desc {
+	uint16_t wmanufacturerid;
+	int8_t model[MAX_MODEL_LEN + 1];
+};
+
 /* UFS Driver Flags */
 #define UFS_FLAGS_SKIPINIT		(1 << 0)
+#define UFS_FLAGS_VENDOR_SKHYNIX	(U(1) << 2)
 
 typedef struct sense_data {
 	uint8_t		resp_code : 7;