Merge branch 'master' of git://git.denx.de/u-boot-sunxi
[oweals/u-boot.git] / drivers / usb / host / ehci-omap.c
index c4ce4870875b14fbf0f9da97a680c1bcbe7617e7..ab459c8cc927cb1a954c2ee21de03b296d84698e 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2011 Ilya Yanok, Emcraft Systems
  * (C) Copyright 2004-2008
@@ -7,8 +8,6 @@
  *     Sunil Kumar <sunilsaini05@gmail.com>
  *     Shashi Ranjan <shashiranjanmca05@gmail.com>
  *
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
@@ -28,21 +27,48 @@ static struct omap_ehci *const ehci = (struct omap_ehci *)OMAP_EHCI_BASE;
 
 static int omap_uhh_reset(void)
 {
-/*
- * Soft resetting the UHH module causes instability issues on
- * all OMAPs so we just avoid it.
- *
- * See OMAP36xx Errata
- *  i571: USB host EHCI may stall when entering smart-standby mode
- *  i660: USBHOST Configured In Smart-Idle Can Lead To a Deadlock
- *
- * On OMAP4/5, soft-resetting the UHH module will put it into
- * Smart-Idle mode and lead to a deadlock.
- *
- * On OMAP3, this doesn't seem to be the case but still instabilities
- * are observed on beagle (3530 ES1.0) if soft-reset is used.
- * e.g. NFS root failures with Linux kernel.
- */
+       int timeout = 0;
+       u32 rev;
+
+       rev = readl(&uhh->rev);
+
+       /* Soft RESET */
+       writel(OMAP_UHH_SYSCONFIG_SOFTRESET, &uhh->sysc);
+
+       switch (rev) {
+       case OMAP_USBHS_REV1:
+               /* Wait for soft RESET to complete */
+               while (!(readl(&uhh->syss) & 0x1)) {
+                       if (timeout > 100) {
+                               printf("%s: RESET timeout\n", __func__);
+                               return -1;
+                       }
+                       udelay(10);
+                       timeout++;
+               }
+
+               /* Set No-Idle, No-Standby */
+               writel(OMAP_UHH_SYSCONFIG_VAL, &uhh->sysc);
+               break;
+
+       default:        /* Rev. 2 onwards */
+
+               udelay(2); /* Need to wait before accessing SYSCONFIG back */
+
+               /* Wait for soft RESET to complete */
+               while ((readl(&uhh->sysc) & 0x1)) {
+                       if (timeout > 100) {
+                               printf("%s: RESET timeout\n", __func__);
+                               return -1;
+                       }
+                       udelay(10);
+                       timeout++;
+               }
+
+               writel(OMAP_UHH_SYSCONFIG_VAL, &uhh->sysc);
+               break;
+       }
+
        return 0;
 }