📄 usb_host.patch
字号:
diff -Nru linux26-cvs/drivers/usb/core/hcd.c linux26-amd/drivers/usb/core/hcd.c--- linux26-cvs/drivers/usb/core/hcd.c 2005-03-23 13:53:02.000000000 +0100+++ linux26-amd/drivers/usb/core/hcd.c 2005-06-03 16:48:29.183911000 +0200@@ -670,6 +670,7 @@ bus->root_hub = NULL; bus->hcpriv = NULL; bus->busnum = -1;+ bus->otg_port = 0; bus->bandwidth_allocated = 0; bus->bandwidth_int_reqs = 0; bus->bandwidth_isoc_reqs = 0;diff -Nru linux26-cvs/drivers/usb/core/hcd.h linux26-amd/drivers/usb/core/hcd.h--- linux26-cvs/drivers/usb/core/hcd.h 2005-03-23 13:53:02.000000000 +0100+++ linux26-amd/drivers/usb/core/hcd.h 2005-06-03 16:48:29.203912000 +0200@@ -206,6 +206,10 @@ int (*hub_suspend)(struct usb_hcd *); int (*hub_resume)(struct usb_hcd *); int (*start_port_reset)(struct usb_hcd *, unsigned port_num);+#if defined(CONFIG_USB_OTG) && defined(CONFIG_USB_PORT_AMD5536OTG)+ int (*start_otg)(struct usb_hcd *);+ void (*stop_otg)(struct usb_hcd *);+#endif }; extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);diff -Nru linux26-cvs/drivers/usb/core/hcd-pci.c linux26-amd/drivers/usb/core/hcd-pci.c--- linux26-cvs/drivers/usb/core/hcd-pci.c 2005-03-23 13:53:02.000000000 +0100+++ linux26-amd/drivers/usb/core/hcd-pci.c 2005-06-03 16:48:29.173911000 +0200@@ -186,6 +186,11 @@ usb_register_bus (&hcd->self); +#if defined(CONFIG_USB_OTG) && defined(CONFIG_USB_PORT_AMD5536OTG)++ if ((retval = driver->start_otg (hcd)) < 0)+ dev_warn (hcd->self.controller, "OTG init error %d\n", retval);+#endif if ((retval = driver->start (hcd)) < 0) { dev_err (hcd->self.controller, "init error %d\n", retval); usb_hcd_pci_remove (dev);@@ -232,6 +237,9 @@ usb_disconnect (&hcd->self.root_hub); hcd->driver->stop (hcd);+#if defined(CONFIG_USB_OTG) && defined(CONFIG_USB_PORT_AMD5536OTG)+ hcd->driver->stop_otg (hcd);+#endif hcd_buffer_destroy (hcd); hcd->state = USB_STATE_HALT; pci_set_drvdata(dev, NULL);diff -Nru linux26-cvs/drivers/usb/core/hub.c linux26-amd/drivers/usb/core/hub.c--- linux26-cvs/drivers/usb/core/hub.c 2005-03-23 13:53:03.000000000 +0100+++ linux26-amd/drivers/usb/core/hub.c 2005-08-16 11:04:15.593591000 +0200@@ -1149,6 +1149,10 @@ { int err; int c;+#ifdef CONFIG_USB_OTG_WHITELIST_RELAXED+ unsigned port1 = 0;+ struct usb_device *root = udev->bus->root_hub;+#endif err = usb_get_configuration(udev); if (err < 0) {@@ -1175,14 +1179,29 @@ udev->descriptor.iSerialNumber); #ifdef CONFIG_USB_OTG++#ifdef CONFIG_USB_OTG_WHITELIST_RELAXED+ + if (udev->parent) {++ struct usb_device *tdev = udev;++ while (tdev->parent != root)+ tdev = tdev->parent;+ for (port1 = 1; port1 <= root->maxchild; port1++) {+ if (root->children[port1-1] == tdev)+ break;+ }+ }+ root = udev->parent;+#endif /* * OTG-aware devices on OTG-capable root hubs may be able to use SRP, * to wake us after we've powered off VBUS; and HNP, switching roles * "host" to "peripheral". The OTG descriptor helps figure this out. */ if (!udev->bus->is_b_host- && udev->config- && udev->parent == udev->bus->root_hub) {+ && udev->config) { struct usb_otg_descriptor *desc = 0; struct usb_bus *bus = udev->bus; @@ -1191,6 +1210,8 @@ le16_to_cpu(udev->config[0].desc.wTotalLength), USB_DT_OTG, (void **) &desc) == 0) { if (desc->bmAttributes & USB_OTG_HNP) {++#ifndef CONFIG_USB_OTG_WHITELIST_RELAXED unsigned port1; struct usb_device *root = udev->parent; @@ -1199,15 +1220,24 @@ if (root->children[port1-1] == udev) break; }-- dev_info(&udev->dev,- "Dual-Role OTG device on %sHNP port\n",- (port1 == bus->otg_port)- ? "" : "non-");+#endif+ if (udev->parent != bus->root_hub) {+ dev_info(&udev->dev,+ "Dual-Role OTG device connected through hub(s)\n");+ bus->b_hnp_enable = 0;+ }+ else if (port1 == bus->otg_port) {+ dev_info(&udev->dev,+ "Dual-Role OTG device on HNP port\n");+ bus->b_hnp_enable = 1;+ }+ else {+ dev_info(&udev->dev,+ "Dual-Role OTG device on non-HNP port\n");+ bus->b_hnp_enable = 0;+ } /* enable HNP before suspend, it's simpler */- if (port1 == bus->otg_port)- bus->b_hnp_enable = 1; err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), USB_REQ_SET_FEATURE, 0,@@ -1220,16 +1250,22 @@ * customize to match your product. */ dev_info(&udev->dev,- "can't set HNP mode; %d\n",+ "Device Not Responding (trying to set HNP mode: %d)\n", err); bus->b_hnp_enable = 0;+ goto fail; } } } } - if (!is_targeted(udev)) {-+#ifdef CONFIG_USB_OTG_WHITELIST_RELAXED+ if (port1 && (port1 == udev->bus->otg_port) \+ && !is_targeted(udev))+#else+ if (!is_targeted(udev))+#endif+ { /* Maybe it can talk to us, though we can't talk to it. * (Includes HNP test device.) */@@ -1239,10 +1275,12 @@ err = __usb_suspend_device(udev, udev->bus->otg_port, PM_SUSPEND_MEM);- if (err < 0)+ if (err < 0) { dev_dbg(&udev->dev, "HNP fail, %d\n", err);+ goto fail;+ } }- err = -ENODEV;+ err = -ENOTCONN; goto fail; } #endif@@ -2529,6 +2567,16 @@ } up (&udev->serialize);++#ifdef CONFIG_USB_OTG++ /* don't want to disturb HNP: no retry */+ if ((udev->bus->is_b_host || udev->bus->b_hnp_enable)+ && (status == -ENOTCONN))+ /* FIXME: rather keep the port enabled until */+ /* disconnect, but it works this way */+ goto loop;+#endif if (status) goto loop_disable; diff -Nru linux26-cvs/drivers/usb/core/Kconfig linux26-amd/drivers/usb/core/Kconfig--- linux26-cvs/drivers/usb/core/Kconfig 2005-03-23 13:53:02.000000000 +0100+++ linux26-amd/drivers/usb/core/Kconfig 2005-06-01 11:21:39.000000000 +0200@@ -80,6 +80,12 @@ default n +config USB_OTG_HIGHSPEED+ bool+ depends on USB_OTG+ default n++ config USB_OTG_WHITELIST bool "Rely on OTG Targeted Peripherals List" depends on USB_OTGdiff -Nru linux26-cvs/drivers/usb/core/Makefile linux26-amd/drivers/usb/core/Makefile--- linux26-cvs/drivers/usb/core/Makefile 2005-03-23 13:53:02.000000000 +0100+++ linux26-amd/drivers/usb/core/Makefile 2005-06-03 16:48:29.153912000 +0200@@ -6,8 +6,10 @@ config.o file.o buffer.o sysfs.o ifeq ($(CONFIG_PCI),y)+ifneq ($(CONFIG_SOC_AU1X00),y) usbcore-objs += hcd-pci.o endif+endif ifeq ($(CONFIG_USB_DEVICEFS),y) usbcore-objs += devio.o inode.o devices.odiff -Nru linux26-cvs/drivers/usb/core/usb.c linux26-amd/drivers/usb/core/usb.c--- linux26-cvs/drivers/usb/core/usb.c 2005-03-23 13:53:03.000000000 +0100+++ linux26-amd/drivers/usb/core/usb.c 2005-07-04 10:05:29.243911000 +0200@@ -85,6 +85,11 @@ static int usb_generic_driver_data; +#if defined(CONFIG_USB_OTG) && defined(CONFIG_USB_PORT_AMD5536OTG) ++struct otg_transceiver * (*usb_otg_get_transceiver)(void) = NULL;+#endif+ /* called from driver core with usb_bus_type.subsys writelock */ int usb_probe_interface(struct device *dev) {@@ -1393,6 +1398,58 @@ return 0; } +#if defined(CONFIG_USB_OTG) && defined(CONFIG_USB_PORT_AMD5536OTG) +/*+ * To be called from OTG controller driver+ */+int usb_host_register_otg(struct otg_transceiver * (*get_transceiver)(void))+{+ struct list_head *tmp;+ struct usb_bus *bus;+ struct usb_hcd *hcd;++ if (get_transceiver) {+ usb_otg_get_transceiver = get_transceiver;+ down (&usb_bus_list_lock);+ tmp = usb_bus_list.next;+ while (tmp != &usb_bus_list) {+ bus = list_entry(tmp, struct usb_bus, bus_list);+ tmp = tmp->next;+ hcd = container_of (bus, struct usb_hcd, self);+ hcd->driver->start_otg (hcd);+ }+ up (&usb_bus_list_lock);+ pr_info("USB OTG driver registered\n");+ return 0;+ }+ else {+ printk(KERN_ERR "can't register OTG, no device\n");+ return -ENODEV;+ }+}++void usb_host_deregister_otg(void)+{+ struct list_head *tmp;+ struct usb_bus *bus;+ struct usb_hcd *hcd;++ down (&usb_bus_list_lock);+ tmp = usb_bus_list.next;+ while (tmp != &usb_bus_list) {+ bus = list_entry(tmp, struct usb_bus, bus_list);+ tmp = tmp->next;+ if (bus->otg_port) {+ hcd = container_of (bus, struct usb_hcd, self);+ hcd->driver->stop_otg (hcd);+ }+ }+ up (&usb_bus_list_lock);+ usb_otg_get_transceiver = NULL;+ pr_info("USB OTG driver deregistered\n");+}+#endif+ struct bus_type usb_bus_type = { .name = "usb", .match = usb_device_match,@@ -1536,4 +1593,10 @@ #endif EXPORT_SYMBOL (usb_buffer_unmap_sg); +#if defined(CONFIG_USB_OTG) && defined(CONFIG_USB_PORT_AMD5536OTG) +EXPORT_SYMBOL(usb_host_register_otg);+EXPORT_SYMBOL(usb_host_deregister_otg);+EXPORT_SYMBOL(usb_otg_get_transceiver);+#endif+ MODULE_LICENSE("GPL");diff -Nru linux26-cvs/drivers/usb/host/ehci-au1xxx.c linux26-amd/drivers/usb/host/ehci-au1xxx.c--- linux26-cvs/drivers/usb/host/ehci-au1xxx.c 1970-01-01 01:00:00.000000000 +0100+++ linux26-amd/drivers/usb/host/ehci-au1xxx.c 2005-08-02 16:43:52.740644000 +0200@@ -0,0 +1,387 @@+/*+ * EHCI HCD (Host Controller Driver) for USB.+ *+ * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>+ *+ * Bus Glue for AMD Alchemy Au1xxx+ *+ * Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org>+ *+ * Modified for AMD Alchemy Au1200 EHC+ * by K.Boge <karsten.boge@amd.com>+ *+ * This file is licenced under the GPL.+ */++#include <asm/mach-au1x00/au1000.h>++#ifndef CONFIG_SOC_AU1200+#error "Alchemy chip doesn't have EHC"+#else /* Au1200 */++#define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG)+#define USB_MCFG_PFEN (1<<31)+#define USB_MCFG_RDCOMB (1<<30)+#define USB_MCFG_SSDEN (1<<23)+#define USB_MCFG_PHYPLLEN (1<<19)+#define USB_MCFG_EHCCLKEN (1<<17)+#define USB_MCFG_UCAM (1<<7)+#define USB_MCFG_EBMEN (1<<3)+#define USB_MCFG_EMEMEN (1<<2)++#define USBH_ENABLE_CE (USB_MCFG_PHYPLLEN | USB_MCFG_EHCCLKEN)+#ifdef CONFIG_DMA_COHERENT+#define USBH_ENABLE_INIT (USBH_ENABLE_CE \+ | USB_MCFG_PFEN | USB_MCFG_RDCOMB \+ | USB_MCFG_SSDEN | USB_MCFG_UCAM \+ | USB_MCFG_EBMEN | USB_MCFG_EMEMEN)+#else+#define USBH_ENABLE_INIT (USBH_ENABLE_CE \+ | USB_MCFG_PFEN | USB_MCFG_RDCOMB \+ | USB_MCFG_SSDEN \+ | USB_MCFG_EBMEN | USB_MCFG_EMEMEN)+#endif+#define USBH_DISABLE (USB_MCFG_EBMEN | USB_MCFG_EMEMEN)++#endif /* Au1200 */++extern int usb_disabled(void);++/*-------------------------------------------------------------------------*/++static void au1xxx_start_ehc(struct platform_device *dev)+{+ pr_debug(__FILE__ ": starting Au1xxx EHCI USB Controller\n");++ /* write HW defaults again in case Yamon cleared them */+ if (au_readl(USB_HOST_CONFIG) == 0) {+ au_writel(0x00d02000, USB_HOST_CONFIG);+ au_readl(USB_HOST_CONFIG);+ udelay(1000);+ }+ /* enable host controller */+ au_writel(USBH_ENABLE_CE | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);+ au_readl(USB_HOST_CONFIG);+ udelay(1000);+ au_writel(USBH_ENABLE_INIT | au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);+ au_readl(USB_HOST_CONFIG);+ udelay(1000);++ pr_debug(__FILE__ ": Clock to USB host has been enabled\n");+}++static void au1xxx_stop_ehc(struct platform_device *dev)+{+ pr_debug(__FILE__ ": stopping Au1xxx EHCI USB Controller\n");++ /* Disable mem */+ au_writel(~USBH_DISABLE & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);+ udelay(1000);+ /* Disable clock */+ au_writel(~USB_MCFG_EHCCLKEN & au_readl(USB_HOST_CONFIG), USB_HOST_CONFIG);+ au_readl(USB_HOST_CONFIG);+}+++/*-------------------------------------------------------------------------*/+++static irqreturn_t usb_ehci_au1xxx_hcim_irq (int irq, void *__hcd,+ struct pt_regs * r)+{+ struct usb_hcd *hcd = __hcd;++ return usb_hcd_irq(irq, hcd, r);+}++/*-------------------------------------------------------------------------*/++void usb_ehci_au1xxx_remove (struct usb_hcd *, struct platform_device *);++/* configure so an HC device and id are always provided */+/* always called with process context; sleeping is OK */++
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -