ehci-omap: Clean up added ehci-omap.c
authorGovindraj.R <govindraj.raja@ti.com>
Mon, 6 Feb 2012 03:55:34 +0000 (03:55 +0000)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Sun, 12 Feb 2012 09:11:31 +0000 (10:11 +0100)
Clean up added ehci-omap.c and make it generic for re-use across
omap-soc having same ehci ip block. Also pass the modes to be configured
from board file and configure the ports accordingly. All usb layers
are not cache aligned, till then keep cache off for usb ops as ehci will use
internally dma for all usb ops.

* Add a generic common header ehci-omap.h having common ip block
  data and reg shifts.
* Rename and modify ehci-omap3 to ehci.h retain only conflicting
  sysc reg shifts remove others and move to common header file.
* pass the board data for beagle/panda accordinly to use
  ehci ports.

Acked-by: Igor Grinberg <grinberg@compulab.co.il>
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
arch/arm/include/asm/arch-omap3/ehci.h [new file with mode: 0644]
arch/arm/include/asm/arch-omap3/ehci_omap3.h [deleted file]
arch/arm/include/asm/arch-omap4/ehci.h [new file with mode: 0644]
arch/arm/include/asm/ehci-omap.h [new file with mode: 0644]
board/ti/beagle/beagle.c
board/ti/panda/panda.c
drivers/usb/host/ehci-omap.c

