[RFC/PATCH 2/2] usb: host: xhci: give xhci a platform_device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



NOT FOR MERGING!!!

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.

NYET-Signed-off-by: Felipe Balbi <balbi@xxxxxx>
---
 drivers/usb/host/xhci.c |  179 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 178 insertions(+), 1 deletions(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 06e7023..fe06de1 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"
 
@@ -175,6 +176,13 @@ int xhci_reset(struct xhci_hcd *xhci)
 	return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
 }
 
+static int xhci_hcd_reset(struct usb_hcd *hcd)
+{
+	struct xhci_hcd		*xhci = hcd_to_xhci(hcd);
+
+	return xhci_reset(xhci);
+}
+
 /*
  * Free IRQs
  * free all IRQs request
@@ -2997,6 +3005,173 @@ MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_LICENSE("GPL");
 
+static const struct hc_driver xhci_hc_driver = {
+	.description		= "xhci-hcd",
+	.product_desc		= "xHCI Host Controller",
+	.hcd_priv_size		= sizeof(struct xhci_hcd *),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq			= xhci_irq,
+	.flags			= HCD_MEMORY | HCD_USB3 | HCD_SHARED,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset			= xhci_hcd_reset,
+	.start			= xhci_run,
+	.stop			= xhci_stop,
+	.shutdown		= xhci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue		= xhci_urb_enqueue,
+	.urb_dequeue		= xhci_urb_dequeue,
+	.alloc_dev		= xhci_alloc_dev,
+	.free_dev		= xhci_free_dev,
+	.alloc_streams		= xhci_alloc_streams,
+	.free_streams		= xhci_free_streams,
+	.add_endpoint		= xhci_add_endpoint,
+	.drop_endpoint		= xhci_drop_endpoint,
+	.endpoint_reset		= xhci_endpoint_reset,
+	.check_bandwidth	= xhci_check_bandwidth,
+	.reset_bandwidth	= xhci_reset_bandwidth,
+	.address_device		= xhci_address_device,
+	.update_hub_device	= xhci_update_hub_device,
+	.reset_device		= xhci_discover_or_reset_device,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number	= xhci_get_frame,
+
+	/* Root hub support */
+	.hub_control		= xhci_hub_control,
+	.hub_status_data	= xhci_hub_status_data,
+	.bus_suspend		= xhci_bus_suspend,
+	.bus_resume		= xhci_bus_resume,
+};
+
+static int xhci_probe(struct platform_device *pdev)
+{
+	struct usb_hcd		*hcd;
+	struct xhci_hcd		*xhci;
+	struct resource		*res;
+
+	int			irq;
+	int			ret;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	irq = platform_get_irq(pdev, 0);
+	if (!irq) {
+		dev_err(&pdev->dev, "No IRQ found\n");
+		ret = -ENODEV;
+		goto err0;
+	}
+
+	hcd = usb_create_hcd(&xhci_hc_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 = -ENOMEM;
+		goto err1;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
+				xhci_hc_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 = -EFAULT;
+		goto err2;
+	}
+
+	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "failed to add XHCI HCD\n");
+		goto err3;
+	}
+
+	xhci = hcd_to_xhci(hcd);
+	xhci->shared_hcd = usb_create_shared_hcd(&xhci_hc_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
@@ -3027,7 +3202,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);
 
@@ -3036,5 +3212,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.rc1

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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux