The Renesas R-Mobile SoC (r8a7740) has USB EHCI and OHCI controllers.

The ehci and ohci blocks share a common register and clocking infrastructure.
Initialization of the host controller and clocks is common between these and
is factored out into the rmobile-common.c file.

Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu...@renesas.com>
---
 drivers/usb/host/Kconfig          |    4 +
 drivers/usb/host/Makefile         |    1 +
 drivers/usb/host/ehci-hcd.c       |    5 +
 drivers/usb/host/ehci-rmobile.c   |  384 +++++++++++++++++++++++++++++++++++++
 drivers/usb/host/ohci-hcd.c       |   21 +-
 drivers/usb/host/ohci-rmobile.c   |  377 ++++++++++++++++++++++++++++++++++++
 drivers/usb/host/rmobile-common.c |  145 ++++++++++++++
 drivers/usb/host/rmobile-common.h |   53 +++++
 include/linux/usb/rmobile.h       |  254 ++++++++++++++++++++++++
 9 files changed, 1243 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/host/ehci-rmobile.c
 create mode 100644 drivers/usb/host/ohci-rmobile.c
 create mode 100644 drivers/usb/host/rmobile-common.c
 create mode 100644 drivers/usb/host/rmobile-common.h
 create mode 100644 include/linux/usb/rmobile.h

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index c59a112..56506e35 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -682,3 +682,7 @@ config USB_HCD_SSB
          for ehci and ohci.
 
          If unsure, say N.
+
+config USB_RMOBILE_COMMON
+       bool
+       default y if ARCH_R8A7740
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 001fbff..02a0cdc 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -46,3 +46,4 @@ obj-$(CONFIG_USB_FSL_MPH_DR_OF)       += fsl-mph-dr-of.o
 obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
 obj-$(CONFIG_USB_HCD_BCMA)     += bcma-hcd.o
 obj-$(CONFIG_USB_HCD_SSB)      += ssb-hcd.o
+obj-$(CONFIG_USB_RMOBILE_COMMON) += rmobile-common.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index b416a3f..ecd16a4 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1342,6 +1342,11 @@ MODULE_LICENSE ("GPL");
 #define        PLATFORM_DRIVER         ehci_hcd_sead3_driver
 #endif
 
+#if defined(CONFIG_ARCH_R8A7740)
+#include "ehci-rmobile.c"
+#define PLATFORM_DRIVER                ehci_hcd_rmobile_driver
+#endif
+
 #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
        !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
        !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