diff --git a/arch/arm/include/asm/arch-omap3/ehci.h b/arch/arm/include/asm/arch-omap3/ehci.h
new file mode 100644 (file)
index 0000000..0f73d20
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * (C) Copyright 2011
+ * Alexander Holler <holler@ahsoftware.de>
+ *
+ * Based on "drivers/usb/host/ehci-omap.c" from Linux 2.6.37
+ *
+ * See there for additional Copyrights.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+#ifndef _OMAP3_EHCI_H_
+#define _OMAP3_EHCI_H_
+
+/* USB/EHCI registers */
+#define OMAP_USBTLL_BASE                               0x48062000UL
+#define OMAP_UHH_BASE                                  0x48064000UL
+#define OMAP_EHCI_BASE                                 0x48064800UL
+
+/* TLL Register Set */
+#define OMAP_USBTLL_SYSCONFIG_SOFTRESET                        (1 << 1)
+#define OMAP_USBTLL_SYSCONFIG_ENAWAKEUP                        (1 << 2)
+#define OMAP_USBTLL_SYSCONFIG_SIDLEMODE                        (1 << 3)
+#define OMAP_USBTLL_SYSCONFIG_CACTIVITY                        (1 << 8)
+#define OMAP_USBTLL_SYSSTATUS_RESETDONE                        1
+
+/* UHH Register Set */
+#define OMAP_UHH_SYSCONFIG_SOFTRESET                   (1 << 1)
+#define OMAP_UHH_SYSCONFIG_CACTIVITY                   (1 << 8)
+#define OMAP_UHH_SYSCONFIG_SIDLEMODE                   (1 << 3)
+#define OMAP_UHH_SYSCONFIG_ENAWAKEUP                   (1 << 2)
+#define OMAP_UHH_SYSCONFIG_MIDLEMODE                   (1 << 12)
+#define OMAP_UHH_SYSSTATUS_EHCI_RESETDONE              (1 << 2)
+
+#define OMAP_UHH_SYSCONFIG_VAL         (OMAP_UHH_SYSCONFIG_CACTIVITY | \
+                                       OMAP_UHH_SYSCONFIG_SIDLEMODE | \
+                                       OMAP_UHH_SYSCONFIG_ENAWAKEUP | \
+                                       OMAP_UHH_SYSCONFIG_MIDLEMODE)
+
+#endif /* _OMAP3_EHCI_H_ */
diff --git a/arch/arm/include/asm/arch-omap3/ehci_omap3.h b/arch/arm/include/asm/arch-omap3/ehci_omap3.h
deleted file mode 100644 (file)
index cd01f50..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * (C) Copyright 2011
- * Alexander Holler <holler@ahsoftware.de>
- *
- * Based on "drivers/usb/host/ehci-omap.c" from Linux 2.6.37
- *
- * See there for additional Copyrights.
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * 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 the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301 USA
- */
-#ifndef _EHCI_OMAP3_H_
-#define _EHCI_OMAP3_H_
-
-/* USB/EHCI registers */
-#define OMAP3_USBTLL_BASE                              0x48062000UL
-#define OMAP3_UHH_BASE                                 0x48064000UL
-#define OMAP3_EHCI_BASE                                        0x48064800UL
-
-/* TLL Register Set */
-#define        OMAP_USBTLL_SYSCONFIG                           (0x10)
-#define        OMAP_USBTLL_SYSCONFIG_SOFTRESET                 (1 << 1)
-#define        OMAP_USBTLL_SYSCONFIG_ENAWAKEUP                 (1 << 2)
-#define        OMAP_USBTLL_SYSCONFIG_SIDLEMODE                 (1 << 3)
-#define        OMAP_USBTLL_SYSCONFIG_CACTIVITY                 (1 << 8)
-
-#define        OMAP_USBTLL_SYSSTATUS                           (0x14)
-#define        OMAP_USBTLL_SYSSTATUS_RESETDONE                 (1 << 0)
-
-/* UHH Register Set */
-#define        OMAP_UHH_SYSCONFIG                              (0x10)
-#define        OMAP_UHH_SYSCONFIG_SOFTRESET                    (1 << 1)
-#define        OMAP_UHH_SYSCONFIG_CACTIVITY                    (1 << 8)
-#define        OMAP_UHH_SYSCONFIG_SIDLEMODE                    (1 << 3)
-#define        OMAP_UHH_SYSCONFIG_ENAWAKEUP                    (1 << 2)
-#define        OMAP_UHH_SYSCONFIG_MIDLEMODE                    (1 << 12)
-
-#define        OMAP_UHH_HOSTCONFIG                             (0x40)
-#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN             (1 << 2)
-#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN             (1 << 3)
-#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN            (1 << 4)
-
-#endif /* _EHCI_OMAP3_H_ */
diff --git a/arch/arm/include/asm/arch-omap4/ehci.h b/arch/arm/include/asm/arch-omap4/ehci.h
new file mode 100644 (file)
index 0000000..984c8b9
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * OMAP EHCI port support
+ * Based on LINUX KERNEL
+ * drivers/usb/host/ehci-omap.c and drivers/mfd/omap-usb-host.c
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Govindraj R <govindraj.raja@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _OMAP4_EHCI_H_
+#define _OMAP4_EHCI_H_
+
+#define OMAP_EHCI_BASE                         (OMAP44XX_L4_CORE_BASE + 0x64C00)
+#define OMAP_UHH_BASE                          (OMAP44XX_L4_CORE_BASE + 0x64000)
+#define OMAP_USBTLL_BASE                       (OMAP44XX_L4_CORE_BASE + 0x62000)
+
+/* UHH, TLL and opt clocks */
+#define CM_L3INIT_HSUSBHOST_CLKCTRL            0x4A009358UL
+
+#define HSUSBHOST_CLKCTRL_CLKSEL_UTMI_P1_MASK  (1 << 24)
+
+/* TLL Register Set */
+#define OMAP_USBTLL_SYSCONFIG_SIDLEMODE                (1 << 3)
+#define OMAP_USBTLL_SYSCONFIG_ENAWAKEUP                (1 << 2)
+#define OMAP_USBTLL_SYSCONFIG_SOFTRESET                (1 << 1)
+#define OMAP_USBTLL_SYSCONFIG_CACTIVITY                (1 << 8)
+#define OMAP_USBTLL_SYSSTATUS_RESETDONE                1
+
+#define OMAP_UHH_SYSCONFIG_SOFTRESET           1
+#define OMAP_UHH_SYSSTATUS_EHCI_RESETDONE      (1 << 2)
+#define OMAP_UHH_SYSCONFIG_NOIDLE              (1 << 2)
+#define OMAP_UHH_SYSCONFIG_NOSTDBY             (1 << 4)
+
+#define OMAP_UHH_SYSCONFIG_VAL (OMAP_UHH_SYSCONFIG_NOIDLE | \
+                                       OMAP_UHH_SYSCONFIG_NOSTDBY)
+
+#endif /* _OMAP4_EHCI_H_ */
diff --git a/arch/arm/include/asm/ehci-omap.h b/arch/arm/include/asm/ehci-omap.h
new file mode 100644 (file)
index 0000000..e72c5df
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * OMAP EHCI port support
+ * Based on LINUX KERNEL
+ * drivers/usb/host/ehci-omap.c and drivers/mfd/omap-usb-host.c
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com*
+ * Author: Govindraj R <govindraj.raja@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _OMAP_COMMON_EHCI_H_
+#define _OMAP_COMMON_EHCI_H_
+
+enum usbhs_omap_port_mode {
+       OMAP_USBHS_PORT_MODE_UNUSED,
+       OMAP_EHCI_PORT_MODE_PHY,
+       OMAP_EHCI_PORT_MODE_TLL,
+       OMAP_EHCI_PORT_MODE_HSIC,
+};
+
+#ifdef CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS
+#define OMAP_HS_USB_PORTS      CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS
+#else
+#define OMAP_HS_USB_PORTS      3
+#endif
+
+#define is_ehci_phy_mode(x)    ((x) == OMAP_EHCI_PORT_MODE_PHY)
+#define is_ehci_tll_mode(x)    ((x) == OMAP_EHCI_PORT_MODE_TLL)
+#define is_ehci_hsic_mode(x)   ((x) == OMAP_EHCI_PORT_MODE_HSIC)
+
+/* Values of UHH_REVISION - Note: these are not given in the TRM */
+#define OMAP_USBHS_REV1                                        0x00000010 /* OMAP3 */
+#define OMAP_USBHS_REV2                                        0x50700100 /* OMAP4 */
+
+/* UHH Register Set */
+#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN             (1 << 2)
+#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN             (1 << 3)
+#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN            (1 << 4)
+#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN             (1 << 5)
+
+#define OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS             1
+#define OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS             (1 << 11)
+#define OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS             (1 << 12)
+#define OMAP4_UHH_HOSTCONFIG_APP_START_CLK             (1 << 31)
+
+#define OMAP_P1_MODE_CLEAR                             (3 << 16)
+#define OMAP_P1_MODE_TLL                               (1 << 16)
+#define OMAP_P1_MODE_HSIC                              (3 << 16)
+#define OMAP_P2_MODE_CLEAR                             (3 << 18)
+#define OMAP_P2_MODE_TLL                               (1 << 18)
+#define OMAP_P2_MODE_HSIC                              (3 << 18)
+#define OMAP_P3_MODE_HSIC                              (3 << 20)
+
+/* EHCI Register Set */
+#define EHCI_INSNREG04_DISABLE_UNSUSPEND               (1 << 5)
+#define EHCI_INSNREG05_ULPI_CONTROL_SHIFT              31
+#define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT              24
+#define EHCI_INSNREG05_ULPI_OPSEL_SHIFT                        22
+#define EHCI_INSNREG05_ULPI_REGADD_SHIFT               16
+
+#define OMAP_REV1_TLL_CHANNEL_COUNT                    3
+#define OMAP_REV2_TLL_CHANNEL_COUNT                    2
+
+/* TLL Register Set */
+#define OMAP_TLL_CHANNEL_CONF(num)                     (0x004 * num)
+#define OMAP_TLL_CHANNEL_CONF_DRVVBUS                  (1 << 16)
+#define OMAP_TLL_CHANNEL_CONF_CHRGVBUS                 (1 << 15)
+#define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF           (1 << 11)
+#define OMAP_TLL_CHANNEL_CONF_CHANMODE_TRANSPARENT_UTMI        (2 << 1)
+#define OMAP_TLL_CHANNEL_CONF_CHANEN                   1
+
+struct omap_usbhs_board_data {
+       enum usbhs_omap_port_mode port_mode[OMAP_HS_USB_PORTS];
+};
+
+struct omap_usbtll {
+       u32 rev;                /* 0x00 */
+       u32 hwinfo;             /* 0x04 */
+       u8 reserved1[0x8];
+       u32 sysc;               /* 0x10 */
+       u32 syss;               /* 0x14 */
+       u32 irqst;              /* 0x18 */
+       u32 irqen;              /* 0x1c */
+       u8 reserved2[0x10];
+       u32 shared_conf;        /* 0x30 */
+       u8 reserved3[0xc];
+       u32 channel_conf;       /* 0x40 */
+};
+
+struct omap_uhh {
+       u32 rev;        /* 0x00 */
+       u32 hwinfo;     /* 0x04 */
+       u8 reserved1[0x8];
+       u32 sysc;       /* 0x10 */
+       u32 syss;       /* 0x14 */
+       u8 reserved2[0x28];
+       u32 hostconfig; /* 0x40 */
+       u32 debugcsr;   /* 0x44 */
+};
+
+struct omap_ehci {
+       u32 hccapbase;          /* 0x00 */
+       u32 hcsparams;          /* 0x04 */
+       u32 hccparams;          /* 0x08 */
+       u8 reserved1[0x04];
+       u32 usbcmd;             /* 0x10 */
+       u32 usbsts;             /* 0x14 */
+       u32 usbintr;            /* 0x18 */
+       u32 frindex;            /* 0x1c */
+       u32 ctrldssegment;      /* 0x20 */
+       u32 periodiclistbase;   /* 0x24 */
+       u32 asysnclistaddr;     /* 0x28 */
+       u8 reserved2[0x24];
+       u32 configflag;         /* 0x50 */
+       u32 portsc_i;           /* 0x54 */
+       u8 reserved3[0x38];
+       u32 insreg00;           /* 0x90 */
+       u32 insreg01;           /* 0x94 */
+       u32 insreg02;           /* 0x98 */
+       u32 insreg03;           /* 0x9c */
+       u32 insreg04;           /* 0xa0 */
+       u32 insreg05_utmi_ulpi; /* 0xa4 */
+       u32 insreg06;           /* 0xa8 */
+       u32 insreg07;           /* 0xac */
+       u32 insreg08;           /* 0xb0 */
+};
+
+int omap_ehci_hcd_init(struct omap_usbhs_board_data *usbhs_pdata);
+int omap_ehci_hcd_stop(void);
+
+#endif /* _OMAP_COMMON_EHCI_H_ */
index 624ff70d86402dd97bddae2f529391d3c53a0054..87578763bb737eaf656370fd3dfa18a7eace9146 100644 (file)
 #include "beagle.h"
 #include <command.h>
 
