From: Tero Kristo <t-kri...@ti.com>

Add a custom reset function for the usb_host_fs/fsusb IP block, and
connect it to the OMAP4 FSUSB block.

This is the first of two fixes required to get rid of the boot
warning:

omap_hwmod: usb_host_fs: _wait_target_disable failed

and to allow the module to idle.

It may be necessary to use this reset method for OMAP2xxx SoCs as
well; this is left for a future patch.

Signed-off-by: Tero Kristo <t-kri...@ti.com>
[p...@pwsan.com: rewrote the custom reset function, documented it and
 updated the commit message, and moved the code to mach-omap2/fs-usb.c]
Signed-off-by: Paul Walmsley <p...@pwsan.com>
Cc: BenoƮt Cousson <b-cous...@ti.com>
Cc: Felipe Balbi <ba...@ti.com>
---
 arch/arm/mach-omap2/Makefile               |    4 --
 arch/arm/mach-omap2/cm.h                   |    8 +++-
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    1 
 arch/arm/mach-omap2/usb-fs.c               |   62 ++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/usb.h      |    3 +
 5 files changed, 73 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index bc2ac4f..fc2ff91 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -245,9 +245,7 @@ omap-hsmmc-$(CONFIG_MMC_OMAP_HS)    := hsmmc.o
 obj-y                                  += $(omap-hsmmc-m) $(omap-hsmmc-y)
 
 
-usbfs-$(CONFIG_ARCH_OMAP_OTG)          := usb-fs.o
-obj-y                                  += $(usbfs-m) $(usbfs-y)
-obj-y                                  += usb-musb.o
+obj-y                                  += usb-fs.o usb-musb.o
 obj-y                                  += omap_phy_internal.o
 
 obj-$(CONFIG_MACH_OMAP2_TUSB6010)      += usb-tusb6010.o
diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h
index a7bc096..99978c7 100644
--- a/arch/arm/mach-omap2/cm.h
+++ b/arch/arm/mach-omap2/cm.h
@@ -1,7 +1,7 @@
 /*
  * OMAP2+ Clock Management prototypes
  *
- * Copyright (C) 2007-2009 Texas Instruments, Inc.
+ * Copyright (C) 2007-2012 Texas Instruments, Inc.
  * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Written by Paul Walmsley
@@ -14,6 +14,12 @@
 #define __ARCH_ASM_MACH_OMAP2_CM_H
 
 /*
+ * MAX_MODULE_SOFTRESET_TIME: maximum time in microseconds to wait for
+ * an IP block to finish an OCP SOFTRESET.
+ */
+#define MAX_MODULE_SOFTRESET_WAIT      10000
+
+/*
  * MAX_MODULE_READY_TIME: max duration in microseconds to wait for the
  * PRCM to request that a module exit the inactive state in the case of
  * OMAP2 & 3.
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c 
b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index a93ce48..02daacc 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -3314,6 +3314,7 @@ static struct omap_hwmod_class_sysconfig 
omap44xx_usb_host_fs_sysc = {
 static struct omap_hwmod_class omap44xx_usb_host_fs_hwmod_class = {
        .name   = "usb_host_fs",
        .sysc   = &omap44xx_usb_host_fs_sysc,
+       .reset  = omap_usb_host_fs_reset,
 };
 
 /* usb_host_fs */
