📄 usb_host.patch
字号:
+/**+ * usb_ehci_au1xxx_probe - initialize Au1xxx-based HCDs+ * Context: !in_interrupt()+ *+ * Allocates basic resources for this USB host controller, and+ * then invokes the start() method for the HCD associated with it+ * through the hotplug entry's driver_data.+ *+ */+int usb_ehci_au1xxx_probe (const struct hc_driver *driver,+ struct usb_hcd **hcd_out,+ struct platform_device *dev)+{+ int retval;+ struct usb_hcd *hcd = 0;++ unsigned int *addr = NULL;++#if defined(CONFIG_SOC_AU1200) && ( \+ defined(CONFIG_DMA_COHERENT) || defined(CONFIG_CPU_HAS_LLSC))++ /* Au1200 AB USB does not support coherent memory */+ if (!(read_c0_prid() & 0xff)) {+ pr_info("Au1200 ehci: !!! This is chip revision AB !!!\n");+ pr_info(" !!! update your board or re-configure the kernel !!!\n");+ return -ENODEV;+ }+#endif+ if (!request_mem_region(dev->resource[0].start,+ dev->resource[0].end + 1+ - dev->resource[0].start, hcd_name)) {+ pr_debug("request_mem_region failed\n");+ return -EBUSY;+ }+ + au1xxx_start_ehc(dev);+ + addr = ioremap(dev->resource[0].start,+ dev->resource[0].end + 1+ - dev->resource[0].start);+ if (!addr) {+ pr_debug("ioremap failed\n");+ retval = -ENOMEM;+ goto err1;+ }++ if(dev->resource[1].flags != IORESOURCE_IRQ) {+ pr_debug ("resource[1] is not IORESOURCE_IRQ\n");+ retval = -ENOMEM;+ goto err1;+ }++ hcd = usb_create_hcd(driver);+ if (hcd == NULL) {+ pr_debug ("usb_create_hcd failed\n");+ retval = -ENOMEM;+ goto err1;+ }++ hcd->irq = dev->resource[1].start;+ hcd->regs = addr;+ hcd->self.controller = &dev->dev;++ retval = hcd_buffer_create (hcd);+ if (retval != 0) {+ pr_debug ("pool alloc fail\n");+ goto err2;+ }++ if ((retval = driver->reset (hcd)) < 0) {+ pr_debug ("can't reset hc\n");+ goto err2;+ }++ retval = request_irq (hcd->irq, usb_ehci_au1xxx_hcim_irq,+ SA_SHIRQ | SA_INTERRUPT,+ hcd->driver->description, hcd);+ if (retval != 0) {+ pr_debug("request_irq failed\n");+ retval = -EBUSY;+ goto err3;+ }++ pr_info ("%s (Au1xxx) at 0x%p, irq %d\n",+ hcd->driver->description, hcd->regs, hcd->irq);++ hcd->self.bus_name = "au1xxx";++ usb_register_bus (&hcd->self);++#ifdef CONFIG_USB_OTG_HIGHSPEED+ if ((retval = driver->start_otg (hcd)) < 0)+ pr_info ("OTG init failed\n");+#endif+ if ((retval = driver->start (hcd)) < 0)+ {+ usb_ehci_au1xxx_remove(hcd, dev);+ pr_info ("bad driver->start\n");+ return retval;+ }++ *hcd_out = hcd;+ return 0;++ err3:+ hcd_buffer_destroy (hcd);+ err2:+ usb_put_hcd(hcd);+ err1:+ au1xxx_stop_ehc(dev);+ release_mem_region(dev->resource[0].start,+ dev->resource[0].end + 1+ - dev->resource[0].start);+ return retval;+}+++/* may be called without controller electrically present */+/* may be called with controller, bus, and devices active */++/**+ * usb_ehci_hcd_au1xxx_remove - shutdown processing for Au1xxx-based HCDs+ * @dev: USB Host Controller being removed+ * Context: !in_interrupt()+ *+ * Reverses the effect of usb_ehci_hcd_au1xxx_probe(), first invoking+ * the HCD's stop() method. It is always called from a thread+ * context, normally "rmmod", "apmd", or something similar.+ *+ */+void usb_ehci_au1xxx_remove (struct usb_hcd *hcd, struct platform_device *dev)+{+ pr_info ("remove: %s, state %x\n", hcd->self.bus_name, hcd->state);++ if (in_interrupt ())+ BUG ();++ if (HCD_IS_RUNNING (hcd->state))+ hcd->state = USB_STATE_QUIESCING;++ pr_debug ("%s: roothub graceful disconnect\n", hcd->self.bus_name);+ usb_disconnect (&hcd->self.root_hub);++ hcd->driver->stop (hcd);+#ifdef CONFIG_USB_OTG_HIGHSPEED+ hcd->driver->stop_otg (hcd);+#endif+ hcd_buffer_destroy (hcd);+ hcd->state = USB_STATE_HALT;++ free_irq (hcd->irq, hcd);+ iounmap (hcd->regs);+ release_mem_region(dev->resource[0].start,+ dev->resource[0].end + 1+ - dev->resource[0].start);++ usb_deregister_bus (&hcd->self);++ au1xxx_stop_ehc(dev);+}++/*-------------------------------------------------------------------------*/++static const struct hc_driver ehci_au1xxx_hc_driver = {+ .description = hcd_name,+ .product_desc = "Au1xxx EHCI",+ .hcd_priv_size = sizeof(struct ehci_hcd),++ /*+ * generic hardware linkage+ */+ .irq = ehci_irq,+ .flags = HCD_MEMORY | HCD_USB2,++ /*+ * basic lifecycle operations+ */+ .reset = ehci_hc_reset,+ .start = ehci_start,+#ifdef CONFIG_PM+ /* suspend: ehci_au1xxx_suspend, -- tbd */+ /* resume: ehci_au1xxx_resume, -- tbd */+#endif /*CONFIG_PM*/+ .stop = ehci_stop,++ /*+ * managing i/o requests and associated device resources+ */+ .urb_enqueue = ehci_urb_enqueue,+ .urb_dequeue = ehci_urb_dequeue,+ .endpoint_disable = ehci_endpoint_disable,++ /*+ * scheduling support+ */+ .get_frame_number = ehci_get_frame,++ /*+ * root hub support+ */+ .hub_status_data = ehci_hub_status_data,+ .hub_control = ehci_hub_control,+#ifdef CONFIG_USB_SUSPEND+ .hub_suspend = ehci_hub_suspend,+ .hub_resume = ehci_hub_resume,+#endif+ .start_port_reset = ehci_start_port_reset,+#ifdef CONFIG_USB_OTG_HIGHSPEED+ .start_otg = ehci_start_otg,+ .stop_otg = ehci_stop_otg,+#endif+};++/*-------------------------------------------------------------------------*/++static int ehci_hcd_au1xxx_drv_probe(struct device *dev)+{+ struct platform_device *pdev = to_platform_device(dev);+ struct usb_hcd *hcd = NULL;+ int ret;++ pr_debug ("In ehci_hcd_au1xxx_drv_probe\n");++ if (usb_disabled())+ return -ENODEV;++ ret = usb_ehci_au1xxx_probe(&ehci_au1xxx_hc_driver, &hcd, pdev);++ if (ret == 0)+ dev_set_drvdata(dev, hcd);++ return ret;+}++static int ehci_hcd_au1xxx_drv_remove(struct device *dev)+{+ struct platform_device *pdev = to_platform_device(dev);+ struct usb_hcd *hcd = dev_get_drvdata(dev);++ usb_ehci_au1xxx_remove(hcd, pdev);+ dev_set_drvdata(dev, NULL);+ return 0;+}+ /*TBD*/+/*static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)+{+ struct platform_device *pdev = to_platform_device(dev);+ struct usb_hcd *hcd = dev_get_drvdata(dev);++ return 0;+}+static int ehci_hcd_au1xxx_drv_resume(struct device *dev)+{+ struct platform_device *pdev = to_platform_device(dev);+ struct usb_hcd *hcd = dev_get_drvdata(dev);++ return 0;+}+*/++static struct device_driver ehci_hcd_au1xxx_driver = {+ .name = "au1xxx-ehci",+ .bus = &platform_bus_type,+ .probe = ehci_hcd_au1xxx_drv_probe,+ .remove = ehci_hcd_au1xxx_drv_remove,+ /*.suspend = ehci_hcd_au1xxx_drv_suspend, */+ /*.resume = ehci_hcd_au1xxx_drv_resume, */+};++static int __init ehci_hcd_au1xxx_init (void)+{+ pr_debug (DRIVER_INFO " (Au1xxx)\n");++ return driver_register(&ehci_hcd_au1xxx_driver);+}++static void __exit ehci_hcd_au1xxx_cleanup (void)+{+ driver_unregister(&ehci_hcd_au1xxx_driver);+}++module_init (ehci_hcd_au1xxx_init);+module_exit (ehci_hcd_au1xxx_cleanup);diff -Nru linux26-cvs/drivers/usb/host/ehci.h linux26-amd/drivers/usb/host/ehci.h--- linux26-cvs/drivers/usb/host/ehci.h 2005-03-23 13:53:13.000000000 +0100+++ linux26-amd/drivers/usb/host/ehci.h 2005-06-03 16:54:08.856027000 +0200@@ -69,6 +69,14 @@ /* per root hub port */ unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; +#ifdef CONFIG_USB_OTG_HIGHSPEED+ /*+ * OTG controller needs software interaction+ */+ struct otg_transceiver *transceiver;+ unsigned power_budget;+#endif+ /* per-HC memory pools (could be per-bus, but ...) */ struct dma_pool *qh_pool; /* qh per active urb */ struct dma_pool *qtd_pool; /* one or more per qh */diff -Nru linux26-cvs/drivers/usb/host/ehci-hcd.c linux26-amd/drivers/usb/host/ehci-hcd.c--- linux26-cvs/drivers/usb/host/ehci-hcd.c 2005-03-23 13:53:13.000000000 +0100+++ linux26-amd/drivers/usb/host/ehci-hcd.c 2005-07-25 17:34:22.373273000 +0200@@ -40,6 +40,7 @@ #include <linux/interrupt.h> #include <linux/reboot.h> #include <linux/usb.h>+#include <linux/usb_otg.h> #include <linux/moduleparam.h> #include <linux/dma-mapping.h> @@ -123,6 +124,10 @@ #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */+#if (EHCI_SHRINK_JIFFIES < 1)+#undef EHCI_SHRINK_JIFFIES+#define EHCI_SHRINK_JIFFIES 1+#endif /* Initial IRQ latency: faster than hw default */ static int log2_irq_thresh = 0; // 0 to 6@@ -276,7 +281,7 @@ spin_unlock_irqrestore (&ehci->lock, flags); } -#ifdef CONFIG_PCI+#if defined(CONFIG_PCI) && !defined(CONFIG_SOC_AU1X00) /* EHCI 0.96 (and later) section 5.1 says how to kick BIOS/SMM/... * off the controller (maybe it can boot from highspeed USB disks).@@ -332,7 +337,9 @@ { struct ehci_hcd *ehci = hcd_to_ehci (hcd); u32 temp;+#if defined(CONFIG_PCI) && !defined(CONFIG_SOC_AU1X00) unsigned count = 256/4;+#endif spin_lock_init (&ehci->lock); @@ -341,7 +348,7 @@ dbg_hcs_params (ehci, "reset"); dbg_hcc_params (ehci, "reset"); -#ifdef CONFIG_PCI+#if defined(CONFIG_PCI) && !defined(CONFIG_SOC_AU1X00) /* EHCI 0.96 and later may have "extended capabilities" */ if (hcd->self.controller->bus == &pci_bus_type) { struct pci_dev *pdev = to_pci_dev(hcd->self.controller);@@ -395,7 +402,7 @@ HCS_N_PCC(ehci->hcs_params), HCS_N_PORTS(ehci->hcs_params)); -#ifdef CONFIG_PCI+#if defined(CONFIG_PCI) && !defined(CONFIG_SOC_AU1X00) if (hcd->self.controller->bus == &pci_bus_type) { struct pci_dev *pdev; @@ -465,7 +472,7 @@ } writel (ehci->periodic_dma, &ehci->regs->frame_list); -#ifdef CONFIG_PCI+#if defined(CONFIG_PCI) && !defined(CONFIG_SOC_AU1X00) if (hcd->self.controller->bus == &pci_bus_type) { struct pci_dev *pdev; u16 port_wake;@@ -1135,6 +1142,68 @@ /*-------------------------------------------------------------------------*/ +#if defined(CONFIG_USB_OTG_HIGHSPEED) && defined(CONFIG_USB_PORT_AMD5536OTG)++static int ehci_start_otg (struct usb_hcd *hcd)+{+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);++ if (!hcd->self.otg_port) {+ hcd->self.otg_port = USB_OTG_PORT;+ ehci->power_budget = OTG_PWR_BUDGET;+ }+ if (usb_otg_get_transceiver) {+ ehci->transceiver = usb_otg_get_transceiver();+ if (ehci->transceiver) {+ int status;++ if (ehci->transceiver->host) {+ ehci_err (ehci, "OTG already registered\n");+ return -EBUSY;+ }+ ehci->transceiver->host = &hcd->self;+ hcd->self.hand_over = 0;+ status = ehci->transceiver->set_host(+ ehci->transceiver, &hcd->self);++ ehci_dbg (ehci, "init %s transceiver, status %d\n",+ ehci->transceiver->label, status);++ /* if (status)+ put_device(ehci->transceiver->dev); */+ return status;+ }+ else {+ ehci_err (ehci, "can't find transceiver\n");+ return -ENODEV;+ }+ }+ else {+ ehci_info (ehci, "OTG driver not loaded\n");+ return 0;+ }+}++static void ehci_stop_otg (struct usb_hcd *hcd)+{+ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -