Separate the  Samsung OHCI EXYNOS host controller driver from ohci-hcd
host code so that it can be built as a separate driver module.
This work is part of enabling multi-platform kernels on ARM;
however, note that other changes are still needed before EXYNOS can
be booted with a multi-platform kernel. We currently expect those
to get merged for 3.11.

Signed-off-by: Manjunath Goudar <manjunath.gou...@linaro.org>
Cc: Arnd Bergmann <a...@arndb.de>
Cc: Jingoo Han <jg1....@samsung.com>
Cc: Kukjin Kim <kgene....@samsung.com>
Cc: Greg KH <g...@kroah.com>
Cc: Alan Stern <st...@rowland.harvard.edu>
Cc: linux-usb@vger.kernel.org
---
 drivers/usb/host/Kconfig         |    2 +-
 drivers/usb/host/Makefile        |    1 +
 drivers/usb/host/ohci-exynos.c   |  140 +++++++++++++++++++-------------------
 drivers/usb/host/ohci-hcd.c      |    5 --
 drivers/usb/host/ohci-platform.c |    2 +-
 5 files changed, 72 insertions(+), 78 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index bbf1907..42ce228 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -445,7 +445,7 @@ config USB_OHCI_SH
          If you use the PCI OHCI controller, this option is not necessary.
 
 config USB_OHCI_EXYNOS
-       boolean "OHCI support for Samsung EXYNOS SoC Series"
+       tristate "OHCI support for Samsung EXYNOS SoC Series"
        depends on USB_OHCI_HCD && ARCH_EXYNOS
        help
         Enable support for the Samsung Exynos SOC's on-chip OHCI controller.
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index a20a8d9..f148671 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o
 
 obj-$(CONFIG_USB_OHCI_HCD)     += ohci-hcd.o
 obj-$(CONFIG_USB_OHCI_PCI)     += ohci-pci.o
+obj-$(CONFIG_USB_OHCI_EXYNOS)  += ohci-exynos.o
 
 obj-$(CONFIG_USB_UHCI_HCD)     += uhci-hcd.o
 obj-$(CONFIG_USB_FHCI_HCD)     += fhci.o
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index e3b7e85..59d6e23 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -12,25 +12,39 @@
  */
 
 #include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/usb-exynos.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
 #include <linux/usb/phy.h>
 #include <linux/usb/samsung_usb_phy.h>
+#include <linux/usb/otg.h>
 #include <plat/usb-phy.h>
 
+#include "ohci.h"
+
+#define DRIVER_DESC "OHCI exynos driver"
+
+static const char hcd_name[] = "ohci-exynos";
+static struct hc_driver __read_mostly exynos_ohci_hc_driver;
+
+#define to_exynos_ohci(hcd) (struct exynos_ohci_hcd *)(hcd_to_ohci(hcd)->priv)
+
 struct exynos_ohci_hcd {
-       struct device *dev;
-       struct usb_hcd *hcd;
        struct clk *clk;
        struct usb_phy *phy;
        struct usb_otg *otg;
        struct exynos4_ohci_platdata *pdata;
 };
 
-static void exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci)
+static void exynos_ohci_phy_enable(struct platform_device *pdev)
 {
-       struct platform_device *pdev = to_platform_device(exynos_ohci->dev);
+       struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
 
        if (exynos_ohci->phy)
                usb_phy_init(exynos_ohci->phy);
@@ -38,9 +52,9 @@ static void exynos_ohci_phy_enable(struct exynos_ohci_hcd 
*exynos_ohci)
                exynos_ohci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
 }
 
-static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci)
+static void exynos_ohci_phy_disable(struct platform_device *pdev)
 {
-       struct platform_device *pdev = to_platform_device(exynos_ohci->dev);
+       struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
 
        if (exynos_ohci->phy)
                usb_phy_shutdown(exynos_ohci->phy);
@@ -60,7 +74,7 @@ static int ohci_exynos_start(struct usb_hcd *hcd)
 
        ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci);
 
-       ret = ohci_run(ohci);
+       ret = ohci_run(hcd);
        if (ret < 0) {
                dev_err(hcd->self.controller, "can't start %s\n",
                        hcd->self.bus_name);
@@ -71,34 +85,6 @@ static int ohci_exynos_start(struct usb_hcd *hcd)
        return 0;
 }
 
-static const struct hc_driver exynos_ohci_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "EXYNOS OHCI Host Controller",
-       .hcd_priv_size          = sizeof(struct ohci_hcd),
-
-       .irq                    = ohci_irq,
-       .flags                  = HCD_MEMORY|HCD_USB11,
-
-       .reset                  = ohci_exynos_reset,
-       .start                  = ohci_exynos_start,
-       .stop                   = ohci_stop,
-       .shutdown               = ohci_shutdown,
-
-       .get_frame_number       = ohci_get_frame,
-
-       .urb_enqueue            = ohci_urb_enqueue,
-       .urb_dequeue            = ohci_urb_dequeue,
-       .endpoint_disable       = ohci_endpoint_disable,
-
-       .hub_status_data        = ohci_hub_status_data,
-       .hub_control            = ohci_hub_control,
-#ifdef CONFIG_PM
-       .bus_suspend            = ohci_bus_suspend,
-       .bus_resume             = ohci_bus_resume,
-#endif
-       .start_port_reset       = ohci_start_port_reset,
-};
-
 static u64 ohci_exynos_dma_mask = DMA_BIT_MASK(32);
 
 static int exynos_ohci_probe(struct platform_device *pdev)
@@ -122,11 +108,13 @@ static int exynos_ohci_probe(struct platform_device *pdev)
        if (!pdev->dev.coherent_dma_mask)
                pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
-       exynos_ohci = devm_kzalloc(&pdev->dev, sizeof(struct exynos_ohci_hcd),
-                                       GFP_KERNEL);
-       if (!exynos_ohci)
+       hcd = usb_create_hcd(&exynos_ohci_hc_driver,
+                               &pdev->dev, dev_name(&pdev->dev));
+       if (!hcd) {
+               dev_err(&pdev->dev, "Unable to create HCD\n");
                return -ENOMEM;
-
+       }
+       exynos_ohci = to_exynos_ohci(hcd);
        phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
        if (IS_ERR_OR_NULL(phy)) {
                /* Fallback to pdata */
@@ -141,16 +129,6 @@ static int exynos_ohci_probe(struct platform_device *pdev)
                exynos_ohci->otg = phy->otg;
        }
 
-       exynos_ohci->dev = &pdev->dev;
-
-       hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev,
-                                       dev_name(&pdev->dev));
-       if (!hcd) {
-               dev_err(&pdev->dev, "Unable to create HCD\n");
-               return -ENOMEM;
-       }
-
-       exynos_ohci->hcd = hcd;
        exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
 
        if (IS_ERR(exynos_ohci->clk)) {
@@ -187,10 +165,9 @@ static int exynos_ohci_probe(struct platform_device *pdev)
        }
 
        if (exynos_ohci->otg)
-               exynos_ohci->otg->set_host(exynos_ohci->otg,
-                                       &exynos_ohci->hcd->self);
+               exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
 
-       exynos_ohci_phy_enable(exynos_ohci);
+       exynos_ohci_phy_enable(pdev);
 
        ohci = hcd_to_ohci(hcd);
        ohci_hcd_init(ohci);
@@ -201,12 +178,12 @@ static int exynos_ohci_probe(struct platform_device *pdev)
                goto fail_add_hcd;
        }
 
-       platform_set_drvdata(pdev, exynos_ohci);
+       platform_set_drvdata(pdev, hcd);
 
        return 0;
 
 fail_add_hcd:
-       exynos_ohci_phy_disable(exynos_ohci);
+       exynos_ohci_phy_disable(pdev);
 fail_io:
        clk_disable_unprepare(exynos_ohci->clk);
 fail_clk:
