it will make it simpler to re-use the stack if it's not tied to a particular bus. Later patches should come to phase PCI bus to a separate piece of code which doesn't touch xhci.c. Signed-off-by: Felipe Balbi <balbi@xxxxxx> --- drivers/usb/host/xhci.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 125 insertions(+), 1 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index f5fe1ac..d6c9577 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -26,6 +26,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/slab.h> +#include <linux/platform_device.h> #include "xhci.h" @@ -3028,6 +3029,127 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_LICENSE("GPL"); +static int xhci_probe(struct platform_device *pdev) +{ + struct xhci_platform_data *data; + struct usb_hcd *hcd; + struct xhci_hcd *xhci; + struct resource *res; + + int irq; + int ret; + + if (usb_disabled()) + return -ENODEV; + + data = pdev->dev.platform_data; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "No IRQ found\n"); + ret = irq; + goto err0; + } + + hcd = usb_create_hcd(data->driver, &pdev->dev, dev_name(&pdev->dev)); + if (!hcd) { + ret = -ENOMEM; + goto err0; + } + + platform_set_drvdata(pdev, hcd); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "missing memory resource\n"); + ret = -ENODEV; + goto err1; + } + + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, + data->driver->description)) { + dev_err(&pdev->dev, "controller already in use\n"); + ret = -EBUSY; + goto err1; + } + + hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + dev_err(&pdev->dev, "error mapping memory\n"); + ret = -ENOMEM; + goto err2; + } + + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (ret) { + dev_err(&pdev->dev, "failed to add XHCI HCD\n"); + goto err3; + } + + xhci = hcd_to_xhci(hcd); + xhci->shared_hcd = usb_create_shared_hcd(data->driver, &pdev->dev, + dev_name(&pdev->dev), hcd); + if (!xhci->shared_hcd) { + dev_err(&pdev->dev, "failed to create shared HCD\n"); + ret = -ENOMEM; + goto err4; + } + + *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; + + ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); + if (ret) { + dev_err(&pdev->dev, "failed to add shared HCD\n"); + goto err5; + } + + return 0; + +err5: + usb_put_hcd(xhci->shared_hcd); + +err4: + usb_remove_hcd(hcd); + +err3: + iounmap(hcd->regs); + +err2: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + +err1: + usb_put_hcd(hcd); + +err0: + return ret; +} + +static int __devexit xhci_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_remove_hcd(hcd); + usb_put_hcd(hcd); + usb_remove_hcd(xhci->shared_hcd); + usb_put_hcd(xhci->shared_hcd); + + return 0; +} + +static struct platform_driver xhci_driver = { + .probe = xhci_probe, + .remove = __devexit_p(xhci_remove), + .driver = { + .name = "xhci", + }, +}; + static int __init xhci_hcd_init(void) { #ifdef CONFIG_PCI @@ -3058,7 +3180,8 @@ static int __init xhci_hcd_init(void) /* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */ BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8); BUILD_BUG_ON(sizeof(struct xhci_doorbell_array) != 256*32/8); - return 0; + + return platform_driver_register(&xhci_driver); } module_init(xhci_hcd_init); @@ -3067,5 +3190,6 @@ static void __exit xhci_hcd_cleanup(void) #ifdef CONFIG_PCI xhci_unregister_pci(); #endif + platform_driver_unregister(&xhci_driver); } module_exit(xhci_hcd_cleanup); -- 1.7.6 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html