On Thu, 17 Jan 2013, Roger Quadros wrote: > Alan, > > What tree is your patch based off? Roughly speaking, 3.7 plus Greg KH's usb-next branch as of the 3.7 release. This should be pretty much the same as 3.8-rc1 as far as the USB stack is concerned. I haven't tried applying the patch to 3.8-rc3, but any merge problems should be minimal. > Also, could you please send me your > updated patch for ehci-omap.c? I'll then base my work on top of that. Attached are two patches: one to convert ehci-omap to the new library scheme (based on the stuff I just sent Felipe), and a second (based on the first) to illustrate how to allocate additional private space for the PHY values. Thanks to your latest set of changes, you may not need to use the second patch. Alan Stern
drivers/usb/host/Kconfig | 2 - drivers/usb/host/Makefile | 1 drivers/usb/host/ehci-hcd.c | 6 --- drivers/usb/host/ehci-omap.c | 76 +++++++++++++++++++------------------------ 4 files changed, 37 insertions(+), 48 deletions(-) Index: usb-3.7/drivers/usb/host/Kconfig =================================================================== --- usb-3.7.orig/drivers/usb/host/Kconfig +++ usb-3.7/drivers/usb/host/Kconfig @@ -155,7 +155,7 @@ config USB_EHCI_MXC Variation of ARC USB block used in some Freescale chips. config USB_EHCI_HCD_OMAP - bool "EHCI support for OMAP3 and later chips" + tristate "EHCI support for OMAP3 and later chips" depends on USB_EHCI_HCD && ARCH_OMAP default y ---help--- Index: usb-3.7/drivers/usb/host/Makefile =================================================================== --- usb-3.7.orig/drivers/usb/host/Makefile +++ usb-3.7/drivers/usb/host/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o +obj-$(CONFIG_USB_EHCI_HCD_OMAP) += ehci-omap.o obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o Index: usb-3.7/drivers/usb/host/ehci-hcd.c =================================================================== --- usb-3.7.orig/drivers/usb/host/ehci-hcd.c +++ usb-3.7/drivers/usb/host/ehci-hcd.c @@ -1255,11 +1255,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_hcd_sh_driver #endif -#ifdef CONFIG_USB_EHCI_HCD_OMAP -#include "ehci-omap.c" -#define PLATFORM_DRIVER ehci_hcd_omap_driver -#endif - #ifdef CONFIG_PPC_PS3 #include "ehci-ps3.c" #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver @@ -1349,6 +1344,7 @@ MODULE_LICENSE ("GPL"); !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \ !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \ + !IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \ !defined(PLATFORM_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && \ !defined(OF_PLATFORM_DRIVER) && \ Index: usb-3.7/drivers/usb/host/ehci-omap.c =================================================================== --- usb-3.7.orig/drivers/usb/host/ehci-omap.c +++ usb-3.7/drivers/usb/host/ehci-omap.c @@ -36,6 +36,9 @@ * - convert to use hwmod and runtime PM */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/io.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/usb/ulpi.h> @@ -44,6 +47,10 @@ #include <linux/pm_runtime.h> #include <linux/gpio.h> #include <linux/clk.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#include "ehci.h" /* EHCI Register Set */ #define EHCI_INSNREG04 (0xA0) @@ -56,9 +63,11 @@ #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 -/*-------------------------------------------------------------------------*/ +#define DRIVER_DESC "OMAP-EHCI Host Controller driver" -static const struct hc_driver ehci_omap_hc_driver; +static const char hcd_name[] = "ehci-omap"; + +/*-------------------------------------------------------------------------*/ static inline void ehci_write(void __iomem *base, u32 reg, u32 val) @@ -165,6 +174,12 @@ static void disable_put_regulator( /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ +static struct hc_driver __read_mostly ehci_omap_hc_driver; + +static const struct ehci_driver_overrides ehci_omap_overrides __initdata = { + .reset = omap_ehci_init, +}; + /** * ehci_hcd_omap_probe - initialize TI-based HCDs * @@ -322,56 +337,33 @@ static struct platform_driver ehci_hcd_o /*.suspend = ehci_hcd_omap_suspend, */ /*.resume = ehci_hcd_omap_resume, */ .driver = { - .name = "ehci-omap", + .name = hcd_name, } }; /*-------------------------------------------------------------------------*/ -static const struct hc_driver ehci_omap_hc_driver = { - .description = hcd_name, - .product_desc = "OMAP-EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - /* - * basic lifecycle operations - */ - .reset = omap_ehci_init, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, +static int __init ehci_omap_init(void) +{ + if (usb_disabled()) + return -ENODEV; - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, + pr_info("%s: " DRIVER_DESC "\n", hcd_name); - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, + ehci_init_driver(&ehci_omap_hc_driver, &ehci_omap_overrides); + return platform_driver_register(&ehci_hcd_omap_driver); +} +module_init(ehci_omap_init); - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; +static void __exit ehci_omap_cleanup(void) +{ + platform_driver_unregister(&ehci_hcd_omap_driver); +} +module_exit(ehci_omap_cleanup); MODULE_ALIAS("platform:omap-ehci"); MODULE_AUTHOR("Texas Instruments, Inc."); MODULE_AUTHOR("Felipe Balbi <felipe.balbi@xxxxxxxxx>"); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 6388aa6..23c9b9c 100644 drivers/usb/host/ehci-omap.c | 84 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 4 deletions(-) Index: usb-3.7/drivers/usb/host/ehci-omap.c =================================================================== --- usb-3.7.orig/drivers/usb/host/ehci-omap.c +++ usb-3.7/drivers/usb/host/ehci-omap.c @@ -69,6 +69,10 @@ static const char hcd_name[] = "ehci-oma /*-------------------------------------------------------------------------*/ +struct omap_ehci_hcd { + struct usb_phy **phy; /* one PHY for each port */ + int nports; +}; static inline void ehci_write(void __iomem *base, u32 reg, u32 val) { @@ -178,6 +182,7 @@ static struct hc_driver __read_mostly eh static const struct ehci_driver_overrides ehci_omap_overrides __initdata = { .reset = omap_ehci_init, + .extra_priv_size = sizeof(struct omap_ehci_hcd), }; /** @@ -193,6 +198,8 @@ static int ehci_hcd_omap_probe(struct pl struct ehci_hcd_omap_platform_data *pdata = dev->platform_data; struct resource *res; struct usb_hcd *hcd; + struct omap_ehci_hcd *omap_hcd; + struct usb_phy *phy; void __iomem *regs; int ret = -ENODEV; int irq; @@ -207,6 +214,11 @@ static int ehci_hcd_omap_probe(struct pl return -ENODEV; } + if (!pdata) { + dev_err(dev, "Missing platform data\n"); + return -ENODEV; + } + irq = platform_get_irq_byname(pdev, "ehci-irq"); if (irq < 0) { dev_err(dev, "EHCI irq failed\n"); @@ -238,8 +250,24 @@ static int ehci_hcd_omap_probe(struct pl hcd->rsrc_len = resource_size(res); hcd->regs = regs; + omap_hcd = (struct omap_ehci_hcd *) (hcd_to_ehci(hcd))->priv; + + omap_hcd->nports = pdata->nports; + i = sizeof(struct usb_phy *) * omap_hcd->nports; + omap_hcd->phy = devm_kzalloc(&pdev->dev, i, GFP_KERNEL); + if (!omap_hcd->phy) { + dev_err(dev, "Memory allocation failed\n"); + ret = -ENOMEM; + goto err_alloc_phy; + } + + platform_set_drvdata(pdev, hcd); + /* get ehci regulator and enable */ - for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { + for (i = 0 ; i < omap_hcd->nports ; i++) { + struct platform_device *phy_pdev; + struct usbhs_phy_config *phy_config; + if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) { pdata->regulator[i] = NULL; continue; @@ -253,6 +281,33 @@ static int ehci_hcd_omap_probe(struct pl } else { regulator_enable(pdata->regulator[i]); } + + /* instantiate PHY */ + if (!pdata->phy_config[i]) { + dev_dbg(dev, "missing phy_config for port %d\n", i); + continue; + } + + phy_config = pdata->phy_config[i]; + phy_pdev = platform_device_register_data(&pdev->dev, + phy_config->name, i, phy_config->pdata, + phy_config->pdata_size); + if (IS_ERR(phy_pdev)) { + dev_dbg(dev, "error creating PHY device for port %d\n", + i); + } + + phy = usb_get_phy_from_dev(&phy_pdev->dev); + if (IS_ERR(phy)) { + dev_dbg(dev, "could not get USB PHY for port %d\n", i); + platform_device_unregister(phy_pdev); + continue; + } + + usb_phy_init(phy); + omap_hcd->phy[i] = phy; + /* bring PHY out of suspend */ + usb_phy_set_suspend(omap_hcd->phy[i], 0); } pm_runtime_enable(dev); @@ -282,6 +337,14 @@ static int ehci_hcd_omap_probe(struct pl err_pm_runtime: disable_put_regulator(pdata); pm_runtime_put_sync(dev); + for (i = 0 ; i < omap_hcd->nports ; i++) { + phy = omap_hcd->phy[i]; + if (!phy) + continue; + platform_device_unregister(to_platform_device(phy->dev)); + } + +err_alloc_phy: usb_put_hcd(hcd); err_io: @@ -300,13 +363,26 @@ err_io: */ static int ehci_hcd_omap_remove(struct platform_device *pdev) { - struct device *dev = &pdev->dev; - struct usb_hcd *hcd = dev_get_drvdata(dev); - struct ehci_hcd_omap_platform_data *pdata = dev->platform_data; + struct device *dev = &pdev->dev; + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct omap_ehci_hcd *omap_hcd; + int i; usb_remove_hcd(hcd); disable_put_regulator(dev->platform_data); iounmap(hcd->regs); + + omap_hcd = (struct omap_ehci_hcd *) (hcd_to_ehci(hcd))->priv; + for (i = 0; i < omap_hcd->nports; i++) { + struct usb_phy *phy = omap_hcd->phy[i]; + + if (!phy) + continue; + + usb_phy_shutdown(phy); + platform_device_unregister(to_platform_device(phy->dev)); + } + usb_put_hcd(hcd); pm_runtime_put_sync(dev);