@@ -216,16 +193,15 @@ fail_clk:
 
 static int exynos_ohci_remove(struct platform_device *pdev)
 {
-       struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
-       struct usb_hcd *hcd = exynos_ohci->hcd;
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+       struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
 
        usb_remove_hcd(hcd);
 
        if (exynos_ohci->otg)
-               exynos_ohci->otg->set_host(exynos_ohci->otg,
-                                       &exynos_ohci->hcd->self);
+               exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
 
-       exynos_ohci_phy_disable(exynos_ohci);
+       exynos_ohci_phy_disable(pdev);
 
        clk_disable_unprepare(exynos_ohci->clk);
 
@@ -236,8 +212,7 @@ static int exynos_ohci_remove(struct platform_device *pdev)
 
 static void exynos_ohci_shutdown(struct platform_device *pdev)
 {
-       struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
-       struct usb_hcd *hcd = exynos_ohci->hcd;
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
        if (hcd->driver->shutdown)
                hcd->driver->shutdown(hcd);
@@ -246,9 +221,10 @@ static void exynos_ohci_shutdown(struct platform_device 
*pdev)
 #ifdef CONFIG_PM
 static int exynos_ohci_suspend(struct device *dev)
 {
-       struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev);
-       struct usb_hcd *hcd = exynos_ohci->hcd;
+       struct usb_hcd *hcd = dev_get_drvdata(dev);
+       struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       struct platform_device *pdev = to_platform_device(dev);
        unsigned long flags;
        int rc = 0;
 
@@ -268,10 +244,9 @@ static int exynos_ohci_suspend(struct device *dev)
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
        if (exynos_ohci->otg)
-               exynos_ohci->otg->set_host(exynos_ohci->otg,
-                                       &exynos_ohci->hcd->self);
+               exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
 
-       exynos_ohci_phy_disable(exynos_ohci);
+       exynos_ohci_phy_disable(pdev);
 
        clk_disable_unprepare(exynos_ohci->clk);
 
@@ -283,16 +258,16 @@ fail:
 
 static int exynos_ohci_resume(struct device *dev)
 {
-       struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev);
-       struct usb_hcd *hcd = exynos_ohci->hcd;
+       struct usb_hcd *hcd                     = dev_get_drvdata(dev);
+       struct exynos_ohci_hcd *exynos_ohci     = to_exynos_ohci(hcd);
+       struct platform_device *pdev            = to_platform_device(dev);
 
        clk_prepare_enable(exynos_ohci->clk);
 
        if (exynos_ohci->otg)
-               exynos_ohci->otg->set_host(exynos_ohci->otg,
-                                       &exynos_ohci->hcd->self);
+               exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
 
-       exynos_ohci_phy_enable(exynos_ohci);
+       exynos_ohci_phy_enable(pdev);
 
        ohci_resume(hcd, false);
 
@@ -303,6 +278,12 @@ static int exynos_ohci_resume(struct device *dev)
 #define exynos_ohci_resume     NULL
 #endif
 
+static const struct ohci_driver_overrides exynos_overrides = {
+       .extra_priv_size =      sizeof(struct exynos_ohci_hcd),
+       .reset =                ohci_exynos_reset,
+       .start =                ohci_exynos_start,
+};
+
 static const struct dev_pm_ops exynos_ohci_pm_ops = {
        .suspend        = exynos_ohci_suspend,
        .resume         = exynos_ohci_resume,
@@ -327,6 +308,23 @@ static struct platform_driver exynos_ohci_driver = {
                .of_match_table = of_match_ptr(exynos_ohci_match),
        }
 };
+static int __init ehci_exynos_init(void)
+{
+       if (usb_disabled())
+               return -ENODEV;
+
+       pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+       ohci_init_driver(&exynos_ohci_hc_driver, &exynos_overrides);
+       return platform_driver_register(&exynos_ohci_driver);
+}
+module_init(ehci_exynos_init);
+
+static void __exit ehci_exynos_cleanup(void)
+{
+       platform_driver_unregister(&exynos_ohci_driver);
+}
+module_exit(ehci_exynos_cleanup);
 
 MODULE_ALIAS("platform:exynos-ohci");
 MODULE_AUTHOR("Jingoo Han <jg1....@samsung.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 3d624c2..8881e1a 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1152,11 +1152,6 @@ MODULE_LICENSE ("GPL");
 #define S3C2410_PLATFORM_DRIVER        ohci_hcd_s3c2410_driver
 #endif
 
-#ifdef CONFIG_USB_OHCI_EXYNOS
-#include "ohci-exynos.c"
-#define EXYNOS_PLATFORM_DRIVER exynos_ohci_driver
-#endif
-
 #ifdef CONFIG_USB_OHCI_HCD_OMAP1
 #include "ohci-omap.c"
 #define OMAP1_PLATFORM_DRIVER  ohci_hcd_omap_driver
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index c3e7287..545c657 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -46,7 +46,7 @@ static int ohci_platform_start(struct usb_hcd *hcd)
        struct ohci_hcd *ohci = hcd_to_ohci(hcd);
        int err;
 
-       err = ohci_run(ohci);
+       err = ohci_run(hcd);
        if (err < 0) {
                ohci_err(ohci, "can't start\n");
                ohci_stop(hcd);
-- 
1.7.9.5

--
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