diff --git a/arch/arm/mach-omap2/usb-fs.c b/arch/arm/mach-omap2/usb-fs.c
index 1481078..4faf0f7 100644
--- a/arch/arm/mach-omap2/usb-fs.c
+++ b/arch/arm/mach-omap2/usb-fs.c
@@ -1,7 +1,7 @@
 /*
  * Platform level USB initialization for FS USB OTG controller on omap1 and 
24xx
  *
- * Copyright (C) 2004 Texas Instruments, Inc.
+ * Copyright (C) 2004, 2012 Texas Instruments, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,6 +32,8 @@
 #include <plat/usb.h>
 #include <plat/board.h>
 
+#include "cm.h"
+#include "common.h"
 #include "control.h"
 #include "mux.h"
 
@@ -41,6 +43,64 @@
 #define INT_USB_IRQ_HGEN       INT_24XX_USB_IRQ_HGEN
 #define INT_USB_IRQ_OTG                INT_24XX_USB_IRQ_OTG
 
+/* HCCOMMANDSTATUS: the register offset of the HCCOMMANDSTATUS register */
+#define HCCOMMANDSTATUS                        0x0008
+
+/* HCCOMMANDSTATUS_HCR: the bitmask of the host controller reset flag */
+#define HCCOMMANDSTATUS_HCR_MASK       (1 << 0)
+
+/**
+ * omap_usb_host_fs_reset - custom reset function for the FSUSB IP block
+ * @oh: struct omap_hwmod * of the usb_host_fs IP block
+ *
+ * Reset the FSUSB IP block.  This IP block requires a custom
+ * two-stage reset; otherwise the IP block won't idle-ack to the PRCM.
+ * First the OCP SOFTRESET method must be used.  Next, the IP block's
+ * internal reset bit must be toggled.  This will place the OHCI
+ * controller state into UsbSuspend, which allows the IP block to
+ * idle-ack to the PRCM.  Note that the FSUSB still takes almost 4
+ * milliseconds to idle-ack after this function returns.  Returns 0
+ * upon success, -EINVAL if the IP block softreset data wasn't
+ * supplied, or -EBUSY if the IP block reset times out.
+ */
+int omap_usb_host_fs_reset(struct omap_hwmod *oh)
+{
+       int c;
+
+       if (omap_hwmod_softreset(oh))
+               return -EINVAL;
+
+       omap_test_timeout(!(omap_hwmod_read(oh, oh->class->sysc->sysc_offs)
+                          & SYSC_TYPE2_SOFTRESET_MASK),
+                         MAX_MODULE_SOFTRESET_WAIT, c);
+
+       if (c == MAX_MODULE_SOFTRESET_WAIT) {
+               pr_warn("%s: %s: softreset failed (waited %d usec)\n",
+                       __func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
+               return -EBUSY;
+       } else {
+               pr_debug("%s: %s: softreset in %d usec\n", __func__,
+                        oh->name, c);
+       }
+
+       omap_hwmod_write(HCCOMMANDSTATUS_HCR_MASK, oh, HCCOMMANDSTATUS);
+
+       omap_test_timeout(!(omap_hwmod_read(oh, HCCOMMANDSTATUS)
+                           & HCCOMMANDSTATUS_HCR_MASK),
+                         MAX_MODULE_SOFTRESET_WAIT, c);
+
+       if (c == MAX_MODULE_SOFTRESET_WAIT) {
+               pr_warn("%s: %s: host controller reset failed (waited %d 
usec)\n",
+                       __func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
+               return -EBUSY;
+       } else {
+               pr_debug("%s: %s: host controller reset in %d usec\n", __func__,
+                        oh->name, c);
+       }
+
+       return 0;
+}
+
 #if defined(CONFIG_ARCH_OMAP2)
 
 #ifdef CONFIG_USB_GADGET_OMAP
diff --git a/arch/arm/plat-omap/include/plat/usb.h 
b/arch/arm/plat-omap/include/plat/usb.h
index 762eeb0..ac7db50 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -6,6 +6,7 @@
 #include <linux/io.h>
 #include <linux/usb/musb.h>
 #include <plat/board.h>
+#include <plat/omap_hwmod.h>
 
 #define OMAP3_HS_USB_PORTS     3
 
@@ -181,6 +182,8 @@ static inline void omap2_usbfs_init(struct omap_usb_config 
*pdata)
 }
 #endif
 
+extern int omap_usb_host_fs_reset(struct omap_hwmod *oh);
+
 /*-------------------------------------------------------------------------*/
 
 /*


--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to