};
 
                USB1: usb@e0000400 {
-                       compatible = "ohci-be";
+                       compatible = "ibm,usb-ohci-440epx", "ohci-be";
                        reg = <0x00000000 0xe0000400 0x00000060>;
                        interrupt-parent = <&UIC0>;
                        interrupts = <0x15 0x8>;
 
                port_status &= ~PORT_RWC_BITS;
                ehci_writel(ehci, port_status, status_reg);
 
-       } else
+               /* ensure 440EPX ohci controller state is operational */
+               if (ehci->has_amcc_usb23)
+                       set_ohci_hcfs(ehci, 1);
+       } else {
                ehci_dbg (ehci, "port %d high speed\n", index + 1);
+               /* ensure 440EPx ohci controller state is suspended */
+               if (ehci->has_amcc_usb23)
+                       set_ohci_hcfs(ehci, 0);
+       }
 
        return port_status;
 }
 
 {
        struct device_node *dn = op->node;
        struct usb_hcd *hcd;
-       struct ehci_hcd *ehci;
+       struct ehci_hcd *ehci = NULL;
        struct resource res;
        int irq;
        int rv;
 
+       struct device_node *np;
+
        if (usb_disabled())
                return -ENODEV;
 
        }
 
        ehci = hcd_to_ehci(hcd);
+       np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
+       if (np != NULL) {
+               /* claim we really affected by usb23 erratum */
+               if (!of_address_to_resource(np, 0, &res))
+                       ehci->ohci_hcctrl_reg = ioremap(res.start +
+                                       OHCI_HCCTRL_OFFSET, OHCI_HCCTRL_LEN);
+               else
+                       pr_debug(__FILE__ ": no ohci offset in fdt\n");
+               if (!ehci->ohci_hcctrl_reg) {
+                       pr_debug(__FILE__ ": ioremap for ohci hcctrl failed\n");
+               } else {
+                       ehci->has_amcc_usb23 = 1;
+               }
+       }
 
        if (of_get_property(dn, "big-endian", NULL)) {
                ehci->big_endian_mmio = 1;
        irq_dispose_mapping(irq);
 err_irq:
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+       if (ehci->has_amcc_usb23)
+               iounmap(ehci->ohci_hcctrl_reg);
 err_rmr:
        usb_put_hcd(hcd);
 
 static int ehci_hcd_ppc_of_remove(struct of_device *op)
 {
        struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+       struct device_node *np;
+       struct resource res;
+
        dev_set_drvdata(&op->dev, NULL);
 
        dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n");
        irq_dispose_mapping(hcd->irq);
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 
+       /* use request_mem_region to test if the ohci driver is loaded.  if so
+        * ensure the ohci core is operational.
+        */
+       if (ehci->has_amcc_usb23) {
+               np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx");
+               if (np != NULL) {
+                       if (!of_address_to_resource(np, 0, &res))
+                               if (!request_mem_region(res.start,
+                                                           0x4, hcd_name))
+                                       set_ohci_hcfs(ehci, 1);
+                               else
+                                       release_mem_region(res.start, 0x4);
+                       else
+                               pr_debug(__FILE__ ": no ohci offset in fdt\n");
+                       of_node_put(np);
+               }
+
+               iounmap(ehci->ohci_hcctrl_reg);
+       }
        usb_put_hcd(hcd);
 
        return 0;
 
        unsigned                has_fsl_port_bug:1; /* FreeScale */
        unsigned                big_endian_mmio:1;
        unsigned                big_endian_desc:1;
+       unsigned                has_amcc_usb23:1;
+
+       /* required for usb32 quirk */
+       #define OHCI_CTRL_HCFS          (3 << 6)
+       #define OHCI_USB_OPER           (2 << 6)
+       #define OHCI_USB_SUSPEND        (3 << 6)
+
+       #define OHCI_HCCTRL_OFFSET      0x4
+       #define OHCI_HCCTRL_LEN         0x4
+       __hc32                  *ohci_hcctrl_reg;
 
        u8                      sbrn;           /* packed release number */
 
 #endif
 }
 
+/*
+ * On certain ppc-44x SoC there is a HW issue, that could only worked around with
+ * explicit suspend/operate of OHCI. This function hereby makes sense only on that arch.
+ * Other common bits are dependant on has_amcc_usb23 quirk flag.
+ */
+#ifdef CONFIG_44x
+static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational)
+{
+       u32 hc_control;
+
+       hc_control = (readl_be(ehci->ohci_hcctrl_reg) & ~OHCI_CTRL_HCFS);
+       if (operational)
+               hc_control |= OHCI_USB_OPER;
+       else
+               hc_control |= OHCI_USB_SUSPEND;
+
+       writel_be(hc_control, ehci->ohci_hcctrl_reg);
+       (void) readl_be(ehci->ohci_hcctrl_reg);
+}
+#else
+static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational)
+{ }
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 /*
 
 
        int rv;
        int is_bigendian;
+       struct device_node *np;
 
        if (usb_disabled())
                return -ENODEV;
        if (rv == 0)
                return 0;
 
+       /* by now, 440epx is known to show usb_23 erratum */
+       np = of_find_compatible_node(NULL, NULL, "ibm,usb-ehci-440epx");
+
+       /* Work around - At this point ohci_run has executed, the
+       * controller is running, everything, the root ports, etc., is
+       * set up.  If the ehci driver is loaded, put the ohci core in
+       * the suspended state.  The ehci driver will bring it out of
+       * suspended state when / if a non-high speed USB device is
+       * attached to the USB Host port.  If the ehci driver is not
+       * loaded, do nothing. request_mem_region is used to test if
+       * the ehci driver is loaded.
+       */
+       if (np !=  NULL) {
+               if (!of_address_to_resource(np, 0, &res)) {
+                       if (!request_mem_region(res.start, 0x4, hcd_name)) {
+                               writel_be((readl_be(&ohci->regs->control) |
+                                       OHCI_USB_SUSPEND), &ohci->regs->control);
+                                       (void) readl_be(&ohci->regs->control);
+                       } else
+                               release_mem_region(res.start, 0x4);
+               } else
+                   pr_debug(__FILE__ ": cannot get ehci offset from fdt\n");
+       }
+
        iounmap(hcd->regs);
 err_ioremap:
        irq_dispose_mapping(irq);