These patches are for separating the SOC On-Chip ohci host controller from ohci-hcd host code into its own driver module. This work is part of enabling multi-platform kernels on ARM.
Manjunath Goudar (7): USB: OHCI: make ohci-exynos a separate driver USB: OHCI: make ohci-omap a separate driver USB: OHCI: make ohci-omap3 a separate driver USB: OHCI: make ohci-spear a separate driver USB: OHCI: export ohci_hub_control and ohci_hub_status_data USB: OHCI: make ohci-at91 a separate driver USB: OHCI: make ohci-s3c2410 a separate driver
drivers/usb/host/Kconfig | 30 +++++++- drivers/usb/host/Makefile | 6 ++ drivers/usb/host/ohci-at91.c | 135 +++++++++++++++------------------- drivers/usb/host/ohci-exynos.c | 154 +++++++++++++++++---------------------- drivers/usb/host/ohci-hcd.c | 122 ++----------------------------- drivers/usb/host/ohci-hub.c | 8 +- drivers/usb/host/ohci-omap.c | 142 +++++++++++++----------------------- drivers/usb/host/ohci-omap3.c | 122 +++++++++++-------------------- drivers/usb/host/ohci-s3c2410.c | 116 ++++++++++++----------------- drivers/usb/host/ohci-spear.c | 149 ++++++++++++++++--------------------- drivers/usb/host/ohci.h | 9 +++ 11 files changed, 383 insertions(+), 610 deletions(-)
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.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Arnd Bergmann arnd@arndb.de Cc: Jingoo Han jg1.han@samsung.com Cc: Kukjin Kim kgene.kim@samsung.com Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@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 | 154 +++++++++++++++++----------------------- drivers/usb/host/ohci-hcd.c | 20 +----- 4 files changed, 70 insertions(+), 107 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 5391a38..f827386 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -484,7 +484,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 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 8a89c3d..2a4f11f 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_OHCI_HCD_PCI) += ohci-pci.o obj-$(CONFIG_USB_OHCI_HCD_PLATFORM) += ohci-platform.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 07592c0..a5f4c33 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -12,24 +12,38 @@ */
#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-ohci-exynos.h> #include <linux/usb/phy.h> #include <linux/usb/samsung_usb_phy.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <linux/usb/otg.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); @@ -37,9 +51,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); @@ -47,57 +61,6 @@ static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci) exynos_ohci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST); }
-static int ohci_exynos_reset(struct usb_hcd *hcd) -{ - return ohci_init(hcd_to_ohci(hcd)); -} - -static int ohci_exynos_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int ret; - - ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci); - - ret = ohci_run(ohci); - if (ret < 0) { - dev_err(hcd->self.controller, "can't start %s\n", - hcd->self.bus_name); - ohci_stop(hcd); - return ret; - } - - 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) @@ -105,7 +68,6 @@ static int exynos_ohci_probe(struct platform_device *pdev) struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; struct exynos_ohci_hcd *exynos_ohci; struct usb_hcd *hcd; - struct ohci_hcd *ohci; struct resource *res; struct usb_phy *phy; int irq; @@ -121,15 +83,18 @@ 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;
if (of_device_is_compatible(pdev->dev.of_node, "samsung,exynos5440-ohci")) goto skip_phy;
+ } + exynos_ohci = to_exynos_ohci(hcd); phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); if (IS_ERR(phy)) { /* Fallback to pdata */ @@ -146,7 +111,6 @@ static int exynos_ohci_probe(struct platform_device *pdev)
skip_phy:
- exynos_ohci->dev = &pdev->dev;
hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev, dev_name(&pdev->dev)); @@ -155,7 +119,6 @@ skip_phy: return -ENOMEM; }
- exynos_ohci->hcd = hcd; exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
if (IS_ERR(exynos_ohci->clk)) { @@ -192,13 +155,11 @@ skip_phy: }
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); + ohci_setup(hcd);
err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { @@ -206,12 +167,12 @@ skip_phy: 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: @@ -221,16 +182,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);
@@ -241,8 +201,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); @@ -251,9 +210,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;
@@ -273,10 +233,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);
@@ -288,16 +247,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);
@@ -308,6 +267,10 @@ static int exynos_ohci_resume(struct device *dev) #define exynos_ohci_resume NULL #endif
+static const struct ohci_driver_overrides exynos_overrides __initconst = { + .extra_priv_size = sizeof(struct exynos_ohci_hcd), +}; + static const struct dev_pm_ops exynos_ohci_pm_ops = { .suspend = exynos_ohci_suspend, .resume = exynos_ohci_resume, @@ -333,6 +296,23 @@ static struct platform_driver exynos_ohci_driver = { .of_match_table = of_match_ptr(exynos_ohci_match), } }; +static int __init ohci_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(ohci_exynos_init); + +static void __exit ohci_exynos_cleanup(void) +{ + platform_driver_unregister(&exynos_ohci_driver); +} +module_exit(ohci_exynos_cleanup);
MODULE_ALIAS("platform:exynos-ohci"); MODULE_AUTHOR("Jingoo Han jg1.han@samsung.com"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 39c7624..14962f8 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1178,11 +1178,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 @@ -1260,6 +1255,7 @@ MODULE_LICENSE ("GPL");
#if !IS_ENABLED(CONFIG_USB_OHCI_HCD_PCI) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_PLATFORM) && \ + !IS_ENABLED(CONFIG_USB_OHCI_EXYNOS) && \ !defined(PLATFORM_DRIVER) && \ !defined(OMAP1_PLATFORM_DRIVER) && \ !defined(OMAP3_PLATFORM_DRIVER) && \ @@ -1269,7 +1265,6 @@ MODULE_LICENSE ("GPL"); !defined(SM501_OHCI_DRIVER) && \ !defined(TMIO_OHCI_DRIVER) && \ !defined(S3C2410_PLATFORM_DRIVER) && \ - !defined(EXYNOS_PLATFORM_DRIVER) && \ !defined(EP93XX_PLATFORM_DRIVER) && \ !defined(AT91_PLATFORM_DRIVER) && \ !defined(NXP_PLATFORM_DRIVER) && \ @@ -1352,12 +1347,6 @@ static int __init ohci_hcd_mod_init(void) goto error_s3c2410; #endif
-#ifdef EXYNOS_PLATFORM_DRIVER - retval = platform_driver_register(&EXYNOS_PLATFORM_DRIVER); - if (retval < 0) - goto error_exynos; -#endif - #ifdef EP93XX_PLATFORM_DRIVER retval = platform_driver_register(&EP93XX_PLATFORM_DRIVER); if (retval < 0) @@ -1411,10 +1400,6 @@ static int __init ohci_hcd_mod_init(void) platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); error_ep93xx: #endif -#ifdef EXYNOS_PLATFORM_DRIVER - platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER); - error_exynos: -#endif #ifdef S3C2410_PLATFORM_DRIVER platform_driver_unregister(&S3C2410_PLATFORM_DRIVER); error_s3c2410: @@ -1479,9 +1464,6 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef EP93XX_PLATFORM_DRIVER platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); #endif -#ifdef EXYNOS_PLATFORM_DRIVER - platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER); -#endif #ifdef S3C2410_PLATFORM_DRIVER platform_driver_unregister(&S3C2410_PLATFORM_DRIVER); #endif
On Friday 07 June 2013 11:33:27 Manjunath Goudar wrote:
#if !IS_ENABLED(CONFIG_USB_OHCI_HCD_PCI) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_PLATFORM) && \
!IS_ENABLED(CONFIG_USB_OHCI_EXYNOS) && \ !defined(PLATFORM_DRIVER) && \ !defined(OMAP1_PLATFORM_DRIVER) && \ !defined(OMAP3_PLATFORM_DRIVER) && \
@@ -1269,7 +1265,6 @@ MODULE_LICENSE ("GPL"); !defined(SM501_OHCI_DRIVER) && \ !defined(TMIO_OHCI_DRIVER) && \ !defined(S3C2410_PLATFORM_DRIVER) && \
!defined(EXYNOS_PLATFORM_DRIVER) && \ !defined(EP93XX_PLATFORM_DRIVER) && \ !defined(AT91_PLATFORM_DRIVER) && \ !defined(NXP_PLATFORM_DRIVER) && \
Hi Manjunath,
please note that Greg just merged my patch to remove this entire list and the #error statement. The next time you rebase your patch, you will have to remove this hunk in each of your patches.
Arnd
On Fri, 7 Jun 2013, Manjunath Goudar wrote:
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.
-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);
This is wrong. platform_get_drvdata() will return the hcd, not the exynos_ohci_hcd structure.
@@ -37,9 +51,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);
Same problem here.
@@ -121,15 +83,18 @@ 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) {
return -ENOMEM;dev_err(&pdev->dev, "Unable to create HCD\n");
if (of_device_is_compatible(pdev->dev.of_node, "samsung,exynos5440-ohci")) goto skip_phy;
- }
This close brace belongs with the previous "if" statement.
@@ -146,7 +111,6 @@ static int exynos_ohci_probe(struct platform_device *pdev) skip_phy:
- exynos_ohci->dev = &pdev->dev;
hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev, dev_name(&pdev->dev));
This needs to be deleted, because it was done already.
Manjunath, I have already asked you to proof-read your patches before posting them. Please do so. New patches should _not_ have this kind of error.
@@ -192,13 +155,11 @@ skip_phy: } 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);
This call will not work, because you don't set pdev's platform_data until later. The call to platform_set_drvdata() must be moved before this line.
- ohci = hcd_to_ohci(hcd);
- ohci_hcd_init(ohci);
- ohci_setup(hcd);
There's no need to call ohci_setup(), because it will get called anyway as the .reset member of the ohci_hc_driver structure.
Alan Stern
Separate the TI OHCI OMAP1/2 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.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Felipe Balbi balbi@ti.com Cc: Arnd Bergmann arnd@arndb.de Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@rowland.harvard.edu Cc: linux-usb@vger.kernel.org --- drivers/usb/host/Kconfig | 2 +- drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-hcd.c | 20 +----- drivers/usb/host/ohci-omap.c | 142 ++++++++++++++++-------------------------- 4 files changed, 55 insertions(+), 110 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f827386..744673b 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -397,7 +397,7 @@ config USB_OHCI_HCD if USB_OHCI_HCD
config USB_OHCI_HCD_OMAP1 - bool "OHCI support for OMAP1/2 chips" + tristate "OHCI support for OMAP1/2 chips" depends on ARCH_OMAP1 default y ---help--- diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 2a4f11f..1326df2 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_OHCI_HCD_PCI) += ohci-pci.o obj-$(CONFIG_USB_OHCI_HCD_PLATFORM) += ohci-platform.o obj-$(CONFIG_USB_OHCI_EXYNOS) += ohci-exynos.o +obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 14962f8..4bfd890 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1178,11 +1178,6 @@ MODULE_LICENSE ("GPL"); #define S3C2410_PLATFORM_DRIVER ohci_hcd_s3c2410_driver #endif
-#ifdef CONFIG_USB_OHCI_HCD_OMAP1 -#include "ohci-omap.c" -#define OMAP1_PLATFORM_DRIVER ohci_hcd_omap_driver -#endif - #ifdef CONFIG_USB_OHCI_HCD_OMAP3 #include "ohci-omap3.c" #define OMAP3_PLATFORM_DRIVER ohci_hcd_omap3_driver @@ -1256,8 +1251,8 @@ MODULE_LICENSE ("GPL"); #if !IS_ENABLED(CONFIG_USB_OHCI_HCD_PCI) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_PLATFORM) && \ !IS_ENABLED(CONFIG_USB_OHCI_EXYNOS) && \ + !IS_ENABLED(CONFIG_USB_OHCI_HCD_OMAP1) && \ !defined(PLATFORM_DRIVER) && \ - !defined(OMAP1_PLATFORM_DRIVER) && \ !defined(OMAP3_PLATFORM_DRIVER) && \ !defined(OF_PLATFORM_DRIVER) && \ !defined(SA1111_DRIVER) && \ @@ -1305,12 +1300,6 @@ static int __init ohci_hcd_mod_init(void) goto error_platform; #endif
-#ifdef OMAP1_PLATFORM_DRIVER - retval = platform_driver_register(&OMAP1_PLATFORM_DRIVER); - if (retval < 0) - goto error_omap1_platform; -#endif - #ifdef OMAP3_PLATFORM_DRIVER retval = platform_driver_register(&OMAP3_PLATFORM_DRIVER); if (retval < 0) @@ -1424,10 +1413,6 @@ static int __init ohci_hcd_mod_init(void) platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); error_omap3_platform: #endif -#ifdef OMAP1_PLATFORM_DRIVER - platform_driver_unregister(&OMAP1_PLATFORM_DRIVER); - error_omap1_platform: -#endif #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); error_platform: @@ -1482,9 +1467,6 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef OMAP3_PLATFORM_DRIVER platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); #endif -#ifdef OMAP1_PLATFORM_DRIVER - platform_driver_unregister(&OMAP1_PLATFORM_DRIVER); -#endif #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); #endif diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 8747fa6..eee4b72 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -14,12 +14,21 @@ * This file is licenced under the GPL. */
-#include <linux/signal.h> -#include <linux/jiffies.h> -#include <linux/platform_device.h> #include <linux/clk.h> +#include <linux/dma-mapping.h> #include <linux/err.h> #include <linux/gpio.h> +#include <linux/io.h> +#include <linux/jiffies.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/usb/otg.h> +#include <linux/platform_device.h> +#include <linux/signal.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#include "ohci.h"
#include <asm/io.h> #include <asm/mach-types.h> @@ -42,10 +51,7 @@ #define OMAP1510_LB_MMU_RAM_H 0xfffec234 #define OMAP1510_LB_MMU_RAM_L 0xfffec238
- -#ifndef CONFIG_ARCH_OMAP -#error "This file is OMAP bus glue. CONFIG_OMAP must be defined." -#endif +#define DRIVER_DESC "OHCI OMAP driver"
#ifdef CONFIG_TPS65010 #include <linux/i2c/tps65010.h> @@ -71,6 +77,10 @@ static struct clk *usb_dc_ck; static int host_enabled; static int host_initialized;
+static const char hcd_name[] = "ohci-omap"; +static struct hc_driver __read_mostly ohci_omap_hc_driver; + + static void omap_ohci_clock_power(int on) { if (on) { @@ -188,7 +198,7 @@ static void start_hnp(struct ohci_hcd *ohci)
/*-------------------------------------------------------------------------*/
-static int ohci_omap_init(struct usb_hcd *hcd) +static int ohci_omap_reset(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct omap_usb_config *config = hcd->self.controller->platform_data; @@ -201,8 +211,14 @@ static int ohci_omap_init(struct usb_hcd *hcd) ohci_to_hcd(ohci)->self.otg_port = config->otg; /* default/minimum OTG power budget: 8 mA */ ohci_to_hcd(ohci)->power_budget = 8; + ohci->hc_control = OHCI_CTRL_RWC; + writel(OHCI_CTRL_RWC, &ohci->regs->control); }
+ if (config->rwc) { + ohci->hc_control = OHCI_CTRL_RWC; + writel(OHCI_CTRL_RWC, &ohci->regs->control); + } /* boards can use OTG transceivers in non-OTG modes */ need_transceiver = need_transceiver || machine_is_omap_h2() || machine_is_omap_h3(); @@ -238,7 +254,8 @@ static int ohci_omap_init(struct usb_hcd *hcd) omap_1510_local_bus_init(); }
- if ((ret = ohci_init(ohci)) < 0) + ret = ohci_setup(hcd); + if (ret < 0) return ret;
/* board-specific power switching and overcurrent support */ @@ -281,14 +298,6 @@ static int ohci_omap_init(struct usb_hcd *hcd) return 0; }
-static void ohci_omap_stop(struct usb_hcd *hcd) -{ - dev_dbg(hcd->self.controller, "stopping USB Controller\n"); - ohci_stop(hcd); - omap_ohci_clock_power(0); -} - - /*-------------------------------------------------------------------------*/
/** @@ -304,7 +313,6 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, { int retval, irq; struct usb_hcd *hcd = 0; - struct ohci_hcd *ohci;
if (pdev->num_resources != 2) { printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", @@ -354,8 +362,7 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, goto err2; }
- ohci = hcd_to_ohci(hcd); - ohci_hcd_init(ohci); + ohci_setup(hcd);
host_initialized = 0; host_enabled = 1; @@ -418,76 +425,6 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
/*-------------------------------------------------------------------------*/
-static int -ohci_omap_start (struct usb_hcd *hcd) -{ - struct omap_usb_config *config; - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; - - if (!host_enabled) - return 0; - config = hcd->self.controller->platform_data; - if (config->otg || config->rwc) { - ohci->hc_control = OHCI_CTRL_RWC; - writel(OHCI_CTRL_RWC, &ohci->regs->control); - } - - if ((ret = ohci_run (ohci)) < 0) { - dev_err(hcd->self.controller, "can't start\n"); - ohci_stop (hcd); - return ret; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static const struct hc_driver ohci_omap_hc_driver = { - .description = hcd_name, - .product_desc = "OMAP OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .reset = ohci_omap_init, - .start = ohci_omap_start, - .stop = ohci_omap_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 = 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 int ohci_hcd_omap_drv_probe(struct platform_device *dev) { return usb_hcd_omap_probe(&ohci_omap_hc_driver, dev); @@ -553,4 +490,29 @@ static struct platform_driver ohci_hcd_omap_driver = { }, };
+static const struct ohci_driver_overrides omap_overrides __initconst = { + .product_desc = "OMAP OHCI", + .reset = ohci_omap_reset +}; + +static int __init ohci_omap_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ohci_init_driver(&ohci_omap_hc_driver, &omap_overrides); + return platform_driver_register(&ohci_hcd_omap_driver); +} +module_init(ohci_omap_init); + +static void __exit ohci_omap_cleanup(void) +{ + platform_driver_unregister(&ohci_hcd_omap_driver); +} +module_exit(ohci_omap_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_ALIAS("platform:ohci"); +MODULE_LICENSE("GPL");
On Fri, 7 Jun 2013, Manjunath Goudar wrote:
Separate the TI OHCI OMAP1/2 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.
@@ -71,6 +77,10 @@ static struct clk *usb_dc_ck; static int host_enabled; static int host_initialized;
These two variables aren't used for anything. You should get rid of them.
@@ -201,8 +211,14 @@ static int ohci_omap_init(struct usb_hcd *hcd) ohci_to_hcd(ohci)->self.otg_port = config->otg; /* default/minimum OTG power budget: 8 mA */ ohci_to_hcd(ohci)->power_budget = 8;
ohci->hc_control = OHCI_CTRL_RWC;
}writel(OHCI_CTRL_RWC, &ohci->regs->control);
- if (config->rwc) {
ohci->hc_control = OHCI_CTRL_RWC;
writel(OHCI_CTRL_RWC, &ohci->regs->control);
- }
It's better to have two tests. Remove the two lines added to the previous "if" block, and change this test to
if (config->otg || config->rwc) {
@@ -281,14 +298,6 @@ static int ohci_omap_init(struct usb_hcd *hcd) return 0; } -static void ohci_omap_stop(struct usb_hcd *hcd) -{
- dev_dbg(hcd->self.controller, "stopping USB Controller\n");
- ohci_stop(hcd);
- omap_ohci_clock_power(0);
This last line seems to have gotten lost. You need to add it to usb_hcd_omap_remove().
@@ -354,8 +362,7 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, goto err2; }
- ohci = hcd_to_ohci(hcd);
- ohci_hcd_init(ohci);
- ohci_setup(hcd);
Not needed, since you call ohci_setup() from within ohci_omap_reset().
Alan Stern
Separate the TI OHCI OMAP3 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.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Anand Gadiyar gadiyar@ti.com Cc: Felipe Balbi balbi@ti.com Cc: Arnd Bergmann arnd@arndb.de Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@rowland.harvard.edu Cc: linux-usb@vger.kernel.org --- drivers/usb/host/Kconfig | 2 +- drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-hcd.c | 20 +------ drivers/usb/host/ohci-omap3.c | 122 ++++++++++++++--------------------------- 4 files changed, 45 insertions(+), 100 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 744673b..f42db93 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -404,7 +404,7 @@ config USB_OHCI_HCD_OMAP1 Enables support for the OHCI controller on OMAP1/2 chips.
config USB_OHCI_HCD_OMAP3 - bool "OHCI support for OMAP3 and later chips" + tristate "OHCI support for OMAP3 and later chips" depends on (ARCH_OMAP3 || ARCH_OMAP4) default y ---help--- diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 1326df2..ceb4e55 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_USB_OHCI_HCD_PCI) += ohci-pci.o obj-$(CONFIG_USB_OHCI_HCD_PLATFORM) += ohci-platform.o obj-$(CONFIG_USB_OHCI_EXYNOS) += ohci-exynos.o obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o +obj-$(CONFIG_USB_OHCI_HCD_OMAP3) += ohci-omap3.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 4bfd890..8002bbe 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1178,11 +1178,6 @@ MODULE_LICENSE ("GPL"); #define S3C2410_PLATFORM_DRIVER ohci_hcd_s3c2410_driver #endif
-#ifdef CONFIG_USB_OHCI_HCD_OMAP3 -#include "ohci-omap3.c" -#define OMAP3_PLATFORM_DRIVER ohci_hcd_omap3_driver -#endif - #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) #include "ohci-pxa27x.c" #define PLATFORM_DRIVER ohci_hcd_pxa27x_driver @@ -1252,8 +1247,8 @@ MODULE_LICENSE ("GPL"); !IS_ENABLED(CONFIG_USB_OHCI_HCD_PLATFORM) && \ !IS_ENABLED(CONFIG_USB_OHCI_EXYNOS) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_OMAP1) && \ + !IS_ENABLED(CONFIG_USB_OHCI_HCD_OMAP3) && \ !defined(PLATFORM_DRIVER) && \ - !defined(OMAP3_PLATFORM_DRIVER) && \ !defined(OF_PLATFORM_DRIVER) && \ !defined(SA1111_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && \ @@ -1300,12 +1295,6 @@ static int __init ohci_hcd_mod_init(void) goto error_platform; #endif
-#ifdef OMAP3_PLATFORM_DRIVER - retval = platform_driver_register(&OMAP3_PLATFORM_DRIVER); - if (retval < 0) - goto error_omap3_platform; -#endif - #ifdef OF_PLATFORM_DRIVER retval = platform_driver_register(&OF_PLATFORM_DRIVER); if (retval < 0) @@ -1409,10 +1398,6 @@ static int __init ohci_hcd_mod_init(void) platform_driver_unregister(&OF_PLATFORM_DRIVER); error_of_platform: #endif -#ifdef OMAP3_PLATFORM_DRIVER - platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); - error_omap3_platform: -#endif #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); error_platform: @@ -1464,9 +1449,6 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef OF_PLATFORM_DRIVER platform_driver_unregister(&OF_PLATFORM_DRIVER); #endif -#ifdef OMAP3_PLATFORM_DRIVER - platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); -#endif #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); #endif diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index 08e811d..1d30bc8 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c @@ -29,90 +29,22 @@ * - add kernel-doc */
+#include <linux/dma-mapping.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/usb/otg.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> -#include <linux/of.h> -#include <linux/dma-mapping.h> - -/*-------------------------------------------------------------------------*/ - -static int ohci_omap3_init(struct usb_hcd *hcd) -{ - dev_dbg(hcd->self.controller, "starting OHCI controller\n"); - - return ohci_init(hcd_to_ohci(hcd)); -} - -/*-------------------------------------------------------------------------*/ - -static int ohci_omap3_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int ret; - - /* - * RemoteWakeupConnected has to be set explicitly before - * calling ohci_run. The reset value of RWC is 0. - */ - ohci->hc_control = OHCI_CTRL_RWC; - writel(OHCI_CTRL_RWC, &ohci->regs->control); - - ret = ohci_run(ohci); - - if (ret < 0) { - dev_err(hcd->self.controller, "can't start\n"); - ohci_stop(hcd); - } +#include <linux/usb.h> +#include <linux/usb/hcd.h>
- return ret; -} +#include "ohci.h"
-/*-------------------------------------------------------------------------*/ +#define DRIVER_DESC "OHCI OMAP3 driver"
-static const struct hc_driver ohci_omap3_hc_driver = { - .description = hcd_name, - .product_desc = "OMAP3 OHCI Host Controller", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .reset = ohci_omap3_init, - .start = ohci_omap3_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 = 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 const char hcd_name[] = "ohci-omap3"; +static struct hc_driver __read_mostly ohci_omap3_hc_driver;
static u64 omap_ohci_dma_mask = DMA_BIT_MASK(32);
@@ -131,6 +63,7 @@ static u64 omap_ohci_dma_mask = DMA_BIT_MASK(32); static int ohci_hcd_omap3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct ohci_hcd *ohci; struct usb_hcd *hcd = NULL; void __iomem *regs = NULL; struct resource *res; @@ -185,7 +118,16 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev) pm_runtime_enable(dev); pm_runtime_get_sync(dev);
- ohci_hcd_init(hcd_to_ohci(hcd)); + ohci = hcd_to_ohci(hcd); + /* + * RemoteWakeupConnected has to be set explicitly before + * calling ohci_run. The reset value of RWC is 0. + */ + ohci->hc_control = OHCI_CTRL_RWC; + writel(OHCI_CTRL_RWC, &ohci->regs->control); + dev_dbg(hcd->self.controller, "starting OHCI controller\n"); + + ohci_setup(hcd);
ret = usb_add_hcd(hcd, irq, 0); if (ret) { @@ -256,5 +198,25 @@ static struct platform_driver ohci_hcd_omap3_driver = { }, };
+static int __init ohci_omap3_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ohci_init_driver(&ohci_omap3_hc_driver, NULL); + return platform_driver_register(&ohci_hcd_omap3_driver); +} +module_init(ohci_omap3_init); + +static void __exit ohci_omap3_cleanup(void) +{ + platform_driver_unregister(&ohci_hcd_omap3_driver); +} +module_exit(ohci_omap3_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_ALIAS("platform:ohci-omap3"); MODULE_AUTHOR("Anand Gadiyar gadiyar@ti.com"); +MODULE_LICENSE("GPL");
On Friday 07 June 2013 11:33:29 Manjunath Goudar wrote:
/*
* RemoteWakeupConnected has to be set explicitly before
* calling ohci_run. The reset value of RWC is 0.
*/
Just nitpicking, but you still use the wrong commenting style occasionally. The '*' characters should always be aligned vertically, like
/* * RemoteWakeupConnected has to be set explicitly before * calling ohci_run. The reset value of RWC is 0. */
Arnd
On Fri, 7 Jun 2013, Manjunath Goudar wrote:
Separate the TI OHCI OMAP3 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.
@@ -185,7 +118,16 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev) pm_runtime_enable(dev); pm_runtime_get_sync(dev);
- ohci_hcd_init(hcd_to_ohci(hcd));
- ohci = hcd_to_ohci(hcd);
- /*
- RemoteWakeupConnected has to be set explicitly before
- calling ohci_run. The reset value of RWC is 0.
- */
- ohci->hc_control = OHCI_CTRL_RWC;
- writel(OHCI_CTRL_RWC, &ohci->regs->control);
- dev_dbg(hcd->self.controller, "starting OHCI controller\n");
- ohci_setup(hcd);
Don't call ohci_setup().
Apart from that (and the comment format), this is okay.
Alan Stern
Separate the TI OHCI SPEAr 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.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Viresh Kumar viresh.linux@gmail.com Cc: Arnd Bergmann arnd@arndb.de Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@rowland.harvard.edu Cc: linux-usb@vger.kernel.org --- drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-hcd.c | 22 +----- drivers/usb/host/ohci-spear.c | 149 ++++++++++++++++++----------------------- 4 files changed, 75 insertions(+), 105 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f42db93..c347cb3 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -403,6 +403,14 @@ config USB_OHCI_HCD_OMAP1 ---help--- Enables support for the OHCI controller on OMAP1/2 chips.
+config USB_OHCI_HCD_SPEAR + tristate "Support for ST SPEAr on-chip OHCI USB controller" + depends on USB_OHCI_HCD && PLAT_SPEAR + default y + ---help--- + Enables support for the on-chip OHCI controller on + ST SPEAr chips. + config USB_OHCI_HCD_OMAP3 tristate "OHCI support for OMAP3 and later chips" depends on (ARCH_OMAP3 || ARCH_OMAP4) diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index ceb4e55..1e0d83e 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_USB_OHCI_HCD_PLATFORM) += ohci-platform.o obj-$(CONFIG_USB_OHCI_EXYNOS) += ohci-exynos.o obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o obj-$(CONFIG_USB_OHCI_HCD_OMAP3) += ohci-omap3.o +obj-$(CONFIG_USB_OHCI_HCD_SPEAR) += ohci-spear.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 8002bbe..27f0abe 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1208,11 +1208,6 @@ MODULE_LICENSE ("GPL"); #define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver #endif
-#ifdef CONFIG_PLAT_SPEAR -#include "ohci-spear.c" -#define SPEAR_PLATFORM_DRIVER spear_ohci_hcd_driver -#endif - #ifdef CONFIG_PPC_PS3 #include "ohci-ps3.c" #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver @@ -1248,6 +1243,7 @@ MODULE_LICENSE ("GPL"); !IS_ENABLED(CONFIG_USB_OHCI_EXYNOS) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_OMAP1) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_OMAP3) && \ + !IS_ENABLED(CONFIG_USB_OHCI_HCD_SPEAR) && \ !defined(PLATFORM_DRIVER) && \ !defined(OF_PLATFORM_DRIVER) && \ !defined(SA1111_DRIVER) && \ @@ -1258,8 +1254,7 @@ MODULE_LICENSE ("GPL"); !defined(EP93XX_PLATFORM_DRIVER) && \ !defined(AT91_PLATFORM_DRIVER) && \ !defined(NXP_PLATFORM_DRIVER) && \ - !defined(DAVINCI_PLATFORM_DRIVER) && \ - !defined(SPEAR_PLATFORM_DRIVER) + !defined(DAVINCI_PLATFORM_DRIVER) #error "missing bus glue for ohci-hcd" #endif
@@ -1349,19 +1344,9 @@ static int __init ohci_hcd_mod_init(void) goto error_davinci; #endif
-#ifdef SPEAR_PLATFORM_DRIVER - retval = platform_driver_register(&SPEAR_PLATFORM_DRIVER); - if (retval < 0) - goto error_spear; -#endif - return retval;
/* Error path */ -#ifdef SPEAR_PLATFORM_DRIVER - platform_driver_unregister(&SPEAR_PLATFORM_DRIVER); - error_spear: -#endif #ifdef DAVINCI_PLATFORM_DRIVER platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); error_davinci: @@ -1419,9 +1404,6 @@ module_init(ohci_hcd_mod_init);
static void __exit ohci_hcd_mod_exit(void) { -#ifdef SPEAR_PLATFORM_DRIVER - platform_driver_unregister(&SPEAR_PLATFORM_DRIVER); -#endif #ifdef DAVINCI_PLATFORM_DRIVER platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); #endif diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c index 6a7cb14..9e79d24 100644 --- a/drivers/usb/host/ohci-spear.c +++ b/drivers/usb/host/ohci-spear.c @@ -11,94 +11,41 @@ * warranty of any kind, whether express or implied. */
-#include <linux/signal.h> -#include <linux/platform_device.h> +#include <linux/dma-mapping.h> #include <linux/clk.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/signal.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <linux/debugfs.h> +#include <linux/errno.h>
-struct spear_ohci { - struct ohci_hcd ohci; - struct clk *clk; -}; - -#define to_spear_ohci(hcd) (struct spear_ohci *)hcd_to_ohci(hcd) - -static void spear_start_ohci(struct spear_ohci *ohci) -{ - clk_prepare_enable(ohci->clk); -} - -static void spear_stop_ohci(struct spear_ohci *ohci) -{ - clk_disable_unprepare(ohci->clk); -} - -static int ohci_spear_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int ret; - - ret = ohci_init(ohci); - if (ret < 0) - return ret; - ohci->regs = hcd->regs; - - ret = ohci_run(ohci); - if (ret < 0) { - dev_err(hcd->self.controller, "can't start\n"); - ohci_stop(hcd); - return ret; - } - - create_debug_files(ohci); - -#ifdef DEBUG - ohci_dump(ohci, 1); -#endif - return 0; -} - -static const struct hc_driver ohci_spear_hc_driver = { - .description = hcd_name, - .product_desc = "SPEAr OHCI", - .hcd_priv_size = sizeof(struct spear_ohci), - - /* generic hardware linkage */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* basic lifecycle operations */ - .start = ohci_spear_start, - .stop = ohci_stop, - .shutdown = ohci_shutdown, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - - /* 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, +#include "ohci.h"
- /* root hub support */ - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, +#define DRIVER_DESC "OHCI SPEAr driver"
- .start_port_reset = ohci_start_port_reset, +static const char hcd_name[] = "SPEAr-ohci"; +struct spear_ohci { + struct clk *clk; };
+#define to_spear_ohci(hcd) (struct spear_ohci *)(hcd_to_ohci(hcd)->priv) + +static struct hc_driver __read_mostly ohci_spear_hc_driver; static u64 spear_ohci_dma_mask = DMA_BIT_MASK(32);
static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) { const struct hc_driver *driver = &ohci_spear_hc_driver; + struct ohci_hcd *ohci; struct usb_hcd *hcd = NULL; struct clk *usbh_clk; - struct spear_ohci *ohci_p; + struct spear_ohci *sohci_p; struct resource *res; int retval, irq;
@@ -151,16 +98,24 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) goto err_put_hcd; }
- ohci_p = (struct spear_ohci *)hcd_to_ohci(hcd); - ohci_p->clk = usbh_clk; - spear_start_ohci(ohci_p); - ohci_hcd_init(hcd_to_ohci(hcd)); + sohci_p = to_spear_ohci(hcd); + sohci_p->clk = usbh_clk; + hcd_to_ohci(hcd)->regs = hcd->regs; + + ohci_setup(hcd); + clk_prepare_enable(sohci_p->clk); + + ohci = hcd_to_ohci(hcd); + +#ifdef DEBUG + ohci_dump(ohci, 1); +#endif
retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), 0); if (retval == 0) return retval;
- spear_stop_ohci(ohci_p); + clk_disable_unprepare(sohci_p->clk); err_put_hcd: usb_put_hcd(hcd); fail: @@ -172,11 +127,11 @@ fail: static int spear_ohci_hcd_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct spear_ohci *ohci_p = to_spear_ohci(hcd); + struct spear_ohci *sohci_p = to_spear_ohci(hcd);
usb_remove_hcd(hcd); - if (ohci_p->clk) - spear_stop_ohci(ohci_p); + if (sohci_p->clk) + clk_disable_unprepare(sohci_p->clk);
usb_put_hcd(hcd); return 0; @@ -188,13 +143,13 @@ static int spear_ohci_hcd_drv_suspend(struct platform_device *dev, { struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); - struct spear_ohci *ohci_p = to_spear_ohci(hcd); + struct spear_ohci *sohci_p = to_spear_ohci(hcd);
if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies;
- spear_stop_ohci(ohci_p); + clk_disable_unprepare(sohci_p->clk); return 0; }
@@ -202,13 +157,13 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); - struct spear_ohci *ohci_p = to_spear_ohci(hcd); + struct spear_ohci *sohci_p = to_spear_ohci(hcd);
if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies;
- spear_start_ohci(ohci_p); + clk_prepare_enable(sohci_p->clk); ohci_resume(hcd, false); return 0; } @@ -234,4 +189,28 @@ static struct platform_driver spear_ohci_hcd_driver = { }, };
+static const struct ohci_driver_overrides spear_overrides __initconst = { + .extra_priv_size = sizeof(struct spear_ohci), +}; +static int __init ohci_spear_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ohci_init_driver(&ohci_spear_hc_driver, &spear_overrides); + return platform_driver_register(&spear_ohci_hcd_driver); +} +module_init(ohci_spear_init); + +static void __exit ohci_spear_cleanup(void) +{ + platform_driver_unregister(&spear_ohci_hcd_driver); +} +module_exit(ohci_spear_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Deepak Sikri"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:spear-ohci");
you need to cc spear-devel@list.st.com list for SPEAr patches.
On 7 June 2013 11:33, Manjunath Goudar manjunath.goudar@linaro.org wrote:
Separate the TI OHCI SPEAr host controller driver from ohci-hcd
TI ??
host code so that it can be built as a separate driver module. This work is part of enabling multi-platform kernels on ARM.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Viresh Kumar viresh.linux@gmail.com Cc: Arnd Bergmann arnd@arndb.de Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@rowland.harvard.edu Cc: linux-usb@vger.kernel.org
drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-hcd.c | 22 +----- drivers/usb/host/ohci-spear.c | 149 ++++++++++++++++++----------------------- 4 files changed, 75 insertions(+), 105 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f42db93..c347cb3 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -403,6 +403,14 @@ config USB_OHCI_HCD_OMAP1 ---help--- Enables support for the OHCI controller on OMAP1/2 chips.
+config USB_OHCI_HCD_SPEAR
tristate "Support for ST SPEAr on-chip OHCI USB controller"
depends on USB_OHCI_HCD && PLAT_SPEAR
default y
---help---
Enables support for the on-chip OHCI controller on
ST SPEAr chips.
config USB_OHCI_HCD_OMAP3 tristate "OHCI support for OMAP3 and later chips" depends on (ARCH_OMAP3 || ARCH_OMAP4) diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index ceb4e55..1e0d83e 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_USB_OHCI_HCD_PLATFORM) += ohci-platform.o obj-$(CONFIG_USB_OHCI_EXYNOS) += ohci-exynos.o obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o obj-$(CONFIG_USB_OHCI_HCD_OMAP3) += ohci-omap3.o +obj-$(CONFIG_USB_OHCI_HCD_SPEAR) += ohci-spear.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 8002bbe..27f0abe 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1208,11 +1208,6 @@ MODULE_LICENSE ("GPL"); #define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver #endif
-#ifdef CONFIG_PLAT_SPEAR -#include "ohci-spear.c" -#define SPEAR_PLATFORM_DRIVER spear_ohci_hcd_driver -#endif
#ifdef CONFIG_PPC_PS3 #include "ohci-ps3.c" #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver @@ -1248,6 +1243,7 @@ MODULE_LICENSE ("GPL"); !IS_ENABLED(CONFIG_USB_OHCI_EXYNOS) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_OMAP1) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_OMAP3) && \
!IS_ENABLED(CONFIG_USB_OHCI_HCD_SPEAR) && \ !defined(PLATFORM_DRIVER) && \ !defined(OF_PLATFORM_DRIVER) && \ !defined(SA1111_DRIVER) && \
@@ -1258,8 +1254,7 @@ MODULE_LICENSE ("GPL"); !defined(EP93XX_PLATFORM_DRIVER) && \ !defined(AT91_PLATFORM_DRIVER) && \ !defined(NXP_PLATFORM_DRIVER) && \
!defined(DAVINCI_PLATFORM_DRIVER) && \
!defined(SPEAR_PLATFORM_DRIVER)
!defined(DAVINCI_PLATFORM_DRIVER)
#error "missing bus glue for ohci-hcd" #endif
@@ -1349,19 +1344,9 @@ static int __init ohci_hcd_mod_init(void) goto error_davinci; #endif
-#ifdef SPEAR_PLATFORM_DRIVER
retval = platform_driver_register(&SPEAR_PLATFORM_DRIVER);
if (retval < 0)
goto error_spear;
-#endif
return retval; /* Error path */
-#ifdef SPEAR_PLATFORM_DRIVER
platform_driver_unregister(&SPEAR_PLATFORM_DRIVER);
- error_spear:
-#endif #ifdef DAVINCI_PLATFORM_DRIVER platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); error_davinci: @@ -1419,9 +1404,6 @@ module_init(ohci_hcd_mod_init);
static void __exit ohci_hcd_mod_exit(void) { -#ifdef SPEAR_PLATFORM_DRIVER
platform_driver_unregister(&SPEAR_PLATFORM_DRIVER);
-#endif #ifdef DAVINCI_PLATFORM_DRIVER platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); #endif diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c index 6a7cb14..9e79d24 100644 --- a/drivers/usb/host/ohci-spear.c +++ b/drivers/usb/host/ohci-spear.c @@ -11,94 +11,41 @@
- warranty of any kind, whether express or implied.
*/
-#include <linux/signal.h> -#include <linux/platform_device.h> +#include <linux/dma-mapping.h> #include <linux/clk.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/signal.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <linux/debugfs.h> +#include <linux/errno.h>
In alphabetical order please. And please which ones of these are must to have.
-struct spear_ohci {
struct ohci_hcd ohci;
struct clk *clk;
-};
-#define to_spear_ohci(hcd) (struct spear_ohci *)hcd_to_ohci(hcd)
-static void spear_start_ohci(struct spear_ohci *ohci) -{
clk_prepare_enable(ohci->clk);
-}
-static void spear_stop_ohci(struct spear_ohci *ohci) -{
clk_disable_unprepare(ohci->clk);
-}
-static int ohci_spear_start(struct usb_hcd *hcd) -{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
int ret;
ret = ohci_init(ohci);
if (ret < 0)
return ret;
ohci->regs = hcd->regs;
ret = ohci_run(ohci);
if (ret < 0) {
dev_err(hcd->self.controller, "can't start\n");
ohci_stop(hcd);
return ret;
}
create_debug_files(ohci);
-#ifdef DEBUG
ohci_dump(ohci, 1);
-#endif
return 0;
-}
-static const struct hc_driver ohci_spear_hc_driver = {
.description = hcd_name,
.product_desc = "SPEAr OHCI",
.hcd_priv_size = sizeof(struct spear_ohci),
/* generic hardware linkage */
.irq = ohci_irq,
.flags = HCD_USB11 | HCD_MEMORY,
/* basic lifecycle operations */
.start = ohci_spear_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,
-#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
-#endif
/* 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,
+#include "ohci.h"
/* root hub support */
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
+#define DRIVER_DESC "OHCI SPEAr driver"
.start_port_reset = ohci_start_port_reset,
+static const char hcd_name[] = "SPEAr-ohci"; +struct spear_ohci {
struct clk *clk;
};
+#define to_spear_ohci(hcd) (struct spear_ohci *)(hcd_to_ohci(hcd)->priv)
+static struct hc_driver __read_mostly ohci_spear_hc_driver; static u64 spear_ohci_dma_mask = DMA_BIT_MASK(32);
static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) { const struct hc_driver *driver = &ohci_spear_hc_driver;
struct ohci_hcd *ohci; struct usb_hcd *hcd = NULL; struct clk *usbh_clk;
struct spear_ohci *ohci_p;
struct spear_ohci *sohci_p;
why rename this?
struct resource *res; int retval, irq;
@@ -151,16 +98,24 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) goto err_put_hcd; }
ohci_p = (struct spear_ohci *)hcd_to_ohci(hcd);
ohci_p->clk = usbh_clk;
spear_start_ohci(ohci_p);
ohci_hcd_init(hcd_to_ohci(hcd));
sohci_p = to_spear_ohci(hcd);
sohci_p->clk = usbh_clk;
hcd_to_ohci(hcd)->regs = hcd->regs;
ohci_setup(hcd);
clk_prepare_enable(sohci_p->clk);
ohci = hcd_to_ohci(hcd);
+#ifdef DEBUG
ohci_dump(ohci, 1);
+#endif
retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), 0); if (retval == 0) return retval;
spear_stop_ohci(ohci_p);
clk_disable_unprepare(sohci_p->clk);
err_put_hcd: usb_put_hcd(hcd); fail: @@ -172,11 +127,11 @@ fail: static int spear_ohci_hcd_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct spear_ohci *ohci_p = to_spear_ohci(hcd);
struct spear_ohci *sohci_p = to_spear_ohci(hcd); usb_remove_hcd(hcd);
if (ohci_p->clk)
spear_stop_ohci(ohci_p);
if (sohci_p->clk)
clk_disable_unprepare(sohci_p->clk); usb_put_hcd(hcd); return 0;
@@ -188,13 +143,13 @@ static int spear_ohci_hcd_drv_suspend(struct platform_device *dev, { struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd);
struct spear_ohci *ohci_p = to_spear_ohci(hcd);
struct spear_ohci *sohci_p = to_spear_ohci(hcd); if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies;
spear_stop_ohci(ohci_p);
clk_disable_unprepare(sohci_p->clk); return 0;
}
@@ -202,13 +157,13 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd);
struct spear_ohci *ohci_p = to_spear_ohci(hcd);
struct spear_ohci *sohci_p = to_spear_ohci(hcd); if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies;
spear_start_ohci(ohci_p);
clk_prepare_enable(sohci_p->clk); ohci_resume(hcd, false); return 0;
} @@ -234,4 +189,28 @@ static struct platform_driver spear_ohci_hcd_driver = { }, };
+static const struct ohci_driver_overrides spear_overrides __initconst = {
.extra_priv_size = sizeof(struct spear_ohci),
+}; +static int __init ohci_spear_init(void) +{
if (usb_disabled())
return -ENODEV;
pr_info("%s: " DRIVER_DESC "\n", hcd_name);
ohci_init_driver(&ohci_spear_hc_driver, &spear_overrides);
return platform_driver_register(&spear_ohci_hcd_driver);
+} +module_init(ohci_spear_init);
+static void __exit ohci_spear_cleanup(void) +{
platform_driver_unregister(&spear_ohci_hcd_driver);
+} +module_exit(ohci_spear_cleanup);
+MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Deepak Sikri"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:spear-ohci");
I can't really review it functionally.
@Deepak: Can you?
On 7 June 2013 16:00, Viresh Kumar viresh.kumar@linaro.org wrote:
you need to cc spear-devel@list.st.com list for SPEAr patches.
On 7 June 2013 11:33, Manjunath Goudar manjunath.goudar@linaro.org wrote:
Separate the TI OHCI SPEAr host controller driver from ohci-hcd
TI ??
not TI it should ST in second version.
host code so that it can be built as a separate driver module. This work is part of enabling multi-platform kernels on ARM.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Viresh Kumar viresh.linux@gmail.com Cc: Arnd Bergmann arnd@arndb.de Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@rowland.harvard.edu Cc: linux-usb@vger.kernel.org
drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-hcd.c | 22 +----- drivers/usb/host/ohci-spear.c | 149
++++++++++++++++++-----------------------
4 files changed, 75 insertions(+), 105 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f42db93..c347cb3 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -403,6 +403,14 @@ config USB_OHCI_HCD_OMAP1 ---help--- Enables support for the OHCI controller on OMAP1/2 chips.
+config USB_OHCI_HCD_SPEAR
tristate "Support for ST SPEAr on-chip OHCI USB controller"
depends on USB_OHCI_HCD && PLAT_SPEAR
default y
---help---
Enables support for the on-chip OHCI controller on
ST SPEAr chips.
config USB_OHCI_HCD_OMAP3 tristate "OHCI support for OMAP3 and later chips" depends on (ARCH_OMAP3 || ARCH_OMAP4) diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index ceb4e55..1e0d83e 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_USB_OHCI_HCD_PLATFORM) +=
ohci-platform.o
obj-$(CONFIG_USB_OHCI_EXYNOS) += ohci-exynos.o obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o obj-$(CONFIG_USB_OHCI_HCD_OMAP3) += ohci-omap3.o +obj-$(CONFIG_USB_OHCI_HCD_SPEAR) += ohci-spear.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 8002bbe..27f0abe 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1208,11 +1208,6 @@ MODULE_LICENSE ("GPL"); #define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver #endif
-#ifdef CONFIG_PLAT_SPEAR -#include "ohci-spear.c" -#define SPEAR_PLATFORM_DRIVER spear_ohci_hcd_driver -#endif
#ifdef CONFIG_PPC_PS3 #include "ohci-ps3.c" #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver @@ -1248,6 +1243,7 @@ MODULE_LICENSE ("GPL"); !IS_ENABLED(CONFIG_USB_OHCI_EXYNOS) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_OMAP1) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_OMAP3) && \
!IS_ENABLED(CONFIG_USB_OHCI_HCD_SPEAR) && \ !defined(PLATFORM_DRIVER) && \ !defined(OF_PLATFORM_DRIVER) && \ !defined(SA1111_DRIVER) && \
@@ -1258,8 +1254,7 @@ MODULE_LICENSE ("GPL"); !defined(EP93XX_PLATFORM_DRIVER) && \ !defined(AT91_PLATFORM_DRIVER) && \ !defined(NXP_PLATFORM_DRIVER) && \
!defined(DAVINCI_PLATFORM_DRIVER) && \
!defined(SPEAR_PLATFORM_DRIVER)
!defined(DAVINCI_PLATFORM_DRIVER)
#error "missing bus glue for ohci-hcd" #endif
@@ -1349,19 +1344,9 @@ static int __init ohci_hcd_mod_init(void) goto error_davinci; #endif
-#ifdef SPEAR_PLATFORM_DRIVER
retval = platform_driver_register(&SPEAR_PLATFORM_DRIVER);
if (retval < 0)
goto error_spear;
-#endif
return retval; /* Error path */
-#ifdef SPEAR_PLATFORM_DRIVER
platform_driver_unregister(&SPEAR_PLATFORM_DRIVER);
- error_spear:
-#endif #ifdef DAVINCI_PLATFORM_DRIVER platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); error_davinci: @@ -1419,9 +1404,6 @@ module_init(ohci_hcd_mod_init);
static void __exit ohci_hcd_mod_exit(void) { -#ifdef SPEAR_PLATFORM_DRIVER
platform_driver_unregister(&SPEAR_PLATFORM_DRIVER);
-#endif #ifdef DAVINCI_PLATFORM_DRIVER platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); #endif diff --git a/drivers/usb/host/ohci-spear.c
b/drivers/usb/host/ohci-spear.c
index 6a7cb14..9e79d24 100644 --- a/drivers/usb/host/ohci-spear.c +++ b/drivers/usb/host/ohci-spear.c @@ -11,94 +11,41 @@
- warranty of any kind, whether express or implied.
*/
-#include <linux/signal.h> -#include <linux/platform_device.h> +#include <linux/dma-mapping.h> #include <linux/clk.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/signal.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <linux/debugfs.h> +#include <linux/errno.h>
In alphabetical order please. And please which ones of these are must to have.
Ok sure I will arrange in Alphabetical and unnecessary include will be removing V2 version.
-struct spear_ohci {
struct ohci_hcd ohci;
struct clk *clk;
-};
-#define to_spear_ohci(hcd) (struct spear_ohci *)hcd_to_ohci(hcd)
-static void spear_start_ohci(struct spear_ohci *ohci) -{
clk_prepare_enable(ohci->clk);
-}
-static void spear_stop_ohci(struct spear_ohci *ohci) -{
clk_disable_unprepare(ohci->clk);
-}
-static int ohci_spear_start(struct usb_hcd *hcd) -{
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
int ret;
ret = ohci_init(ohci);
if (ret < 0)
return ret;
ohci->regs = hcd->regs;
ret = ohci_run(ohci);
if (ret < 0) {
dev_err(hcd->self.controller, "can't start\n");
ohci_stop(hcd);
return ret;
}
create_debug_files(ohci);
-#ifdef DEBUG
ohci_dump(ohci, 1);
-#endif
return 0;
-}
-static const struct hc_driver ohci_spear_hc_driver = {
.description = hcd_name,
.product_desc = "SPEAr OHCI",
.hcd_priv_size = sizeof(struct spear_ohci),
/* generic hardware linkage */
.irq = ohci_irq,
.flags = HCD_USB11 | HCD_MEMORY,
/* basic lifecycle operations */
.start = ohci_spear_start,
.stop = ohci_stop,
.shutdown = ohci_shutdown,
-#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
-#endif
/* 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,
+#include "ohci.h"
/* root hub support */
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
+#define DRIVER_DESC "OHCI SPEAr driver"
.start_port_reset = ohci_start_port_reset,
+static const char hcd_name[] = "SPEAr-ohci"; +struct spear_ohci {
struct clk *clk;
};
+#define to_spear_ohci(hcd) (struct spear_ohci
*)(hcd_to_ohci(hcd)->priv)
+static struct hc_driver __read_mostly ohci_spear_hc_driver; static u64 spear_ohci_dma_mask = DMA_BIT_MASK(32);
static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) { const struct hc_driver *driver = &ohci_spear_hc_driver;
struct ohci_hcd *ohci; struct usb_hcd *hcd = NULL; struct clk *usbh_clk;
struct spear_ohci *ohci_p;
struct spear_ohci *sohci_p;
why rename this?
renaming for making similarity with ehci-spear driver.
struct resource *res; int retval, irq;
@@ -151,16 +98,24 @@ static int spear_ohci_hcd_drv_probe(struct
platform_device *pdev)
goto err_put_hcd; }
ohci_p = (struct spear_ohci *)hcd_to_ohci(hcd);
ohci_p->clk = usbh_clk;
spear_start_ohci(ohci_p);
ohci_hcd_init(hcd_to_ohci(hcd));
sohci_p = to_spear_ohci(hcd);
sohci_p->clk = usbh_clk;
hcd_to_ohci(hcd)->regs = hcd->regs;
ohci_setup(hcd);
clk_prepare_enable(sohci_p->clk);
ohci = hcd_to_ohci(hcd);
+#ifdef DEBUG
ohci_dump(ohci, 1);
+#endif
retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), 0); if (retval == 0) return retval;
spear_stop_ohci(ohci_p);
clk_disable_unprepare(sohci_p->clk);
err_put_hcd: usb_put_hcd(hcd); fail: @@ -172,11 +127,11 @@ fail: static int spear_ohci_hcd_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct spear_ohci *ohci_p = to_spear_ohci(hcd);
struct spear_ohci *sohci_p = to_spear_ohci(hcd); usb_remove_hcd(hcd);
if (ohci_p->clk)
spear_stop_ohci(ohci_p);
if (sohci_p->clk)
clk_disable_unprepare(sohci_p->clk); usb_put_hcd(hcd); return 0;
@@ -188,13 +143,13 @@ static int spear_ohci_hcd_drv_suspend(struct
platform_device *dev,
{ struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd);
struct spear_ohci *ohci_p = to_spear_ohci(hcd);
struct spear_ohci *sohci_p = to_spear_ohci(hcd); if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies;
spear_stop_ohci(ohci_p);
clk_disable_unprepare(sohci_p->clk); return 0;
}
@@ -202,13 +157,13 @@ static int spear_ohci_hcd_drv_resume(struct
platform_device *dev)
{ struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd);
struct spear_ohci *ohci_p = to_spear_ohci(hcd);
struct spear_ohci *sohci_p = to_spear_ohci(hcd); if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies;
spear_start_ohci(ohci_p);
clk_prepare_enable(sohci_p->clk); ohci_resume(hcd, false); return 0;
} @@ -234,4 +189,28 @@ static struct platform_driver spear_ohci_hcd_driver
= {
},
};
+static const struct ohci_driver_overrides spear_overrides __initconst =
{
.extra_priv_size = sizeof(struct spear_ohci),
+}; +static int __init ohci_spear_init(void) +{
if (usb_disabled())
return -ENODEV;
pr_info("%s: " DRIVER_DESC "\n", hcd_name);
ohci_init_driver(&ohci_spear_hc_driver, &spear_overrides);
return platform_driver_register(&spear_ohci_hcd_driver);
+} +module_init(ohci_spear_init);
+static void __exit ohci_spear_cleanup(void) +{
platform_driver_unregister(&spear_ohci_hcd_driver);
+} +module_exit(ohci_spear_cleanup);
+MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Deepak Sikri"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:spear-ohci");
I can't really review it functionally.
@Deepak: Can you?
Manjunath Goudar
On Fri, 7 Jun 2013, Manjunath Goudar wrote:
Separate the TI OHCI SPEAr 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.
@@ -151,16 +98,24 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) goto err_put_hcd; }
- ohci_p = (struct spear_ohci *)hcd_to_ohci(hcd);
- ohci_p->clk = usbh_clk;
- spear_start_ohci(ohci_p);
- ohci_hcd_init(hcd_to_ohci(hcd));
- sohci_p = to_spear_ohci(hcd);
- sohci_p->clk = usbh_clk;
- hcd_to_ohci(hcd)->regs = hcd->regs;
This line isn't needed. It is one of the first things that ohci_init() does.
- ohci_setup(hcd);
Don't call ohci_setup().
- clk_prepare_enable(sohci_p->clk);
- ohci = hcd_to_ohci(hcd);
+#ifdef DEBUG
- ohci_dump(ohci, 1);
+#endif
I suspect this debugging stuff isn't needed any more. You can get rid of it.
@@ -188,13 +143,13 @@ static int spear_ohci_hcd_drv_suspend(struct platform_device *dev, { struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- struct spear_ohci *ohci_p = to_spear_ohci(hcd);
- struct spear_ohci *sohci_p = to_spear_ohci(hcd);
if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies;
- spear_stop_ohci(ohci_p);
- clk_disable_unprepare(sohci_p->clk); return 0;
}
This routine needs to call ohci_suspend() just before the clk_disable_unprepare(). I don't know how that got left out, but it looks like the same problem exists in several of the ohci glue files. I guess they should all be fixed at once, in a separate patch.
@@ -202,13 +157,13 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd);
- struct spear_ohci *ohci_p = to_spear_ohci(hcd);
- struct spear_ohci *sohci_p = to_spear_ohci(hcd);
if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies;
- spear_start_ohci(ohci_p);
clk_prepare_enable(sohci_p->clk);
You got an extra space character after the tab.
Alan Stern
In order to make ohci-at91 and ohci-s3c2410 as a separate driver, ohci_hub_control and ohci_hub_status_data symbol needs to be exported. This work is part of enabling multi-platform kernels on ARM.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Arnd Bergmann arnd@arndb.de Cc: Alan Stern stern@rowland.harvard.edu Cc: Greg KH greg@kroah.com Cc: linux-usb@vger.kernel.org --- drivers/usb/host/ohci-hub.c | 8 ++++---- drivers/usb/host/ohci.h | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 2347ab8..c601e70 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -437,8 +437,7 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
/* build "status change" packet (one or two bytes) from HC registers */
-static int -ohci_hub_status_data (struct usb_hcd *hcd, char *buf) +int ohci_hub_status_data(struct usb_hcd *hcd, char *buf) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int i, changed = 0, length = 1; @@ -503,6 +502,7 @@ done:
return changed ? length : 0; } +EXPORT_SYMBOL_GPL(ohci_hub_status_data);
/*-------------------------------------------------------------------------*/
@@ -645,7 +645,7 @@ static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port) return 0; }
-static int ohci_hub_control ( +int ohci_hub_control( struct usb_hcd *hcd, u16 typeReq, u16 wValue, @@ -773,4 +773,4 @@ error: } return retval; } - +EXPORT_SYMBOL_GPL(ohci_hub_control); diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index e2e5faa..d0d9b60 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -738,3 +738,12 @@ extern int ohci_setup(struct usb_hcd *hcd); extern int ohci_suspend(struct usb_hcd *hcd, bool do_wakeup); extern int ohci_resume(struct usb_hcd *hcd, bool hibernated); #endif +extern int ohci_hub_control( + struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, + u16 wLength +); +extern int ohci_hub_status_data(struct usb_hcd *hcd, char *buf);
On Fri, 7 Jun 2013, Manjunath Goudar wrote:
In order to make ohci-at91 and ohci-s3c2410 as a separate driver, ohci_hub_control and ohci_hub_status_data symbol needs to be exported. This work is part of enabling multi-platform kernels on ARM.
No, we are not going to export those two routines. You can copy the approach used by Stephen Warren in the ehci-tegra conversion.
Alan Stern
Separate the TI OHCI Atmel 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.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Arnd Bergmann arnd@arndb.de Cc: Alan Stern stern@rowland.harvard.edu Cc: Greg KH greg@kroah.com Cc: linux-usb@vger.kernel.org --- drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-at91.c | 135 ++++++++++++++++++------------------------ drivers/usb/host/ohci-hcd.c | 20 +------ 4 files changed, 67 insertions(+), 97 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index c347cb3..0aabd84 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -411,6 +411,14 @@ config USB_OHCI_HCD_SPEAR Enables support for the on-chip OHCI controller on ST SPEAr chips.
+config USB_OHCI_HCD_AT91 + tristate "Support for Atmel on-chip OHCI USB controller" + depends on USB_OHCI_HCD && ARCH_AT91 + default y + ---help--- + Enables support for the on-chip OHCI controller on + Atmel chips. + config USB_OHCI_HCD_OMAP3 tristate "OHCI support for OMAP3 and later chips" depends on (ARCH_OMAP3 || ARCH_OMAP4) diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 1e0d83e..746ffc7 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_USB_OHCI_EXYNOS) += ohci-exynos.o obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o obj-$(CONFIG_USB_OHCI_HCD_OMAP3) += ohci-omap3.o obj-$(CONFIG_USB_OHCI_HCD_SPEAR) += ohci-spear.o +obj-$(CONFIG_USB_OHCI_HCD_AT91) += ohci-at91.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index a0cb44f..b4a88a6 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -13,16 +13,25 @@ */
#include <linux/clk.h> -#include <linux/platform_device.h> +#include <linux/dma-mapping.h> #include <linux/of_platform.h> #include <linux/of_gpio.h> +#include <linux/platform_device.h> #include <linux/platform_data/atmel.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h>
#include <mach/hardware.h> #include <asm/gpio.h>
#include <mach/cpu.h>
+ +#include "ohci.h" + #ifndef CONFIG_ARCH_AT91 #error "CONFIG_ARCH_AT91 must be defined." #endif @@ -32,6 +41,12 @@ for ((index) = 0; (index) < AT91_MAX_USBH_PORTS; (index)++)
/* interface and function clocks; sometimes also an AHB clock */ + +#define DRIVER_DESC "OHCI Atmel driver" + +static const char hcd_name[] = "ohci-atmel"; + +static struct hc_driver __read_mostly ohci_at91_hc_driver; static struct clk *iclk, *fclk, *hclk; static int clocked;
@@ -111,6 +126,8 @@ static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); static int usb_hcd_at91_probe(const struct hc_driver *driver, struct platform_device *pdev) { + struct at91_usbh_data *board; + struct ohci_hcd *ohci; int retval; struct usb_hcd *hcd = NULL;
@@ -163,8 +180,11 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, goto err5; }
+ board = hcd->self.controller->platform_data; + ohci = hcd_to_ohci(hcd); + ohci->num_ports = board->ports; at91_start_hc(pdev); - ohci_hcd_init(hcd_to_ohci(hcd)); + ohci_setup(hcd);
retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED); if (retval == 0) @@ -221,36 +241,6 @@ static void usb_hcd_at91_remove(struct usb_hcd *hcd, }
/*-------------------------------------------------------------------------*/ - -static int -ohci_at91_reset (struct usb_hcd *hcd) -{ - struct at91_usbh_data *board = hcd->self.controller->platform_data; - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; - - if ((ret = ohci_init(ohci)) < 0) - return ret; - - ohci->num_ports = board->ports; - return 0; -} - -static int -ohci_at91_start (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; - - if ((ret = ohci_run(ohci)) < 0) { - dev_err(hcd->self.controller, "can't start %s\n", - hcd->self.bus_name); - ohci_stop(hcd); - return ret; - } - return 0; -} - static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable) { if (!valid_port(port)) @@ -413,51 +403,6 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/*-------------------------------------------------------------------------*/
-static const struct hc_driver ohci_at91_hc_driver = { - .description = hcd_name, - .product_desc = "AT91 OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .reset = ohci_at91_reset, - .start = ohci_at91_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_at91_hub_status_data, - .hub_control = ohci_at91_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 ohci_hcd_at91_overcurrent_irq(int irq, void *data) { struct platform_device *pdev = data; @@ -686,7 +631,7 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) * REVISIT: some boards will be able to turn VBUS off... */ if (at91_suspend_entering_slow_clock()) { - ohci_usb_reset (ohci); + ohci_restart(ohci); /* flush the writes */ (void) ohci_readl (ohci, &ohci->regs->control); at91_stop_clock(); @@ -727,3 +672,37 @@ static struct platform_driver ohci_hcd_at91_driver = { .of_match_table = of_match_ptr(at91_ohci_dt_ids), }, }; + +static int __init ohci_at91_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + ohci_init_driver(&ohci_at91_hc_driver, NULL); + + /* + * The Atmel HW has some unusual quirks, which require Atmel-specific + * workarounds. We override certain hc_driver functions here to + * achieve that. We explicitly do not enhance ohci_driver_overrides to + * allow this more easily, since this is an unusual case, and we don't + * want to encourage others to override these functions by making it + * too easy. + */ + + ohci_at91_hc_driver.hub_status_data = ohci_at91_hub_status_data; + ohci_at91_hc_driver.hub_control = ohci_at91_hub_control; + + return platform_driver_register(&ohci_hcd_at91_driver); +} +module_init(ohci_at91_init); + +static void __exit ohci_at91_cleanup(void) +{ + platform_driver_unregister(&ohci_hcd_at91_driver); +} +module_exit(ohci_at91_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 27f0abe..00409b9 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1188,11 +1188,6 @@ MODULE_LICENSE ("GPL"); #define EP93XX_PLATFORM_DRIVER ohci_hcd_ep93xx_driver #endif
-#ifdef CONFIG_ARCH_AT91 -#include "ohci-at91.c" -#define AT91_PLATFORM_DRIVER ohci_hcd_at91_driver -#endif - #ifdef CONFIG_ARCH_LPC32XX #include "ohci-nxp.c" #define NXP_PLATFORM_DRIVER usb_hcd_nxp_driver @@ -1244,6 +1239,7 @@ MODULE_LICENSE ("GPL"); !IS_ENABLED(CONFIG_USB_OHCI_HCD_OMAP1) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_OMAP3) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_SPEAR) && \ + !IS_ENABLED(CONFIG_USB_OHCI_HCD_AT91) && \ !defined(PLATFORM_DRIVER) && \ !defined(OF_PLATFORM_DRIVER) && \ !defined(SA1111_DRIVER) && \ @@ -1252,7 +1248,6 @@ MODULE_LICENSE ("GPL"); !defined(TMIO_OHCI_DRIVER) && \ !defined(S3C2410_PLATFORM_DRIVER) && \ !defined(EP93XX_PLATFORM_DRIVER) && \ - !defined(AT91_PLATFORM_DRIVER) && \ !defined(NXP_PLATFORM_DRIVER) && \ !defined(DAVINCI_PLATFORM_DRIVER) #error "missing bus glue for ohci-hcd" @@ -1326,12 +1321,6 @@ static int __init ohci_hcd_mod_init(void) goto error_ep93xx; #endif
-#ifdef AT91_PLATFORM_DRIVER - retval = platform_driver_register(&AT91_PLATFORM_DRIVER); - if (retval < 0) - goto error_at91; -#endif - #ifdef NXP_PLATFORM_DRIVER retval = platform_driver_register(&NXP_PLATFORM_DRIVER); if (retval < 0) @@ -1355,10 +1344,6 @@ static int __init ohci_hcd_mod_init(void) platform_driver_unregister(&NXP_PLATFORM_DRIVER); error_nxp: #endif -#ifdef AT91_PLATFORM_DRIVER - platform_driver_unregister(&AT91_PLATFORM_DRIVER); - error_at91: -#endif #ifdef EP93XX_PLATFORM_DRIVER platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); error_ep93xx: @@ -1410,9 +1395,6 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef NXP_PLATFORM_DRIVER platform_driver_unregister(&NXP_PLATFORM_DRIVER); #endif -#ifdef AT91_PLATFORM_DRIVER - platform_driver_unregister(&AT91_PLATFORM_DRIVER); -#endif #ifdef EP93XX_PLATFORM_DRIVER platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); #endif
On Fri, 7 Jun 2013, Manjunath Goudar wrote:
Separate the TI OHCI Atmel 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.
--- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -411,6 +411,14 @@ config USB_OHCI_HCD_SPEAR Enables support for the on-chip OHCI controller on ST SPEAr chips. +config USB_OHCI_HCD_AT91
tristate "Support for Atmel on-chip OHCI USB controller"
depends on USB_OHCI_HCD && ARCH_AT91
default y
---help---
Enables support for the on-chip OHCI controller on
Atmel chips.
Notice the "depends on" line you added here?
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index a0cb44f..b4a88a6 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -13,16 +13,25 @@
...
#ifndef CONFIG_ARCH_AT91 #error "CONFIG_ARCH_AT91 must be defined." #endif
As a result of the "depends on" line, this test will never succeed. You can remove these three lines.
@@ -111,6 +126,8 @@ static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); static int usb_hcd_at91_probe(const struct hc_driver *driver, struct platform_device *pdev) {
- struct at91_usbh_data *board;
Tab character where it should be a space.
- struct ohci_hcd *ohci; int retval; struct usb_hcd *hcd = NULL;
@@ -163,8 +180,11 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, goto err5; }
- board = hcd->self.controller->platform_data;
- ohci = hcd_to_ohci(hcd);
- ohci->num_ports = board->ports; at91_start_hc(pdev);
- ohci_hcd_init(hcd_to_ohci(hcd));
- ohci_setup(hcd);
Don't call ohci_setup().
@@ -727,3 +672,37 @@ static struct platform_driver ohci_hcd_at91_driver = { .of_match_table = of_match_ptr(at91_ohci_dt_ids), }, };
+static int __init ohci_at91_init(void) +{
- if (usb_disabled())
return -ENODEV;
- pr_info("%s: " DRIVER_DESC "\n", hcd_name);
- ohci_init_driver(&ohci_at91_hc_driver, NULL);
- /*
- The Atmel HW has some unusual quirks, which require Atmel-specific
- workarounds. We override certain hc_driver functions here to
- achieve that. We explicitly do not enhance ohci_driver_overrides to
- allow this more easily, since this is an unusual case, and we don't
- want to encourage others to override these functions by making it
- too easy.
- */
- ohci_at91_hc_driver.hub_status_data = ohci_at91_hub_status_data;
- ohci_at91_hc_driver.hub_control = ohci_at91_hub_control;
Since the hub_status_data and hub_control routines aren't going to be exported, you can't do it like this. Instead, save the values of ohci_at91_hc_driver.hub_status_data and ohci_at91_hc_driver.hub_control before overwriting them.
Alan Stern
Separate the Samsung OHCI S3CXXXX 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.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Arnd Bergmann arnd@arndb.de Cc: Alan Stern stern@rowland.harvard.edu Cc: Greg KH greg@kroah.com Cc: linux-usb@vger.kernel.org --- drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-hcd.c | 20 +------ drivers/usb/host/ohci-s3c2410.c | 116 ++++++++++++++++----------------------- 4 files changed, 58 insertions(+), 87 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0aabd84..a863c60 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -411,6 +411,14 @@ config USB_OHCI_HCD_SPEAR Enables support for the on-chip OHCI controller on ST SPEAr chips.
+config USB_OHCI_HCD_S3CXXXX + tristate "Support for S3CXXXX on-chip OHCI USB controller" + depends on USB_OHCI_HCD && (ARCH_S3C24XX) || (ARCH_S3C64XX) + default y + ---help--- + Enables support for the on-chip OHCI controller on + S3CXXXX chips. + config USB_OHCI_HCD_AT91 tristate "Support for Atmel on-chip OHCI USB controller" depends on USB_OHCI_HCD && ARCH_AT91 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 746ffc7..4290701 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o obj-$(CONFIG_USB_OHCI_HCD_OMAP3) += ohci-omap3.o obj-$(CONFIG_USB_OHCI_HCD_SPEAR) += ohci-spear.o obj-$(CONFIG_USB_OHCI_HCD_AT91) += ohci-at91.o +obj-$(CONFIG_USB_OHCI_HCD_S3CXXXX) += ohci-s3c2410.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 00409b9..8e5d979 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1173,11 +1173,6 @@ MODULE_LICENSE ("GPL"); #define SA1111_DRIVER ohci_hcd_sa1111_driver #endif
-#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX) -#include "ohci-s3c2410.c" -#define S3C2410_PLATFORM_DRIVER ohci_hcd_s3c2410_driver -#endif - #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) #include "ohci-pxa27x.c" #define PLATFORM_DRIVER ohci_hcd_pxa27x_driver @@ -1240,13 +1235,13 @@ MODULE_LICENSE ("GPL"); !IS_ENABLED(CONFIG_USB_OHCI_HCD_OMAP3) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_SPEAR) && \ !IS_ENABLED(CONFIG_USB_OHCI_HCD_AT91) && \ + !IS_ENABLED(CONFIG_USB_OHCI_HCD_S3CXXXX) && \ !defined(PLATFORM_DRIVER) && \ !defined(OF_PLATFORM_DRIVER) && \ !defined(SA1111_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && \ !defined(SM501_OHCI_DRIVER) && \ !defined(TMIO_OHCI_DRIVER) && \ - !defined(S3C2410_PLATFORM_DRIVER) && \ !defined(EP93XX_PLATFORM_DRIVER) && \ !defined(NXP_PLATFORM_DRIVER) && \ !defined(DAVINCI_PLATFORM_DRIVER) @@ -1309,12 +1304,6 @@ static int __init ohci_hcd_mod_init(void) goto error_tmio; #endif
-#ifdef S3C2410_PLATFORM_DRIVER - retval = platform_driver_register(&S3C2410_PLATFORM_DRIVER); - if (retval < 0) - goto error_s3c2410; -#endif - #ifdef EP93XX_PLATFORM_DRIVER retval = platform_driver_register(&EP93XX_PLATFORM_DRIVER); if (retval < 0) @@ -1348,10 +1337,6 @@ static int __init ohci_hcd_mod_init(void) platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); error_ep93xx: #endif -#ifdef S3C2410_PLATFORM_DRIVER - platform_driver_unregister(&S3C2410_PLATFORM_DRIVER); - error_s3c2410: -#endif #ifdef TMIO_OHCI_DRIVER platform_driver_unregister(&TMIO_OHCI_DRIVER); error_tmio: @@ -1398,9 +1383,6 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef EP93XX_PLATFORM_DRIVER platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); #endif -#ifdef S3C2410_PLATFORM_DRIVER - platform_driver_unregister(&S3C2410_PLATFORM_DRIVER); -#endif #ifdef TMIO_OHCI_DRIVER platform_driver_unregister(&TMIO_OHCI_DRIVER); #endif diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index e125770..14843d2 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -19,14 +19,27 @@ * This file is licenced under the GPL. */
-#include <linux/platform_device.h> #include <linux/clk.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> #include <linux/platform_data/usb-ohci-s3c2410.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#include "ohci.h" +
#define valid_port(idx) ((idx) == 1 || (idx) == 2)
/* clock device associated with the hcd */
+ +#define DRIVER_DESC "OHCI S3CXXXX driver" + +static const char hcd_name[] = "ohci-s3cxxxx"; + static struct clk *clk; static struct clk *usb_clk;
@@ -371,10 +384,9 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, goto err_put; }
+ ohci_setup(hcd); s3c2410_start_hc(dev, hcd);
- ohci_hcd_init(hcd_to_ohci(hcd)); - retval = usb_add_hcd(hcd, dev->resource[1].start, 0); if (retval != 0) goto err_ioremap; @@ -391,71 +403,7 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
/*-------------------------------------------------------------------------*/
-static int -ohci_s3c2410_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) { - dev_err(hcd->self.controller, "can't start %s\n", - hcd->self.bus_name); - ohci_stop(hcd); - return ret; - } - - return 0; -} - - -static const struct hc_driver ohci_s3c2410_hc_driver = { - .description = hcd_name, - .product_desc = "S3C24XX OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .start = ohci_s3c2410_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_s3c2410_hub_status_data, - .hub_control = ohci_s3c2410_hub_control, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - .start_port_reset = ohci_start_port_reset, -}; - -/* device driver */ +static struct hc_driver __read_mostly ohci_s3c2410_hc_driver;
static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev) { @@ -532,4 +480,36 @@ static struct platform_driver ohci_hcd_s3c2410_driver = { }, };
+static int __init ohci_s3cxxxx_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + ohci_init_driver(&ohci_s3c2410_hc_driver, NULL); + + /* + * The Samsung HW has some unusual quirks, which require Sumsung-specific + * workarounds. We override certain hc_driver functions here to + * achieve that. We explicitly do not enhance ohci_driver_overrides to + * allow this more easily, since this is an unusual case, and we don't + * want to encourage others to override these functions by making it + * too easy. + */ + + ohci_s3c2410_hc_driver.hub_status_data = ohci_s3c2410_hub_status_data; + ohci_s3c2410_hc_driver.hub_control = ohci_s3c2410_hub_control; + + return platform_driver_register(&ohci_hcd_s3c2410_driver); +} +module_init(ohci_s3cxxxx_init); + +static void __exit ohci_s3cxxxx_cleanup(void) +{ + platform_driver_unregister(&ohci_hcd_s3c2410_driver); +} +module_exit(ohci_s3cxxxx_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:s3c2410-ohci");
On Friday 07 June 2013 11:33:33 Manjunath Goudar wrote:
ohci_setup(hcd); s3c2410_start_hc(dev, hcd);
ohci_hcd_init(hcd_to_ohci(hcd));
I'm not sure about this part: s3c2410_start_hc is where the clock gets enabled, presumable we are not supposed to touch the ohci registers before it gets called, so ohci_init() being called implicitly by ohci_setup() seems like a bad idea.
Arnd
On Fri, 7 Jun 2013, Manjunath Goudar wrote:
Separate the Samsung OHCI S3CXXXX 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.
@@ -371,10 +384,9 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, goto err_put; }
- ohci_setup(hcd);
Don't call ohci_setup().
@@ -532,4 +480,36 @@ static struct platform_driver ohci_hcd_s3c2410_driver = { }, }; +static int __init ohci_s3cxxxx_init(void) +{
- if (usb_disabled())
return -ENODEV;
- pr_info("%s: " DRIVER_DESC "\n", hcd_name);
- ohci_init_driver(&ohci_s3c2410_hc_driver, NULL);
- /*
- The Samsung HW has some unusual quirks, which require Sumsung-specific
- workarounds. We override certain hc_driver functions here to
- achieve that. We explicitly do not enhance ohci_driver_overrides to
- allow this more easily, since this is an unusual case, and we don't
- want to encourage others to override these functions by making it
- too easy.
- */
- ohci_s3c2410_hc_driver.hub_status_data = ohci_s3c2410_hub_status_data;
- ohci_s3c2410_hc_driver.hub_control = ohci_s3c2410_hub_control;
Like in ohci-at91, save the pointers before overwriting them.
Alan Stern
On 7 June 2013 11:33, Manjunath Goudar manjunath.goudar@linaro.org wrote:
These patches are for separating the SOC On-Chip ohci host controller from ohci-hcd host code into its own driver module. This work is part of enabling multi-platform kernels on ARM.
Manjunath Goudar (7): USB: OHCI: make ohci-exynos a separate driver USB: OHCI: make ohci-omap a separate driver USB: OHCI: make ohci-omap3 a separate driver USB: OHCI: make ohci-spear a separate driver USB: OHCI: export ohci_hub_control and ohci_hub_status_data USB: OHCI: make ohci-at91 a separate driver USB: OHCI: make ohci-s3c2410 a separate driver
drivers/usb/host/Kconfig | 30 +++++++- drivers/usb/host/Makefile | 6 ++ drivers/usb/host/ohci-at91.c | 135 +++++++++++++++------------------- drivers/usb/host/ohci-exynos.c | 154 +++++++++++++++++---------------------- drivers/usb/host/ohci-hcd.c | 122 ++----------------------------- drivers/usb/host/ohci-hub.c | 8 +- drivers/usb/host/ohci-omap.c | 142 +++++++++++++----------------------- drivers/usb/host/ohci-omap3.c | 122 +++++++++++-------------------- drivers/usb/host/ohci-s3c2410.c | 116 ++++++++++++----------------- drivers/usb/host/ohci-spear.c | 149 ++++++++++++++++--------------------- drivers/usb/host/ohci.h | 9 +++ 11 files changed, 383 insertions(+), 610 deletions(-)
-- 1.7.9.5
sure I will fix the all review comments in V2 series.
These patches are for separating the SOC On-Chip ohci host controller from ohci-hcd host code into its own driver module. This work is part of enabling multi-platform kernels on ARM.
V2: In patch 5/6 and 6/6: -Set non-standard fields in hc_driver manually, rather than relying on an expanded struct ohci_driver_overrides. -Save orig_ohci_hub_control and orig_ohci_hub_status_data rather than relying on ohci_hub_control and hub_status_data being exported. -ohci_setup() has been removed because it is called in .reset member of the ohci_hc_driver structure.
In patch 1/6 to 4/6 -ohci_setup() has been removed because it is called in .reset member of the ohci_hc_driver structure.
Manjunath Goudar (6): USB: OHCI: make ohci-exynos a separate driver USB: OHCI: make ohci-omap a separate driver USB: OHCI: make ohci-omap3 a separate driver USB: OHCI: make ohci-spear a separate driver USB: OHCI: make ohci-at91 a separate driver USB: OHCI: make ohci-s3c2410 a separate driver
drivers/usb/host/Kconfig | 30 ++++++- drivers/usb/host/Makefile | 6 ++ drivers/usb/host/ohci-at91.c | 148 +++++++++++++++------------------- drivers/usb/host/ohci-exynos.c | 167 ++++++++++++++++----------------------- drivers/usb/host/ohci-hcd.c | 108 ------------------------- drivers/usb/host/ohci-omap.c | 156 ++++++++++++------------------------ drivers/usb/host/ohci-omap3.c | 120 ++++++++++------------------ drivers/usb/host/ohci-s3c2410.c | 129 ++++++++++++++---------------- drivers/usb/host/ohci-spear.c | 140 +++++++++++++------------------- 9 files changed, 370 insertions(+), 634 deletions(-)
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; it would be nice to have in 3.11.
V2: -exynos_ohci_hcd structure assignment error fixed. -Removed multiple usb_create_hcd() from prob funtion. -platform_set_drvdata() called before exynos_ohci_phy_enable(). -ohci_setup() removed because it is called in .reset member of the ohci_hc_driver structure
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Arnd Bergmann arnd@arndb.de Cc: Jingoo Han jg1.han@samsung.com Cc: Kukjin Kim kgene.kim@samsung.com Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@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 | 167 +++++++++++++++++----------------------- drivers/usb/host/ohci-hcd.c | 18 ----- 4 files changed, 71 insertions(+), 117 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f35f71e..75456f2 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -463,7 +463,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 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 d1a34e0..bf4a4b2 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_OHCI_HCD_PCI) += ohci-pci.o obj-$(CONFIG_USB_OHCI_HCD_PLATFORM) += ohci-platform.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 b0b542c..6ff830c 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -12,24 +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-ohci-exynos.h> #include <linux/usb/phy.h> #include <linux/usb/samsung_usb_phy.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <linux/usb/otg.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 usb_hcd *hcd = platform_get_drvdata(pdev); + struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
if (exynos_ohci->phy) usb_phy_init(exynos_ohci->phy); @@ -37,9 +52,10 @@ 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 usb_hcd *hcd = platform_get_drvdata(pdev); + struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
if (exynos_ohci->phy) usb_phy_shutdown(exynos_ohci->phy); @@ -47,63 +63,11 @@ static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci) exynos_ohci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST); }
-static int ohci_exynos_reset(struct usb_hcd *hcd) -{ - return ohci_init(hcd_to_ohci(hcd)); -} - -static int ohci_exynos_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int ret; - - ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci); - - ret = ohci_run(ohci); - if (ret < 0) { - dev_err(hcd->self.controller, "can't start %s\n", - hcd->self.bus_name); - ohci_stop(hcd); - return ret; - } - - 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 int exynos_ohci_probe(struct platform_device *pdev) { struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; struct exynos_ohci_hcd *exynos_ohci; struct usb_hcd *hcd; - struct ohci_hcd *ohci; struct resource *res; struct usb_phy *phy; int irq; @@ -119,10 +83,14 @@ 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);
if (of_device_is_compatible(pdev->dev.of_node, "samsung,exynos5440-ohci")) @@ -143,17 +111,6 @@ static int exynos_ohci_probe(struct platform_device *pdev) }
skip_phy: - - 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)) { @@ -190,26 +147,21 @@ skip_phy: }
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); + platform_set_drvdata(pdev, hcd);
- ohci = hcd_to_ohci(hcd); - ohci_hcd_init(ohci); + exynos_ohci_phy_enable(pdev);
err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { dev_err(&pdev->dev, "Failed to add USB HCD\n"); goto fail_add_hcd; } - - platform_set_drvdata(pdev, exynos_ohci); - 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: @@ -219,16 +171,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);
@@ -239,8 +190,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); @@ -249,9 +199,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;
@@ -271,10 +222,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);
@@ -286,16 +236,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);
@@ -306,6 +256,10 @@ static int exynos_ohci_resume(struct device *dev) #define exynos_ohci_resume NULL #endif
+static const struct ohci_driver_overrides exynos_overrides __initconst = { + .extra_priv_size = sizeof(struct exynos_ohci_hcd), +}; + static const struct dev_pm_ops exynos_ohci_pm_ops = { .suspend = exynos_ohci_suspend, .resume = exynos_ohci_resume, @@ -331,6 +285,23 @@ static struct platform_driver exynos_ohci_driver = { .of_match_table = of_match_ptr(exynos_ohci_match), } }; +static int __init ohci_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(ohci_exynos_init); + +static void __exit ohci_exynos_cleanup(void) +{ + platform_driver_unregister(&exynos_ohci_driver); +} +module_exit(ohci_exynos_cleanup);
MODULE_ALIAS("platform:exynos-ohci"); MODULE_AUTHOR("Jingoo Han jg1.han@samsung.com"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index a9d3437..2980bb6 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1182,11 +1182,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 @@ -1336,12 +1331,6 @@ static int __init ohci_hcd_mod_init(void) goto error_s3c2410; #endif
-#ifdef EXYNOS_PLATFORM_DRIVER - retval = platform_driver_register(&EXYNOS_PLATFORM_DRIVER); - if (retval < 0) - goto error_exynos; -#endif - #ifdef EP93XX_PLATFORM_DRIVER retval = platform_driver_register(&EP93XX_PLATFORM_DRIVER); if (retval < 0) @@ -1395,10 +1384,6 @@ static int __init ohci_hcd_mod_init(void) platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); error_ep93xx: #endif -#ifdef EXYNOS_PLATFORM_DRIVER - platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER); - error_exynos: -#endif #ifdef S3C2410_PLATFORM_DRIVER platform_driver_unregister(&S3C2410_PLATFORM_DRIVER); error_s3c2410: @@ -1463,9 +1448,6 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef EP93XX_PLATFORM_DRIVER platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); #endif -#ifdef EXYNOS_PLATFORM_DRIVER - platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER); -#endif #ifdef S3C2410_PLATFORM_DRIVER platform_driver_unregister(&S3C2410_PLATFORM_DRIVER); #endif
On Wed, 12 Jun 2013, Manjunath Goudar wrote:
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; it would be nice to have in 3.11.
V2: -exynos_ohci_hcd structure assignment error fixed. -Removed multiple usb_create_hcd() from prob funtion. -platform_set_drvdata() called before exynos_ohci_phy_enable(). -ohci_setup() removed because it is called in .reset member of the ohci_hc_driver structure
--- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -12,24 +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-ohci-exynos.h> #include <linux/usb/phy.h> #include <linux/usb/samsung_usb_phy.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <linux/usb/otg.h>
+#include "ohci.h"
+#define DRIVER_DESC "OHCI exynos driver"
I think the word "EXYNOS" is supposed to be in all capital letters. Apart from that,
Acked-by: Alan Stern stern@rowland.harvard.edu
On Thursday, June 13, 2013 12:54 AM, Manjunath Goudar wrote:
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; it would be nice to have in 3.11.
V2: -exynos_ohci_hcd structure assignment error fixed. -Removed multiple usb_create_hcd() from prob funtion. -platform_set_drvdata() called before exynos_ohci_phy_enable(). -ohci_setup() removed because it is called in .reset member of the ohci_hc_driver structure
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Arnd Bergmann arnd@arndb.de Cc: Jingoo Han jg1.han@samsung.com Cc: Kukjin Kim kgene.kim@samsung.com Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@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 | 167 +++++++++++++++++----------------------- drivers/usb/host/ohci-hcd.c | 18 ----- 4 files changed, 71 insertions(+), 117 deletions(-)
CC'ed Vivek Gautam
Hi Manjunath Goudar,
It looks good. I tested this patch on Exynos4210. It works properly. I really appreciate your work.
Acked-by: Jingoo Han jg1.han@samsung.com
Also, I agree on Alan's opinion.
+#define DRIVER_DESC "OHCI exynos driver"
Please, replace 'exynos' with 'EXYNOS'.
Best regards, Jingoo Han
On 20 June 2013 09:40, Jingoo Han jg1.han@samsung.com wrote:
On Thursday, June 13, 2013 12:54 AM, Manjunath Goudar wrote:
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; it would be nice to have in 3.11.
V2: -exynos_ohci_hcd structure assignment error fixed. -Removed multiple usb_create_hcd() from prob funtion. -platform_set_drvdata() called before exynos_ohci_phy_enable(). -ohci_setup() removed because it is called in .reset member of the ohci_hc_driver structure
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Arnd Bergmann arnd@arndb.de Cc: Jingoo Han jg1.han@samsung.com Cc: Kukjin Kim kgene.kim@samsung.com Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@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 | 167
+++++++++++++++++-----------------------
drivers/usb/host/ohci-hcd.c | 18 ----- 4 files changed, 71 insertions(+), 117 deletions(-)
CC'ed Vivek Gautam
Hi Manjunath Goudar,
It looks good. I tested this patch on Exynos4210. It works properly. I really appreciate your work.
Acked-by: Jingoo Han jg1.han@samsung.com
Also, I agree on Alan's opinion.
+#define DRIVER_DESC "OHCI exynos driver"
Please, replace 'exynos' with 'EXYNOS'.
Thank you very much. I fixed his comment in V3,when I am sending V3 vesrion I will add CC to Vivek Gautam.
Thanks Manjunath Goudar
Best regards,
Jingoo Han
Separate the TI OHCI OMAP1/2 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; it would be nice to have in 3.11.
V2: -omap_ohci_clock_power(0) called in usb_hcd_omap_remove(). -Removed ohci_setup() call from usb_hcd_omap_probe() and ohci_omap_reset(). -host_enabled and host_initialized variables aren't used for anything thats what removed.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Felipe Balbi balbi@ti.com Cc: Arnd Bergmann arnd@arndb.de Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@rowland.harvard.edu Cc: linux-usb@vger.kernel.org --- drivers/usb/host/Kconfig | 2 +- drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-hcd.c | 18 ----- drivers/usb/host/ohci-omap.c | 156 +++++++++++++----------------------------- 4 files changed, 51 insertions(+), 126 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 75456f2..7a87c72 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -376,7 +376,7 @@ config USB_OHCI_HCD if USB_OHCI_HCD
config USB_OHCI_HCD_OMAP1 - bool "OHCI support for OMAP1/2 chips" + tristate "OHCI support for OMAP1/2 chips" depends on ARCH_OMAP1 default y ---help--- diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index bf4a4b2..52f2c44 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_OHCI_HCD_PCI) += ohci-pci.o obj-$(CONFIG_USB_OHCI_HCD_PLATFORM) += ohci-platform.o obj-$(CONFIG_USB_OHCI_EXYNOS) += ohci-exynos.o +obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 2980bb6..1abc1e7 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1182,11 +1182,6 @@ MODULE_LICENSE ("GPL"); #define S3C2410_PLATFORM_DRIVER ohci_hcd_s3c2410_driver #endif
-#ifdef CONFIG_USB_OHCI_HCD_OMAP1 -#include "ohci-omap.c" -#define OMAP1_PLATFORM_DRIVER ohci_hcd_omap_driver -#endif - #ifdef CONFIG_USB_OHCI_HCD_OMAP3 #include "ohci-omap3.c" #define OMAP3_PLATFORM_DRIVER ohci_hcd_omap3_driver @@ -1289,12 +1284,6 @@ static int __init ohci_hcd_mod_init(void) goto error_platform; #endif
-#ifdef OMAP1_PLATFORM_DRIVER - retval = platform_driver_register(&OMAP1_PLATFORM_DRIVER); - if (retval < 0) - goto error_omap1_platform; -#endif - #ifdef OMAP3_PLATFORM_DRIVER retval = platform_driver_register(&OMAP3_PLATFORM_DRIVER); if (retval < 0) @@ -1408,10 +1397,6 @@ static int __init ohci_hcd_mod_init(void) platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); error_omap3_platform: #endif -#ifdef OMAP1_PLATFORM_DRIVER - platform_driver_unregister(&OMAP1_PLATFORM_DRIVER); - error_omap1_platform: -#endif #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); error_platform: @@ -1466,9 +1451,6 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef OMAP3_PLATFORM_DRIVER platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); #endif -#ifdef OMAP1_PLATFORM_DRIVER - platform_driver_unregister(&OMAP1_PLATFORM_DRIVER); -#endif #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); #endif diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 8747fa6..b900dba 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -14,12 +14,21 @@ * This file is licenced under the GPL. */
-#include <linux/signal.h> -#include <linux/jiffies.h> -#include <linux/platform_device.h> #include <linux/clk.h> +#include <linux/dma-mapping.h> #include <linux/err.h> #include <linux/gpio.h> +#include <linux/io.h> +#include <linux/jiffies.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/usb/otg.h> +#include <linux/platform_device.h> +#include <linux/signal.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#include "ohci.h"
#include <asm/io.h> #include <asm/mach-types.h> @@ -42,10 +51,7 @@ #define OMAP1510_LB_MMU_RAM_H 0xfffec234 #define OMAP1510_LB_MMU_RAM_L 0xfffec238
- -#ifndef CONFIG_ARCH_OMAP -#error "This file is OMAP bus glue. CONFIG_OMAP must be defined." -#endif +#define DRIVER_DESC "OHCI OMAP driver"
#ifdef CONFIG_TPS65010 #include <linux/i2c/tps65010.h> @@ -68,8 +74,9 @@ extern int ocpi_enable(void);
static struct clk *usb_host_ck; static struct clk *usb_dc_ck; -static int host_enabled; -static int host_initialized; + +static const char hcd_name[] = "ohci-omap"; +static struct hc_driver __read_mostly ohci_omap_hc_driver;
static void omap_ohci_clock_power(int on) { @@ -188,21 +195,21 @@ static void start_hnp(struct ohci_hcd *ohci)
/*-------------------------------------------------------------------------*/
-static int ohci_omap_init(struct usb_hcd *hcd) +static int ohci_omap_reset(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct omap_usb_config *config = hcd->self.controller->platform_data; int need_transceiver = (config->otg != 0); - int ret;
dev_dbg(hcd->self.controller, "starting USB Controller\n");
- if (config->otg) { + if (config->otg || config->rwc) { ohci_to_hcd(ohci)->self.otg_port = config->otg; /* default/minimum OTG power budget: 8 mA */ ohci_to_hcd(ohci)->power_budget = 8; + ohci->hc_control = OHCI_CTRL_RWC; + writel(OHCI_CTRL_RWC, &ohci->regs->control); } - /* boards can use OTG transceivers in non-OTG modes */ need_transceiver = need_transceiver || machine_is_omap_h2() || machine_is_omap_h3(); @@ -238,9 +245,6 @@ static int ohci_omap_init(struct usb_hcd *hcd) omap_1510_local_bus_init(); }
- if ((ret = ohci_init(ohci)) < 0) - return ret; - /* board-specific power switching and overcurrent support */ if (machine_is_omap_osk() || machine_is_omap_innovator()) { u32 rh = roothub_a (ohci); @@ -281,14 +285,6 @@ static int ohci_omap_init(struct usb_hcd *hcd) return 0; }
-static void ohci_omap_stop(struct usb_hcd *hcd) -{ - dev_dbg(hcd->self.controller, "stopping USB Controller\n"); - ohci_stop(hcd); - omap_ohci_clock_power(0); -} - - /*-------------------------------------------------------------------------*/
/** @@ -304,7 +300,6 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, { int retval, irq; struct usb_hcd *hcd = 0; - struct ohci_hcd *ohci;
if (pdev->num_resources != 2) { printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", @@ -354,12 +349,6 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, goto err2; }
- ohci = hcd_to_ohci(hcd); - ohci_hcd_init(ohci); - - host_initialized = 0; - host_enabled = 1; - irq = platform_get_irq(pdev, 0); if (irq < 0) { retval = -ENXIO; @@ -368,12 +357,8 @@ static int usb_hcd_omap_probe (const struct hc_driver *driver, retval = usb_add_hcd(hcd, irq, 0); if (retval) goto err3; - - host_initialized = 1; - - if (!host_enabled) - omap_ohci_clock_power(0); - + + omap_ohci_clock_power(0); return 0; err3: iounmap(hcd->regs); @@ -402,6 +387,8 @@ err0: static inline void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev) { + dev_dbg(hcd->self.controller, "stopping USB Controller\n"); + omap_ohci_clock_power(0); usb_remove_hcd(hcd); if (!IS_ERR_OR_NULL(hcd->phy)) { (void) otg_set_host(hcd->phy->otg, 0); @@ -418,76 +405,6 @@ usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
/*-------------------------------------------------------------------------*/
-static int -ohci_omap_start (struct usb_hcd *hcd) -{ - struct omap_usb_config *config; - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; - - if (!host_enabled) - return 0; - config = hcd->self.controller->platform_data; - if (config->otg || config->rwc) { - ohci->hc_control = OHCI_CTRL_RWC; - writel(OHCI_CTRL_RWC, &ohci->regs->control); - } - - if ((ret = ohci_run (ohci)) < 0) { - dev_err(hcd->self.controller, "can't start\n"); - ohci_stop (hcd); - return ret; - } - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static const struct hc_driver ohci_omap_hc_driver = { - .description = hcd_name, - .product_desc = "OMAP OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .reset = ohci_omap_init, - .start = ohci_omap_start, - .stop = ohci_omap_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 = 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 int ohci_hcd_omap_drv_probe(struct platform_device *dev) { return usb_hcd_omap_probe(&ohci_omap_hc_driver, dev); @@ -553,4 +470,29 @@ static struct platform_driver ohci_hcd_omap_driver = { }, };
+static const struct ohci_driver_overrides omap_overrides __initconst = { + .product_desc = "OMAP OHCI", + .reset = ohci_omap_reset +}; + +static int __init ohci_omap_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ohci_init_driver(&ohci_omap_hc_driver, &omap_overrides); + return platform_driver_register(&ohci_hcd_omap_driver); +} +module_init(ohci_omap_init); + +static void __exit ohci_omap_cleanup(void) +{ + platform_driver_unregister(&ohci_hcd_omap_driver); +} +module_exit(ohci_omap_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_ALIAS("platform:ohci"); +MODULE_LICENSE("GPL");
On Wed, 12 Jun 2013, Manjunath Goudar wrote:
Separate the TI OHCI OMAP1/2 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; it would be nice to have in 3.11.
V2: -omap_ohci_clock_power(0) called in usb_hcd_omap_remove(). -Removed ohci_setup() call from usb_hcd_omap_probe() and ohci_omap_reset().
You were supposed to remove the call from usb_hcd_omap_probe but leave in the call from ohci_omap_reset.
-host_enabled and host_initialized variables aren't used for anything thats what removed.
@@ -188,21 +195,21 @@ static void start_hnp(struct ohci_hcd *ohci) /*-------------------------------------------------------------------------*/ -static int ohci_omap_init(struct usb_hcd *hcd) +static int ohci_omap_reset(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct omap_usb_config *config = hcd->self.controller->platform_data; int need_transceiver = (config->otg != 0);
- int ret;
dev_dbg(hcd->self.controller, "starting USB Controller\n");
- if (config->otg) {
- if (config->otg || config->rwc) { ohci_to_hcd(ohci)->self.otg_port = config->otg; /* default/minimum OTG power budget: 8 mA */ ohci_to_hcd(ohci)->power_budget = 8;
These three lines are supposed to run only when config->otg is set, not when config->rwc is set. The next two lines can run when either one is set.
Also, "ohci_to_hcd(ohci)" should be replaced by "hcd".
ohci->hc_control = OHCI_CTRL_RWC;
}writel(OHCI_CTRL_RWC, &ohci->regs->control);
Don't remove this blank line.
/* boards can use OTG transceivers in non-OTG modes */ need_transceiver = need_transceiver || machine_is_omap_h2() || machine_is_omap_h3(); @@ -238,9 +245,6 @@ static int ohci_omap_init(struct usb_hcd *hcd) omap_1510_local_bus_init(); }
- if ((ret = ohci_init(ohci)) < 0)
return ret;
This should call ohci_setup instead of ohci_init.
Alan Stern
On Wed, 12 Jun 2013, Manjunath Goudar wrote:
Separate the TI OHCI OMAP1/2 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; it would be nice to have in 3.11.
V2: -omap_ohci_clock_power(0) called in usb_hcd_omap_remove(). -Removed ohci_setup() call from usb_hcd_omap_probe() and ohci_omap_reset(). -host_enabled and host_initialized variables aren't used for anything thats what removed.
There's one more thing I just noticed.
@@ -188,21 +195,21 @@ static void start_hnp(struct ohci_hcd *ohci) /*-------------------------------------------------------------------------*/ -static int ohci_omap_init(struct usb_hcd *hcd) +static int ohci_omap_reset(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct omap_usb_config *config = hcd->self.controller->platform_data; int need_transceiver = (config->otg != 0);
- int ret;
dev_dbg(hcd->self.controller, "starting USB Controller\n");
- if (config->otg) {
- if (config->otg || config->rwc) { ohci_to_hcd(ohci)->self.otg_port = config->otg; /* default/minimum OTG power budget: 8 mA */ ohci_to_hcd(ohci)->power_budget = 8;
ohci->hc_control = OHCI_CTRL_RWC;
writel(OHCI_CTRL_RWC, &ohci->regs->control);
This last line must not appear here, because ohci->regs doesn't get set until ohci_setup() calls ohci_init(). Removing it entirely is safe because ohci_run() does the same thing later on. Or you can move both of these last two lines after the call to ohci_setup().
Alan Stern
Separate the TI OHCI OMAP3 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; it would be nice to have in 3.11.
V2: -ohci_setup() removed because it is called in .reset member of the ohci_hc_driver structure. -The improper multi-line commenting style written in proper way. ('*' characters aligned in vertically).
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Anand Gadiyar gadiyar@ti.com Cc: Felipe Balbi balbi@ti.com Cc: Arnd Bergmann arnd@arndb.de Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@rowland.harvard.edu Cc: linux-usb@vger.kernel.org --- drivers/usb/host/Kconfig | 2 +- drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-hcd.c | 18 ------- drivers/usb/host/ohci-omap3.c | 120 ++++++++++++++--------------------------- 4 files changed, 42 insertions(+), 99 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 7a87c72..db20e43 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -383,7 +383,7 @@ config USB_OHCI_HCD_OMAP1 Enables support for the OHCI controller on OMAP1/2 chips.
config USB_OHCI_HCD_OMAP3 - bool "OHCI support for OMAP3 and later chips" + tristate "OHCI support for OMAP3 and later chips" depends on (ARCH_OMAP3 || ARCH_OMAP4) default y ---help--- diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 52f2c44..9f2f5f3 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_USB_OHCI_HCD_PCI) += ohci-pci.o obj-$(CONFIG_USB_OHCI_HCD_PLATFORM) += ohci-platform.o obj-$(CONFIG_USB_OHCI_EXYNOS) += ohci-exynos.o obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o +obj-$(CONFIG_USB_OHCI_HCD_OMAP3) += ohci-omap3.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 1abc1e7..cad51d2 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1182,11 +1182,6 @@ MODULE_LICENSE ("GPL"); #define S3C2410_PLATFORM_DRIVER ohci_hcd_s3c2410_driver #endif
-#ifdef CONFIG_USB_OHCI_HCD_OMAP3 -#include "ohci-omap3.c" -#define OMAP3_PLATFORM_DRIVER ohci_hcd_omap3_driver -#endif - #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) #include "ohci-pxa27x.c" #define PLATFORM_DRIVER ohci_hcd_pxa27x_driver @@ -1284,12 +1279,6 @@ static int __init ohci_hcd_mod_init(void) goto error_platform; #endif
-#ifdef OMAP3_PLATFORM_DRIVER - retval = platform_driver_register(&OMAP3_PLATFORM_DRIVER); - if (retval < 0) - goto error_omap3_platform; -#endif - #ifdef OF_PLATFORM_DRIVER retval = platform_driver_register(&OF_PLATFORM_DRIVER); if (retval < 0) @@ -1393,10 +1382,6 @@ static int __init ohci_hcd_mod_init(void) platform_driver_unregister(&OF_PLATFORM_DRIVER); error_of_platform: #endif -#ifdef OMAP3_PLATFORM_DRIVER - platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); - error_omap3_platform: -#endif #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); error_platform: @@ -1448,9 +1433,6 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef OF_PLATFORM_DRIVER platform_driver_unregister(&OF_PLATFORM_DRIVER); #endif -#ifdef OMAP3_PLATFORM_DRIVER - platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); -#endif #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); #endif diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index 8f71357..b7c75ab 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c @@ -29,90 +29,22 @@ * - add kernel-doc */
+#include <linux/dma-mapping.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/usb/otg.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> -#include <linux/of.h> -#include <linux/dma-mapping.h> - -/*-------------------------------------------------------------------------*/ - -static int ohci_omap3_init(struct usb_hcd *hcd) -{ - dev_dbg(hcd->self.controller, "starting OHCI controller\n"); - - return ohci_init(hcd_to_ohci(hcd)); -} - -/*-------------------------------------------------------------------------*/ - -static int ohci_omap3_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int ret; - - /* - * RemoteWakeupConnected has to be set explicitly before - * calling ohci_run. The reset value of RWC is 0. - */ - ohci->hc_control = OHCI_CTRL_RWC; - writel(OHCI_CTRL_RWC, &ohci->regs->control); +#include <linux/usb.h> +#include <linux/usb/hcd.h>
- ret = ohci_run(ohci); +#include "ohci.h"
- if (ret < 0) { - dev_err(hcd->self.controller, "can't start\n"); - ohci_stop(hcd); - } +#define DRIVER_DESC "OHCI OMAP3 driver"
- return ret; -} - -/*-------------------------------------------------------------------------*/ - -static const struct hc_driver ohci_omap3_hc_driver = { - .description = hcd_name, - .product_desc = "OMAP3 OHCI Host Controller", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .reset = ohci_omap3_init, - .start = ohci_omap3_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 = 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 const char hcd_name[] = "ohci-omap3"; +static struct hc_driver __read_mostly ohci_omap3_hc_driver;
/* * configure so an HC device and id are always provided @@ -129,6 +61,7 @@ static const struct hc_driver ohci_omap3_hc_driver = { static int ohci_hcd_omap3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct ohci_hcd *ohci; struct usb_hcd *hcd = NULL; void __iomem *regs = NULL; struct resource *res; @@ -185,7 +118,14 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev) pm_runtime_enable(dev); pm_runtime_get_sync(dev);
- ohci_hcd_init(hcd_to_ohci(hcd)); + ohci = hcd_to_ohci(hcd); + /* + * RemoteWakeupConnected has to be set explicitly before + * calling ohci_run. The reset value of RWC is 0. + */ + ohci->hc_control = OHCI_CTRL_RWC; + writel(OHCI_CTRL_RWC, &ohci->regs->control); + dev_dbg(hcd->self.controller, "starting OHCI controller\n");
ret = usb_add_hcd(hcd, irq, 0); if (ret) { @@ -256,5 +196,25 @@ static struct platform_driver ohci_hcd_omap3_driver = { }, };
+static int __init ohci_omap3_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ohci_init_driver(&ohci_omap3_hc_driver, NULL); + return platform_driver_register(&ohci_hcd_omap3_driver); +} +module_init(ohci_omap3_init); + +static void __exit ohci_omap3_cleanup(void) +{ + platform_driver_unregister(&ohci_hcd_omap3_driver); +} +module_exit(ohci_omap3_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_ALIAS("platform:ohci-omap3"); MODULE_AUTHOR("Anand Gadiyar gadiyar@ti.com"); +MODULE_LICENSE("GPL");
On Wed, 12 Jun 2013, Manjunath Goudar wrote:
Separate the TI OHCI OMAP3 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; it would be nice to have in 3.11.
V2: -ohci_setup() removed because it is called in .reset member of the ohci_hc_driver structure. -The improper multi-line commenting style written in proper way. ('*' characters aligned in vertically).
Generally okay, just one problem...
@@ -185,7 +118,14 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev) pm_runtime_enable(dev); pm_runtime_get_sync(dev);
- ohci_hcd_init(hcd_to_ohci(hcd));
- ohci = hcd_to_ohci(hcd);
- /*
* RemoteWakeupConnected has to be set explicitly before
* calling ohci_run. The reset value of RWC is 0.
*/
- ohci->hc_control = OHCI_CTRL_RWC;
- writel(OHCI_CTRL_RWC, &ohci->regs->control);
ohci->regs doesn't get set until usb_add_hcd, so this line must not appear here. You can simply remove it.
- dev_dbg(hcd->self.controller, "starting OHCI controller\n");
ret = usb_add_hcd(hcd, irq, 0); if (ret) {
Alan Stern
Separate the ST OHCI SPEAr 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; it would be nice to have in 3.11.
V2: -ohci_setup() removed because it is called in .reset member of the ohci_hc_driver structure. -debugging stuff isn't needed any more that's what removed.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Viresh Kumar viresh.linux@gmail.com Cc: Arnd Bergmann arnd@arndb.de Cc: Greg KH greg@kroah.com Cc: Alan Stern stern@rowland.harvard.edu Cc: linux-usb@vger.kernel.org --- drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-hcd.c | 18 ------ drivers/usb/host/ohci-spear.c | 140 +++++++++++++++++------------------------ 4 files changed, 65 insertions(+), 102 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index db20e43..46c2f42 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -382,6 +382,14 @@ config USB_OHCI_HCD_OMAP1 ---help--- Enables support for the OHCI controller on OMAP1/2 chips.
+config USB_OHCI_HCD_SPEAR + tristate "Support for ST SPEAr on-chip OHCI USB controller" + depends on USB_OHCI_HCD && PLAT_SPEAR + default y + ---help--- + Enables support for the on-chip OHCI controller on + ST SPEAr chips. + config USB_OHCI_HCD_OMAP3 tristate "OHCI support for OMAP3 and later chips" depends on (ARCH_OMAP3 || ARCH_OMAP4) diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 9f2f5f3..26cb6b3 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_USB_OHCI_HCD_PLATFORM) += ohci-platform.o obj-$(CONFIG_USB_OHCI_EXYNOS) += ohci-exynos.o obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o obj-$(CONFIG_USB_OHCI_HCD_OMAP3) += ohci-omap3.o +obj-$(CONFIG_USB_OHCI_HCD_SPEAR) += ohci-spear.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index cad51d2..34ec156 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1212,11 +1212,6 @@ MODULE_LICENSE ("GPL"); #define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver #endif
-#ifdef CONFIG_PLAT_SPEAR -#include "ohci-spear.c" -#define SPEAR_PLATFORM_DRIVER spear_ohci_hcd_driver -#endif - #ifdef CONFIG_PPC_PS3 #include "ohci-ps3.c" #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver @@ -1333,19 +1328,9 @@ static int __init ohci_hcd_mod_init(void) goto error_davinci; #endif
-#ifdef SPEAR_PLATFORM_DRIVER - retval = platform_driver_register(&SPEAR_PLATFORM_DRIVER); - if (retval < 0) - goto error_spear; -#endif - return retval;
/* Error path */ -#ifdef SPEAR_PLATFORM_DRIVER - platform_driver_unregister(&SPEAR_PLATFORM_DRIVER); - error_spear: -#endif #ifdef DAVINCI_PLATFORM_DRIVER platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); error_davinci: @@ -1403,9 +1388,6 @@ module_init(ohci_hcd_mod_init);
static void __exit ohci_hcd_mod_exit(void) { -#ifdef SPEAR_PLATFORM_DRIVER - platform_driver_unregister(&SPEAR_PLATFORM_DRIVER); -#endif #ifdef DAVINCI_PLATFORM_DRIVER platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); #endif diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c index cc9dd9e..31ff3fc 100644 --- a/drivers/usb/host/ohci-spear.c +++ b/drivers/usb/host/ohci-spear.c @@ -11,92 +11,37 @@ * warranty of any kind, whether express or implied. */
-#include <linux/signal.h> -#include <linux/platform_device.h> #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/signal.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#include "ohci.h"
+#define DRIVER_DESC "OHCI SPEAr driver" + +static const char hcd_name[] = "SPEAr-ohci"; struct spear_ohci { - struct ohci_hcd ohci; struct clk *clk; };
-#define to_spear_ohci(hcd) (struct spear_ohci *)hcd_to_ohci(hcd) - -static void spear_start_ohci(struct spear_ohci *ohci) -{ - clk_prepare_enable(ohci->clk); -} - -static void spear_stop_ohci(struct spear_ohci *ohci) -{ - clk_disable_unprepare(ohci->clk); -} - -static int ohci_spear_start(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int ret; - - ret = ohci_init(ohci); - if (ret < 0) - return ret; - ohci->regs = hcd->regs; - - ret = ohci_run(ohci); - if (ret < 0) { - dev_err(hcd->self.controller, "can't start\n"); - ohci_stop(hcd); - return ret; - } - - create_debug_files(ohci); - -#ifdef DEBUG - ohci_dump(ohci, 1); -#endif - return 0; -} - -static const struct hc_driver ohci_spear_hc_driver = { - .description = hcd_name, - .product_desc = "SPEAr OHCI", - .hcd_priv_size = sizeof(struct spear_ohci), - - /* generic hardware linkage */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* basic lifecycle operations */ - .start = ohci_spear_start, - .stop = ohci_stop, - .shutdown = ohci_shutdown, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - - /* 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, +#define to_spear_ohci(hcd) (struct spear_ohci *)(hcd_to_ohci(hcd)->priv)
- /* root hub support */ - .hub_status_data = ohci_hub_status_data, - .hub_control = ohci_hub_control, - - .start_port_reset = ohci_start_port_reset, -}; +static struct hc_driver __read_mostly ohci_spear_hc_driver;
static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) { const struct hc_driver *driver = &ohci_spear_hc_driver; + struct ohci_hcd *ohci; struct usb_hcd *hcd = NULL; struct clk *usbh_clk; - struct spear_ohci *ohci_p; + struct spear_ohci *sohci_p; struct resource *res; int retval, irq;
@@ -151,16 +96,18 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) goto err_put_hcd; }
- ohci_p = (struct spear_ohci *)hcd_to_ohci(hcd); - ohci_p->clk = usbh_clk; - spear_start_ohci(ohci_p); - ohci_hcd_init(hcd_to_ohci(hcd)); + sohci_p = to_spear_ohci(hcd); + sohci_p->clk = usbh_clk; + + clk_prepare_enable(sohci_p->clk); + + ohci = hcd_to_ohci(hcd);
retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), 0); if (retval == 0) return retval;
- spear_stop_ohci(ohci_p); + clk_disable_unprepare(sohci_p->clk); err_put_hcd: usb_put_hcd(hcd); fail: @@ -172,11 +119,11 @@ fail: static int spear_ohci_hcd_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct spear_ohci *ohci_p = to_spear_ohci(hcd); + struct spear_ohci *sohci_p = to_spear_ohci(hcd);
usb_remove_hcd(hcd); - if (ohci_p->clk) - spear_stop_ohci(ohci_p); + if (sohci_p->clk) + clk_disable_unprepare(sohci_p->clk);
usb_put_hcd(hcd); return 0; @@ -188,13 +135,14 @@ static int spear_ohci_hcd_drv_suspend(struct platform_device *dev, { struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); - struct spear_ohci *ohci_p = to_spear_ohci(hcd); + struct spear_ohci *sohci_p = to_spear_ohci(hcd);
if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies;
- spear_stop_ohci(ohci_p); + clk_disable_unprepare(sohci_p->clk); + return 0; }
@@ -202,13 +150,13 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); - struct spear_ohci *ohci_p = to_spear_ohci(hcd); + struct spear_ohci *sohci_p = to_spear_ohci(hcd);
if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies;
- spear_start_ohci(ohci_p); + clk_prepare_enable(sohci_p->clk); ohci_resume(hcd, false); return 0; } @@ -234,4 +182,28 @@ static struct platform_driver spear_ohci_hcd_driver = { }, };
+static const struct ohci_driver_overrides spear_overrides __initconst = { + .extra_priv_size = sizeof(struct spear_ohci), +}; +static int __init ohci_spear_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ohci_init_driver(&ohci_spear_hc_driver, &spear_overrides); + return platform_driver_register(&spear_ohci_hcd_driver); +} +module_init(ohci_spear_init); + +static void __exit ohci_spear_cleanup(void) +{ + platform_driver_unregister(&spear_ohci_hcd_driver); +} +module_exit(ohci_spear_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Deepak Sikri"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:spear-ohci");
On Wed, 12 Jun 2013, Manjunath Goudar wrote:
Separate the ST OHCI SPEAr 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; it would be nice to have in 3.11.
V2: -ohci_setup() removed because it is called in .reset member of the ohci_hc_driver structure. -debugging stuff isn't needed any more that's what removed.
Acked-by: Alan Stern stern@rowland.harvard.edu
Separate the TI OHCI Atmel 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; it would be nice to have in 3.11.
V2: -Set non-standard fields in ohci_at91_hc_driver manually, rather than relying on an expanded struct ohci_driver_overrides. -Save orig_ohci_hub_control and orig_ohci_hub_status_data rather than relying on ohci_hub_control and hub_status_data being exported. -ohci_setup() has been removed because it is called in .reset member of the ohci_hc_driver structure.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Arnd Bergmann arnd@arndb.de Cc: Alan Stern stern@rowland.harvard.edu Cc: Greg KH greg@kroah.com Cc: linux-usb@vger.kernel.org --- drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-at91.c | 148 +++++++++++++++++++----------------------- drivers/usb/host/ohci-hcd.c | 18 ----- 4 files changed, 74 insertions(+), 101 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 46c2f42..e4dc9ab 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -390,6 +390,14 @@ config USB_OHCI_HCD_SPEAR Enables support for the on-chip OHCI controller on ST SPEAr chips.
+config USB_OHCI_HCD_AT91 + tristate "Support for Atmel on-chip OHCI USB controller" + depends on USB_OHCI_HCD && ARCH_AT91 + default y + ---help--- + Enables support for the on-chip OHCI controller on + Atmel chips. + config USB_OHCI_HCD_OMAP3 tristate "OHCI support for OMAP3 and later chips" depends on (ARCH_OMAP3 || ARCH_OMAP4) diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 26cb6b3..f3e02c0 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_USB_OHCI_EXYNOS) += ohci-exynos.o obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o obj-$(CONFIG_USB_OHCI_HCD_OMAP3) += ohci-omap3.o obj-$(CONFIG_USB_OHCI_HCD_SPEAR) += ohci-spear.o +obj-$(CONFIG_USB_OHCI_HCD_AT91) += ohci-at91.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 2ee1496..fb2f127 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -13,27 +13,41 @@ */
#include <linux/clk.h> -#include <linux/platform_device.h> +#include <linux/dma-mapping.h> #include <linux/of_platform.h> #include <linux/of_gpio.h> +#include <linux/platform_device.h> #include <linux/platform_data/atmel.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h>
#include <mach/hardware.h> #include <asm/gpio.h>
#include <mach/cpu.h>
-#ifndef CONFIG_ARCH_AT91 -#error "CONFIG_ARCH_AT91 must be defined." -#endif + +#include "ohci.h"
#define valid_port(index) ((index) >= 0 && (index) < AT91_MAX_USBH_PORTS) #define at91_for_each_port(index) \ for ((index) = 0; (index) < AT91_MAX_USBH_PORTS; (index)++)
/* interface and function clocks; sometimes also an AHB clock */ + +#define DRIVER_DESC "OHCI Atmel driver" + +static const char hcd_name[] = "ohci-atmel"; + +static struct hc_driver __read_mostly ohci_at91_hc_driver; static struct clk *iclk, *fclk, *hclk; static int clocked; +static int (*orig_ohci_hub_control)(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + u16 wIndex, char *buf, u16 wLength); +static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);
extern int usb_disabled(void);
@@ -111,6 +125,8 @@ static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); static int usb_hcd_at91_probe(const struct hc_driver *driver, struct platform_device *pdev) { + struct at91_usbh_data *board; + struct ohci_hcd *ohci; int retval; struct usb_hcd *hcd = NULL;
@@ -163,8 +179,11 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, goto err5; }
+ board = hcd->self.controller->platform_data; + ohci = hcd_to_ohci(hcd); + ohci->num_ports = board->ports; at91_start_hc(pdev); - ohci_hcd_init(hcd_to_ohci(hcd)); + ohci_setup(hcd);
retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED); if (retval == 0) @@ -221,36 +240,6 @@ static void usb_hcd_at91_remove(struct usb_hcd *hcd, }
/*-------------------------------------------------------------------------*/ - -static int -ohci_at91_reset (struct usb_hcd *hcd) -{ - struct at91_usbh_data *board = hcd->self.controller->platform_data; - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; - - if ((ret = ohci_init(ohci)) < 0) - return ret; - - ohci->num_ports = board->ports; - return 0; -} - -static int -ohci_at91_start (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - int ret; - - if ((ret = ohci_run(ohci)) < 0) { - dev_err(hcd->self.controller, "can't start %s\n", - hcd->self.bus_name); - ohci_stop(hcd); - return ret; - } - return 0; -} - static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable) { if (!valid_port(port)) @@ -281,7 +270,7 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf) { struct at91_usbh_data *pdata = hcd->self.controller->platform_data; - int length = ohci_hub_status_data(hcd, buf); + int length = orig_ohci_hub_status_data(hcd, buf); int port;
at91_for_each_port(port) { @@ -359,7 +348,8 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, break; }
- ret = ohci_hub_control(hcd, typeReq, wValue, wIndex + 1, buf, wLength); + ret = orig_ohci_hub_control(hcd, typeReq, wValue, wIndex + 1, + buf, wLength); if (ret) goto out;
@@ -413,51 +403,6 @@ static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/*-------------------------------------------------------------------------*/
-static const struct hc_driver ohci_at91_hc_driver = { - .description = hcd_name, - .product_desc = "AT91 OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .reset = ohci_at91_reset, - .start = ohci_at91_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_at91_hub_status_data, - .hub_control = ohci_at91_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 ohci_hcd_at91_overcurrent_irq(int irq, void *data) { struct platform_device *pdev = data; @@ -686,7 +631,7 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) * REVISIT: some boards will be able to turn VBUS off... */ if (at91_suspend_entering_slow_clock()) { - ohci_usb_reset (ohci); + ohci_restart(ohci); /* flush the writes */ (void) ohci_readl (ohci, &ohci->regs->control); at91_stop_clock(); @@ -727,3 +672,40 @@ static struct platform_driver ohci_hcd_at91_driver = { .of_match_table = of_match_ptr(at91_ohci_dt_ids), }, }; + +static int __init ohci_at91_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + ohci_init_driver(&ohci_at91_hc_driver, NULL); + + /* + * The Atmel HW has some unusual quirks, which require Atmel-specific + * workarounds. We override certain hc_driver functions here to + * achieve that. We explicitly do not enhance ohci_driver_overrides to + * allow this more easily, since this is an unusual case, and we don't + * want to encourage others to override these functions by making it + * too easy. + */ + + orig_ohci_hub_control = ohci_at91_hc_driver.hub_control; + orig_ohci_hub_status_data = ohci_at91_hc_driver.hub_status_data; + + ohci_at91_hc_driver.hub_status_data = ohci_at91_hub_status_data; + ohci_at91_hc_driver.hub_control = ohci_at91_hub_control; + + return platform_driver_register(&ohci_hcd_at91_driver); +} +module_init(ohci_at91_init); + +static void __exit ohci_at91_cleanup(void) +{ + platform_driver_unregister(&ohci_hcd_at91_driver); +} +module_exit(ohci_at91_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 34ec156..b48c892 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1192,11 +1192,6 @@ MODULE_LICENSE ("GPL"); #define EP93XX_PLATFORM_DRIVER ohci_hcd_ep93xx_driver #endif
-#ifdef CONFIG_ARCH_AT91 -#include "ohci-at91.c" -#define AT91_PLATFORM_DRIVER ohci_hcd_at91_driver -#endif - #ifdef CONFIG_ARCH_LPC32XX #include "ohci-nxp.c" #define NXP_PLATFORM_DRIVER usb_hcd_nxp_driver @@ -1310,12 +1305,6 @@ static int __init ohci_hcd_mod_init(void) goto error_ep93xx; #endif
-#ifdef AT91_PLATFORM_DRIVER - retval = platform_driver_register(&AT91_PLATFORM_DRIVER); - if (retval < 0) - goto error_at91; -#endif - #ifdef NXP_PLATFORM_DRIVER retval = platform_driver_register(&NXP_PLATFORM_DRIVER); if (retval < 0) @@ -1339,10 +1328,6 @@ static int __init ohci_hcd_mod_init(void) platform_driver_unregister(&NXP_PLATFORM_DRIVER); error_nxp: #endif -#ifdef AT91_PLATFORM_DRIVER - platform_driver_unregister(&AT91_PLATFORM_DRIVER); - error_at91: -#endif #ifdef EP93XX_PLATFORM_DRIVER platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); error_ep93xx: @@ -1394,9 +1379,6 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef NXP_PLATFORM_DRIVER platform_driver_unregister(&NXP_PLATFORM_DRIVER); #endif -#ifdef AT91_PLATFORM_DRIVER - platform_driver_unregister(&AT91_PLATFORM_DRIVER); -#endif #ifdef EP93XX_PLATFORM_DRIVER platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); #endif
On Wed, 12 Jun 2013, Manjunath Goudar wrote:
Separate the TI OHCI Atmel 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; it would be nice to have in 3.11.
V2: -Set non-standard fields in ohci_at91_hc_driver manually, rather than relying on an expanded struct ohci_driver_overrides. -Save orig_ohci_hub_control and orig_ohci_hub_status_data rather than relying on ohci_hub_control and hub_status_data being exported. -ohci_setup() has been removed because it is called in .reset member of the ohci_hc_driver structure.
@@ -111,6 +125,8 @@ static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); static int usb_hcd_at91_probe(const struct hc_driver *driver, struct platform_device *pdev) {
- struct at91_usbh_data *board;
- struct ohci_hcd *ohci;
Variables are supposed to be not aligned at all (in which case you don't use tabs) or all aligned the same way. In this case you put a tab before the "*board"; therefore the "*ohci" should line up with it.
No, this isn't an artifact of my email program. They really are not aligned.
@@ -163,8 +179,11 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, goto err5; }
- board = hcd->self.controller->platform_data;
- ohci = hcd_to_ohci(hcd);
- ohci->num_ports = board->ports; at91_start_hc(pdev);
- ohci_hcd_init(hcd_to_ohci(hcd));
- ohci_setup(hcd);
Didn't you say above that this version of the patch removes the call to ohci_setup()?
@@ -686,7 +631,7 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) * REVISIT: some boards will be able to turn VBUS off... */ if (at91_suspend_entering_slow_clock()) {
ohci_usb_reset (ohci);
ohci_restart(ohci);
Why did you change this? Did we discuss it earlier?
Alan Stern
On 20 June 2013 01:46, Alan Stern stern@rowland.harvard.edu wrote:
On Wed, 12 Jun 2013, Manjunath Goudar wrote:
Separate the TI OHCI Atmel 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; it would be nice to have in 3.11.
V2: -Set non-standard fields in ohci_at91_hc_driver manually, rather than relying on an expanded struct ohci_driver_overrides. -Save orig_ohci_hub_control and orig_ohci_hub_status_data rather than relying on ohci_hub_control and hub_status_data being exported. -ohci_setup() has been removed because it is called in .reset member of the ohci_hc_driver structure.
@@ -111,6 +125,8 @@ static void usb_hcd_at91_remove (struct usb_hcd *,
struct platform_device *);
static int usb_hcd_at91_probe(const struct hc_driver *driver, struct platform_device *pdev) {
struct at91_usbh_data *board;
struct ohci_hcd *ohci;
Variables are supposed to be not aligned at all (in which case you don't use tabs) or all aligned the same way. In this case you put a tab before the "*board"; therefore the "*ohci" should line up with it.
No, this isn't an artifact of my email program. They really are not aligned.
@@ -163,8 +179,11 @@ static int usb_hcd_at91_probe(const struct
hc_driver *driver,
goto err5; }
board = hcd->self.controller->platform_data;
ohci = hcd_to_ohci(hcd);
ohci->num_ports = board->ports; at91_start_hc(pdev);
ohci_hcd_init(hcd_to_ohci(hcd));
ohci_setup(hcd);
Didn't you say above that this version of the patch removes the call to ohci_setup()?
@@ -686,7 +631,7 @@ ohci_hcd_at91_drv_suspend(struct platform_device
*pdev, pm_message_t mesg)
* REVISIT: some boards will be able to turn VBUS off... */ if (at91_suspend_entering_slow_clock()) {
ohci_usb_reset (ohci);
ohci_restart(ohci);
Why did you change this? Did we discuss it earlier?
We are not discussed regarding this,I think we need to call use ohci_resume() instead of ohci_restart().
Manjunath Goudar
Alan Stern
On Thu, 20 Jun 2013, Manjunath Goudar wrote:
@@ -686,7 +631,7 @@ ohci_hcd_at91_drv_suspend(struct platform_device
*pdev, pm_message_t mesg)
* REVISIT: some boards will be able to turn VBUS off... */ if (at91_suspend_entering_slow_clock()) {
ohci_usb_reset (ohci);
ohci_restart(ohci);
Why did you change this? Did we discuss it earlier?
We are not discussed regarding this,I think we need to call use ohci_resume() instead of ohci_restart().
Why? Don't you think the current code has a good reason for calling ohci_usb_reset()?
Alan Stern
On 20 June 2013 22:23, Alan Stern stern@rowland.harvard.edu wrote:
On Thu, 20 Jun 2013, Manjunath Goudar wrote:
@@ -686,7 +631,7 @@ ohci_hcd_at91_drv_suspend(struct platform_device
*pdev, pm_message_t mesg)
* REVISIT: some boards will be able to turn VBUS off... */ if (at91_suspend_entering_slow_clock()) {
ohci_usb_reset (ohci);
ohci_restart(ohci);
Why did you change this? Did we discuss it earlier?
We are not discussed regarding this,I think we need to call use ohci_resume() instead of ohci_restart().
Why? Don't you think the current code has a good reason for calling ohci_usb_reset()?
Here ohci_usb_reset() is static function,that is what I am planing to call ohci_setup() or ohci_restart() because it is calling ohci_usb_reset(), If not calling, we can make ohci_usb_reset() function as non-static function or use directly ohci_usb_reset() function code here.
Let me know which one is good approach.
Alan Stern
On Fri, 21 Jun 2013, Manjunath Goudar wrote:
On 20 June 2013 22:23, Alan Stern stern@rowland.harvard.edu wrote:
On Thu, 20 Jun 2013, Manjunath Goudar wrote:
@@ -686,7 +631,7 @@ ohci_hcd_at91_drv_suspend(struct platform_device
*pdev, pm_message_t mesg)
* REVISIT: some boards will be able to turn VBUS off... */ if (at91_suspend_entering_slow_clock()) {
ohci_usb_reset (ohci);
ohci_restart(ohci);
Why did you change this? Did we discuss it earlier?
We are not discussed regarding this,I think we need to call use ohci_resume() instead of ohci_restart().
Why? Don't you think the current code has a good reason for calling ohci_usb_reset()?
Here ohci_usb_reset() is static function,that is what I am planing to call ohci_setup() or ohci_restart() because it is calling ohci_usb_reset(), If not calling, we can make ohci_usb_reset() function as non-static function or use directly ohci_usb_reset() function code here.
Let me know which one is good approach.
As a general rule, you should never change code that you don't understand. Do you _know_ that it will be safe to call ohci_setup() or ohci_restart() at this point?
It might be a good idea to get in touch with the person who wrote that routine originally and ask why they used ohci_usb_reset().
Alan Stern
On 21 June 2013 22:03, Alan Stern stern@rowland.harvard.edu wrote:
On Fri, 21 Jun 2013, Manjunath Goudar wrote:
On 20 June 2013 22:23, Alan Stern stern@rowland.harvard.edu wrote:
On Thu, 20 Jun 2013, Manjunath Goudar wrote:
@@ -686,7 +631,7 @@ ohci_hcd_at91_drv_suspend(struct
platform_device
*pdev, pm_message_t mesg)
* REVISIT: some boards will be able to turn VBUS off... */ if (at91_suspend_entering_slow_clock()) {
ohci_usb_reset (ohci);
ohci_restart(ohci);
Why did you change this? Did we discuss it earlier?
We are not discussed regarding this,I think we need to call use ohci_resume() instead of ohci_restart().
Why? Don't you think the current code has a good reason for calling ohci_usb_reset()?
Here ohci_usb_reset() is static function,that is what I am planing to
call
ohci_setup() or ohci_restart() because it is calling ohci_usb_reset(), If not calling, we can make ohci_usb_reset() function as non-static function or use directly ohci_usb_reset() function code here.
Let me know which one is good approach.
As a general rule, you should never change code that you don't understand. Do you _know_ that it will be safe to call ohci_setup() or ohci_restart() at this point?
From David Brownell comment I am understanding,instead of calling
ohci_setup() or ohci_restart(),we can use directly below code.
ohci->hc_control &= OHCI_CTRL_RWC; ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); ohci->rh_state = OHCI_RH_HALTED;
the 3rd line code is written by you,I want to know what exactly it is doing. Is it required here?
It might be a good idea to get in touch with the person who wrote that routine originally and ask why they used ohci_usb_reset().
yes I will.
Hi David,
As I understood ohci_usb_reset() is calling for to notice disconnect,reconnect, or wakeup without the 48 MHz clock active. After fix power management hanging(869aa98c) issue by Patrice Vilchez,I think ohci_usb_reset() is not required to call. what is your opinion about this.
Manjunath Goudar
Alan Stern
On Sun, 23 Jun 2013, Manjunath Goudar wrote:
As a general rule, you should never change code that you don't understand. Do you _know_ that it will be safe to call ohci_setup() or ohci_restart() at this point?
From David Brownell comment I am understanding,instead of calling ohci_setup() or ohci_restart(),we can use directly below code.
ohci->hc_control &= OHCI_CTRL_RWC; ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); ohci->rh_state = OHCI_RH_HALTED;
Of course you can use that code; that's exactly what ohci_usb_reset() does now.
the 3rd line code is written by you,I want to know what exactly it is doing. Is it required here?
Yes, it is required. ohci->rh_state stores the current state of the root hub. When the controller is reset, the root hub goes into the HALTED state; this line records that fact.
It might be a good idea to get in touch with the person who wrote that routine originally and ask why they used ohci_usb_reset().
yes I will.
Hi David,
As I understood ohci_usb_reset() is calling for to notice disconnect,reconnect, or wakeup without the 48 MHz clock active. After fix power management hanging(869aa98c) issue by Patrice Vilchez,I think ohci_usb_reset() is not required to call. what is your opinion about this.
Sadly, David Brownell died in 2011. I can tell you, though, that commit 869aa98c does not eliminate the need to call ohci_usb_reset().
Alan Stern
On 23 June 2013 00:38, Alan Stern stern@rowland.harvard.edu wrote:
On Sun, 23 Jun 2013, Manjunath Goudar wrote:
As a general rule, you should never change code that you don't understand. Do you _know_ that it will be safe to call ohci_setup() or ohci_restart() at this point?
From David Brownell comment I am understanding,instead of calling ohci_setup() or ohci_restart(),we can use directly below code.
ohci->hc_control &= OHCI_CTRL_RWC; ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); ohci->rh_state = OHCI_RH_HALTED;
Of course you can use that code; that's exactly what ohci_usb_reset() does now.
OK then I will use above three line code for ohci_usb_reset() alternative.
the 3rd line code is written by you,I want to know what exactly it is doing.
Is it required here?
Yes, it is required. ohci->rh_state stores the current state of the root hub. When the controller is reset, the root hub goes into the HALTED state; this line records that fact.
Thank you for spending your valuable time, answering my doubt.
It might be a good idea to get in touch with the person who wrote that routine originally and ask why they used ohci_usb_reset().
yes I will.
Hi David,
As I understood ohci_usb_reset() is calling for to notice disconnect,reconnect, or wakeup without the 48 MHz clock active. After fix power management hanging(869aa98c) issue by Patrice Vilchez,I think ohci_usb_reset() is not required to call. what is your opinion about
this.
Sadly, David Brownell died in 2011. I can tell you, though, that commit 869aa98c does not eliminate the need to call ohci_usb_reset().
So sad :( :(
Alan Stern
Separate the Samsung OHCI S3CXXXX 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; it would be nice to have in 3.11.
V2: -Set non-standard fields in ohci_s3c2410_hc_driver manually, rather than relying on an expanded struct ohci_driver_overrides. -Save orig_ohci_hub_control and orig_ohci_hub_status_data rather than relying on ohci_hub_control and hub_status_data being exported. -ohci_setup() has been removed because it is called in .reset member of the ohci_hc_driver structure.
Signed-off-by: Manjunath Goudar manjunath.goudar@linaro.org Cc: Arnd Bergmann arnd@arndb.de Cc: Alan Stern stern@rowland.harvard.edu Cc: Greg KH greg@kroah.com Cc: linux-usb@vger.kernel.org --- drivers/usb/host/Kconfig | 8 +++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ohci-hcd.c | 18 ------ drivers/usb/host/ohci-s3c2410.c | 129 ++++++++++++++++++--------------------- 4 files changed, 67 insertions(+), 89 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index e4dc9ab..0b7b0f7 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -390,6 +390,14 @@ config USB_OHCI_HCD_SPEAR Enables support for the on-chip OHCI controller on ST SPEAr chips.
+config USB_OHCI_HCD_S3CXXXX + tristate "Support for S3CXXXX on-chip OHCI USB controller" + depends on USB_OHCI_HCD && (ARCH_S3C24XX) || (ARCH_S3C64XX) + default y + ---help--- + Enables support for the on-chip OHCI controller on + S3CXXXX chips. + config USB_OHCI_HCD_AT91 tristate "Support for Atmel on-chip OHCI USB controller" depends on USB_OHCI_HCD && ARCH_AT91 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index f3e02c0..9fa4b3e 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_USB_OHCI_HCD_OMAP1) += ohci-omap.o obj-$(CONFIG_USB_OHCI_HCD_OMAP3) += ohci-omap3.o obj-$(CONFIG_USB_OHCI_HCD_SPEAR) += ohci-spear.o obj-$(CONFIG_USB_OHCI_HCD_AT91) += ohci-at91.o +obj-$(CONFIG_USB_OHCI_HCD_S3CXXXX) += ohci-s3c2410.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index b48c892..b69a49e 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1177,11 +1177,6 @@ MODULE_LICENSE ("GPL"); #define SA1111_DRIVER ohci_hcd_sa1111_driver #endif
-#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX) -#include "ohci-s3c2410.c" -#define S3C2410_PLATFORM_DRIVER ohci_hcd_s3c2410_driver -#endif - #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) #include "ohci-pxa27x.c" #define PLATFORM_DRIVER ohci_hcd_pxa27x_driver @@ -1293,12 +1288,6 @@ static int __init ohci_hcd_mod_init(void) goto error_tmio; #endif
-#ifdef S3C2410_PLATFORM_DRIVER - retval = platform_driver_register(&S3C2410_PLATFORM_DRIVER); - if (retval < 0) - goto error_s3c2410; -#endif - #ifdef EP93XX_PLATFORM_DRIVER retval = platform_driver_register(&EP93XX_PLATFORM_DRIVER); if (retval < 0) @@ -1332,10 +1321,6 @@ static int __init ohci_hcd_mod_init(void) platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); error_ep93xx: #endif -#ifdef S3C2410_PLATFORM_DRIVER - platform_driver_unregister(&S3C2410_PLATFORM_DRIVER); - error_s3c2410: -#endif #ifdef TMIO_OHCI_DRIVER platform_driver_unregister(&TMIO_OHCI_DRIVER); error_tmio: @@ -1382,9 +1367,6 @@ static void __exit ohci_hcd_mod_exit(void) #ifdef EP93XX_PLATFORM_DRIVER platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); #endif -#ifdef S3C2410_PLATFORM_DRIVER - platform_driver_unregister(&S3C2410_PLATFORM_DRIVER); -#endif #ifdef TMIO_OHCI_DRIVER platform_driver_unregister(&TMIO_OHCI_DRIVER); #endif diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index e125770..8018bb1 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -19,17 +19,34 @@ * This file is licenced under the GPL. */
-#include <linux/platform_device.h> #include <linux/clk.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> #include <linux/platform_data/usb-ohci-s3c2410.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#include "ohci.h" +
#define valid_port(idx) ((idx) == 1 || (idx) == 2)
/* clock device associated with the hcd */
+ +#define DRIVER_DESC "OHCI S3CXXXX driver" + +static const char hcd_name[] = "ohci-s3cxxxx"; + static struct clk *clk; static struct clk *usb_clk;
+static int (*orig_ohci_hub_control)(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + u16 wIndex, char *buf, u16 wLength); +static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf); + /* forward definitions */
static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc); @@ -93,7 +110,7 @@ ohci_s3c2410_hub_status_data(struct usb_hcd *hcd, char *buf) int orig; int portno;
- orig = ohci_hub_status_data(hcd, buf); + orig = orig_ohci_hub_status_data(hcd, buf);
if (info == NULL) return orig; @@ -164,7 +181,7 @@ static int ohci_s3c2410_hub_control( * process the request straight away and exit */
if (info == NULL) { - ret = ohci_hub_control(hcd, typeReq, wValue, + ret = orig_ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); goto out; } @@ -214,7 +231,7 @@ static int ohci_s3c2410_hub_control( break; }
- ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); + ret = orig_ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); if (ret) goto out;
@@ -371,10 +388,9 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, goto err_put; }
+ ohci_setup(hcd); s3c2410_start_hc(dev, hcd);
- ohci_hcd_init(hcd_to_ohci(hcd)); - retval = usb_add_hcd(hcd, dev->resource[1].start, 0); if (retval != 0) goto err_ioremap; @@ -391,71 +407,7 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
/*-------------------------------------------------------------------------*/
-static int -ohci_s3c2410_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) { - dev_err(hcd->self.controller, "can't start %s\n", - hcd->self.bus_name); - ohci_stop(hcd); - return ret; - } - - return 0; -} - - -static const struct hc_driver ohci_s3c2410_hc_driver = { - .description = hcd_name, - .product_desc = "S3C24XX OHCI", - .hcd_priv_size = sizeof(struct ohci_hcd), - - /* - * generic hardware linkage - */ - .irq = ohci_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .start = ohci_s3c2410_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_s3c2410_hub_status_data, - .hub_control = ohci_s3c2410_hub_control, -#ifdef CONFIG_PM - .bus_suspend = ohci_bus_suspend, - .bus_resume = ohci_bus_resume, -#endif - .start_port_reset = ohci_start_port_reset, -}; - -/* device driver */ +static struct hc_driver __read_mostly ohci_s3c2410_hc_driver;
static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev) { @@ -532,4 +484,39 @@ static struct platform_driver ohci_hcd_s3c2410_driver = { }, };
+static int __init ohci_s3cxxxx_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + ohci_init_driver(&ohci_s3c2410_hc_driver, NULL); + + /* + * The Samsung HW has some unusual quirks, which require Sumsung-specific + * workarounds. We override certain hc_driver functions here to + * achieve that. We explicitly do not enhance ohci_driver_overrides to + * allow this more easily, since this is an unusual case, and we don't + * want to encourage others to override these functions by making it + * too easy. + */ + + orig_ohci_hub_control = ohci_s3c2410_hc_driver.hub_control; + orig_ohci_hub_status_data = ohci_s3c2410_hc_driver.hub_status_data; + + ohci_s3c2410_hc_driver.hub_status_data = ohci_s3c2410_hub_status_data; + ohci_s3c2410_hc_driver.hub_control = ohci_s3c2410_hub_control; + + return platform_driver_register(&ohci_hcd_s3c2410_driver); +} +module_init(ohci_s3cxxxx_init); + +static void __exit ohci_s3cxxxx_cleanup(void) +{ + platform_driver_unregister(&ohci_hcd_s3c2410_driver); +} +module_exit(ohci_s3cxxxx_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:s3c2410-ohci");
On Wed, 12 Jun 2013, Manjunath Goudar wrote:
Separate the Samsung OHCI S3CXXXX 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; it would be nice to have in 3.11.
V2: -Set non-standard fields in ohci_s3c2410_hc_driver manually, rather than relying on an expanded struct ohci_driver_overrides. -Save orig_ohci_hub_control and orig_ohci_hub_status_data rather than relying on ohci_hub_control and hub_status_data being exported. -ohci_setup() has been removed because it is called in .reset member of the ohci_hc_driver structure.
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index e4dc9ab..0b7b0f7 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -390,6 +390,14 @@ config USB_OHCI_HCD_SPEAR Enables support for the on-chip OHCI controller on ST SPEAr chips. +config USB_OHCI_HCD_S3CXXXX
tristate "Support for S3CXXXX on-chip OHCI USB controller"
depends on USB_OHCI_HCD && (ARCH_S3C24XX) || (ARCH_S3C64XX)
The use of parentheses here is wrong.
+static int (*orig_ohci_hub_control)(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16 wIndex, char *buf, u16 wLength);
Avoid having more than 80 columns in a line.
@@ -371,10 +388,9 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, goto err_put; }
- ohci_setup(hcd); s3c2410_start_hc(dev, hcd);
I thought this patch was supposed to get rid of the call to ohci_setup()?
Alan Stern
HI Alan,
Can you review this patch series.
Thanks Manjunath Goudar
On 12 June 2013 21:23, Manjunath Goudar manjunath.goudar@linaro.org wrote:
These patches are for separating the SOC On-Chip ohci host controller from ohci-hcd host code into its own driver module. This work is part of enabling multi-platform kernels on ARM.
V2: In patch 5/6 and 6/6: -Set non-standard fields in hc_driver manually, rather than relying on an expanded struct ohci_driver_overrides. -Save orig_ohci_hub_control and orig_ohci_hub_status_data rather than relying on ohci_hub_control and hub_status_data being exported. -ohci_setup() has been removed because it is called in .reset member of the ohci_hc_driver structure.
In patch 1/6 to 4/6 -ohci_setup() has been removed because it is called in .reset member of the ohci_hc_driver structure.
Manjunath Goudar (6): USB: OHCI: make ohci-exynos a separate driver USB: OHCI: make ohci-omap a separate driver USB: OHCI: make ohci-omap3 a separate driver USB: OHCI: make ohci-spear a separate driver USB: OHCI: make ohci-at91 a separate driver USB: OHCI: make ohci-s3c2410 a separate driver
drivers/usb/host/Kconfig | 30 ++++++- drivers/usb/host/Makefile | 6 ++ drivers/usb/host/ohci-at91.c | 148 +++++++++++++++------------------- drivers/usb/host/ohci-exynos.c | 167 ++++++++++++++++----------------------- drivers/usb/host/ohci-hcd.c | 108 ------------------------- drivers/usb/host/ohci-omap.c | 156 ++++++++++++------------------------ drivers/usb/host/ohci-omap3.c | 120 ++++++++++------------------ drivers/usb/host/ohci-s3c2410.c | 129 ++++++++++++++---------------- drivers/usb/host/ohci-spear.c | 140 +++++++++++++------------------- 9 files changed, 370 insertions(+), 634 deletions(-)
-- 1.7.9.5