+#ifdef CONFIG_USB_EHCI
+#include <usb.h>
+#include <asm/ehci-omap.h>
+#endif
+
 #define pr_debug(fmt, args...) debug(fmt, ##args)
 
 #define TWL4030_I2C_BUS                        0
@@ -449,6 +454,23 @@ void show_boot_progress(int val)
        if(val == 15)
                usb_stop();
 }
+
+static struct omap_usbhs_board_data usbhs_bdata = {
+       .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+       .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED
+};
+
+int ehci_hcd_init(void)
+{
+       return omap_ehci_hcd_init(&usbhs_bdata);
+}
+
+int ehci_hcd_stop(void)
+{
+       return omap_ehci_hcd_stop();
+}
+
 #endif /* CONFIG_USB_EHCI */
 
 #ifndef CONFIG_SPL_BUILD
index fc8c0b4bc603f23e6ab9bf9bfd3eba717e713691..ca4b8b35ebdb51ab1d630a8c719046ef9693f0d2 100644 (file)
 #include <asm/arch/mmc_host_def.h>
 #include <asm/arch/clocks.h>
 #include <asm/arch/gpio.h>
+#include <asm/gpio.h>
 
 #include "panda_mux_data.h"
 
+#ifdef CONFIG_USB_EHCI
+#include <usb.h>
+#include <asm/arch/ehci.h>
+#include <asm/ehci-omap.h>
+#endif
+
 #define PANDA_ULPI_PHY_TYPE_GPIO       182
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -177,6 +184,37 @@ int board_mmc_init(bd_t *bis)
 }
 #endif
 
