obj-$(CONFIG_ARCH_MX1) += clock-imx1.o mm-imx1.o
 obj-$(CONFIG_MACH_MX21) += clock-imx21.o mm-imx21.o
 
-obj-$(CONFIG_ARCH_MX25) += clock-imx25.o mm-imx25.o
+obj-$(CONFIG_ARCH_MX25) += clock-imx25.o mm-imx25.o ehci-imx25.o
 
 obj-$(CONFIG_MACH_MX27) += cpu-imx27.o pm-imx27.o
-obj-$(CONFIG_MACH_MX27) += clock-imx27.o mm-imx27.o
+obj-$(CONFIG_MACH_MX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO)        += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
 
--- /dev/null
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, 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 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define USBCTRL_OTGBASE_OFFSET 0x600
+
+#define MX25_OTG_SIC_SHIFT     29
+#define MX25_OTG_SIC_MASK      (0x3 << MX25_OTG_SIC_SHIFT)
+#define MX25_OTG_PM_BIT                (1 << 24)
+
+#define MX25_H1_SIC_SHIFT      21
+#define MX25_H1_SIC_MASK       (0x3 << MX25_H1_SIC_SHIFT)
+#define MX25_H1_PM_BIT         (1 << 8)
+#define MX25_H1_IPPUE_UP_BIT   (1 << 7)
+#define MX25_H1_IPPUE_DOWN_BIT (1 << 6)
+#define MX25_H1_TLL_BIT                (1 << 5)
+#define MX25_H1_USBTE_BIT      (1 << 4)
+
+int mx25_initialize_usb_hw(int port, unsigned int flags)
+{
+       unsigned int v;
+
+       v = readl(MX25_IO_ADDRESS(MX25_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+       switch (port) {
+       case 0: /* OTG port */
+               v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT);
+               v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
+
+               if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+                       v |= MX25_OTG_PM_BIT;
+
+               break;
+       case 1: /* H1 port */
+               v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_TLL_BIT |
+                       MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT | MX25_H1_IPPUE_UP_BIT);
+               v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
+
+               if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+                       v |= MX25_H1_PM_BIT;
+
+               if (!(flags & MXC_EHCI_TTL_ENABLED))
+                       v |= MX25_H1_TLL_BIT;
+
+               if (flags & MXC_EHCI_INTERNAL_PHY)
+                       v |= MX25_H1_USBTE_BIT;
+
+               if (flags & MXC_EHCI_IPPUE_DOWN)
+                       v |= MX25_H1_IPPUE_DOWN_BIT;
+
+               if (flags & MXC_EHCI_IPPUE_UP)
+                       v |= MX25_H1_IPPUE_UP_BIT;
+
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       writel(v, MX25_IO_ADDRESS(MX25_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+       return 0;
+}
+
 
--- /dev/null
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, 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 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define USBCTRL_OTGBASE_OFFSET 0x600
+
+#define MX27_OTG_SIC_SHIFT     29
+#define MX27_OTG_SIC_MASK      (0x3 << MX27_OTG_SIC_SHIFT)
+#define MX27_OTG_PM_BIT                (1 << 24)
+
+#define MX27_H2_SIC_SHIFT      21
+#define MX27_H2_SIC_MASK       (0x3 << MX27_H2_SIC_SHIFT)
+#define MX27_H2_PM_BIT         (1 << 16)
+#define MX27_H2_DT_BIT         (1 << 5)
+
+#define MX27_H1_SIC_SHIFT      13
+#define MX27_H1_SIC_MASK       (0x3 << MX27_H1_SIC_SHIFT)
+#define MX27_H1_PM_BIT         (1 << 8)
+#define MX27_H1_DT_BIT         (1 << 4)
+
+int mx27_initialize_usb_hw(int port, unsigned int flags)
+{
+       unsigned int v;
+
+       v = readl(MX27_IO_ADDRESS(MX27_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+       switch (port) {
+       case 0: /* OTG port */
+               v &= ~(MX27_OTG_SIC_MASK | MX27_OTG_PM_BIT);
+               v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX27_OTG_SIC_SHIFT;
+
+               if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+                       v |= MX27_OTG_PM_BIT;
+               break;
+       case 1: /* H1 port */
+               v &= ~(MX27_H1_SIC_MASK | MX27_H1_PM_BIT | MX27_H1_DT_BIT);
+               v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX27_H1_SIC_SHIFT;
+
+               if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+                       v |= MX27_H1_PM_BIT;
+
+               if (!(flags & MXC_EHCI_TTL_ENABLED))
+                       v |= MX27_H1_DT_BIT;
+
+               break;
+       case 2: /* H2 port */
+               v &= ~(MX27_H2_SIC_MASK | MX27_H2_PM_BIT | MX27_H2_DT_BIT);
+               v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX27_H2_SIC_SHIFT;
+
+               if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+                       v |= MX27_H2_PM_BIT;
+
+               if (!(flags & MXC_EHCI_TTL_ENABLED))
+                       v |= MX27_H2_DT_BIT;
+
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       writel(v, MX27_IO_ADDRESS(MX27_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+       return 0;
+}
+
 
 # Object file lists.
 
 obj-y                          := mm.o devices.o cpu.o
-obj-$(CONFIG_SOC_IMX31)                += clock-imx31.o iomux-imx31.o
-obj-$(CONFIG_SOC_IMX35)                += clock-imx35.o
+obj-$(CONFIG_SOC_IMX31)                += clock-imx31.o iomux-imx31.o ehci-imx31.o
+obj-$(CONFIG_SOC_IMX35)                += clock-imx35.o ehci-imx35.o
 obj-$(CONFIG_MACH_MX31ADS)     += mach-mx31ads.o
 obj-$(CONFIG_MACH_MX31LILLY)   += mach-mx31lilly.o mx31lilly-db.o
 obj-$(CONFIG_MACH_MX31LITE)    += mach-mx31lite.o mx31lite-db.o
 
--- /dev/null
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, 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 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define USBCTRL_OTGBASE_OFFSET 0x600
+
+#define MX31_OTG_SIC_SHIFT     29
+#define MX31_OTG_SIC_MASK      (0x3 << MX31_OTG_SIC_SHIFT)
+#define MX31_OTG_PM_BIT                (1 << 24)
+
+#define MX31_H2_SIC_SHIFT      21
+#define MX31_H2_SIC_MASK       (0x3 << MX31_H2_SIC_SHIFT)
+#define MX31_H2_PM_BIT         (1 << 16)
+#define MX31_H2_DT_BIT         (1 << 5)
+
+#define MX31_H1_SIC_SHIFT      13
+#define MX31_H1_SIC_MASK       (0x3 << MX31_H1_SIC_SHIFT)
+#define MX31_H1_PM_BIT         (1 << 8)
+#define MX31_H1_DT_BIT         (1 << 4)
+
+int mx31_initialize_usb_hw(int port, unsigned int flags)
+{
+       unsigned int v;
+
+       v = readl(MX31_IO_ADDRESS(MX31_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+       switch (port) {
+       case 0: /* OTG port */
+               v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
+               v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_OTG_SIC_SHIFT;
+
+               if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+                       v |= MX31_OTG_PM_BIT;
+
+               break;
+       case 1: /* H1 port */
+               v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
+               v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H1_SIC_SHIFT;
+
+               if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+                       v |= MX31_H1_PM_BIT;
+
+               if (!(flags & MXC_EHCI_TTL_ENABLED))
+                       v |= MX31_H1_DT_BIT;
+
+               break;
+       case 2: /* H2 port */
+               v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
+               v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H2_SIC_SHIFT;
+
+               if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+                       v |= MX31_H2_PM_BIT;
+
+               if (!(flags & MXC_EHCI_TTL_ENABLED))
+                       v |= MX31_H2_DT_BIT;
+
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       writel(v, MX31_IO_ADDRESS(MX31_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+       return 0;
+}
+
 
--- /dev/null
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, 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 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define USBCTRL_OTGBASE_OFFSET 0x600
+
+#define MX35_OTG_SIC_SHIFT     29
+#define MX35_OTG_SIC_MASK      (0x3 << MX35_OTG_SIC_SHIFT)
+#define MX35_OTG_PM_BIT                (1 << 24)
+
+#define MX35_H1_SIC_SHIFT      21
+#define MX35_H1_SIC_MASK       (0x3 << MX35_H1_SIC_SHIFT)
+#define MX35_H1_PM_BIT         (1 << 8)
+#define MX35_H1_IPPUE_UP_BIT   (1 << 7)
+#define MX35_H1_IPPUE_DOWN_BIT (1 << 6)
+#define MX35_H1_TLL_BIT                (1 << 5)
+#define MX35_H1_USBTE_BIT      (1 << 4)
+
+int mx35_initialize_usb_hw(int port, unsigned int flags)
+{
+       unsigned int v;
+
+       v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+       switch (port) {
+       case 0: /* OTG port */
+               v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
+               v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_OTG_SIC_SHIFT;
+
+               if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+                       v |= MX35_OTG_PM_BIT;
+
+               break;
+       case 1: /* H1 port */
+               v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
+                       MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
+               v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_H1_SIC_SHIFT;
+
+               if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+                       v |= MX35_H1_PM_BIT;
+
+               if (!(flags & MXC_EHCI_TTL_ENABLED))
+                       v |= MX35_H1_TLL_BIT;
+
+               if (flags & MXC_EHCI_INTERNAL_PHY)
+                       v |= MX35_H1_USBTE_BIT;
+
+               if (flags & MXC_EHCI_IPPUE_DOWN)
+                       v |= MX35_H1_IPPUE_DOWN_BIT;
+
+               if (flags & MXC_EHCI_IPPUE_UP)
+                       v |= MX35_H1_IPPUE_UP_BIT;
+
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       writel(v, MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+       return 0;
+}
+
 
 #
 
 # Object file lists.
-obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o
+obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o
 obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
 
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
 
--- /dev/null
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, 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 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define MXC_OTG_OFFSET                 0
+#define MXC_H1_OFFSET                  0x200
+#define MXC_H2_OFFSET                  0x400
+
+/* USB_CTRL */
+#define MXC_OTG_UCTRL_OWIE_BIT         (1 << 27)       /* OTG wakeup intr enable */
+#define MXC_OTG_UCTRL_OPM_BIT          (1 << 24)       /* OTG power mask */
+#define MXC_H1_UCTRL_H1UIE_BIT         (1 << 12)       /* Host1 ULPI interrupt enable */
+#define MXC_H1_UCTRL_H1WIE_BIT         (1 << 11)       /* HOST1 wakeup intr enable */
+#define MXC_H1_UCTRL_H1PM_BIT          (1 <<  8)               /* HOST1 power mask */
+
+/* USB_PHY_CTRL_FUNC */
+#define MXC_OTG_PHYCTRL_OC_DIS_BIT     (1 << 8)        /* OTG Disable Overcurrent Event */
+#define MXC_H1_OC_DIS_BIT              (1 << 5)        /* UH1 Disable Overcurrent Event */
+
+/* USBH2CTRL */
+#define MXC_H2_UCTRL_H2UIE_BIT         (1 << 8)
+#define MXC_H2_UCTRL_H2WIE_BIT         (1 << 7)
+#define MXC_H2_UCTRL_H2PM_BIT          (1 << 4)
+
+#define MXC_USBCMD_OFFSET              0x140
+
+/* USBCMD */
+#define MXC_UCMD_ITC_NO_THRESHOLD_MASK (~(0xff << 16)) /* Interrupt Threshold Control */
+
+int mx51_initialize_usb_hw(int port, unsigned int flags)
+{
+       unsigned int v;
+       void __iomem *usb_base;
+       void __iomem *usbotg_base;
+       void __iomem *usbother_base;
+       int ret = 0;
+
+       usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+       if (!usb_base) {
+               printk(KERN_ERR "%s(): ioremap failed\n", __func__);
+               return -ENOMEM;
+       }
+
+       switch (port) {
+       case 0: /* OTG port */
+               usbotg_base = usb_base + MXC_OTG_OFFSET;
+               break;
+       case 1: /* Host 1 port */
+               usbotg_base = usb_base + MXC_H1_OFFSET;
+               break;
+       case 2: /* Host 2 port */
+               usbotg_base = usb_base + MXC_H2_OFFSET;
+               break;
+       default:
+               printk(KERN_ERR"%s no such port %d\n", __func__, port);
+               ret = -ENOENT;
+               goto error;
+       }
+       usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+       switch (port) {
+       case 0: /*OTG port */
+               if (flags & MXC_EHCI_INTERNAL_PHY) {
+                       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+                       if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
+                               /* OC/USBPWR is not used */
+                               v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
+                       } else {
+                               /* OC/USBPWR is used */
+                               v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
+                       }
+                       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+                       v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
+                       if (flags & MXC_EHCI_WAKEUP_ENABLED)
+                               v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
+                       else
+                               v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
+                       if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+                               v |= MXC_OTG_UCTRL_OPM_BIT;
+                       else
+                               v &= ~MXC_OTG_UCTRL_OPM_BIT;
+                       __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
+               }
+               break;
+       case 1: /* Host 1 */
+               /*Host ULPI */
+               v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
+               if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+                       /* HOST1 wakeup/ULPI intr enable */
+                       v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+               } else {
+                       /* HOST1 wakeup/ULPI intr disable */
+                       v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+               }
+
+               if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+                       v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+               else
+                       v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+               __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
+
+               v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+               if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+                       v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
+               else
+                       v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
+               __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+               v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
+               if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
+                       /* Interrupt Threshold Control:Immediate (no threshold) */
+                       v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
+               __raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
+               break;
+       case 2: /* Host 2 ULPI */
+               v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
+               if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+                       /* HOST1 wakeup/ULPI intr enable */
+                       v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+               } else {
+                       /* HOST1 wakeup/ULPI intr disable */
+                       v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+               }
+
+               if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+                       v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+               else
+                       v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+               __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
+               break;
+       }
+
+error:
+       iounmap(usb_base);
+       return ret;
+}
+
 
  */
 
 #include <linux/platform_device.h>
-#include <linux/io.h>
 
 #include <mach/hardware.h>
 #include <mach/mxc_ehci.h>
 
-#define USBCTRL_OTGBASE_OFFSET 0x600
-
-#define MX31_OTG_SIC_SHIFT     29
-#define MX31_OTG_SIC_MASK      (0x3 << MX31_OTG_SIC_SHIFT)
-#define MX31_OTG_PM_BIT                (1 << 24)
-
-#define MX31_H2_SIC_SHIFT      21
-#define MX31_H2_SIC_MASK       (0x3 << MX31_H2_SIC_SHIFT)
-#define MX31_H2_PM_BIT         (1 << 16)
-#define MX31_H2_DT_BIT         (1 << 5)
-
-#define MX31_H1_SIC_SHIFT      13
-#define MX31_H1_SIC_MASK       (0x3 << MX31_H1_SIC_SHIFT)
-#define MX31_H1_PM_BIT         (1 << 8)
-#define MX31_H1_DT_BIT         (1 << 4)
-
-#define MX35_OTG_SIC_SHIFT     29
-#define MX35_OTG_SIC_MASK      (0x3 << MX35_OTG_SIC_SHIFT)
-#define MX35_OTG_PM_BIT                (1 << 24)
-
-#define MX35_H1_SIC_SHIFT      21
-#define MX35_H1_SIC_MASK       (0x3 << MX35_H1_SIC_SHIFT)
-#define MX35_H1_PM_BIT         (1 << 8)
-#define MX35_H1_IPPUE_UP_BIT   (1 << 7)
-#define MX35_H1_IPPUE_DOWN_BIT (1 << 6)
-#define MX35_H1_TLL_BIT                (1 << 5)
-#define MX35_H1_USBTE_BIT      (1 << 4)
-
-#define MXC_OTG_OFFSET         0
-#define MXC_H1_OFFSET          0x200
-#define MXC_H2_OFFSET          0x400
-
-/* USB_CTRL */
-#define MXC_OTG_UCTRL_OWIE_BIT         (1 << 27)       /* OTG wakeup intr enable */
-#define MXC_OTG_UCTRL_OPM_BIT          (1 << 24)       /* OTG power mask */
-#define MXC_H1_UCTRL_H1UIE_BIT         (1 << 12)       /* Host1 ULPI interrupt enable */
-#define MXC_H1_UCTRL_H1WIE_BIT         (1 << 11)       /* HOST1 wakeup intr enable */
-#define MXC_H1_UCTRL_H1PM_BIT          (1 <<  8)               /* HOST1 power mask */
-
-/* USB_PHY_CTRL_FUNC */
-#define MXC_OTG_PHYCTRL_OC_DIS_BIT     (1 << 8)        /* OTG Disable Overcurrent Event */
-#define MXC_H1_OC_DIS_BIT                      (1 << 5)        /* UH1 Disable Overcurrent Event */
-
-/* USBH2CTRL */
-#define MXC_H2_UCTRL_H2UIE_BIT         (1 << 8)
-#define MXC_H2_UCTRL_H2WIE_BIT         (1 << 7)
-#define MXC_H2_UCTRL_H2PM_BIT          (1 << 4)
-
-#define MXC_USBCMD_OFFSET                      0x140
-
-/* USBCMD */
-#define MXC_UCMD_ITC_NO_THRESHOLD_MASK (~(0xff << 16)) /* Interrupt Threshold Control */
-
 int mxc_initialize_usb_hw(int port, unsigned int flags)
 {
-       unsigned int v;
 #if defined(CONFIG_SOC_IMX25)
-       if (cpu_is_mx25()) {
-               v = readl(MX25_IO_ADDRESS(MX25_USB_BASE_ADDR +
-                                    USBCTRL_OTGBASE_OFFSET));
-
-               switch (port) {
-               case 0: /* OTG port */
-                       v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
-                       v |= (flags & MXC_EHCI_INTERFACE_MASK)
-                                       << MX35_OTG_SIC_SHIFT;
-                       if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-                               v |= MX35_OTG_PM_BIT;
-
-                       break;
-               case 1: /* H1 port */
-                       v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
-                               MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
-                       v |= (flags & MXC_EHCI_INTERFACE_MASK)
-                                               << MX35_H1_SIC_SHIFT;
-                       if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-                               v |= MX35_H1_PM_BIT;
-
-                       if (!(flags & MXC_EHCI_TTL_ENABLED))
-                               v |= MX35_H1_TLL_BIT;
-
-                       if (flags & MXC_EHCI_INTERNAL_PHY)
-                               v |= MX35_H1_USBTE_BIT;
-
-                       if (flags & MXC_EHCI_IPPUE_DOWN)
-                               v |= MX35_H1_IPPUE_DOWN_BIT;
-
-                       if (flags & MXC_EHCI_IPPUE_UP)
-                               v |= MX35_H1_IPPUE_UP_BIT;
-
-                       break;
-               default:
-                       return -EINVAL;
-               }
-
-               writel(v, MX25_IO_ADDRESS(MX25_USB_BASE_ADDR +
-                                    USBCTRL_OTGBASE_OFFSET));
-               return 0;
-       }
+       if (cpu_is_mx25())
+               return mx25_initialize_usb_hw(port, flags);
 #endif /* if defined(CONFIG_SOC_IMX25) */
 #if defined(CONFIG_ARCH_MX3)
-       if (cpu_is_mx31()) {
-               v = readl(MX31_IO_ADDRESS(MX31_USB_BASE_ADDR +
-                                    USBCTRL_OTGBASE_OFFSET));
-
-               switch (port) {
-               case 0: /* OTG port */
-                       v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
-                       v |= (flags & MXC_EHCI_INTERFACE_MASK)
-                                       << MX31_OTG_SIC_SHIFT;
-                       if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-                               v |= MX31_OTG_PM_BIT;
-
-                       break;
-               case 1: /* H1 port */
-                       v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
-                       v |= (flags & MXC_EHCI_INTERFACE_MASK)
-                                               << MX31_H1_SIC_SHIFT;
-                       if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-                               v |= MX31_H1_PM_BIT;
-
-                       if (!(flags & MXC_EHCI_TTL_ENABLED))
-                               v |= MX31_H1_DT_BIT;
-
-                       break;
-               case 2: /* H2 port */
-                       v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
-                       v |= (flags & MXC_EHCI_INTERFACE_MASK)
-                                               << MX31_H2_SIC_SHIFT;
-                       if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-                               v |= MX31_H2_PM_BIT;
-
-                       if (!(flags & MXC_EHCI_TTL_ENABLED))
-                               v |= MX31_H2_DT_BIT;
-
-                       break;
-               default:
-                       return -EINVAL;
-               }
-
-               writel(v, MX31_IO_ADDRESS(MX31_USB_BASE_ADDR +
-                                    USBCTRL_OTGBASE_OFFSET));
-               return 0;
-       }
-
-       if (cpu_is_mx35()) {
-               v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-                                    USBCTRL_OTGBASE_OFFSET));
-
-               switch (port) {
-               case 0: /* OTG port */
-                       v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
-                       v |= (flags & MXC_EHCI_INTERFACE_MASK)
-                                       << MX35_OTG_SIC_SHIFT;
-                       if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-                               v |= MX35_OTG_PM_BIT;
-
-                       break;
-               case 1: /* H1 port */
-                       v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
-                               MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
-                       v |= (flags & MXC_EHCI_INTERFACE_MASK)
-                                               << MX35_H1_SIC_SHIFT;
-                       if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-                               v |= MX35_H1_PM_BIT;
-
-                       if (!(flags & MXC_EHCI_TTL_ENABLED))
-                               v |= MX35_H1_TLL_BIT;
-
-                       if (flags & MXC_EHCI_INTERNAL_PHY)
-                               v |= MX35_H1_USBTE_BIT;
-
-                       if (flags & MXC_EHCI_IPPUE_DOWN)
-                               v |= MX35_H1_IPPUE_DOWN_BIT;
-
-                       if (flags & MXC_EHCI_IPPUE_UP)
-                               v |= MX35_H1_IPPUE_UP_BIT;
-
-                       break;
-               default:
-                       return -EINVAL;
-               }
-
-               writel(v, MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-                                    USBCTRL_OTGBASE_OFFSET));
-               return 0;
-       }
+       if (cpu_is_mx31())
+               return mx31_initialize_usb_hw(port, flags);
+       if (cpu_is_mx35())
+               return mx35_initialize_usb_hw(port, flags);
 #endif /* CONFIG_ARCH_MX3 */
 #ifdef CONFIG_MACH_MX27
-       if (cpu_is_mx27()) {
-               /* On i.MX27 we can use the i.MX31 USBCTRL bits, they
-                * are identical
-                */
-               v = readl(MX27_IO_ADDRESS(MX27_USB_BASE_ADDR +
-                                    USBCTRL_OTGBASE_OFFSET));
-               switch (port) {
-               case 0: /* OTG port */
-                       v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
-                       v |= (flags & MXC_EHCI_INTERFACE_MASK)
-                                       << MX31_OTG_SIC_SHIFT;
-                       if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-                               v |= MX31_OTG_PM_BIT;
-                       break;
-               case 1: /* H1 port */
-                       v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
-                       v |= (flags & MXC_EHCI_INTERFACE_MASK)
-                                               << MX31_H1_SIC_SHIFT;
-                       if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-                               v |= MX31_H1_PM_BIT;
-
-                       if (!(flags & MXC_EHCI_TTL_ENABLED))
-                               v |= MX31_H1_DT_BIT;
-
-                       break;
-               case 2: /* H2 port */
-                       v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
-                       v |= (flags & MXC_EHCI_INTERFACE_MASK)
-                                               << MX31_H2_SIC_SHIFT;
-                       if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-                               v |= MX31_H2_PM_BIT;
-
-                       if (!(flags & MXC_EHCI_TTL_ENABLED))
-                               v |= MX31_H2_DT_BIT;
-
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               writel(v, MX27_IO_ADDRESS(MX27_USB_BASE_ADDR +
-                                    USBCTRL_OTGBASE_OFFSET));
-               return 0;
-       }
+       if (cpu_is_mx27())
+               return mx27_initialize_usb_hw(port, flags);
 #endif /* CONFIG_MACH_MX27 */
 #ifdef CONFIG_SOC_IMX51
-       if (cpu_is_mx51()) {
-               void __iomem *usb_base;
-               void __iomem *usbotg_base;
-               void __iomem *usbother_base;
-               int ret = 0;
-
-               usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
-               if (!usb_base) {
-                       printk(KERN_ERR "%s(): ioremap failed\n", __func__);
-                       return -ENOMEM;
-               }
-
-               switch (port) {
-               case 0: /* OTG port */
-                       usbotg_base = usb_base + MXC_OTG_OFFSET;
-                       break;
-               case 1: /* Host 1 port */
-                       usbotg_base = usb_base + MXC_H1_OFFSET;
-                       break;
-               case 2: /* Host 2 port */
-                       usbotg_base = usb_base + MXC_H2_OFFSET;
-                       break;
-               default:
-                       printk(KERN_ERR"%s no such port %d\n", __func__, port);
-                       ret = -ENOENT;
-                       goto error;
-               }
-               usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-               switch (port) {
-               case 0: /*OTG port */
-                       if (flags & MXC_EHCI_INTERNAL_PHY) {
-                               v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-                               if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
-                                       /* OC/USBPWR is not used */
-                                       v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
-                               } else {
-                                       /* OC/USBPWR is used */
-                                       v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
-                               }
-                               __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-                               v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
-                               if (flags & MXC_EHCI_WAKEUP_ENABLED)
-                                       v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
-                               else
-                                       v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
-                               if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                                       v |= MXC_OTG_UCTRL_OPM_BIT;
-                               else
-                                       v &= ~MXC_OTG_UCTRL_OPM_BIT;
-                               __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-                       }
-                       break;
-               case 1: /* Host 1 */
-                       /*Host ULPI */
-                       v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
-                       if (flags & MXC_EHCI_WAKEUP_ENABLED) {
-                               /* HOST1 wakeup/ULPI intr enable */
-                               v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
-                       } else {
-                               /* HOST1 wakeup/ULPI intr disable */
-                               v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
-                       }
-
-                       if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                               v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
-                       else
-                               v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
-                       __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-
-                       v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-                       if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                               v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
-                       else
-                               v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
-                       __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-                       v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
-                       if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
-                               /* Interrupt Threshold Control:Immediate (no threshold) */
-                               v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
-                       __raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
-                       break;
-               case 2: /* Host 2 ULPI */
-                       v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
-                       if (flags & MXC_EHCI_WAKEUP_ENABLED) {
-                               /* HOST1 wakeup/ULPI intr enable */
-                               v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
-                       } else {
-                               /* HOST1 wakeup/ULPI intr disable */
-                               v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
-                       }
-
-                       if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                               v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
-                       else
-                               v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
-                       __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
-                       break;
-               }
-
-error:
-               iounmap(usb_base);
-               return ret;
-       }
+       if (cpu_is_mx51())
+               return mx51_initialize_usb_hw(port, flags);
 #endif
        printk(KERN_WARNING
                "%s() unable to setup USBCONTROL for this CPU\n", __func__);
 
 
 int mxc_initialize_usb_hw(int port, unsigned int flags);
 
+int mx51_initialize_usb_hw(int port, unsigned int flags);
+int mx25_initialize_usb_hw(int port, unsigned int flags);
+int mx31_initialize_usb_hw(int port, unsigned int flags);
+int mx35_initialize_usb_hw(int port, unsigned int flags);
+int mx27_initialize_usb_hw(int port, unsigned int flags);
+
 #endif /* __INCLUDE_ASM_ARCH_MXC_EHCI_H */