[PATCH 04/11] ARM: OMAP2+: usb_host_fs: add custom reset for usb_host_fs (fsusb)
Paul Walmsley
paul at pwsan.com
Thu Jun 7 02:13:09 EDT 2012
From: Tero Kristo <t-kristo at 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-kristo at ti.com>
[paul at 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 <paul at pwsan.com>
Cc: Benoît Cousson <b-cousson at ti.com>
Cc: Felipe Balbi <balbi at 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);
+
/*-------------------------------------------------------------------------*/
/*
More information about the linux-arm-kernel
mailing list