+#ifdef CONFIG_USB_EHCI
+
+static struct omap_usbhs_board_data usbhs_bdata = {
+       .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+       .port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
+};
+
+int ehci_hcd_init(void)
+{
+       int ret;
+       unsigned int utmi_clk;
+
+       /* Now we can enable our port clocks */
+       utmi_clk = readl((void *)CM_L3INIT_HSUSBHOST_CLKCTRL);
+       utmi_clk |= HSUSBHOST_CLKCTRL_CLKSEL_UTMI_P1_MASK;
+       sr32((void *)CM_L3INIT_HSUSBHOST_CLKCTRL, 0, 32, utmi_clk);
+
+       ret = omap_ehci_hcd_init(&usbhs_bdata);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+int ehci_hcd_stop(void)
+{
+       return omap_ehci_hcd_stop();
+}
+#endif
+
 /*
  * get_board_rev() - get board revision
  */
index 93d3bb7344dee8206d76b89d2d7793ce4316f430..00f787fc9701c8e5b71a38cf59b6cd8e1c8ef00b 100644 (file)
  */
 #include <common.h>
 #include <usb.h>
+#include <usb/ulpi.h>
+#include <errno.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
-#include <asm/arch/clocks.h>
-#include <asm/arch/clocks_omap3.h>
-#include <asm/arch/ehci_omap3.h>
-#include <asm/arch/sys_proto.h>
+#include <asm/arch/ehci.h>
+#include <asm/ehci-omap.h>
 #include "ehci-core.h"
 
+static struct omap_uhh *const uhh = (struct omap_uhh *)OMAP_UHH_BASE;
+static struct omap_usbtll *const usbtll = (struct omap_usbtll *)OMAP_USBTLL_BASE;
+static struct omap_ehci *const ehci = (struct omap_ehci *)OMAP_EHCI_BASE;
+
+static int omap_uhh_reset(void)
+{
+       unsigned long init = get_timer(0);
+
+       /* perform UHH soft reset, and wait until reset is complete */
+       writel(OMAP_UHH_SYSCONFIG_SOFTRESET, &uhh->sysc);
+
+       /* Wait for UHH reset to complete */
+       while (!(readl(&uhh->syss) & OMAP_UHH_SYSSTATUS_EHCI_RESETDONE))
+               if (get_timer(init) > CONFIG_SYS_HZ) {
+                       debug("OMAP UHH error: timeout resetting ehci\n");
+                       return -EL3RST;
+               }
+
+       return 0;
+}
+
+static int omap_ehci_tll_reset(void)
+{
+       unsigned long init = get_timer(0);
+
+       /* perform TLL soft reset, and wait until reset is complete */
+       writel(OMAP_USBTLL_SYSCONFIG_SOFTRESET, &usbtll->sysc);
+
+       /* Wait for TLL reset to complete */
+       while (!(readl(&usbtll->syss) & OMAP_USBTLL_SYSSTATUS_RESETDONE))
+               if (get_timer(init) > CONFIG_SYS_HZ) {
+                       debug("OMAP EHCI error: timeout resetting TLL\n");
+                       return -EL3RST;
+       }
+
+       return 0;
+}
+
+static void omap_usbhs_hsic_init(int port)
+{
+       unsigned int reg;
+
+       /* Enable channels now */
+       reg = readl(&usbtll->channel_conf + port);
+
+       setbits_le32(&reg, (OMAP_TLL_CHANNEL_CONF_CHANMODE_TRANSPARENT_UTMI
+               | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
+               | OMAP_TLL_CHANNEL_CONF_DRVVBUS
+               | OMAP_TLL_CHANNEL_CONF_CHRGVBUS
+               | OMAP_TLL_CHANNEL_CONF_CHANEN));
+
+       writel(reg, &usbtll->channel_conf + port);
+}
+
+static void omap_ehci_soft_phy_reset(int port)
+{
+       struct ulpi_viewport ulpi_vp;
+
+       ulpi_vp.viewport_addr = (u32)&ehci->insreg05_utmi_ulpi;
+       ulpi_vp.port_num = port;
+
+       ulpi_reset(&ulpi_vp);
+}
+
 inline int __board_usb_init(void)
 {
        return 0;
@@ -72,31 +136,31 @@ static inline void omap_ehci_phy_reset(int on, int delay)
 #endif
 
 /* Reset is needed otherwise the kernel-driver will throw an error. */
-int ehci_hcd_stop(void)
+int omap_ehci_hcd_stop(void)
 {
-       debug("Resetting OMAP3 EHCI\n");
+       debug("Resetting OMAP EHCI\n");
        omap_ehci_phy_reset(1, 0);
-       writel(OMAP_UHH_SYSCONFIG_SOFTRESET,
-                       OMAP3_UHH_BASE + OMAP_UHH_SYSCONFIG);
-       /* disable USB clocks */
-       struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
-       sr32(&prcm_base->iclken_usbhost, 0, 1, 0);
-       sr32(&prcm_base->fclken_usbhost, 0, 2, 0);
-       sr32(&prcm_base->iclken3_core, 2, 1, 0);
-       sr32(&prcm_base->fclken3_core, 2, 1, 0);
+
+       if (omap_uhh_reset() < 0)
+               return -1;
+
+       if (omap_ehci_tll_reset() < 0)
+               return -1;
+
        return 0;
 }
 
 /*
- * Initialize the OMAP3 EHCI controller and PHY.
- * Based on "drivers/usb/host/ehci-omap.c" from Linux 2.6.37.
+ * Initialize the OMAP EHCI controller and PHY.
+ * Based on "drivers/usb/host/ehci-omap.c" from Linux 3.1
  * See there for additional Copyrights.
  */
-int ehci_hcd_init(void)
+int omap_ehci_hcd_init(struct omap_usbhs_board_data *usbhs_pdata)
 {
        int ret;
+       unsigned int i, reg = 0, rev = 0;
 
-       debug("Initializing OMAP3 EHCI\n");
+       debug("Initializing OMAP EHCI\n");
 
        ret = board_usb_init();
        if (ret < 0)
@@ -105,52 +169,87 @@ int ehci_hcd_init(void)
        /* Put the PHY in RESET */
        omap_ehci_phy_reset(1, 10);
 
-       struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
-       /* Enable USBHOST_L3_ICLK (USBHOST_MICLK) */
-       sr32(&prcm_base->iclken_usbhost, 0, 1, 1);
-       /*
-        * Enable USBHOST_48M_FCLK (USBHOST_FCLK1)
-        * and USBHOST_120M_FCLK (USBHOST_FCLK2)
-        */
-       sr32(&prcm_base->fclken_usbhost, 0, 2, 3);
-       /* Enable USBTTL_ICLK */
-       sr32(&prcm_base->iclken3_core, 2, 1, 1);
-       /* Enable USBTTL_FCLK */
-       sr32(&prcm_base->fclken3_core, 2, 1, 1);
-       debug("USB clocks enabled\n");
+       ret = omap_uhh_reset();
+       if (ret < 0)
+               return ret;
 
-       /* perform TLL soft reset, and wait until reset is complete */
-       writel(OMAP_USBTLL_SYSCONFIG_SOFTRESET,
-               OMAP3_USBTLL_BASE + OMAP_USBTLL_SYSCONFIG);
-       /* Wait for TLL reset to complete */
-       while (!(readl(OMAP3_USBTLL_BASE + OMAP_USBTLL_SYSSTATUS)
-                       & OMAP_USBTLL_SYSSTATUS_RESETDONE))
-               ;
-       debug("TLL reset done\n");
+       ret = omap_ehci_tll_reset();
+       if (ret)
+               return ret;
 
        writel(OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
                OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
-               OMAP_USBTLL_SYSCONFIG_CACTIVITY,
-               OMAP3_USBTLL_BASE + OMAP_USBTLL_SYSCONFIG);
+               OMAP_USBTLL_SYSCONFIG_CACTIVITY, &usbtll->sysc);
 
        /* Put UHH in NoIdle/NoStandby mode */
-       writel(OMAP_UHH_SYSCONFIG_ENAWAKEUP
-               | OMAP_UHH_SYSCONFIG_SIDLEMODE
-               | OMAP_UHH_SYSCONFIG_CACTIVITY
-               | OMAP_UHH_SYSCONFIG_MIDLEMODE,
-               OMAP3_UHH_BASE + OMAP_UHH_SYSCONFIG);
-
-       /* setup burst configurations */
-       writel(OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
-               | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
-               | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN,
-               OMAP3_UHH_BASE + OMAP_UHH_HOSTCONFIG);
+       writel(OMAP_UHH_SYSCONFIG_VAL, &uhh->sysc);
+
+       /* setup ULPI bypass and burst configurations */
+       clrsetbits_le32(&reg, OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN,
+               (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN |
+               OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN |
+               OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN));
+
+       rev = readl(&uhh->rev);
+       if (rev == OMAP_USBHS_REV1) {
+               if (is_ehci_phy_mode(usbhs_pdata->port_mode[0]))
+                       clrbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS);
+               else
+                       setbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS);
+
+               if (is_ehci_phy_mode(usbhs_pdata->port_mode[1]))
+                       clrbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS);
+               else
+                       setbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS);
+
+               if (is_ehci_phy_mode(usbhs_pdata->port_mode[2]))
+                       clrbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS);
+               else
+                       setbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS);
+       } else if (rev == OMAP_USBHS_REV2) {
+               clrsetbits_le32(&reg, (OMAP_P1_MODE_CLEAR | OMAP_P2_MODE_CLEAR),
+                                       OMAP4_UHH_HOSTCONFIG_APP_START_CLK);
+
+               /* Clear port mode fields for PHY mode*/
+
+               if (is_ehci_hsic_mode(usbhs_pdata->port_mode[0]))
+                       setbits_le32(&reg, OMAP_P1_MODE_HSIC);
+
+               if (is_ehci_hsic_mode(usbhs_pdata->port_mode[1]))
+                       setbits_le32(&reg, OMAP_P2_MODE_HSIC);
+
+               if (is_ehci_hsic_mode(usbhs_pdata->port_mode[2]))
+                       setbits_le32(&reg, OMAP_P3_MODE_HSIC);
+       }
+
+       debug("OMAP UHH_REVISION 0x%x\n", rev);
+       writel(reg, &uhh->hostconfig);
+
+       for (i = 0; i < OMAP_HS_USB_PORTS; i++)
+               if (is_ehci_hsic_mode(usbhs_pdata->port_mode[i]))
+                       omap_usbhs_hsic_init(i);
 
        omap_ehci_phy_reset(0, 10);
 
-       hccr = (struct ehci_hccr *)(OMAP3_EHCI_BASE);
-       hcor = (struct ehci_hcor *)(OMAP3_EHCI_BASE + 0x10);
+       /*
+        * An undocumented "feature" in the OMAP3 EHCI controller,
+        * causes suspended ports to be taken out of suspend when
+        * the USBCMD.Run/Stop bit is cleared (for example when
+        * we do ehci_bus_suspend).
+        * This breaks suspend-resume if the root-hub is allowed
+        * to suspend. Writing 1 to this undocumented register bit
+        * disables this feature and restores normal behavior.
+        */
+       writel(EHCI_INSNREG04_DISABLE_UNSUSPEND, &ehci->insreg04);
+
+       for (i = 0; i < OMAP_HS_USB_PORTS; i++)
+               if (is_ehci_phy_mode(usbhs_pdata->port_mode[i]))
+                       omap_ehci_soft_phy_reset(i);
+
+       dcache_disable();
+       hccr = (struct ehci_hccr *)(OMAP_EHCI_BASE);
+       hcor = (struct ehci_hcor *)(OMAP_EHCI_BASE + 0x10);
 
-       debug("OMAP3 EHCI init done\n");
+       debug("OMAP EHCI init done\n");
        return 0;
 }