fix(ufs): add reset before DME_LINKSTARTUP

This change aims to make the UFS code more robust by performing a
controller reset if linkstartup fails. This idea was borrowed from
Linux's ufshcd_link_startup function.

Signed-off-by: Jorge Troncoso <jatron@google.com>
Change-Id: I6b52148d1bf155b11198dc82a39b1120057adaaf
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 695a614..ae42e32 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -169,18 +169,30 @@
 	return 0;
 }
 
-static int ufshc_link_startup(uintptr_t base)
+static int ufshc_dme_link_startup(uintptr_t base)
 {
 	uic_cmd_t cmd;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.op = DME_LINKSTARTUP;
+	return ufshc_send_uic_cmd(base, &cmd);
+}
+
+static int ufshc_link_startup(uintptr_t base)
+{
 	int data, result;
 	int retries;
 
-	for (retries = 10; retries > 0; retries--) {
-		memset(&cmd, 0, sizeof(cmd));
-		cmd.op = DME_LINKSTARTUP;
-		result = ufshc_send_uic_cmd(base, &cmd);
-		if (result != 0)
+	for (retries = DME_LINKSTARTUP_RETRIES; retries > 0; retries--) {
+		result = ufshc_dme_link_startup(base);
+		if (result != 0) {
+			/* Reset controller before trying again */
+			result = ufshc_reset(base);
+			if (result != 0) {
+				return result;
+			}
 			continue;
+		}
 		while ((mmio_read_32(base + HCS) & HCS_DP) == 0)
 			;
 		data = mmio_read_32(base + IS);
diff --git a/include/drivers/ufs.h b/include/drivers/ufs.h
index 686d4c6..c074e85 100644
--- a/include/drivers/ufs.h
+++ b/include/drivers/ufs.h
@@ -258,6 +258,9 @@
 /* maximum number of retries for a general UIC command  */
 #define UFS_UIC_COMMAND_RETRIES		3
 
+/* maximum number of link-startup retries */
+#define DME_LINKSTARTUP_RETRIES		10
+
 #define HCE_ENABLE_OUTER_RETRIES	3
 #define HCE_ENABLE_INNER_RETRIES	50
 #define HCE_ENABLE_TIMEOUT_US		100