diff --git a/drivers/usb/host/ehci-rmobile.c b/drivers/usb/host/ehci-rmobile.c
new file mode 100644
index 0000000..77444d4
--- /dev/null
+++ b/drivers/usb/host/ehci-rmobile.c
@@ -0,0 +1,384 @@
+/*
+ * Driver for EHCI on Renesas ARM SoC (rmobile)
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu...@renesas.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details
+ *
+ * Current support is only r8a7740.
+ */
+
+#include <linux/device.h>
+#include <linux/signal.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+#include <linux/workqueue.h>
+#include <linux/usb/rmobile.h>
+#include <linux/pm_runtime.h>
+#include "rmobile-common.h"
+
+static void rmobile_relinquish_port(struct usb_hcd *hcd, int portnum)
+{
+       struct rmobile_hci *hci = dev_get_drvdata(hcd->self.controller);
+
+       if ((!hci->handed_over) && (!hci->relinquish_count)) {
+               pr_err("Reset Host Controller\n");
+               hci->relinquish_count++;
+               rmobile_vbus_control(hci, 0);
+               if (hci->pdata->oci_irq)
+                       disable_irq(hci->pdata->oci_irq);
+               return;
+       }
+
+       hci->handed_over = 0;
+       hci->relinquish_count = 0;
+       ehci_relinquish_port(hcd, portnum);
+}
+
+static int rmobile_port_handed_over(struct usb_hcd *hcd, int portnum)
+{
+       struct rmobile_hci *hci = dev_get_drvdata(hcd->self.controller);
+
+       hci->handed_over = 1;
+
+       return ehci_port_handed_over(hcd, portnum);
+}
+
+static int rmobile_hub_control(struct usb_hcd *hcd,
+               u16 typereq, u16 value, u16 index, char *buf, u16 length)
+{
+       int retval;
+       struct rmobile_hci *hci = dev_get_drvdata(hcd->self.controller);
+
+       retval = ehci_hub_control(hcd, typereq, value, index, buf, length);
+
+       /* VBUS ON/OFF control */
+       if (!retval)
+               rmobile_vbus_setup(typereq, value, hci);
+
+       return retval;
+}
+
+static const struct hc_driver ehci_rmobile_hc_driver = {
+       .description = hcd_name,
+       .product_desc = "R-Mobile EHCI",
+       .hcd_priv_size = sizeof(struct ehci_hcd),
+
+       /*
+        * generic hardware linkage
+        */
+       .irq = ehci_irq,
+       .flags = HCD_MEMORY | HCD_USB2,
+
+       /*
+        * basic lifecycle operations
+        */
+       .reset = ehci_init,
+       .start = ehci_run,
+       .stop = ehci_stop,
+       .shutdown = ehci_shutdown,
+
+       /*
+        * managing i/o requests and associated device resources
+        */
+       .urb_enqueue = ehci_urb_enqueue,
+       .urb_dequeue = ehci_urb_dequeue,
+       .endpoint_disable = ehci_endpoint_disable,
+       .endpoint_reset = ehci_endpoint_reset,
+
+       /*
+        * scheduling support
+        */
+       .get_frame_number = ehci_get_frame,
+
+       /*
+        * root hub support
+        */
+       .hub_status_data = ehci_hub_status_data,
+       .hub_control = rmobile_hub_control,
+       .bus_suspend = ehci_bus_suspend,
+       .bus_resume = ehci_bus_resume,
+       .relinquish_port = rmobile_relinquish_port,
+       .port_handed_over = rmobile_port_handed_over,
+
+       .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+};
+
+static irqreturn_t rmobile_over_current_irq(int irq, void *_hcd)
+{
+       struct usb_hcd *hcd = _hcd;
+               rmobile_over_current_check(
+                       dev_get_drvdata(hcd->self.controller));
+       return IRQ_HANDLED;
+}
+
+#define EHCI_OFFSET            0x1000
+#define EHCI_SIZE              0x1000
+#define RMOBILE_IRQF \
+       (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_SHARED)
+
+static int ehci_hcd_drv_probe(struct platform_device *pdev)
+{
+       int retval, irq;
+       struct usb_hcd *hcd;
+       struct ehci_hcd *ehci;
+       struct rmobile_hci *hci;
+       struct rmobile_usb_platdata *pdata;
+       struct resource *r;
+       void __iomem *regs;
+
+       if (usb_disabled())
+               return -ENODEV;
+
+       pr_debug("Initializing Renesas R-Mobile USB Host Controller\n");
+
+       pdata = pdev->dev.platform_data;
+       if (!pdata) {
+               retval = -ENODEV;
+               goto err0;
+       }
+
+       /* OHCI irq */
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               pr_err("no resource of IORESOURCE_IRQ");
+               retval = -ENODEV;
+               goto err0;
+       }
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!r) {
+               pr_err("no resource of IORESOURCE_MEM");
+               retval = -ENODEV;
+               goto err0;
+       }
+
+       if (EHCI_OFFSET + EHCI_SIZE > resource_size(r)) {
+               retval = -ENOMEM;
+               goto err0;
+       }
+
+       if (!request_mem_region(r->start + EHCI_OFFSET, EHCI_SIZE,
+                       ehci_rmobile_hc_driver.description)) {
+               dev_dbg(&pdev->dev, "controller already in use\n");
+               retval = -EBUSY;
+               goto err0;
+       }
+
+       regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
+       if (regs == NULL) {
+               dev_dbg(&pdev->dev, "error mapping memory\n");
+               retval = -ENOMEM;
+               goto err1;
+       }
+
+       hcd = usb_create_hcd(&ehci_rmobile_hc_driver,
+                               &pdev->dev, dev_name(&pdev->dev));
+       if (!hcd) {
+               retval = -ENOMEM;
+               goto err1;
+       }
+
+       hci = devm_kzalloc(&pdev->dev, sizeof(struct rmobile_hci),
+                               GFP_KERNEL);
+       if (!hci) {
+               retval = -ENOMEM;
+               goto err1;
+       }
+
+       platform_set_drvdata(pdev, hci);
+
+       hcd->rsrc_start = r->start + EHCI_OFFSET;
+       hcd->rsrc_len = EHCI_SIZE;
+       hcd->regs = regs + EHCI_OFFSET;
+
+       hci->hcd = hcd;
+       hci->phys_base = r->start;
+       hci->base = regs;
+
+       hci->pdata = pdata;
+       if (pdata->oci_irq) {
+               if (!pdata->check_oci) {
+                       retval = -ENODEV;
+                       goto err2;
+               }
+
+               retval = request_irq(pdata->oci_irq,
+                                       rmobile_over_current_irq,
+                                       RMOBILE_IRQF,
+                                       dev_name(&pdev->dev), hcd);
+               if (!retval)
+                       goto err2;
+
+               disable_irq(pdata->oci_irq);
+       }
+
+       pm_suspend_ignore_children(&pdev->dev, true);
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_noresume(&pdev->dev);
+
+       rmobile_hc_start(hcd, pdev);
+
+       ehci = hcd_to_ehci(hcd);
+       ehci->caps = hcd->regs;
+       ehci->regs = hcd->regs +
+               HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
+
+       /* cache this readonly data; minimize chip reads */
+       ehci->hcs_params = readl(&ehci->caps->hcs_params);
+       ehci->sbrn = 0x20;
+       hcd->has_tt = 0;
+
+       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       if (retval)
+               goto err3;
+
+       return retval;
+
+err3:
+       rmobile_hc_stop(hcd, pdev);
+
+       pm_runtime_disable(&pdev->dev);
+
+       if (pdata->oci_irq)
+               free_irq(pdata->oci_irq, hcd);
+err2:
+       usb_put_hcd(hcd);
+err1:
+       release_mem_region(r->start + EHCI_OFFSET, EHCI_SIZE);
+err0:
+       dev_err(&pdev->dev, "%s init fail, %d\n",
+               dev_name(&pdev->dev), retval);
+
+       return retval;
+}
+
+static int ehci_hcd_drv_remove(struct platform_device *pdev)
+{
+       struct rmobile_hci *hci = platform_get_drvdata(pdev);
+       struct usb_hcd *hcd = hci->hcd;
+
+       usb_remove_hcd(hcd);
+       rmobile_hc_stop(hcd, pdev);
+       if (hci->pdata->oci_irq)
+               free_irq(hci->pdata->oci_irq, hcd);
+
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+       pm_runtime_disable(&pdev->dev);
+       pm_runtime_set_suspended(&pdev->dev);
+
+       usb_put_hcd(hcd);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static void rmobile_ehci_save_register(struct platform_device *pdev)
+{
+       struct rmobile_hci *hci = platform_get_drvdata(pdev);
+       struct ehci_hcd *ehci = hcd_to_ehci(hci->hcd);
+       struct rmobile_ehci_reg *reg = &hci->ehci_reg;
+
+       if (reg->save_flag)
+               return;
+
+       reg->usbintr = ehci_readl(ehci, &ehci->regs->intr_enable);
+       reg->usbcmd = ehci_readl(ehci, &ehci->regs->command);
+       reg->usbsts = ehci_readl(ehci, &ehci->regs->status);
+       reg->frindex = ehci_readl(ehci, &ehci->regs->frame_index);
+       reg->periodiclistbase = ehci_readl(ehci, &ehci->regs->frame_list);
+       reg->asynclistaddr = ehci_readl(ehci, &ehci->regs->async_next);
+       reg->configflag = ehci_readl(ehci, &ehci->regs->configured_flag);
+       reg->portsc = ehci_readl(ehci, &ehci->regs->port_status[0]);
+
+       reg->save_flag = 1;
+}
+
+static void rmobile_ehci_load_register(struct platform_device *pdev)
+{
+       struct rmobile_hci *hci = platform_get_drvdata(pdev);
+       struct ehci_hcd *ehci = hcd_to_ehci(hci->hcd);
+       struct rmobile_ehci_reg *reg = &hci->ehci_reg;
+
+       if (!reg->save_flag)
+               return;
+
+       ehci_writel(ehci, reg->configflag, &ehci->regs->configured_flag);
+       ehci_writel(ehci, reg->portsc, &ehci->regs->port_status[0]);
+       ehci_writel(ehci, reg->asynclistaddr, &ehci->regs->async_next);
+       ehci_writel(ehci, reg->periodiclistbase, &ehci->regs->frame_list);
+       ehci_writel(ehci, reg->frindex, &ehci->regs->frame_index);
+       ehci_writel(ehci, reg->usbsts, &ehci->regs->status);
+       ehci_writel(ehci, reg->usbcmd, &ehci->regs->command);
+       ehci_writel(ehci, reg->usbintr, &ehci->regs->intr_enable);
+
+       reg->save_flag = 0;
+}
+
+static int ehci_hcd_drv_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rmobile_hci *hci = platform_get_drvdata(pdev);
+       struct usb_hcd *hcd = dev_get_drvdata(dev);
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+       unsigned long flags;
+
+       ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
+       spin_lock_irqsave(&ehci->lock, flags);
+
+       if (hci->pdata->oci_irq)
+               disable_irq(hci->pdata->oci_irq);
+
+       rmobile_vbus_control(hci, 0);
+       rmobile_ehci_save_register(pdev);
+       rmobile_hc_stop(hcd, pdev);
+
+       pm_runtime_put(dev);
+
+       spin_unlock_irqrestore(&ehci->lock, flags);
+
+       return 0;
+}
+
+static int ehci_hcd_drv_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rmobile_hci *hci = platform_get_drvdata(pdev);
+       struct usb_hcd *hcd = dev_get_drvdata(dev);
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+       pm_runtime_get_sync(dev);
+
+       rmobile_hc_start(hcd, pdev);
+       rmobile_ehci_load_register(pdev);
+       rmobile_vbus_control(hci, 1);
+
+       ehci_prepare_ports_for_controller_resume(ehci);
+
+       return 0;
+}
+static const struct dev_pm_ops ehci_hcd_pm_ops = {
+       .suspend        = ehci_hcd_drv_suspend,
+       .resume         = ehci_hcd_drv_resume,
+};
+#endif /* CONFIG_PM */
+
+static struct platform_driver ehci_hcd_rmobile_driver = {
+       .probe = ehci_hcd_drv_probe,
+       .remove = ehci_hcd_drv_remove,
+       .shutdown = usb_hcd_platform_shutdown,
+       .driver = {
+               .name = "rmobile-ehci",
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_PM
+               .pm     = &ehci_hcd_pm_ops,
+#endif
+       }
+};
+
+MODULE_ALIAS("platform:rmobile-ehci");
+MODULE_AUTHOR("Nobuhiro Iwamatsu <nobuhiro.iwamatsu...@renesas.com>");
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 180a2b0..e439750 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1191,6 +1191,11 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ohci_platform_driver
 #endif
 
+#ifdef CONFIG_ARCH_R8A7740
+#include "ohci-rmobile.c"
+#define RMOBILE_OHCI_DRIVER    ohci_hcd_rmobile_driver
+#endif
+
 #if    !defined(PCI_DRIVER) &&         \
        !defined(PLATFORM_DRIVER) &&    \
        !defined(OMAP1_PLATFORM_DRIVER) &&      \
@@ -1199,7 +1204,8 @@ MODULE_LICENSE ("GPL");
        !defined(SA1111_DRIVER) &&      \
        !defined(PS3_SYSTEM_BUS_DRIVER) && \
        !defined(SM501_OHCI_DRIVER) && \
-       !defined(TMIO_OHCI_DRIVER)
+       !defined(TMIO_OHCI_DRIVER) && \
+       !defined(RMOBILE_OHCI_DRIVER)
 #error "missing bus glue for ohci-hcd"
 #endif
 
@@ -1277,9 +1283,19 @@ static int __init ohci_hcd_mod_init(void)
                goto error_tmio;
 #endif
 
+#ifdef RMOBILE_OHCI_DRIVER
+       retval = platform_driver_register(&RMOBILE_OHCI_DRIVER);
+       if (retval < 0)
+               goto error_rmobile;
+#endif
+
        return retval;
 
        /* Error path */
+#ifdef RMOBILE_OHCI_DRIVER
+       platform_driver_unregister(&RMOBILE_OHCI_DRIVER);
+ error_rmobile:
+#endif
 #ifdef TMIO_OHCI_DRIVER
        platform_driver_unregister(&TMIO_OHCI_DRIVER);
  error_tmio:
@@ -1329,6 +1345,9 @@ module_init(ohci_hcd_mod_init);
 
 static void __exit ohci_hcd_mod_exit(void)
 {
+#ifdef RMOBILE_OHCI_DRIVER
+       platform_driver_unregister(&RMOBILE_OHCI_DRIVER);
+#endif
 #ifdef TMIO_OHCI_DRIVER
        platform_driver_unregister(&TMIO_OHCI_DRIVER);
 #endif
diff --git a/drivers/usb/host/ohci-rmobile.c b/drivers/usb/host/ohci-rmobile.c
new file mode 100644
index 0000000..89dbec8
--- /dev/null
+++ b/drivers/usb/host/ohci-rmobile.c
@@ -0,0 +1,377 @@
+/*
+ * Driver for OHCI on Renesas ARM SoC (rmobile)
+ *
+ * Copyright (C) 2011, 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013       Nobuhiro Iwamatsu 
<nobuhiro.iwamatsu...@renesas.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details
+ *
+ * Current support is only r8a7740.
+ */
+
+#include <linux/device.h>
+#include <linux/signal.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+#include <linux/usb/rmobile.h>
+#include <linux/pm_runtime.h>
+#include "rmobile-common.h"
+
+static int rmobile_hub_control(struct usb_hcd *hcd,
+       u16 typereq, u16 value, u16 index, char *buf, u16 length)
+{
+       int retval;
+       struct rmobile_hci *hci = dev_get_drvdata(hcd->self.controller);
+
+       retval = ohci_hub_control(hcd, typereq, value, index, buf, length);
+
+       /* VBUS ON/OFF control */
+       if (!retval)
+               rmobile_vbus_setup(typereq, value, hci);
+
+       return retval;
+}
+
+static int ohci_rmobile_start(struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       int ret;
+
+       ret = ohci_init(ohci);
+       if (ret < 0)
+               return ret;
+
+       ret = ohci_run(ohci);
+       if (ret < 0) {
+               pr_err("can't start %s", hcd->self.bus_name);
+               ohci_stop(hcd);
+               return ret;
+       }
+
+       return 0;
+}
+
+static struct hc_driver ohci_rmobile_hc_driver = {
+       .description            = hcd_name,
+       .product_desc           = "R-Mobile OHCI",
+       .hcd_priv_size          = sizeof(struct ohci_hcd),
+
+       /*
+        * generic hardware linkage
+        */
+       .irq                    = ohci_irq,
+       .flags                  = HCD_USB11 | HCD_MEMORY,
+
+       /*
+        * basic lifecycle operations
+        */
+       .start                  = ohci_rmobile_start,
+       .stop                   = ohci_stop,
+       .shutdown               = ohci_shutdown,
+
+       /*
+        * managing i/o requests and associated device resources
+        */
+       .urb_enqueue            = ohci_urb_enqueue,
+       .urb_dequeue            = ohci_urb_dequeue,
+       .endpoint_disable       = ohci_endpoint_disable,
+
+       /*
+        * scheduling support
+        */
+       .get_frame_number       = ohci_get_frame,
+
+       /*
+        * root hub support
+        */
+       .hub_status_data        = ohci_hub_status_data,
+       .hub_control            = rmobile_hub_control,
+#ifdef CONFIG_PM
+       .bus_suspend            = ohci_bus_suspend,
+       .bus_resume             = ohci_bus_resume,
+#endif
+       .start_port_reset       = ohci_start_port_reset,
+};
+
+static irqreturn_t rmobile_over_current_irq(int irq, void *_hcd)
+{
+       struct usb_hcd *hcd = _hcd;
+               rmobile_over_current_check(
+                       dev_get_drvdata(hcd->self.controller));
+       return IRQ_HANDLED;
+}
+
+#define OHCI_OFFSET            0x0
+#define OHCI_SIZE              0x1000
+#define RMOBILE_IRQF \
+       (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_SHARED)
+
+static int ohci_hcd_drv_probe(struct platform_device *pdev)
+{
+       int retval, irq;
+       struct usb_hcd *hcd;
+       struct rmobile_hci *hci;
+       struct rmobile_usb_platdata *pdata;
+       struct resource *r;
+       void __iomem *regs;
+
+       if (usb_disabled())
+               return -ENODEV;
+
+       pr_debug("Initializing Renesas R-Mobile USB Host Controller\n");
+
+       pdata = pdev->dev.platform_data;
+       if (!pdata) {
+               retval = -ENODEV;
+               goto err0;
+       }
+
+       /* OHCI irq */
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               pr_err("no resource of IORESOURCE_IRQ");
+               retval = -ENODEV;
+               goto err0;
+       }
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!r) {
+               pr_err("no resource of IORESOURCE_MEM");
+               retval = -ENODEV;
+               goto err0;
+       }
+
+       if (OHCI_OFFSET + OHCI_SIZE > resource_size(r)) {
+               retval = -ENOMEM;
+               goto err0;
+       }
+
+       if (!request_mem_region(r->start + OHCI_OFFSET, OHCI_SIZE,
+                       ohci_rmobile_hc_driver.description)) {
+               dev_dbg(&pdev->dev, "controller already in use\n");
+               retval = -EBUSY;
+               goto err0;
+       }
+
+       regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
+       if (regs == NULL) {
+               dev_dbg(&pdev->dev, "error mapping memory\n");
+               retval = -ENOMEM;
+               goto err1;
+       }
+
+       hcd = usb_create_hcd(&ohci_rmobile_hc_driver,
+                       &pdev->dev, dev_name(&pdev->dev));
+       if (!hcd) {
+               retval = -ENOMEM;
+               goto err1;
+       }
+
+       hci = devm_kzalloc(&pdev->dev, sizeof(struct rmobile_hci),
+                       GFP_KERNEL);
+       if (!hci) {
+               retval = -ENOMEM;
+               goto err1;
+       }
+
+       platform_set_drvdata(pdev, hci);
+
+       hcd->rsrc_start = r->start + OHCI_OFFSET;
+       hcd->rsrc_len = OHCI_SIZE;
+       hcd->regs = regs + OHCI_OFFSET;
+
+       hci->hcd = hcd;
+       hci->phys_base = r->start;
+       hci->base = regs;
+
+       hci->pdata = pdata;
+       if (pdata->oci_irq) {
+               if (!pdata->check_oci) {
+                       retval = -ENODEV;
+                       goto err2;
+               }
+
+               retval = request_irq(pdata->oci_irq,
+                                       rmobile_over_current_irq,
+                                       RMOBILE_IRQF,
+                                       dev_name(&pdev->dev), hcd);
+               if (retval)
+                       goto err2;
+               disable_irq(pdata->oci_irq);
+       }
+
+       pm_suspend_ignore_children(&pdev->dev, true);
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_noresume(&pdev->dev);
+
+       rmobile_hc_start(hcd, pdev);
+       ohci_hcd_init(hcd_to_ohci(hcd));
+
+       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       if (retval)
+               goto err3;
+
+       return retval;
+
+err3:
+       rmobile_hc_stop(hcd, pdev);
+
+       pm_runtime_disable(&pdev->dev);
+
+       if (pdata->oci_irq)
+               free_irq(pdata->oci_irq, hcd);
+err2:
+       usb_put_hcd(hcd);
+err1:
+       release_mem_region(r->start + OHCI_OFFSET, OHCI_SIZE);
+err0:
+       dev_err(&pdev->dev, "Init %s fail, %d\n",
+               dev_name(&pdev->dev), retval);
+
+       return retval;
+}
+
+static int ohci_hcd_drv_remove(struct platform_device *pdev)
+{
+       struct rmobile_hci *hci = platform_get_drvdata(pdev);
+       struct usb_hcd *hcd = hci->hcd;
+
+       usb_remove_hcd(hcd);
+       rmobile_hc_stop(hcd, pdev);
+       if (hci->pdata->oci_irq)
+               free_irq(hci->pdata->oci_irq, hcd);
+
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+       pm_runtime_disable(&pdev->dev);
+       pm_runtime_set_suspended(&pdev->dev);
+       usb_put_hcd(hcd);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static void rmobile_ohci_save_register(struct platform_device *pdev)
+{
+       struct rmobile_hci *hci = platform_get_drvdata(pdev);
+       struct ohci_hcd *ohci = hcd_to_ohci(hci->hcd);
+       struct rmobile_ohci_reg *reg = &hci->ohci_reg;
+
+       if (reg->save_flag)
+               return;
+
+       reg->hcinterruptenable = ohci_readl(ohci, &ohci->regs->intrenable);
+       reg->hccontrol = ohci_readl(ohci, &ohci->regs->control);
+       reg->hccommandstatus = ohci_readl(ohci, &ohci->regs->cmdstatus);
+       reg->hchcca = ohci_readl(ohci, &ohci->regs->hcca);
+       reg->hccontrolheaded =
+                ohci_readl(ohci, &ohci->regs->ed_controlhead);
+       reg->hccontrolcurrented =
+                ohci_readl(ohci, &ohci->regs->ed_controlcurrent);
+       reg->hcbulkheaded = ohci_readl(ohci, &ohci->regs->ed_bulkhead);
+       reg->hcbulkcurrented =
+                ohci_readl(ohci, &ohci->regs->ed_bulkcurrent);
+       reg->hcfminterval = ohci_readl(ohci, &ohci->regs->fminterval);
+       reg->hcperiodicstart = ohci_readl(ohci, &ohci->regs->periodicstart);
+       reg->hclsthreshold = ohci_readl(ohci, &ohci->regs->lsthresh);
+
+       reg->hcrhdescrptora = ohci_readl(ohci, &ohci->regs->roothub.a);
+       reg->hcrhdescrptorb = ohci_readl(ohci, &ohci->regs->roothub.b);
+       reg->hcrhstatus = ohci_readl(ohci, &ohci->regs->roothub.status);
+       reg->hcrhportstatus =
+                ohci_readl(ohci, &ohci->regs->roothub.portstatus[0]);
+
+       reg->save_flag = 1;
+}
+
+static void rmobile_ohci_load_register(struct platform_device *pdev)
+{
+       struct rmobile_hci *hci = platform_get_drvdata(pdev);
+       struct ohci_hcd *ohci = hcd_to_ohci(hci->hcd);
+       struct rmobile_ohci_reg *reg = &hci->ohci_reg;
+
+       if (reg->save_flag == 0)
+               return;
+
+       ohci_writel(ohci, reg->hcrhportstatus,
+                &ohci->regs->roothub.portstatus[0]);
+       ohci_writel(ohci, reg->hcrhstatus, &ohci->regs->roothub.status);
+       ohci_writel(ohci, reg->hcrhdescrptorb, &ohci->regs->roothub.b);
+       ohci_writel(ohci, reg->hcrhdescrptora, &ohci->regs->roothub.a);
+
+       ohci_writel(ohci, reg->hclsthreshold, &ohci->regs->lsthresh);
+       ohci_writel(ohci, reg->hcperiodicstart, &ohci->regs->periodicstart);
+       ohci_writel(ohci, reg->hcfminterval, &ohci->regs->fminterval);
+       ohci_writel(ohci, reg->hcbulkcurrented, &ohci->regs->ed_bulkcurrent);
+       ohci_writel(ohci, reg->hcbulkheaded, &ohci->regs->ed_bulkhead);
+       ohci_writel(ohci, reg->hccontrolcurrented,
+                &ohci->regs->ed_controlcurrent);
+       ohci_writel(ohci, reg->hccontrolheaded,
+                &ohci->regs->ed_controlhead);
+       ohci_writel(ohci, reg->hchcca, &ohci->regs->hcca);
+       ohci_writel(ohci, reg->hccommandstatus, &ohci->regs->cmdstatus);
+       ohci_writel(ohci, reg->hccontrol, &ohci->regs->control);
+       ohci_writel(ohci, reg->hcinterruptenable, &ohci->regs->intrenable);
+
+       reg->save_flag = 0;
+}
+
+static int ohci_hcd_drv_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct rmobile_hci *hci = platform_get_drvdata(pdev);
+       struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+       if (hci->pdata->oci_irq)
+               disable_irq(hci->pdata->oci_irq);
+
+       rmobile_vbus_control(hci, 0);
+       rmobile_ohci_save_register(pdev);
+       rmobile_hc_stop(hcd, pdev);
+
+       pm_runtime_put(dev);
+
+       return 0;
+}
+
+static int ohci_hcd_drv_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct usb_hcd *hcd = dev_get_drvdata(dev);
+       struct rmobile_hci *hci = platform_get_drvdata(pdev);
+
+       pm_runtime_get_sync(dev);
+
+       rmobile_hc_start(hcd, pdev);
+       rmobile_ohci_load_register(pdev);
+       rmobile_vbus_control(hci, 1);
+
+       ohci_resume(hcd, false);
+
+       return 0;
+}
+#else
+#define ohci_hcd_drv_suspend NULL
+#define ohci_hcd_drv_resume  NULL
+#endif
+
+static const struct dev_pm_ops ohci_hcd_pm_ops = {
+       .suspend        = ohci_hcd_drv_suspend,
+       .resume         = ohci_hcd_drv_resume,
+};
+
+static struct platform_driver ohci_hcd_rmobile_driver = {
+       .probe          = ohci_hcd_drv_probe,
+       .remove         = ohci_hcd_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
+       .driver         = {
+               .name   = "rmobile-ohci",
+               .owner  = THIS_MODULE,
+               .pm     = &ohci_hcd_pm_ops,
+       },
+};
+
+MODULE_ALIAS("platform:rmobile-ohci");
+MODULE_AUTHOR("Nobuhiro Iwamatsu <nobuhiro.iwamatsu...@renesas.com>");
diff --git a/drivers/usb/host/rmobile-common.c 
b/drivers/usb/host/rmobile-common.c
new file mode 100644
index 0000000..9acf48a
--- /dev/null
+++ b/drivers/usb/host/rmobile-common.c
@@ -0,0 +1,145 @@
+/*
+ * Driver for Renesas ARM SoC (rmobile)
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details
+ *
+ * Current support is only r8a7740.
+ */
+
+#include <linux/export.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/rmobile.h>
+#include <asm/io.h>
+#include "rmobile-common.h"
+
+#define AHB_WRITE(h, d, a) __raw_writel(d, h->base + a)
+void rmobile_hc_start(struct usb_hcd *hcd, struct platform_device *pdev)
+{
+       u32 data;
+       struct clk *clk;
+       struct rmobile_hci *hci = platform_get_drvdata(pdev);
+
+       if (hci->pdata->common_clock)
+               hci->pdata->common_clock(pdev, 1);
+       else {
+               /* Start Clock */
+               clk = clk_get(&pdev->dev, "host");
+               if (!IS_ERR(clk)) {
+                       clk_enable(clk);
+                       clk_put(clk);
+               }
+
+               clk = clk_get(&pdev->dev, "pci");
+               if (!IS_ERR(clk)) {
+                       clk_enable(clk);
+                       clk_put(clk);
+               }
+
+               /* Clock & Direct Power Down */
+               data = __raw_readl(hci->base + USBCTR);
+               data &= ~(DIRPD | PCICLK_MASK);
+               AHB_WRITE(hci, data, USBCTR);
+               AHB_WRITE(hci, data & ~PLL_RST, USBCTR);
+       }
+
+       data = SMODE_READY_CTR | MMODE_HBUSREQ |
+                       MMODE_WR_INCR | MMODE_BYTE_BURST | MMODE_HTRANS;
+
+       if (data == __raw_readl(hci->base + AHB_BUS_CTR))
+               return;
+
+       /* AHB-PCI Bridge Communication Registers */
+       AHB_WRITE(hci, data, AHB_BUS_CTR);
+       AHB_WRITE(hci, (PHYS_OFFSET & 0xf0000000) | PREFETCH,
+                               PCIAHB_WIN1_CTR);
+       AHB_WRITE(hci, 0xf0000000 | PREFETCH, PCIAHB_WIN2_CTR);
+       AHB_WRITE(hci, hci->phys_base | PCIWIN2_PCICMD, AHBPCI_WIN2_CTR);
+       data = __raw_readl(hci->base + PCI_ARBITER_CTR);
+       AHB_WRITE(hci, data | PCIBP_MODE | PCIREQ1 | PCIREQ0,
+                               PCI_ARBITER_CTR);
+
+       /* PCI Configuration Registers for AHBPCI */
+       AHB_WRITE(hci, PCIWIN1_PCICMD | AHB_CFG_AHBPCI, AHBPCI_WIN1_CTR);
+       AHB_WRITE(hci, hci->phys_base + AHBPCI_OFFSET,
+                               PCI_CONF_AHBPCI_BASEAD);
+       AHB_WRITE(hci, PHYS_OFFSET & 0xf0000000, PCI_CONF_AHBPCI_WIN1_BASEAD);
+       AHB_WRITE(hci, 0xf0000000, PCI_CONF_AHBPCI_WIN2_BASEAD);
+       AHB_WRITE(hci, SERREN | PERREN | MASTEREN | MEMEN,
+                               PCI_CONF_AHBPCI_CMND_STS);
+
+       /* PCI Configuration Registers for EHCI */
+       AHB_WRITE(hci, PCIWIN1_PCICMD | AHB_CFG_HOST, AHBPCI_WIN1_CTR);
+       AHB_WRITE(hci, hci->phys_base + OHCI_OFFSET, OHCI_BASEAD);
+       AHB_WRITE(hci, hci->phys_base + EHCI_OFFSET, EHCI_BASEAD);
+
+       data = SERREN | PERREN | MASTEREN | MEMEN;
+       AHB_WRITE(hci, data, OHCI_CMND_STS);
+       AHB_WRITE(hci, data, EHCI_CMND_STS);
+
+       /* enable pci interrupt */
+       data = __raw_readl(hci->base + PCI_INT_ENABLE);
+       data |= USBH_PMEEN | USBH_INTBEN | USBH_INTAEN;
+       AHB_WRITE(hci, data, PCI_INT_ENABLE);
+}
+EXPORT_SYMBOL(rmobile_hc_start);
+
+void rmobile_hc_stop(struct usb_hcd *hcd, struct platform_device *pdev)
+{
+       struct rmobile_hci *hci = platform_get_drvdata(pdev);
+
+       rmobile_vbus_control(hci, 0);
+
+       if (hci->pdata->common_clock)
+               hci->pdata->common_clock(pdev, 0);
+       else {
+               /* Clock & Direct Power Down */
+               struct clk *clk;
+               u32 data = __raw_readl(hci->base + USBCTR);
+               data |= DIRPD | PLL_RST | PCICLK_MASK;
+               __raw_writel(data, hci->base + USBCTR);
+
+               /* Stop Clock */
+               clk = clk_get(&pdev->dev, "host");
+               if (!IS_ERR(clk)) {
+                       clk_disable(clk);
+                       clk_put(clk);
+               }
+               clk = clk_get(&pdev->dev, "pci");
+               if (!IS_ERR(clk)) {
+                       clk_disable(clk);
+                       clk_put(clk);
+               }
+       }
+}
+EXPORT_SYMBOL(rmobile_hc_stop);
+
+void rmobile_vbus_setup(u16 typereq,
+                       u16 value, struct rmobile_hci *hci)
+{
+       if (value == USB_PORT_FEAT_POWER) {
+               if (typereq == SetPortFeature) {
+                       rmobile_vbus_control(hci, 1);
+                       if (hci->pdata->oci_irq) {
+                               mdelay(OVER_CURRENT_TIME);
+                               if (!rmobile_over_current_check(hci))
+                                       enable_irq(hci->pdata->oci_irq);
+                       }
+               } else if (typereq == ClearPortFeature) {
+                       if (hci->vbus_flag) {
+                               if (hci->pdata->oci_irq)
+                                       disable_irq(hci->pdata->oci_irq);
+                               rmobile_vbus_control(hci, 0);
+                       } else
+                               hci->vbus_flag = 1;
+               }
+       }
+}
+EXPORT_SYMBOL(rmobile_vbus_setup);
diff --git a/drivers/usb/host/rmobile-common.h 
b/drivers/usb/host/rmobile-common.h
new file mode 100644
index 0000000..2f1db92
--- /dev/null
+++ b/drivers/usb/host/rmobile-common.h
@@ -0,0 +1,53 @@
+/*
+ * Driver for OHCI and EHCI on Renesas ARM SoC (rmobile)
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details
+ */
+
+#include <linux/usb/rmobile.h>
+
+struct rmobile_hci {
+       struct usb_hcd *hcd;
+
+       u32 phys_base;
+       void __iomem *base;
+
+       int vbus_flag;
+       u32 relinquish_count;
+       u32 handed_over;
+
+       /* platform data */
+       struct rmobile_usb_platdata *pdata;
+
+       /* backup area */
+       struct rmobile_ehci_reg ehci_reg;
+       struct rmobile_ohci_reg ohci_reg;
+};
+
+static inline void rmobile_vbus_control(struct rmobile_hci *hci, int on)
+{
+       if (hci->pdata->set_vbus)
+               hci->pdata->set_vbus(on);
+       hci->vbus_flag = on ? 0 : 1;
+}
+
+static inline int rmobile_over_current_check(struct rmobile_hci *hci)
+{
+       if (hci->pdata->check_oci()) {
+               pr_err("USB Over Current\n");
+               rmobile_vbus_control(hci, 0);
+               return 1;
+       }
+       return 0;
+}
+
+void rmobile_hc_start(struct usb_hcd *hcd,
+       struct platform_device *pdev);
+void rmobile_hc_stop(struct usb_hcd *hcd,
+       struct platform_device *pdev);
+void rmobile_vbus_setup(u16 typereq,
+       u16 value, struct rmobile_hci *hci);
diff --git a/include/linux/usb/rmobile.h b/include/linux/usb/rmobile.h
new file mode 100644
index 0000000..8f26303
--- /dev/null
+++ b/include/linux/usb/rmobile.h
@@ -0,0 +1,254 @@
+#ifndef __LINUX_USB_RMOBILE_H
+#define __LINUX_USB_RMOBILE_H
+
+#include <linux/platform_device.h>
+
+struct rmobile_usb_platdata {
+       /* VBUS power on */
+       void (*set_vbus)(int on);
+
+       /* Overcurrent */
+       int oci_irq;
+       int (*check_oci)(void);
+
+       /* common clock */
+       void (*common_clock)(struct platform_device *pdev, int on);
+};
+
+/* OverCurrent parameter */
+#define OVER_CURRENT_TIME      5
+
+/* Register offset */
+#define OHCI_OFFSET            0x0
+#define OHCI_SIZE              0x1000
+
+#define EHCI_OFFSET            0x1000
+#define EHCI_SIZE              0x1000
+
+/* PCI Configuration Registers */
+#define VID_DID                0x0000
+#define CMND_STS       0x0004
+#define BASEAD         0x0010
+#define PM_CONTROL     0x0044
+
+#define PCI_CONF_OHCI_OFFSET   0x10000
+#define OHCI_VID_DID   (PCI_CONF_OHCI_OFFSET + VID_DID)
+#define OHCI_CMND_STS  (PCI_CONF_OHCI_OFFSET + CMND_STS)
+#define OHCI_BASEAD            (PCI_CONF_OHCI_OFFSET + BASEAD)
+#define OHCI_PM_CONTROL        (PCI_CONF_OHCI_OFFSET + PM_CONTROL)
+
+#define PCI_CONF_EHCI_OFFSET   0x10100
+#define EHCI_VID_DID   (PCI_CONF_EHCI_OFFSET + VID_DID)
+#define EHCI_CMND_STS  (PCI_CONF_EHCI_OFFSET + CMND_STS)
+#define EHCI_BASEAD            (PCI_CONF_EHCI_OFFSET + BASEAD)
+#define EHCI_PM_CONTROL        (PCI_CONF_EHCI_OFFSET + BASEAD)
+
+/* PCI Configuration Registers for AHB-PCI Bridge Registers */
+#define PCI_CONF_AHBPCI_OFFSET 0x10000
+#define PCI_CONF_AHBPCI_VID_DID                        (PCI_CONF_AHBPCI_OFFSET 
+ 0x0000)
+#define PCI_CONF_AHBPCI_CMND_STS               (PCI_CONF_AHBPCI_OFFSET + 
0x0004)
+#define PCI_CONF_AHBPCI_REVID_CC               (PCI_CONF_AHBPCI_OFFSET + 
0x0008)
+#define PCI_CONF_AHBPCI_CLS_LT_HT_BIST (PCI_CONF_AHBPCI_OFFSET + 0x000C)
+#define PCI_CONF_AHBPCI_BASEAD                 (PCI_CONF_AHBPCI_OFFSET + 
0x0010)
+#define PCI_CONF_AHBPCI_WIN1_BASEAD            (PCI_CONF_AHBPCI_OFFSET + 
0x0014)
+#define PCI_CONF_AHBPCI_WIN2_BASEAD            (PCI_CONF_AHBPCI_OFFSET + 
0x0018)
+#define PCI_CONF_AHBPCI_SSVID_SSID             (PCI_CONF_AHBPCI_OFFSET + 
0x002C)
+#define PCI_CONF_AHBPCI_INTR_LINE_PIN  (PCI_CONF_AHBPCI_OFFSET + 0x003C)
+
+/* AHB-PCI Bridge PCI Communication Registers */
+#define AHBPCI_OFFSET          0x10800
+#define PCIAHB_WIN1_CTR                (AHBPCI_OFFSET + 0x0000)
+#define PCIAHB_WIN2_CTR                (AHBPCI_OFFSET + 0x0004)
+#define PCIAHB_DCT_CTR         (AHBPCI_OFFSET + 0x0008)
+#define AHBPCI_WIN1_CTR                (AHBPCI_OFFSET + 0x0010)
+#define AHBPCI_WIN2_CTR                (AHBPCI_OFFSET + 0x0014)
+#define AHBPCI_DCT_CTR         (AHBPCI_OFFSET + 0x001C)
+#define PCI_INT_ENABLE         (AHBPCI_OFFSET + 0x0020)
+#define PCI_INT_STATUS         (AHBPCI_OFFSET + 0x0024)
+#define AHB_BUS_CTR                    (AHBPCI_OFFSET + 0x0030)
+#define USBCTR                         (AHBPCI_OFFSET + 0x0034)
+#define PCI_ARBITER_CTR                (AHBPCI_OFFSET + 0x0040)
+#define PCI_UNIT_REV           (AHBPCI_OFFSET + 0x004C)
+
+/* CMND_STS (0x10004) */
+#define DETPERR                        (1 << 31)               /* RW */
+#define SIGSERR                        (1 << 30)               /* RW */
+#define REMABORT               (1 << 29)               /* RW */
+#define RETABORT               (1 << 28)               /* RW */
+#define SIGTABORT              (1 << 27)               /* RW */
+#define DEVTIM                 ((1 << 26)|(1 << 25))   /* R */
+#define MDPERR                 (1 << 24)               /* R */
+#define FBTBCAP                        (1 << 23)               /* R */
+#define _66MCAP                        (1 << 21)               /* R */
+#define CAPLIST                        (1 << 20)               /* R */
+#define FBTBEN                 (1 << 9)                /* R */
+#define SERREN                 (1 << 8)                /* RW */
+#define STEPCTR                        (1 << 7)                /* R */
+#define PERREN                 (1 << 6)                /* RW */
+#define VGAPSNP                        (1 << 5)                /* R */
+#define MWINVEN                        (1 << 4)                /* R */
+#define SPECIALC               (1 << 3)                /* R */
+#define MASTEREN               (1 << 2)                /* RW */
+#define MEMEN                  (1 << 1)                /* RW */
+#define IOEN                   (1 << 0)                /* R */
+
+/* WIN1_BASEAD (0x10014) */
+#define PCI_WIN1_BASEADR       0xF0000000              /* RW */
+#define WIN1_PREFETCH          (1 << 3)                /* R */
+#define WIN1_TYPE              ((1 << 2)|(1 << 1))     /* R */
+#define WIN1_MEM               (1 << 0)                /* R */
+
+/* WIN2_BASEAD (0x10018) */
+#define PCI_WIN2_BASEADR       0xF0000000              /* RW */
+#define WIN2_PREFETCH          (1 << 3)                /* R */
+#define WIN2_TYPE              ((1 << 2)|(1 << 1))     /* R */
+#define WIN2_MEM               (1 << 0)                /* R */
+
+/* PCIAHB_WIN1_CTR (0x10800) */
+#define AHB_BASEADR            ((1 << 31)|(1 << 30))   /* RW */
+#define ENDIAN_CTR             0x000001C0              /* RW */
+#define PREFETCH               ((1 << 1)|(1 << 0))     /* RW */
+
+/* PCIAHB_WIN2_CTR (0x10804) */
+#define AHB_BASE_ADR           (1 << 31)_(1 << 28)     /* RW */
+#define ENDIAN_CTR             0x000001C0              /* RW */
+#define PREFETCH               ((1 << 1)|(1 << 0))     /* RW */
+
+/* PCIAHB_DCT_CTR (0x10808) */
+#define PCIAHB_DISCARD_TIMER   0x0000FFF0              /* RW */
+#define DISCARD_EN             (1 << 0)                /* RW */
+
+/* AHBPCI_WIN1_CTR (0x10810) */
+#define PCIWIN1_BASEADR                0xFFFFF800              /* RW */
+#define ENDIAN_CTR             0x000001C0              /* RW */
+#define CFGTYPE                        (1 << 4)                /* RW */
+#define PCICMD                 0x0000000E              /* RW */
+#define PCIWIN1_PCICMD         ((1 << 3)|(1 << 1))
+#define AHB_CFG_AHBPCI         0x40000000
+#define AHB_CFG_HOST           0x80000000
+
+/* AHBPCI_WIN2_CTR (0x10814) */
+#define PCIWIN2_BASEADR                0xFFFF0000              /* RW */
+#define ENDIAN_CTR             0x000001C0              /* RW */
+#define BURST_EN               (1 << 5)                /* RW */
+#define PCICMD                 0x0000000E              /* RW */
+#define PCIWIN2_PCICMD         ((1 << 2)|(1 << 1))
+#define PCIWIN2_PREFETCH       (1 << 0)                /* RW */
+
+/* AHBPCI_DCT_CTR (0x1081C) */
+#define AHBPCI_DISCARD_TIMER   (1 << 15)_(1 << 4)      /* RW */
+#define DISCARD_EN             (1 << 0)                /* RW */
+
+/* PCI_INT_ENABLE (0x10820) */
+#define USBH_PMEEN             (1 << 19)               /* RW */
+#define USBH_INTBEN            (1 << 17)               /* RW */
+#define USBH_INTAEN            (1 << 16)               /* RW */
+#define AHBPCI_WIN_INTEN       (1 << 14)               /* RW */
+#define PCIAHB_WIN2_INTEN      (1 << 13)               /* RW */
+#define PCIAHB_WIN1_INTEN      (1 << 12)               /* RW */
+#define DMA_AHBPCI_INTEN       (1 << 9)                /* RW */
+#define DMA_PCIAHB_INTEN       (1 << 8)                /* RW */
+#define RESERR_INTEN           (1 << 5)                /* RW */
+#define SIGSERR_INTEN          (1 << 4)                /* RW */
+#define PERR_INTEN             (1 << 3)                /* RW */
+#define REMABORT_INTEN         (1 << 2)                /* RW */
+#define RETABORT_INTEN         (1 << 1)                /* RW */
+#define SIGTABORT_INTEN                (1 << 0)                /* RW */
+
+/* PCI_INT_STATUS (0x10824) */
+#define USBH_PME               (1 << 19)               /* R */
+#define USBH_INTB              (1 << 17)               /* R */
+#define USBH_INTA              (1 << 16)               /* R */
+#define AHBPCI_WIN_INT         (1 << 14)               /* RW */
+#define PCIAHB_WIN2_INT                (1 << 13)               /* RW */
+#define PCIAHB_WIN1_INT                (1 << 12)               /* RW */
+#define DMA_AHBPCI_INT         (1 << 9)                /* RW */
+#define DMA_PCIAHB_INT         (1 << 8)                /* RW */
+#define RESERR_INT             (1 << 5)                /* RW */
+#define SIGSERR_INT            (1 << 4)                /* RW */
+#define PERR_INT               (1 << 3)                /* RW */
+#define REMABORT_INT           (1 << 2)                /* RW */
+#define RETABORT_INT           (1 << 1)                /* RW */
+#define SIGTABORT_INT          (1 << 0)                /* RW */
+
+/* AHB_BUS_CTR (0x10830) */
+#define SMODE_READY_CTR                (1 << 17)               /* RW */
+#define SMODE_READ_BURST       (1 << 16)               /* RW */
+#define MMODE_HBUSREQ          (1 << 7)                /* RW */
+#define MMODE_BOUNDARY         ((1 << 6)|(1 << 5))     /* RW */
+#define MMODE_BURST_WIDTH      ((1 << 4)|(1 << 3))     /* RW */
+#define MMODE_SINGLE_MODE      ((1 << 4)|(1 << 3))     /* RW */
+#define MMODE_WR_INCR          (1 << 2)                /* RW */
+#define MMODE_BYTE_BURST       (1 << 1)                /* RW */
+#define MMODE_HTRANS           (1 << 0)                /* RW */
+#define AHB_BUS_CTR_SET        \
+       ((1 << 17) | (1 << 7) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1))
+
+/* USBCTR (0x10834) */
+#define DIRPD                  (1 << 8)                /* RW */
+#define PLL_RST                        (1 << 2)                /* RW */
+#define PCICLK_MASK            (1 << 1)                /* RW */
+#define USBH_RST               (1 << 0)                /* RW */
+
+/* PCI_ARBITER_CTR (0x10840) */
+#define PCIBUS_PARK_TIMER      0x00FF0000              /* RW */
+#define PCIBUS_PARK_TIMER_SET  0x00070000
+#define PCIBP_MODE             (1 << 12)               /* RW */
+#define PCIREQ7                        (1 << 7)                /* RW */
+#define PCIREQ6                        (1 << 6)                /* RW */
+#define PCIREQ5                        (1 << 5)                /* RW */
+#define PCIREQ4                        (1 << 4)                /* RW */
+#define PCIREQ3                        (1 << 3)                /* RW */
+#define PCIREQ2                        (1 << 2)                /* RW */
+#define PCIREQ1                        (1 << 1)                /* RW */
+#define PCIREQ0                        (1 << 0)                /* RW */
+
+/*-------------------------------------------------------------------------*/
+
+struct rmobile_ohci_reg {
+       u32     hcrevision;     
+       u32     hccontrol;      
+       u32     hccommandstatus;
+       u32     hcinterruptstatus;
+       u32     hcinterruptenable;
+       u32     hcinterruptdisable;
+       u32     hchcca;
+       u32     hcperiodiccurrented;
+       u32     hccontrolheaded;
+       u32     hccontrolcurrented;     
+       u32     hcbulkheaded;
+       u32     hcbulkcurrented;
+       u32     hcdonehead;
+       u32     hcfminterval;
+       u32     hcfmremaining;
+       u32     hcfmnumber;
+       u32     hcperiodicstart;
+       u32     hclsthreshold;
+       u32     hcrhdescrptora;
+       u32     hcrhdescrptorb;
+       u32     hcrhstatus;     
+       u32     hcrhportstatus;
+
+       u32     save_flag;
+};
+
+struct rmobile_ehci_reg {
+       u32     hciversion;
+       u32     hcsparams;
+       u32     hccparams;
+       u32     hcsp_portroute;
+       u32     usbcmd;
+       u32     usbsts;
+       u32     usbintr;
+       u32     frindex;
+       u32     ctrldssegment;
+       u32     periodiclistbase;
+       u32     asynclistaddr;  
+       u32     reserved_1[9];
+       u32     configflag;
+       u32     portsc; 
+
+       u32     save_flag;
+};
+
+#endif /* __LINUX_USB_RMOBILE_H */
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" 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