[RFC/PATCH] usb: host: xhci: add support for XHCI on SoCs

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

 



SoCs will generally use the platform bus type,
in order to simplify re-use of xHCI driver by
SoCs, we introduce a generic file which is to
be re-used by anyone with an xHCI using the
platform bus_type.

Also avoid always compiling xhci-pci.c, not
all architectures have PCI.

Signed-off-by: Felipe Balbi <balbi@xxxxxx>
---
 drivers/usb/host/Kconfig         |    4 +
 drivers/usb/host/Makefile        |    5 +-
 drivers/usb/host/xhci-platform.c |  234 ++++++++++++++++++++++++++++++++++++++
 drivers/usb/host/xhci.c          |   14 ++-
 drivers/usb/host/xhci.h          |    6 +
 5 files changed, 261 insertions(+), 2 deletions(-)
 create mode 100644 drivers/usb/host/xhci-platform.c

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index ab085f1..f91619a 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -27,6 +27,10 @@ config USB_XHCI_HCD
 	  To compile this driver as a module, choose M here: the
 	  module will be called xhci-hcd.
 
+config USB_XHCI_PLATFORM
+	bool
+	depends on USB_XHCI_HCD
+
 config USB_XHCI_HCD_DEBUGGING
 	bool "Debugging for the xHCI host controller"
 	depends on USB_XHCI_HCD
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 624a362..fd4f2ab 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -11,9 +11,12 @@ fhci-y += fhci-mem.o fhci-tds.o fhci-sched.o
 
 fhci-$(CONFIG_FHCI_DEBUG) += fhci-dbg.o
 
-xhci-hcd-y := xhci.o xhci-mem.o xhci-pci.o
+xhci-hcd-y := xhci.o xhci-mem.o
 xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o
 
+xhci-hcd-$(CONFIG_PCI)		+= xhci-pci.o
+xhci-hcd-$(CONFIG_USB_XHCI_PLATFORM) += xhci-platform.o
+
 obj-$(CONFIG_USB_WHCI_HCD)	+= whci/
 
 obj-$(CONFIG_PCI)		+= pci-quirks.o
diff --git a/drivers/usb/host/xhci-platform.c b/drivers/usb/host/xhci-platform.c
new file mode 100644
index 0000000..7a6e7f8
--- /dev/null
+++ b/drivers/usb/host/xhci-platform.c
@@ -0,0 +1,234 @@
+/**
+ * xhci-platform.c - XHCI Platform Driver Glue
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Authors: Felipe Balbi <balbi@xxxxxx>,
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The names of the above-listed copyright holders may not be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2, as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/usb.h>
+
+#include <linux/usb/hcd.h>
+
+#include "xhci.h"
+
+static const char hcd_name[] = "xhci_hcd";
+
+static int xhci_platform_setup(struct usb_hcd *hcd)
+{
+	return 0;
+}
+
+static const struct hc_driver xhci_platform_hc_driver= {
+	.description		= hcd_name,
+	.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_platform_setup,
+	.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 __devinit xhci_platform_probe(struct platform_device *pdev)
+{
+	const struct hc_driver	*driver = &xhci_platform_hc_driver;
+	struct xhci_hcd		*xhci;
+	struct usb_hcd		*hcd;
+	struct resource		*res;
+	int			ret;
+	int			irq;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_err(&pdev->dev, "found HC with no IRQ\n");
+		ret = -ENODEV;
+		goto err0;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "missing memory address\n");
+		ret = -ENXIO;
+		goto err0;
+	}
+
+	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+	if (!hcd) {
+		dev_err(&pdev->dev, "can't create HCD\n");
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+	platform_set_drvdata(pdev, hcd);
+
+	res = request_mem_region(res->start, resource_size(res),
+			driver->description);
+	if (!res) {
+		dev_err(&pdev->dev, "controller in use\n");
+		ret = -EBUSY;
+		goto err1;
+	}
+
+	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		dev_err(&pdev->dev, "failed mapping memory\n");
+		ret = -EFAULT;
+		goto err2;
+	}
+
+	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (ret) {
+		dev_err(&pdev->dev, "failed adding HCD\n");
+		goto err3;
+	}
+
+	xhci = hcd_to_xhci(hcd);
+	xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev,
+			dev_name(&pdev->dev), hcd);
+	if (!xhci->shared_hcd) {
+		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 adding 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(res->start, resource_size(res));
+
+err1:
+	usb_put_hcd(hcd);
+
+err0:
+	return ret;
+}
+
+static int __devexit xhci_platform_remove(struct platform_device *pdev)
+{
+	struct usb_hcd		*hcd = platform_get_drvdata(pdev);
+	struct xhci_hcd		*xhci = hcd_to_xhci(hcd);
+
+	usb_remove_hcd(xhci->shared_hcd);
+	usb_put_hcd(xhci->shared_hcd);
+
+	usb_remove_hcd(hcd);
+
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+static struct platform_driver xhci_platform_driver = {
+	.probe		= xhci_platform_probe,
+	.remove		= __devexit_p(xhci_platform_remove),
+	.driver		= {
+		.name	= "xhci",
+	},
+};
+
+MODULE_AUTHOR("Felipe Balbi <balbi@xxxxxx>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("XHCI Platform Glue Driver");
+
+int __init xhci_register_platform(void)
+{
+	return platform_driver_register(&xhci_platform_driver);
+}
+
+void __exit xhci_unregister_platform(void)
+{
+	platform_driver_unregister(&xhci_platform_driver);
+}
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index f647d91..ae1c4d4 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3057,9 +3057,9 @@ MODULE_LICENSE("GPL");
 
 static int __init xhci_hcd_init(void)
 {
-#ifdef CONFIG_PCI
 	int retval = 0;
 
+#ifdef CONFIG_PCI
 	retval = xhci_register_pci();
 
 	if (retval < 0) {
@@ -3067,6 +3067,14 @@ static int __init xhci_hcd_init(void)
 		return retval;
 	}
 #endif
+
+#ifdef CONFIG_USB_XHCI_PLATFORM
+	retval = xhci_register_platform();
+	if (retval) {
+		printk(KERN_DEBUG "Problem registering Platform driver.\n");
+		return retval;
+	}
+#endif
 	/*
 	 * Check the compiler generated sizes of structures that must be laid
 	 * out in specific ways for hardware access.
@@ -3094,5 +3102,9 @@ static void __exit xhci_hcd_cleanup(void)
 #ifdef CONFIG_PCI
 	xhci_unregister_pci();
 #endif
+
+#ifdef CONFIG_USB_XHCI_PLATFORM
+	xhci_unregister_platform();
+#endif
 }
 module_exit(xhci_hcd_cleanup);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index cae8e23..78637ce 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1485,6 +1485,12 @@ int xhci_register_pci(void);
 void xhci_unregister_pci(void);
 #endif
 
+#ifdef CONFIG_USB_XHCI_PLATFORM
+/* xHCI Platform glue */
+int xhci_register_platform(void);
+void xhci_unregister_platform(void);
+#endif
+
 /* xHCI host controller glue */
 void xhci_quiesce(struct xhci_hcd *xhci);
 int xhci_halt(struct xhci_hcd *xhci);
-- 
1.7.6.396.ge0613

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