diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/Kconfig | 22 | ||||
-rw-r--r-- | drivers/usb/host/ehci-au1xxx.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/ehci-dbg.c | 231 | ||||
-rw-r--r-- | drivers/usb/host/ehci-fsl.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 159 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 98 | ||||
-rw-r--r-- | drivers/usb/host/ehci-ixp4xx.c | 152 | ||||
-rw-r--r-- | drivers/usb/host/ehci-orion.c | 272 | ||||
-rw-r--r-- | drivers/usb/host/ehci-pci.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/ehci-ppc-of.c | 238 | ||||
-rw-r--r-- | drivers/usb/host/ehci-ppc-soc.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/ehci-ps3.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/ehci-q.c | 25 | ||||
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 152 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 40 | ||||
-rw-r--r-- | drivers/usb/host/isp116x-hcd.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/ohci-at91.c | 31 | ||||
-rw-r--r-- | drivers/usb/host/ohci-dbg.c | 213 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 34 | ||||
-rw-r--r-- | drivers/usb/host/ohci-sh.c | 143 | ||||
-rw-r--r-- | drivers/usb/host/ohci-sm501.c | 264 | ||||
-rw-r--r-- | drivers/usb/host/ohci.h | 7 | ||||
-rw-r--r-- | drivers/usb/host/r8a66597.h | 2 |
23 files changed, 1834 insertions, 259 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 49a91c5ee51b..d97b16b52efa 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -29,15 +29,6 @@ config USB_EHCI_HCD | |||
29 | To compile this driver as a module, choose M here: the | 29 | To compile this driver as a module, choose M here: the |
30 | module will be called ehci-hcd. | 30 | module will be called ehci-hcd. |
31 | 31 | ||
32 | config USB_EHCI_SPLIT_ISO | ||
33 | bool "Full speed ISO transactions (EXPERIMENTAL)" | ||
34 | depends on USB_EHCI_HCD && EXPERIMENTAL | ||
35 | default n | ||
36 | ---help--- | ||
37 | This code is new and hasn't been used with many different | ||
38 | EHCI or USB 2.0 transaction translator implementations. | ||
39 | It should work for ISO-OUT transfers, like audio. | ||
40 | |||
41 | config USB_EHCI_ROOT_HUB_TT | 32 | config USB_EHCI_ROOT_HUB_TT |
42 | bool "Root Hub Transaction Translators (EXPERIMENTAL)" | 33 | bool "Root Hub Transaction Translators (EXPERIMENTAL)" |
43 | depends on USB_EHCI_HCD && EXPERIMENTAL | 34 | depends on USB_EHCI_HCD && EXPERIMENTAL |
@@ -69,21 +60,30 @@ config USB_EHCI_TT_NEWSCHED | |||
69 | 60 | ||
70 | config USB_EHCI_BIG_ENDIAN_MMIO | 61 | config USB_EHCI_BIG_ENDIAN_MMIO |
71 | bool | 62 | bool |
72 | depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX) | 63 | depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX) |
73 | default y | 64 | default y |
74 | 65 | ||
75 | config USB_EHCI_BIG_ENDIAN_DESC | 66 | config USB_EHCI_BIG_ENDIAN_DESC |
76 | bool | 67 | bool |
77 | depends on USB_EHCI_HCD && 440EPX | 68 | depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX) |
78 | default y | 69 | default y |
79 | 70 | ||
80 | config USB_EHCI_FSL | 71 | config USB_EHCI_FSL |
81 | bool | 72 | bool |
73 | depends on USB_EHCI_HCD | ||
82 | select USB_EHCI_ROOT_HUB_TT | 74 | select USB_EHCI_ROOT_HUB_TT |
83 | default y if MPC834x || PPC_MPC831x | 75 | default y if MPC834x || PPC_MPC831x |
84 | ---help--- | 76 | ---help--- |
85 | Variation of ARC USB block used in some Freescale chips. | 77 | Variation of ARC USB block used in some Freescale chips. |
86 | 78 | ||
79 | config USB_EHCI_HCD_PPC_OF | ||
80 | bool "EHCI support for PPC USB controller on OF platform bus" | ||
81 | depends on USB_EHCI_HCD && PPC_OF | ||
82 | default y | ||
83 | ---help--- | ||
84 | Enables support for the USB controller present on the PowerPC | ||
85 | OpenFirmware platform bus. | ||
86 | |||
87 | config USB_ISP116X_HCD | 87 | config USB_ISP116X_HCD |
88 | tristate "ISP116X HCD support" | 88 | tristate "ISP116X HCD support" |
89 | depends on USB | 89 | depends on USB |
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index 766ef68a0b43..da7532d38bf1 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c | |||
@@ -222,6 +222,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = { | |||
222 | .hub_control = ehci_hub_control, | 222 | .hub_control = ehci_hub_control, |
223 | .bus_suspend = ehci_bus_suspend, | 223 | .bus_suspend = ehci_bus_suspend, |
224 | .bus_resume = ehci_bus_resume, | 224 | .bus_resume = ehci_bus_resume, |
225 | .relinquish_port = ehci_relinquish_port, | ||
225 | }; | 226 | }; |
226 | 227 | ||
227 | /*-------------------------------------------------------------------------*/ | 228 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index c9cc4413198e..64ebfc5548a3 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
@@ -323,7 +323,43 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { } | |||
323 | 323 | ||
324 | #else | 324 | #else |
325 | 325 | ||
326 | /* troubleshooting help: expose state in sysfs */ | 326 | /* troubleshooting help: expose state in debugfs */ |
327 | |||
328 | static int debug_async_open(struct inode *, struct file *); | ||
329 | static int debug_periodic_open(struct inode *, struct file *); | ||
330 | static int debug_registers_open(struct inode *, struct file *); | ||
331 | static int debug_async_open(struct inode *, struct file *); | ||
332 | static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); | ||
333 | static int debug_close(struct inode *, struct file *); | ||
334 | |||
335 | static const struct file_operations debug_async_fops = { | ||
336 | .owner = THIS_MODULE, | ||
337 | .open = debug_async_open, | ||
338 | .read = debug_output, | ||
339 | .release = debug_close, | ||
340 | }; | ||
341 | static const struct file_operations debug_periodic_fops = { | ||
342 | .owner = THIS_MODULE, | ||
343 | .open = debug_periodic_open, | ||
344 | .read = debug_output, | ||
345 | .release = debug_close, | ||
346 | }; | ||
347 | static const struct file_operations debug_registers_fops = { | ||
348 | .owner = THIS_MODULE, | ||
349 | .open = debug_registers_open, | ||
350 | .read = debug_output, | ||
351 | .release = debug_close, | ||
352 | }; | ||
353 | |||
354 | static struct dentry *ehci_debug_root; | ||
355 | |||
356 | struct debug_buffer { | ||
357 | ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ | ||
358 | struct usb_bus *bus; | ||
359 | struct mutex mutex; /* protect filling of buffer */ | ||
360 | size_t count; /* number of characters filled into buffer */ | ||
361 | char *page; | ||
362 | }; | ||
327 | 363 | ||
328 | #define speed_char(info1) ({ char tmp; \ | 364 | #define speed_char(info1) ({ char tmp; \ |
329 | switch (info1 & (3 << 12)) { \ | 365 | switch (info1 & (3 << 12)) { \ |
@@ -441,10 +477,8 @@ done: | |||
441 | *nextp = next; | 477 | *nextp = next; |
442 | } | 478 | } |
443 | 479 | ||
444 | static ssize_t | 480 | static ssize_t fill_async_buffer(struct debug_buffer *buf) |
445 | show_async (struct class_device *class_dev, char *buf) | ||
446 | { | 481 | { |
447 | struct usb_bus *bus; | ||
448 | struct usb_hcd *hcd; | 482 | struct usb_hcd *hcd; |
449 | struct ehci_hcd *ehci; | 483 | struct ehci_hcd *ehci; |
450 | unsigned long flags; | 484 | unsigned long flags; |
@@ -452,14 +486,13 @@ show_async (struct class_device *class_dev, char *buf) | |||
452 | char *next; | 486 | char *next; |
453 | struct ehci_qh *qh; | 487 | struct ehci_qh *qh; |
454 | 488 | ||
455 | *buf = 0; | 489 | hcd = bus_to_hcd(buf->bus); |
456 | |||
457 | bus = class_get_devdata(class_dev); | ||
458 | hcd = bus_to_hcd(bus); | ||
459 | ehci = hcd_to_ehci (hcd); | 490 | ehci = hcd_to_ehci (hcd); |
460 | next = buf; | 491 | next = buf->page; |
461 | size = PAGE_SIZE; | 492 | size = PAGE_SIZE; |
462 | 493 | ||
494 | *next = 0; | ||
495 | |||
463 | /* dumps a snapshot of the async schedule. | 496 | /* dumps a snapshot of the async schedule. |
464 | * usually empty except for long-term bulk reads, or head. | 497 | * usually empty except for long-term bulk reads, or head. |
465 | * one QH per line, and TDs we know about | 498 | * one QH per line, and TDs we know about |
@@ -477,16 +510,12 @@ show_async (struct class_device *class_dev, char *buf) | |||
477 | } | 510 | } |
478 | spin_unlock_irqrestore (&ehci->lock, flags); | 511 | spin_unlock_irqrestore (&ehci->lock, flags); |
479 | 512 | ||
480 | return strlen (buf); | 513 | return strlen(buf->page); |
481 | } | 514 | } |
482 | static CLASS_DEVICE_ATTR (async, S_IRUGO, show_async, NULL); | ||
483 | 515 | ||
484 | #define DBG_SCHED_LIMIT 64 | 516 | #define DBG_SCHED_LIMIT 64 |
485 | 517 | static ssize_t fill_periodic_buffer(struct debug_buffer *buf) | |
486 | static ssize_t | ||
487 | show_periodic (struct class_device *class_dev, char *buf) | ||
488 | { | 518 | { |
489 | struct usb_bus *bus; | ||
490 | struct usb_hcd *hcd; | 519 | struct usb_hcd *hcd; |
491 | struct ehci_hcd *ehci; | 520 | struct ehci_hcd *ehci; |
492 | unsigned long flags; | 521 | unsigned long flags; |
@@ -500,10 +529,9 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
500 | return 0; | 529 | return 0; |
501 | seen_count = 0; | 530 | seen_count = 0; |
502 | 531 | ||
503 | bus = class_get_devdata(class_dev); | 532 | hcd = bus_to_hcd(buf->bus); |
504 | hcd = bus_to_hcd(bus); | ||
505 | ehci = hcd_to_ehci (hcd); | 533 | ehci = hcd_to_ehci (hcd); |
506 | next = buf; | 534 | next = buf->page; |
507 | size = PAGE_SIZE; | 535 | size = PAGE_SIZE; |
508 | 536 | ||
509 | temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size); | 537 | temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size); |
@@ -623,14 +651,10 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
623 | 651 | ||
624 | return PAGE_SIZE - size; | 652 | return PAGE_SIZE - size; |
625 | } | 653 | } |
626 | static CLASS_DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL); | ||
627 | |||
628 | #undef DBG_SCHED_LIMIT | 654 | #undef DBG_SCHED_LIMIT |
629 | 655 | ||
630 | static ssize_t | 656 | static ssize_t fill_registers_buffer(struct debug_buffer *buf) |
631 | show_registers (struct class_device *class_dev, char *buf) | ||
632 | { | 657 | { |
633 | struct usb_bus *bus; | ||
634 | struct usb_hcd *hcd; | 658 | struct usb_hcd *hcd; |
635 | struct ehci_hcd *ehci; | 659 | struct ehci_hcd *ehci; |
636 | unsigned long flags; | 660 | unsigned long flags; |
@@ -639,15 +663,14 @@ show_registers (struct class_device *class_dev, char *buf) | |||
639 | static char fmt [] = "%*s\n"; | 663 | static char fmt [] = "%*s\n"; |
640 | static char label [] = ""; | 664 | static char label [] = ""; |
641 | 665 | ||
642 | bus = class_get_devdata(class_dev); | 666 | hcd = bus_to_hcd(buf->bus); |
643 | hcd = bus_to_hcd(bus); | ||
644 | ehci = hcd_to_ehci (hcd); | 667 | ehci = hcd_to_ehci (hcd); |
645 | next = buf; | 668 | next = buf->page; |
646 | size = PAGE_SIZE; | 669 | size = PAGE_SIZE; |
647 | 670 | ||
648 | spin_lock_irqsave (&ehci->lock, flags); | 671 | spin_lock_irqsave (&ehci->lock, flags); |
649 | 672 | ||
650 | if (bus->controller->power.power_state.event) { | 673 | if (buf->bus->controller->power.power_state.event) { |
651 | size = scnprintf (next, size, | 674 | size = scnprintf (next, size, |
652 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" | 675 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" |
653 | "%s\n" | 676 | "%s\n" |
@@ -763,9 +786,7 @@ show_registers (struct class_device *class_dev, char *buf) | |||
763 | } | 786 | } |
764 | 787 | ||
765 | if (ehci->reclaim) { | 788 | if (ehci->reclaim) { |
766 | temp = scnprintf (next, size, "reclaim qh %p%s\n", | 789 | temp = scnprintf(next, size, "reclaim qh %p\n", ehci->reclaim); |
767 | ehci->reclaim, | ||
768 | ehci->reclaim_ready ? " ready" : ""); | ||
769 | size -= temp; | 790 | size -= temp; |
770 | next += temp; | 791 | next += temp; |
771 | } | 792 | } |
@@ -789,26 +810,150 @@ done: | |||
789 | 810 | ||
790 | return PAGE_SIZE - size; | 811 | return PAGE_SIZE - size; |
791 | } | 812 | } |
792 | static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL); | ||
793 | 813 | ||
794 | static inline void create_debug_files (struct ehci_hcd *ehci) | 814 | static struct debug_buffer *alloc_buffer(struct usb_bus *bus, |
815 | ssize_t (*fill_func)(struct debug_buffer *)) | ||
795 | { | 816 | { |
796 | struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev; | 817 | struct debug_buffer *buf; |
797 | int retval; | 818 | |
819 | buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); | ||
798 | 820 | ||
799 | retval = class_device_create_file(cldev, &class_device_attr_async); | 821 | if (buf) { |
800 | retval = class_device_create_file(cldev, &class_device_attr_periodic); | 822 | buf->bus = bus; |
801 | retval = class_device_create_file(cldev, &class_device_attr_registers); | 823 | buf->fill_func = fill_func; |
824 | mutex_init(&buf->mutex); | ||
825 | } | ||
826 | |||
827 | return buf; | ||
802 | } | 828 | } |
803 | 829 | ||
804 | static inline void remove_debug_files (struct ehci_hcd *ehci) | 830 | static int fill_buffer(struct debug_buffer *buf) |
805 | { | 831 | { |
806 | struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev; | 832 | int ret = 0; |
833 | |||
834 | if (!buf->page) | ||
835 | buf->page = (char *)get_zeroed_page(GFP_KERNEL); | ||
836 | |||
837 | if (!buf->page) { | ||
838 | ret = -ENOMEM; | ||
839 | goto out; | ||
840 | } | ||
841 | |||
842 | ret = buf->fill_func(buf); | ||
807 | 843 | ||
808 | class_device_remove_file(cldev, &class_device_attr_async); | 844 | if (ret >= 0) { |
809 | class_device_remove_file(cldev, &class_device_attr_periodic); | 845 | buf->count = ret; |
810 | class_device_remove_file(cldev, &class_device_attr_registers); | 846 | ret = 0; |
847 | } | ||
848 | |||
849 | out: | ||
850 | return ret; | ||
811 | } | 851 | } |
812 | 852 | ||
813 | #endif /* STUB_DEBUG_FILES */ | 853 | static ssize_t debug_output(struct file *file, char __user *user_buf, |
854 | size_t len, loff_t *offset) | ||
855 | { | ||
856 | struct debug_buffer *buf = file->private_data; | ||
857 | int ret = 0; | ||
858 | |||
859 | mutex_lock(&buf->mutex); | ||
860 | if (buf->count == 0) { | ||
861 | ret = fill_buffer(buf); | ||
862 | if (ret != 0) { | ||
863 | mutex_unlock(&buf->mutex); | ||
864 | goto out; | ||
865 | } | ||
866 | } | ||
867 | mutex_unlock(&buf->mutex); | ||
868 | |||
869 | ret = simple_read_from_buffer(user_buf, len, offset, | ||
870 | buf->page, buf->count); | ||
871 | |||
872 | out: | ||
873 | return ret; | ||
874 | |||
875 | } | ||
876 | |||
877 | static int debug_close(struct inode *inode, struct file *file) | ||
878 | { | ||
879 | struct debug_buffer *buf = file->private_data; | ||
814 | 880 | ||
881 | if (buf) { | ||
882 | if (buf->page) | ||
883 | free_page((unsigned long)buf->page); | ||
884 | kfree(buf); | ||
885 | } | ||
886 | |||
887 | return 0; | ||
888 | } | ||
889 | static int debug_async_open(struct inode *inode, struct file *file) | ||
890 | { | ||
891 | file->private_data = alloc_buffer(inode->i_private, fill_async_buffer); | ||
892 | |||
893 | return file->private_data ? 0 : -ENOMEM; | ||
894 | } | ||
895 | |||
896 | static int debug_periodic_open(struct inode *inode, struct file *file) | ||
897 | { | ||
898 | file->private_data = alloc_buffer(inode->i_private, | ||
899 | fill_periodic_buffer); | ||
900 | |||
901 | return file->private_data ? 0 : -ENOMEM; | ||
902 | } | ||
903 | |||
904 | static int debug_registers_open(struct inode *inode, struct file *file) | ||
905 | { | ||
906 | file->private_data = alloc_buffer(inode->i_private, | ||
907 | fill_registers_buffer); | ||
908 | |||
909 | return file->private_data ? 0 : -ENOMEM; | ||
910 | } | ||
911 | |||
912 | static inline void create_debug_files (struct ehci_hcd *ehci) | ||
913 | { | ||
914 | struct usb_bus *bus = &ehci_to_hcd(ehci)->self; | ||
915 | |||
916 | ehci->debug_dir = debugfs_create_dir(bus->bus_name, ehci_debug_root); | ||
917 | if (!ehci->debug_dir) | ||
918 | goto dir_error; | ||
919 | |||
920 | ehci->debug_async = debugfs_create_file("async", S_IRUGO, | ||
921 | ehci->debug_dir, bus, | ||
922 | &debug_async_fops); | ||
923 | if (!ehci->debug_async) | ||
924 | goto async_error; | ||
925 | |||
926 | ehci->debug_periodic = debugfs_create_file("periodic", S_IRUGO, | ||
927 | ehci->debug_dir, bus, | ||
928 | &debug_periodic_fops); | ||
929 | if (!ehci->debug_periodic) | ||
930 | goto periodic_error; | ||
931 | |||
932 | ehci->debug_registers = debugfs_create_file("registers", S_IRUGO, | ||
933 | ehci->debug_dir, bus, | ||
934 | &debug_registers_fops); | ||
935 | if (!ehci->debug_registers) | ||
936 | goto registers_error; | ||
937 | return; | ||
938 | |||
939 | registers_error: | ||
940 | debugfs_remove(ehci->debug_periodic); | ||
941 | periodic_error: | ||
942 | debugfs_remove(ehci->debug_async); | ||
943 | async_error: | ||
944 | debugfs_remove(ehci->debug_dir); | ||
945 | dir_error: | ||
946 | ehci->debug_periodic = NULL; | ||
947 | ehci->debug_async = NULL; | ||
948 | ehci->debug_dir = NULL; | ||
949 | } | ||
950 | |||
951 | static inline void remove_debug_files (struct ehci_hcd *ehci) | ||
952 | { | ||
953 | debugfs_remove(ehci->debug_registers); | ||
954 | debugfs_remove(ehci->debug_periodic); | ||
955 | debugfs_remove(ehci->debug_async); | ||
956 | debugfs_remove(ehci->debug_dir); | ||
957 | } | ||
958 | |||
959 | #endif /* STUB_DEBUG_FILES */ | ||
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 430821cb95c8..adb0defa1631 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -25,7 +25,7 @@ | |||
25 | 25 | ||
26 | #include "ehci-fsl.h" | 26 | #include "ehci-fsl.h" |
27 | 27 | ||
28 | /* FIXME: Power Managment is un-ported so temporarily disable it */ | 28 | /* FIXME: Power Management is un-ported so temporarily disable it */ |
29 | #undef CONFIG_PM | 29 | #undef CONFIG_PM |
30 | 30 | ||
31 | /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */ | 31 | /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */ |
@@ -323,6 +323,7 @@ static const struct hc_driver ehci_fsl_hc_driver = { | |||
323 | .hub_control = ehci_hub_control, | 323 | .hub_control = ehci_hub_control, |
324 | .bus_suspend = ehci_bus_suspend, | 324 | .bus_suspend = ehci_bus_suspend, |
325 | .bus_resume = ehci_bus_resume, | 325 | .bus_resume = ehci_bus_resume, |
326 | .relinquish_port = ehci_relinquish_port, | ||
326 | }; | 327 | }; |
327 | 328 | ||
328 | static int ehci_fsl_drv_probe(struct platform_device *pdev) | 329 | static int ehci_fsl_drv_probe(struct platform_device *pdev) |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 5f2d74ed5ad7..4caa6a8b9a37 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
34 | #include <linux/moduleparam.h> | 34 | #include <linux/moduleparam.h> |
35 | #include <linux/dma-mapping.h> | 35 | #include <linux/dma-mapping.h> |
36 | #include <linux/debugfs.h> | ||
36 | 37 | ||
37 | #include "../core/hcd.h" | 38 | #include "../core/hcd.h" |
38 | 39 | ||
@@ -109,7 +110,7 @@ static const char hcd_name [] = "ehci_hcd"; | |||
109 | #define EHCI_TUNE_MULT_TT 1 | 110 | #define EHCI_TUNE_MULT_TT 1 |
110 | #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ | 111 | #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ |
111 | 112 | ||
112 | #define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ | 113 | #define EHCI_IAA_MSECS 10 /* arbitrary */ |
113 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ | 114 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ |
114 | #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ | 115 | #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ |
115 | #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ | 116 | #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ |
@@ -266,6 +267,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci) | |||
266 | 267 | ||
267 | /*-------------------------------------------------------------------------*/ | 268 | /*-------------------------------------------------------------------------*/ |
268 | 269 | ||
270 | static void end_unlink_async(struct ehci_hcd *ehci); | ||
269 | static void ehci_work(struct ehci_hcd *ehci); | 271 | static void ehci_work(struct ehci_hcd *ehci); |
270 | 272 | ||
271 | #include "ehci-hub.c" | 273 | #include "ehci-hub.c" |
@@ -275,25 +277,41 @@ static void ehci_work(struct ehci_hcd *ehci); | |||
275 | 277 | ||
276 | /*-------------------------------------------------------------------------*/ | 278 | /*-------------------------------------------------------------------------*/ |
277 | 279 | ||
278 | static void ehci_watchdog (unsigned long param) | 280 | static void ehci_iaa_watchdog(unsigned long param) |
279 | { | 281 | { |
280 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; | 282 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; |
281 | unsigned long flags; | 283 | unsigned long flags; |
284 | u32 status, cmd; | ||
282 | 285 | ||
283 | spin_lock_irqsave (&ehci->lock, flags); | 286 | spin_lock_irqsave (&ehci->lock, flags); |
287 | WARN_ON(!ehci->reclaim); | ||
284 | 288 | ||
285 | /* lost IAA irqs wedge things badly; seen with a vt8235 */ | 289 | status = ehci_readl(ehci, &ehci->regs->status); |
290 | cmd = ehci_readl(ehci, &ehci->regs->command); | ||
291 | ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd); | ||
292 | |||
293 | /* lost IAA irqs wedge things badly; seen first with a vt8235 */ | ||
286 | if (ehci->reclaim) { | 294 | if (ehci->reclaim) { |
287 | u32 status = ehci_readl(ehci, &ehci->regs->status); | ||
288 | if (status & STS_IAA) { | 295 | if (status & STS_IAA) { |
289 | ehci_vdbg (ehci, "lost IAA\n"); | 296 | ehci_vdbg (ehci, "lost IAA\n"); |
290 | COUNT (ehci->stats.lost_iaa); | 297 | COUNT (ehci->stats.lost_iaa); |
291 | ehci_writel(ehci, STS_IAA, &ehci->regs->status); | 298 | ehci_writel(ehci, STS_IAA, &ehci->regs->status); |
292 | ehci->reclaim_ready = 1; | ||
293 | } | 299 | } |
300 | ehci_writel(ehci, cmd & ~CMD_IAAD, &ehci->regs->command); | ||
301 | end_unlink_async(ehci); | ||
294 | } | 302 | } |
295 | 303 | ||
296 | /* stop async processing after it's idled a bit */ | 304 | spin_unlock_irqrestore(&ehci->lock, flags); |
305 | } | ||
306 | |||
307 | static void ehci_watchdog(unsigned long param) | ||
308 | { | ||
309 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; | ||
310 | unsigned long flags; | ||
311 | |||
312 | spin_lock_irqsave(&ehci->lock, flags); | ||
313 | |||
314 | /* stop async processing after it's idled a bit */ | ||
297 | if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) | 315 | if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) |
298 | start_unlink_async (ehci, ehci->async); | 316 | start_unlink_async (ehci, ehci->async); |
299 | 317 | ||
@@ -363,8 +381,6 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on) | |||
363 | static void ehci_work (struct ehci_hcd *ehci) | 381 | static void ehci_work (struct ehci_hcd *ehci) |
364 | { | 382 | { |
365 | timer_action_done (ehci, TIMER_IO_WATCHDOG); | 383 | timer_action_done (ehci, TIMER_IO_WATCHDOG); |
366 | if (ehci->reclaim_ready) | ||
367 | end_unlink_async (ehci); | ||
368 | 384 | ||
369 | /* another CPU may drop ehci->lock during a schedule scan while | 385 | /* another CPU may drop ehci->lock during a schedule scan while |
370 | * it reports urb completions. this flag guards against bogus | 386 | * it reports urb completions. this flag guards against bogus |
@@ -399,6 +415,7 @@ static void ehci_stop (struct usb_hcd *hcd) | |||
399 | 415 | ||
400 | /* no more interrupts ... */ | 416 | /* no more interrupts ... */ |
401 | del_timer_sync (&ehci->watchdog); | 417 | del_timer_sync (&ehci->watchdog); |
418 | del_timer_sync(&ehci->iaa_watchdog); | ||
402 | 419 | ||
403 | spin_lock_irq(&ehci->lock); | 420 | spin_lock_irq(&ehci->lock); |
404 | if (HC_IS_RUNNING (hcd->state)) | 421 | if (HC_IS_RUNNING (hcd->state)) |
@@ -447,6 +464,10 @@ static int ehci_init(struct usb_hcd *hcd) | |||
447 | ehci->watchdog.function = ehci_watchdog; | 464 | ehci->watchdog.function = ehci_watchdog; |
448 | ehci->watchdog.data = (unsigned long) ehci; | 465 | ehci->watchdog.data = (unsigned long) ehci; |
449 | 466 | ||
467 | init_timer(&ehci->iaa_watchdog); | ||
468 | ehci->iaa_watchdog.function = ehci_iaa_watchdog; | ||
469 | ehci->iaa_watchdog.data = (unsigned long) ehci; | ||
470 | |||
450 | /* | 471 | /* |
451 | * hw default: 1K periodic list heads, one per frame. | 472 | * hw default: 1K periodic list heads, one per frame. |
452 | * periodic_size can shrink by USBCMD update if hcc_params allows. | 473 | * periodic_size can shrink by USBCMD update if hcc_params allows. |
@@ -463,7 +484,6 @@ static int ehci_init(struct usb_hcd *hcd) | |||
463 | ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); | 484 | ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); |
464 | 485 | ||
465 | ehci->reclaim = NULL; | 486 | ehci->reclaim = NULL; |
466 | ehci->reclaim_ready = 0; | ||
467 | ehci->next_uframe = -1; | 487 | ehci->next_uframe = -1; |
468 | 488 | ||
469 | /* | 489 | /* |
@@ -654,8 +674,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
654 | /* complete the unlinking of some qh [4.15.2.3] */ | 674 | /* complete the unlinking of some qh [4.15.2.3] */ |
655 | if (status & STS_IAA) { | 675 | if (status & STS_IAA) { |
656 | COUNT (ehci->stats.reclaim); | 676 | COUNT (ehci->stats.reclaim); |
657 | ehci->reclaim_ready = 1; | 677 | end_unlink_async(ehci); |
658 | bh = 1; | ||
659 | } | 678 | } |
660 | 679 | ||
661 | /* remote wakeup [4.3.1] */ | 680 | /* remote wakeup [4.3.1] */ |
@@ -761,10 +780,16 @@ static int ehci_urb_enqueue ( | |||
761 | 780 | ||
762 | static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | 781 | static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) |
763 | { | 782 | { |
764 | /* if we need to use IAA and it's busy, defer */ | 783 | /* failfast */ |
765 | if (qh->qh_state == QH_STATE_LINKED | 784 | if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) |
766 | && ehci->reclaim | 785 | end_unlink_async(ehci); |
767 | && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) { | 786 | |
787 | /* if it's not linked then there's nothing to do */ | ||
788 | if (qh->qh_state != QH_STATE_LINKED) | ||
789 | ; | ||
790 | |||
791 | /* defer till later if busy */ | ||
792 | else if (ehci->reclaim) { | ||
768 | struct ehci_qh *last; | 793 | struct ehci_qh *last; |
769 | 794 | ||
770 | for (last = ehci->reclaim; | 795 | for (last = ehci->reclaim; |
@@ -774,12 +799,8 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
774 | qh->qh_state = QH_STATE_UNLINK_WAIT; | 799 | qh->qh_state = QH_STATE_UNLINK_WAIT; |
775 | last->reclaim = qh; | 800 | last->reclaim = qh; |
776 | 801 | ||
777 | /* bypass IAA if the hc can't care */ | 802 | /* start IAA cycle */ |
778 | } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim) | 803 | } else |
779 | end_unlink_async (ehci); | ||
780 | |||
781 | /* something else might have unlinked the qh by now */ | ||
782 | if (qh->qh_state == QH_STATE_LINKED) | ||
783 | start_unlink_async (ehci, qh); | 804 | start_unlink_async (ehci, qh); |
784 | } | 805 | } |
785 | 806 | ||
@@ -806,7 +827,19 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
806 | qh = (struct ehci_qh *) urb->hcpriv; | 827 | qh = (struct ehci_qh *) urb->hcpriv; |
807 | if (!qh) | 828 | if (!qh) |
808 | break; | 829 | break; |
809 | unlink_async (ehci, qh); | 830 | switch (qh->qh_state) { |
831 | case QH_STATE_LINKED: | ||
832 | case QH_STATE_COMPLETING: | ||
833 | unlink_async(ehci, qh); | ||
834 | break; | ||
835 | case QH_STATE_UNLINK: | ||
836 | case QH_STATE_UNLINK_WAIT: | ||
837 | /* already started */ | ||
838 | break; | ||
839 | case QH_STATE_IDLE: | ||
840 | WARN_ON(1); | ||
841 | break; | ||
842 | } | ||
810 | break; | 843 | break; |
811 | 844 | ||
812 | case PIPE_INTERRUPT: | 845 | case PIPE_INTERRUPT: |
@@ -829,16 +862,16 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
829 | /* reschedule QH iff another request is queued */ | 862 | /* reschedule QH iff another request is queued */ |
830 | if (!list_empty (&qh->qtd_list) | 863 | if (!list_empty (&qh->qtd_list) |
831 | && HC_IS_RUNNING (hcd->state)) { | 864 | && HC_IS_RUNNING (hcd->state)) { |
832 | int status; | 865 | int schedule_status; |
833 | 866 | ||
834 | status = qh_schedule (ehci, qh); | 867 | schedule_status = qh_schedule (ehci, qh); |
835 | spin_unlock_irqrestore (&ehci->lock, flags); | 868 | spin_unlock_irqrestore (&ehci->lock, flags); |
836 | 869 | ||
837 | if (status != 0) { | 870 | if (schedule_status != 0) { |
838 | // shouldn't happen often, but ... | 871 | // shouldn't happen often, but ... |
839 | // FIXME kill those tds' urbs | 872 | // FIXME kill those tds' urbs |
840 | err ("can't reschedule qh %p, err %d", | 873 | err ("can't reschedule qh %p, err %d", |
841 | qh, status); | 874 | qh, schedule_status); |
842 | } | 875 | } |
843 | return status; | 876 | return status; |
844 | } | 877 | } |
@@ -898,6 +931,7 @@ rescan: | |||
898 | unlink_async (ehci, qh); | 931 | unlink_async (ehci, qh); |
899 | /* FALL THROUGH */ | 932 | /* FALL THROUGH */ |
900 | case QH_STATE_UNLINK: /* wait for hw to finish? */ | 933 | case QH_STATE_UNLINK: /* wait for hw to finish? */ |
934 | case QH_STATE_UNLINK_WAIT: | ||
901 | idle_timeout: | 935 | idle_timeout: |
902 | spin_unlock_irqrestore (&ehci->lock, flags); | 936 | spin_unlock_irqrestore (&ehci->lock, flags); |
903 | schedule_timeout_uninterruptible(1); | 937 | schedule_timeout_uninterruptible(1); |
@@ -959,11 +993,26 @@ MODULE_LICENSE ("GPL"); | |||
959 | #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver | 993 | #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver |
960 | #endif | 994 | #endif |
961 | 995 | ||
962 | #ifdef CONFIG_440EPX | 996 | #if defined(CONFIG_440EPX) && !defined(CONFIG_PPC_MERGE) |
963 | #include "ehci-ppc-soc.c" | 997 | #include "ehci-ppc-soc.c" |
964 | #define PLATFORM_DRIVER ehci_ppc_soc_driver | 998 | #define PLATFORM_DRIVER ehci_ppc_soc_driver |
965 | #endif | 999 | #endif |
966 | 1000 | ||
1001 | #ifdef CONFIG_USB_EHCI_HCD_PPC_OF | ||
1002 | #include "ehci-ppc-of.c" | ||
1003 | #define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver | ||
1004 | #endif | ||
1005 | |||
1006 | #ifdef CONFIG_ARCH_ORION | ||
1007 | #include "ehci-orion.c" | ||
1008 | #define PLATFORM_DRIVER ehci_orion_driver | ||
1009 | #endif | ||
1010 | |||
1011 | #ifdef CONFIG_ARCH_IXP4XX | ||
1012 | #include "ehci-ixp4xx.c" | ||
1013 | #define PLATFORM_DRIVER ixp4xx_ehci_driver | ||
1014 | #endif | ||
1015 | |||
967 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ | 1016 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ |
968 | !defined(PS3_SYSTEM_BUS_DRIVER) | 1017 | !defined(PS3_SYSTEM_BUS_DRIVER) |
969 | #error "missing bus glue for ehci-hcd" | 1018 | #error "missing bus glue for ehci-hcd" |
@@ -978,41 +1027,66 @@ static int __init ehci_hcd_init(void) | |||
978 | sizeof(struct ehci_qh), sizeof(struct ehci_qtd), | 1027 | sizeof(struct ehci_qh), sizeof(struct ehci_qtd), |
979 | sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); | 1028 | sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); |
980 | 1029 | ||
1030 | #ifdef DEBUG | ||
1031 | ehci_debug_root = debugfs_create_dir("ehci", NULL); | ||
1032 | if (!ehci_debug_root) | ||
1033 | return -ENOENT; | ||
1034 | #endif | ||
1035 | |||
981 | #ifdef PLATFORM_DRIVER | 1036 | #ifdef PLATFORM_DRIVER |
982 | retval = platform_driver_register(&PLATFORM_DRIVER); | 1037 | retval = platform_driver_register(&PLATFORM_DRIVER); |
983 | if (retval < 0) | 1038 | if (retval < 0) |
984 | return retval; | 1039 | goto clean0; |
985 | #endif | 1040 | #endif |
986 | 1041 | ||
987 | #ifdef PCI_DRIVER | 1042 | #ifdef PCI_DRIVER |
988 | retval = pci_register_driver(&PCI_DRIVER); | 1043 | retval = pci_register_driver(&PCI_DRIVER); |
989 | if (retval < 0) { | 1044 | if (retval < 0) |
990 | #ifdef PLATFORM_DRIVER | 1045 | goto clean1; |
991 | platform_driver_unregister(&PLATFORM_DRIVER); | ||
992 | #endif | ||
993 | return retval; | ||
994 | } | ||
995 | #endif | 1046 | #endif |
996 | 1047 | ||
997 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1048 | #ifdef PS3_SYSTEM_BUS_DRIVER |
998 | retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER); | 1049 | retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER); |
999 | if (retval < 0) { | 1050 | if (retval < 0) |
1000 | #ifdef PLATFORM_DRIVER | 1051 | goto clean2; |
1001 | platform_driver_unregister(&PLATFORM_DRIVER); | 1052 | #endif |
1053 | |||
1054 | #ifdef OF_PLATFORM_DRIVER | ||
1055 | retval = of_register_platform_driver(&OF_PLATFORM_DRIVER); | ||
1056 | if (retval < 0) | ||
1057 | goto clean3; | ||
1058 | #endif | ||
1059 | return retval; | ||
1060 | |||
1061 | #ifdef OF_PLATFORM_DRIVER | ||
1062 | /* of_unregister_platform_driver(&OF_PLATFORM_DRIVER); */ | ||
1063 | clean3: | ||
1064 | #endif | ||
1065 | #ifdef PS3_SYSTEM_BUS_DRIVER | ||
1066 | ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | ||
1067 | clean2: | ||
1002 | #endif | 1068 | #endif |
1003 | #ifdef PCI_DRIVER | 1069 | #ifdef PCI_DRIVER |
1004 | pci_unregister_driver(&PCI_DRIVER); | 1070 | pci_unregister_driver(&PCI_DRIVER); |
1071 | clean1: | ||
1005 | #endif | 1072 | #endif |
1006 | return retval; | 1073 | #ifdef PLATFORM_DRIVER |
1007 | } | 1074 | platform_driver_unregister(&PLATFORM_DRIVER); |
1075 | clean0: | ||
1076 | #endif | ||
1077 | #ifdef DEBUG | ||
1078 | debugfs_remove(ehci_debug_root); | ||
1079 | ehci_debug_root = NULL; | ||
1008 | #endif | 1080 | #endif |
1009 | |||
1010 | return retval; | 1081 | return retval; |
1011 | } | 1082 | } |
1012 | module_init(ehci_hcd_init); | 1083 | module_init(ehci_hcd_init); |
1013 | 1084 | ||
1014 | static void __exit ehci_hcd_cleanup(void) | 1085 | static void __exit ehci_hcd_cleanup(void) |
1015 | { | 1086 | { |
1087 | #ifdef OF_PLATFORM_DRIVER | ||
1088 | of_unregister_platform_driver(&OF_PLATFORM_DRIVER); | ||
1089 | #endif | ||
1016 | #ifdef PLATFORM_DRIVER | 1090 | #ifdef PLATFORM_DRIVER |
1017 | platform_driver_unregister(&PLATFORM_DRIVER); | 1091 | platform_driver_unregister(&PLATFORM_DRIVER); |
1018 | #endif | 1092 | #endif |
@@ -1022,6 +1096,9 @@ static void __exit ehci_hcd_cleanup(void) | |||
1022 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1096 | #ifdef PS3_SYSTEM_BUS_DRIVER |
1023 | ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | 1097 | ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); |
1024 | #endif | 1098 | #endif |
1099 | #ifdef DEBUG | ||
1100 | debugfs_remove(ehci_debug_root); | ||
1101 | #endif | ||
1025 | } | 1102 | } |
1026 | module_exit(ehci_hcd_cleanup); | 1103 | module_exit(ehci_hcd_cleanup); |
1027 | 1104 | ||
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 735db4aec831..40e8240b7851 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -123,6 +123,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
123 | 123 | ||
124 | if (time_before (jiffies, ehci->next_statechange)) | 124 | if (time_before (jiffies, ehci->next_statechange)) |
125 | msleep(5); | 125 | msleep(5); |
126 | del_timer_sync(&ehci->watchdog); | ||
127 | del_timer_sync(&ehci->iaa_watchdog); | ||
126 | 128 | ||
127 | port = HCS_N_PORTS (ehci->hcs_params); | 129 | port = HCS_N_PORTS (ehci->hcs_params); |
128 | spin_lock_irq (&ehci->lock); | 130 | spin_lock_irq (&ehci->lock); |
@@ -134,7 +136,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
134 | } | 136 | } |
135 | ehci->command = ehci_readl(ehci, &ehci->regs->command); | 137 | ehci->command = ehci_readl(ehci, &ehci->regs->command); |
136 | if (ehci->reclaim) | 138 | if (ehci->reclaim) |
137 | ehci->reclaim_ready = 1; | 139 | end_unlink_async(ehci); |
138 | ehci_work(ehci); | 140 | ehci_work(ehci); |
139 | 141 | ||
140 | /* Unlike other USB host controller types, EHCI doesn't have | 142 | /* Unlike other USB host controller types, EHCI doesn't have |
@@ -170,8 +172,11 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
170 | } | 172 | } |
171 | } | 173 | } |
172 | 174 | ||
175 | /* Apparently some devices need a >= 1-uframe delay here */ | ||
176 | if (ehci->bus_suspended) | ||
177 | udelay(150); | ||
178 | |||
173 | /* turn off now-idle HC */ | 179 | /* turn off now-idle HC */ |
174 | del_timer_sync (&ehci->watchdog); | ||
175 | ehci_halt (ehci); | 180 | ehci_halt (ehci); |
176 | hcd->state = HC_STATE_SUSPENDED; | 181 | hcd->state = HC_STATE_SUSPENDED; |
177 | 182 | ||
@@ -291,14 +296,16 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
291 | /*-------------------------------------------------------------------------*/ | 296 | /*-------------------------------------------------------------------------*/ |
292 | 297 | ||
293 | /* Display the ports dedicated to the companion controller */ | 298 | /* Display the ports dedicated to the companion controller */ |
294 | static ssize_t show_companion(struct class_device *class_dev, char *buf) | 299 | static ssize_t show_companion(struct device *dev, |
300 | struct device_attribute *attr, | ||
301 | char *buf) | ||
295 | { | 302 | { |
296 | struct ehci_hcd *ehci; | 303 | struct ehci_hcd *ehci; |
297 | int nports, index, n; | 304 | int nports, index, n; |
298 | int count = PAGE_SIZE; | 305 | int count = PAGE_SIZE; |
299 | char *ptr = buf; | 306 | char *ptr = buf; |
300 | 307 | ||
301 | ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev))); | 308 | ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); |
302 | nports = HCS_N_PORTS(ehci->hcs_params); | 309 | nports = HCS_N_PORTS(ehci->hcs_params); |
303 | 310 | ||
304 | for (index = 0; index < nports; ++index) { | 311 | for (index = 0; index < nports; ++index) { |
@@ -312,40 +319,21 @@ static ssize_t show_companion(struct class_device *class_dev, char *buf) | |||
312 | } | 319 | } |
313 | 320 | ||
314 | /* | 321 | /* |
315 | * Dedicate or undedicate a port to the companion controller. | 322 | * Sets the owner of a port |
316 | * Syntax is "[-]portnum", where a leading '-' sign means | ||
317 | * return control of the port to the EHCI controller. | ||
318 | */ | 323 | */ |
319 | static ssize_t store_companion(struct class_device *class_dev, | 324 | static void set_owner(struct ehci_hcd *ehci, int portnum, int new_owner) |
320 | const char *buf, size_t count) | ||
321 | { | 325 | { |
322 | struct ehci_hcd *ehci; | ||
323 | int portnum, new_owner, try; | ||
324 | u32 __iomem *status_reg; | 326 | u32 __iomem *status_reg; |
325 | u32 port_status; | 327 | u32 port_status; |
328 | int try; | ||
326 | 329 | ||
327 | ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev))); | 330 | status_reg = &ehci->regs->port_status[portnum]; |
328 | new_owner = PORT_OWNER; /* Owned by companion */ | ||
329 | if (sscanf(buf, "%d", &portnum) != 1) | ||
330 | return -EINVAL; | ||
331 | if (portnum < 0) { | ||
332 | portnum = - portnum; | ||
333 | new_owner = 0; /* Owned by EHCI */ | ||
334 | } | ||
335 | if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params)) | ||
336 | return -ENOENT; | ||
337 | status_reg = &ehci->regs->port_status[--portnum]; | ||
338 | if (new_owner) | ||
339 | set_bit(portnum, &ehci->companion_ports); | ||
340 | else | ||
341 | clear_bit(portnum, &ehci->companion_ports); | ||
342 | 331 | ||
343 | /* | 332 | /* |
344 | * The controller won't set the OWNER bit if the port is | 333 | * The controller won't set the OWNER bit if the port is |
345 | * enabled, so this loop will sometimes require at least two | 334 | * enabled, so this loop will sometimes require at least two |
346 | * iterations: one to disable the port and one to set OWNER. | 335 | * iterations: one to disable the port and one to set OWNER. |
347 | */ | 336 | */ |
348 | |||
349 | for (try = 4; try > 0; --try) { | 337 | for (try = 4; try > 0; --try) { |
350 | spin_lock_irq(&ehci->lock); | 338 | spin_lock_irq(&ehci->lock); |
351 | port_status = ehci_readl(ehci, status_reg); | 339 | port_status = ehci_readl(ehci, status_reg); |
@@ -362,9 +350,39 @@ static ssize_t store_companion(struct class_device *class_dev, | |||
362 | if (try > 1) | 350 | if (try > 1) |
363 | msleep(5); | 351 | msleep(5); |
364 | } | 352 | } |
353 | } | ||
354 | |||
355 | /* | ||
356 | * Dedicate or undedicate a port to the companion controller. | ||
357 | * Syntax is "[-]portnum", where a leading '-' sign means | ||
358 | * return control of the port to the EHCI controller. | ||
359 | */ | ||
360 | static ssize_t store_companion(struct device *dev, | ||
361 | struct device_attribute *attr, | ||
362 | const char *buf, size_t count) | ||
363 | { | ||
364 | struct ehci_hcd *ehci; | ||
365 | int portnum, new_owner; | ||
366 | |||
367 | ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); | ||
368 | new_owner = PORT_OWNER; /* Owned by companion */ | ||
369 | if (sscanf(buf, "%d", &portnum) != 1) | ||
370 | return -EINVAL; | ||
371 | if (portnum < 0) { | ||
372 | portnum = - portnum; | ||
373 | new_owner = 0; /* Owned by EHCI */ | ||
374 | } | ||
375 | if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params)) | ||
376 | return -ENOENT; | ||
377 | portnum--; | ||
378 | if (new_owner) | ||
379 | set_bit(portnum, &ehci->companion_ports); | ||
380 | else | ||
381 | clear_bit(portnum, &ehci->companion_ports); | ||
382 | set_owner(ehci, portnum, new_owner); | ||
365 | return count; | 383 | return count; |
366 | } | 384 | } |
367 | static CLASS_DEVICE_ATTR(companion, 0644, show_companion, store_companion); | 385 | static DEVICE_ATTR(companion, 0644, show_companion, store_companion); |
368 | 386 | ||
369 | static inline void create_companion_file(struct ehci_hcd *ehci) | 387 | static inline void create_companion_file(struct ehci_hcd *ehci) |
370 | { | 388 | { |
@@ -372,16 +390,16 @@ static inline void create_companion_file(struct ehci_hcd *ehci) | |||
372 | 390 | ||
373 | /* with integrated TT there is no companion! */ | 391 | /* with integrated TT there is no companion! */ |
374 | if (!ehci_is_TDI(ehci)) | 392 | if (!ehci_is_TDI(ehci)) |
375 | i = class_device_create_file(ehci_to_hcd(ehci)->self.class_dev, | 393 | i = device_create_file(ehci_to_hcd(ehci)->self.dev, |
376 | &class_device_attr_companion); | 394 | &dev_attr_companion); |
377 | } | 395 | } |
378 | 396 | ||
379 | static inline void remove_companion_file(struct ehci_hcd *ehci) | 397 | static inline void remove_companion_file(struct ehci_hcd *ehci) |
380 | { | 398 | { |
381 | /* with integrated TT there is no companion! */ | 399 | /* with integrated TT there is no companion! */ |
382 | if (!ehci_is_TDI(ehci)) | 400 | if (!ehci_is_TDI(ehci)) |
383 | class_device_remove_file(ehci_to_hcd(ehci)->self.class_dev, | 401 | device_remove_file(ehci_to_hcd(ehci)->self.dev, |
384 | &class_device_attr_companion); | 402 | &dev_attr_companion); |
385 | } | 403 | } |
386 | 404 | ||
387 | 405 | ||
@@ -393,10 +411,8 @@ static int check_reset_complete ( | |||
393 | u32 __iomem *status_reg, | 411 | u32 __iomem *status_reg, |
394 | int port_status | 412 | int port_status |
395 | ) { | 413 | ) { |
396 | if (!(port_status & PORT_CONNECT)) { | 414 | if (!(port_status & PORT_CONNECT)) |
397 | ehci->reset_done [index] = 0; | ||
398 | return port_status; | 415 | return port_status; |
399 | } | ||
400 | 416 | ||
401 | /* if reset finished and it's still not enabled -- handoff */ | 417 | /* if reset finished and it's still not enabled -- handoff */ |
402 | if (!(port_status & PORT_PE)) { | 418 | if (!(port_status & PORT_PE)) { |
@@ -475,8 +491,6 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
475 | * controller by the user. | 491 | * controller by the user. |
476 | */ | 492 | */ |
477 | 493 | ||
478 | if (!(temp & PORT_CONNECT)) | ||
479 | ehci->reset_done [i] = 0; | ||
480 | if ((temp & mask) != 0 | 494 | if ((temp & mask) != 0 |
481 | || ((temp & PORT_RESUME) != 0 | 495 | || ((temp & PORT_RESUME) != 0 |
482 | && time_after_eq(jiffies, | 496 | && time_after_eq(jiffies, |
@@ -864,3 +878,13 @@ error: | |||
864 | spin_unlock_irqrestore (&ehci->lock, flags); | 878 | spin_unlock_irqrestore (&ehci->lock, flags); |
865 | return retval; | 879 | return retval; |
866 | } | 880 | } |
881 | |||
882 | static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) | ||
883 | { | ||
884 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
885 | |||
886 | if (ehci_is_TDI(ehci)) | ||
887 | return; | ||
888 | set_owner(ehci, --portnum, PORT_OWNER); | ||
889 | } | ||
890 | |||
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c new file mode 100644 index 000000000000..3041d8f055f4 --- /dev/null +++ b/drivers/usb/host/ehci-ixp4xx.c | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | * IXP4XX EHCI Host Controller Driver | ||
3 | * | ||
4 | * Author: Vladimir Barinov <vbarinov@ru.mvista.com> | ||
5 | * | ||
6 | * Based on "ehci-fsl.c" by Randy Vinson <rvinson@mvista.com> | ||
7 | * | ||
8 | * 2007 (c) MontaVista Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/platform_device.h> | ||
15 | |||
16 | static int ixp4xx_ehci_init(struct usb_hcd *hcd) | ||
17 | { | ||
18 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
19 | int retval = 0; | ||
20 | |||
21 | ehci->big_endian_desc = 1; | ||
22 | ehci->big_endian_mmio = 1; | ||
23 | |||
24 | ehci->caps = hcd->regs + 0x100; | ||
25 | ehci->regs = hcd->regs + 0x100 | ||
26 | + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
27 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
28 | |||
29 | ehci->is_tdi_rh_tt = 1; | ||
30 | ehci_reset(ehci); | ||
31 | |||
32 | retval = ehci_init(hcd); | ||
33 | if (retval) | ||
34 | return retval; | ||
35 | |||
36 | ehci_port_power(ehci, 0); | ||
37 | |||
38 | return retval; | ||
39 | } | ||
40 | |||
41 | static const struct hc_driver ixp4xx_ehci_hc_driver = { | ||
42 | .description = hcd_name, | ||
43 | .product_desc = "IXP4XX EHCI Host Controller", | ||
44 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
45 | .irq = ehci_irq, | ||
46 | .flags = HCD_MEMORY | HCD_USB2, | ||
47 | .reset = ixp4xx_ehci_init, | ||
48 | .start = ehci_run, | ||
49 | .stop = ehci_stop, | ||
50 | .shutdown = ehci_shutdown, | ||
51 | .urb_enqueue = ehci_urb_enqueue, | ||
52 | .urb_dequeue = ehci_urb_dequeue, | ||
53 | .endpoint_disable = ehci_endpoint_disable, | ||
54 | .get_frame_number = ehci_get_frame, | ||
55 | .hub_status_data = ehci_hub_status_data, | ||
56 | .hub_control = ehci_hub_control, | ||
57 | #if defined(CONFIG_PM) | ||
58 | .bus_suspend = ehci_bus_suspend, | ||
59 | .bus_resume = ehci_bus_resume, | ||
60 | #endif | ||
61 | }; | ||
62 | |||
63 | static int ixp4xx_ehci_probe(struct platform_device *pdev) | ||
64 | { | ||
65 | struct usb_hcd *hcd; | ||
66 | const struct hc_driver *driver = &ixp4xx_ehci_hc_driver; | ||
67 | struct resource *res; | ||
68 | int irq; | ||
69 | int retval; | ||
70 | |||
71 | if (usb_disabled()) | ||
72 | return -ENODEV; | ||
73 | |||
74 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
75 | if (!res) { | ||
76 | dev_err(&pdev->dev, | ||
77 | "Found HC with no IRQ. Check %s setup!\n", | ||
78 | pdev->dev.bus_id); | ||
79 | return -ENODEV; | ||
80 | } | ||
81 | irq = res->start; | ||
82 | |||
83 | hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id); | ||
84 | if (!hcd) { | ||
85 | retval = -ENOMEM; | ||
86 | goto fail_create_hcd; | ||
87 | } | ||
88 | |||
89 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
90 | if (!res) { | ||
91 | dev_err(&pdev->dev, | ||
92 | "Found HC with no register addr. Check %s setup!\n", | ||
93 | pdev->dev.bus_id); | ||
94 | retval = -ENODEV; | ||
95 | goto fail_request_resource; | ||
96 | } | ||
97 | hcd->rsrc_start = res->start; | ||
98 | hcd->rsrc_len = res->end - res->start + 1; | ||
99 | |||
100 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, | ||
101 | driver->description)) { | ||
102 | dev_dbg(&pdev->dev, "controller already in use\n"); | ||
103 | retval = -EBUSY; | ||
104 | goto fail_request_resource; | ||
105 | } | ||
106 | |||
107 | hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); | ||
108 | if (hcd->regs == NULL) { | ||
109 | dev_dbg(&pdev->dev, "error mapping memory\n"); | ||
110 | retval = -EFAULT; | ||
111 | goto fail_ioremap; | ||
112 | } | ||
113 | |||
114 | retval = usb_add_hcd(hcd, irq, IRQF_SHARED); | ||
115 | if (retval) | ||
116 | goto fail_add_hcd; | ||
117 | |||
118 | return retval; | ||
119 | |||
120 | fail_add_hcd: | ||
121 | iounmap(hcd->regs); | ||
122 | fail_ioremap: | ||
123 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
124 | fail_request_resource: | ||
125 | usb_put_hcd(hcd); | ||
126 | fail_create_hcd: | ||
127 | dev_err(&pdev->dev, "init %s fail, %d\n", pdev->dev.bus_id, retval); | ||
128 | return retval; | ||
129 | } | ||
130 | |||
131 | static int ixp4xx_ehci_remove(struct platform_device *pdev) | ||
132 | { | ||
133 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
134 | |||
135 | usb_remove_hcd(hcd); | ||
136 | iounmap(hcd->regs); | ||
137 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
138 | usb_put_hcd(hcd); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | MODULE_ALIAS("ixp4xx-ehci"); | ||
144 | |||
145 | static struct platform_driver ixp4xx_ehci_driver = { | ||
146 | .probe = ixp4xx_ehci_probe, | ||
147 | .remove = ixp4xx_ehci_remove, | ||
148 | .driver = { | ||
149 | .name = "ixp4xx-ehci", | ||
150 | .bus = &platform_bus_type | ||
151 | }, | ||
152 | }; | ||
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c new file mode 100644 index 000000000000..e129981f139f --- /dev/null +++ b/drivers/usb/host/ehci-orion.c | |||
@@ -0,0 +1,272 @@ | |||
1 | /* | ||
2 | * drivers/usb/host/ehci-orion.c | ||
3 | * | ||
4 | * Tzachi Perelstein <tzachi@marvell.com> | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public | ||
7 | * License version 2. This program is licensed "as is" without any | ||
8 | * warranty of any kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <asm/arch/orion.h> | ||
15 | |||
16 | #define rdl(off) __raw_readl(hcd->regs + (off)) | ||
17 | #define wrl(off, val) __raw_writel((val), hcd->regs + (off)) | ||
18 | |||
19 | #define USB_CAUSE 0x310 | ||
20 | #define USB_MASK 0x314 | ||
21 | #define USB_CMD 0x140 | ||
22 | #define USB_MODE 0x1a8 | ||
23 | #define USB_IPG 0x360 | ||
24 | #define USB_PHY_PWR_CTRL 0x400 | ||
25 | #define USB_PHY_TX_CTRL 0x420 | ||
26 | #define USB_PHY_RX_CTRL 0x430 | ||
27 | #define USB_PHY_IVREF_CTRL 0x440 | ||
28 | #define USB_PHY_TST_GRP_CTRL 0x450 | ||
29 | |||
30 | /* | ||
31 | * Implement Orion USB controller specification guidelines | ||
32 | */ | ||
33 | static void orion_usb_setup(struct usb_hcd *hcd) | ||
34 | { | ||
35 | /* | ||
36 | * Clear interrupt cause and mask | ||
37 | */ | ||
38 | wrl(USB_CAUSE, 0); | ||
39 | wrl(USB_MASK, 0); | ||
40 | |||
41 | /* | ||
42 | * Reset controller | ||
43 | */ | ||
44 | wrl(USB_CMD, rdl(USB_CMD) | 0x2); | ||
45 | while (rdl(USB_CMD) & 0x2); | ||
46 | |||
47 | /* | ||
48 | * GL# USB-10: Set IPG for non start of frame packets | ||
49 | * Bits[14:8]=0xc | ||
50 | */ | ||
51 | wrl(USB_IPG, (rdl(USB_IPG) & ~0x7f00) | 0xc00); | ||
52 | |||
53 | /* | ||
54 | * GL# USB-9: USB 2.0 Power Control | ||
55 | * BG_VSEL[7:6]=0x1 | ||
56 | */ | ||
57 | wrl(USB_PHY_PWR_CTRL, (rdl(USB_PHY_PWR_CTRL) & ~0xc0)| 0x40); | ||
58 | |||
59 | /* | ||
60 | * GL# USB-1: USB PHY Tx Control - force calibration to '8' | ||
61 | * TXDATA_BLOCK_EN[21]=0x1, EXT_RCAL_EN[13]=0x1, IMP_CAL[6:3]=0x8 | ||
62 | */ | ||
63 | wrl(USB_PHY_TX_CTRL, (rdl(USB_PHY_TX_CTRL) & ~0x78) | 0x202040); | ||
64 | |||
65 | /* | ||
66 | * GL# USB-3 GL# USB-9: USB PHY Rx Control | ||
67 | * RXDATA_BLOCK_LENGHT[31:30]=0x3, EDGE_DET_SEL[27:26]=0, | ||
68 | * CDR_FASTLOCK_EN[21]=0, DISCON_THRESHOLD[9:8]=0, SQ_THRESH[7:4]=0x1 | ||
69 | */ | ||
70 | wrl(USB_PHY_RX_CTRL, (rdl(USB_PHY_RX_CTRL) & ~0xc2003f0) | 0xc0000010); | ||
71 | |||
72 | /* | ||
73 | * GL# USB-3 GL# USB-9: USB PHY IVREF Control | ||
74 | * PLLVDD12[1:0]=0x2, RXVDD[5:4]=0x3, Reserved[19]=0 | ||
75 | */ | ||
76 | wrl(USB_PHY_IVREF_CTRL, (rdl(USB_PHY_IVREF_CTRL) & ~0x80003 ) | 0x32); | ||
77 | |||
78 | /* | ||
79 | * GL# USB-3 GL# USB-9: USB PHY Test Group Control | ||
80 | * REG_FIFO_SQ_RST[15]=0 | ||
81 | */ | ||
82 | wrl(USB_PHY_TST_GRP_CTRL, rdl(USB_PHY_TST_GRP_CTRL) & ~0x8000); | ||
83 | |||
84 | /* | ||
85 | * Stop and reset controller | ||
86 | */ | ||
87 | wrl(USB_CMD, rdl(USB_CMD) & ~0x1); | ||
88 | wrl(USB_CMD, rdl(USB_CMD) | 0x2); | ||
89 | while (rdl(USB_CMD) & 0x2); | ||
90 | |||
91 | /* | ||
92 | * GL# USB-5 Streaming disable REG_USB_MODE[4]=1 | ||
93 | * TBD: This need to be done after each reset! | ||
94 | * GL# USB-4 Setup USB Host mode | ||
95 | */ | ||
96 | wrl(USB_MODE, 0x13); | ||
97 | } | ||
98 | |||
99 | static int ehci_orion_setup(struct usb_hcd *hcd) | ||
100 | { | ||
101 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
102 | int retval; | ||
103 | |||
104 | retval = ehci_halt(ehci); | ||
105 | if (retval) | ||
106 | return retval; | ||
107 | |||
108 | /* | ||
109 | * data structure init | ||
110 | */ | ||
111 | retval = ehci_init(hcd); | ||
112 | if (retval) | ||
113 | return retval; | ||
114 | |||
115 | ehci_reset(ehci); | ||
116 | ehci_port_power(ehci, 0); | ||
117 | |||
118 | return retval; | ||
119 | } | ||
120 | |||
121 | static const struct hc_driver ehci_orion_hc_driver = { | ||
122 | .description = hcd_name, | ||
123 | .product_desc = "Marvell Orion EHCI", | ||
124 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
125 | |||
126 | /* | ||
127 | * generic hardware linkage | ||
128 | */ | ||
129 | .irq = ehci_irq, | ||
130 | .flags = HCD_MEMORY | HCD_USB2, | ||
131 | |||
132 | /* | ||
133 | * basic lifecycle operations | ||
134 | */ | ||
135 | .reset = ehci_orion_setup, | ||
136 | .start = ehci_run, | ||
137 | #ifdef CONFIG_PM | ||
138 | .suspend = ehci_bus_suspend, | ||
139 | .resume = ehci_bus_resume, | ||
140 | #endif | ||
141 | .stop = ehci_stop, | ||
142 | .shutdown = ehci_shutdown, | ||
143 | |||
144 | /* | ||
145 | * managing i/o requests and associated device resources | ||
146 | */ | ||
147 | .urb_enqueue = ehci_urb_enqueue, | ||
148 | .urb_dequeue = ehci_urb_dequeue, | ||
149 | .endpoint_disable = ehci_endpoint_disable, | ||
150 | |||
151 | /* | ||
152 | * scheduling support | ||
153 | */ | ||
154 | .get_frame_number = ehci_get_frame, | ||
155 | |||
156 | /* | ||
157 | * root hub support | ||
158 | */ | ||
159 | .hub_status_data = ehci_hub_status_data, | ||
160 | .hub_control = ehci_hub_control, | ||
161 | .bus_suspend = ehci_bus_suspend, | ||
162 | .bus_resume = ehci_bus_resume, | ||
163 | }; | ||
164 | |||
165 | static int __init ehci_orion_drv_probe(struct platform_device *pdev) | ||
166 | { | ||
167 | struct resource *res; | ||
168 | struct usb_hcd *hcd; | ||
169 | struct ehci_hcd *ehci; | ||
170 | void __iomem *regs; | ||
171 | int irq, err; | ||
172 | |||
173 | if (usb_disabled()) | ||
174 | return -ENODEV; | ||
175 | |||
176 | pr_debug("Initializing Orion-SoC USB Host Controller\n"); | ||
177 | |||
178 | irq = platform_get_irq(pdev, 0); | ||
179 | if (irq <= 0) { | ||
180 | dev_err(&pdev->dev, | ||
181 | "Found HC with no IRQ. Check %s setup!\n", | ||
182 | pdev->dev.bus_id); | ||
183 | err = -ENODEV; | ||
184 | goto err1; | ||
185 | } | ||
186 | |||
187 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
188 | if (!res) { | ||
189 | dev_err(&pdev->dev, | ||
190 | "Found HC with no register addr. Check %s setup!\n", | ||
191 | pdev->dev.bus_id); | ||
192 | err = -ENODEV; | ||
193 | goto err1; | ||
194 | } | ||
195 | |||
196 | if (!request_mem_region(res->start, res->end - res->start + 1, | ||
197 | ehci_orion_hc_driver.description)) { | ||
198 | dev_dbg(&pdev->dev, "controller already in use\n"); | ||
199 | err = -EBUSY; | ||
200 | goto err1; | ||
201 | } | ||
202 | |||
203 | regs = ioremap(res->start, res->end - res->start + 1); | ||
204 | if (regs == NULL) { | ||
205 | dev_dbg(&pdev->dev, "error mapping memory\n"); | ||
206 | err = -EFAULT; | ||
207 | goto err2; | ||
208 | } | ||
209 | |||
210 | hcd = usb_create_hcd(&ehci_orion_hc_driver, | ||
211 | &pdev->dev, pdev->dev.bus_id); | ||
212 | if (!hcd) { | ||
213 | err = -ENOMEM; | ||
214 | goto err3; | ||
215 | } | ||
216 | |||
217 | hcd->rsrc_start = res->start; | ||
218 | hcd->rsrc_len = res->end - res->start + 1; | ||
219 | hcd->regs = regs; | ||
220 | |||
221 | ehci = hcd_to_ehci(hcd); | ||
222 | ehci->caps = hcd->regs + 0x100; | ||
223 | ehci->regs = hcd->regs + 0x100 + | ||
224 | HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
225 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
226 | ehci->is_tdi_rh_tt = 1; | ||
227 | ehci->sbrn = 0x20; | ||
228 | |||
229 | /* | ||
230 | * setup Orion USB controller | ||
231 | */ | ||
232 | orion_usb_setup(hcd); | ||
233 | |||
234 | err = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED); | ||
235 | if (err) | ||
236 | goto err4; | ||
237 | |||
238 | return 0; | ||
239 | |||
240 | err4: | ||
241 | usb_put_hcd(hcd); | ||
242 | err3: | ||
243 | iounmap(regs); | ||
244 | err2: | ||
245 | release_mem_region(res->start, res->end - res->start + 1); | ||
246 | err1: | ||
247 | dev_err(&pdev->dev, "init %s fail, %d\n", | ||
248 | pdev->dev.bus_id, err); | ||
249 | |||
250 | return err; | ||
251 | } | ||
252 | |||
253 | static int __exit ehci_orion_drv_remove(struct platform_device *pdev) | ||
254 | { | ||
255 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
256 | |||
257 | usb_remove_hcd(hcd); | ||
258 | iounmap(hcd->regs); | ||
259 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
260 | usb_put_hcd(hcd); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | MODULE_ALIAS("platform:orion-ehci"); | ||
266 | |||
267 | static struct platform_driver ehci_orion_driver = { | ||
268 | .probe = ehci_orion_drv_probe, | ||
269 | .remove = __exit_p(ehci_orion_drv_remove), | ||
270 | .shutdown = usb_hcd_platform_shutdown, | ||
271 | .driver.name = "orion-ehci", | ||
272 | }; | ||
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index ad0d4965f2fb..3ba01664f821 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -305,7 +305,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd) | |||
305 | /* emptying the schedule aborts any urbs */ | 305 | /* emptying the schedule aborts any urbs */ |
306 | spin_lock_irq(&ehci->lock); | 306 | spin_lock_irq(&ehci->lock); |
307 | if (ehci->reclaim) | 307 | if (ehci->reclaim) |
308 | ehci->reclaim_ready = 1; | 308 | end_unlink_async(ehci); |
309 | ehci_work(ehci); | 309 | ehci_work(ehci); |
310 | spin_unlock_irq(&ehci->lock); | 310 | spin_unlock_irq(&ehci->lock); |
311 | 311 | ||
@@ -364,6 +364,7 @@ static const struct hc_driver ehci_pci_hc_driver = { | |||
364 | .hub_control = ehci_hub_control, | 364 | .hub_control = ehci_hub_control, |
365 | .bus_suspend = ehci_bus_suspend, | 365 | .bus_suspend = ehci_bus_suspend, |
366 | .bus_resume = ehci_bus_resume, | 366 | .bus_resume = ehci_bus_resume, |
367 | .relinquish_port = ehci_relinquish_port, | ||
367 | }; | 368 | }; |
368 | 369 | ||
369 | /*-------------------------------------------------------------------------*/ | 370 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c new file mode 100644 index 000000000000..ee305b1f99ff --- /dev/null +++ b/drivers/usb/host/ehci-ppc-of.c | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | * EHCI HCD (Host Controller Driver) for USB. | ||
3 | * | ||
4 | * Bus Glue for PPC On-Chip EHCI driver on the of_platform bus | ||
5 | * Tested on AMCC PPC 440EPx | ||
6 | * | ||
7 | * Valentine Barshak <vbarshak@ru.mvista.com> | ||
8 | * | ||
9 | * Based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de> | ||
10 | * and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com> | ||
11 | * | ||
12 | * This file is licenced under the GPL. | ||
13 | */ | ||
14 | |||
15 | #include <linux/signal.h> | ||
16 | |||
17 | #include <linux/of.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | |||
20 | /* called during probe() after chip reset completes */ | ||
21 | static int ehci_ppc_of_setup(struct usb_hcd *hcd) | ||
22 | { | ||
23 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
24 | int retval; | ||
25 | |||
26 | retval = ehci_halt(ehci); | ||
27 | if (retval) | ||
28 | return retval; | ||
29 | |||
30 | retval = ehci_init(hcd); | ||
31 | if (retval) | ||
32 | return retval; | ||
33 | |||
34 | ehci->sbrn = 0x20; | ||
35 | return ehci_reset(ehci); | ||
36 | } | ||
37 | |||
38 | |||
39 | static const struct hc_driver ehci_ppc_of_hc_driver = { | ||
40 | .description = hcd_name, | ||
41 | .product_desc = "OF EHCI", | ||
42 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
43 | |||
44 | /* | ||
45 | * generic hardware linkage | ||
46 | */ | ||
47 | .irq = ehci_irq, | ||
48 | .flags = HCD_MEMORY | HCD_USB2, | ||
49 | |||
50 | /* | ||
51 | * basic lifecycle operations | ||
52 | */ | ||
53 | .reset = ehci_ppc_of_setup, | ||
54 | .start = ehci_run, | ||
55 | .stop = ehci_stop, | ||
56 | .shutdown = ehci_shutdown, | ||
57 | |||
58 | /* | ||
59 | * managing i/o requests and associated device resources | ||
60 | */ | ||
61 | .urb_enqueue = ehci_urb_enqueue, | ||
62 | .urb_dequeue = ehci_urb_dequeue, | ||
63 | .endpoint_disable = ehci_endpoint_disable, | ||
64 | |||
65 | /* | ||
66 | * scheduling support | ||
67 | */ | ||
68 | .get_frame_number = ehci_get_frame, | ||
69 | |||
70 | /* | ||
71 | * root hub support | ||
72 | */ | ||
73 | .hub_status_data = ehci_hub_status_data, | ||
74 | .hub_control = ehci_hub_control, | ||
75 | #ifdef CONFIG_PM | ||
76 | .bus_suspend = ehci_bus_suspend, | ||
77 | .bus_resume = ehci_bus_resume, | ||
78 | #endif | ||
79 | }; | ||
80 | |||
81 | |||
82 | /* | ||
83 | * 440EPx Errata USBH_3 | ||
84 | * Fix: Enable Break Memory Transfer (BMT) in INSNREG3 | ||
85 | */ | ||
86 | #define PPC440EPX_EHCI0_INSREG_BMT (0x1 << 0) | ||
87 | static int __devinit | ||
88 | ppc44x_enable_bmt(struct device_node *dn) | ||
89 | { | ||
90 | __iomem u32 *insreg_virt; | ||
91 | |||
92 | insreg_virt = of_iomap(dn, 1); | ||
93 | if (!insreg_virt) | ||
94 | return -EINVAL; | ||
95 | |||
96 | out_be32(insreg_virt + 3, PPC440EPX_EHCI0_INSREG_BMT); | ||
97 | |||
98 | iounmap(insreg_virt); | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | |||
103 | static int __devinit | ||
104 | ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) | ||
105 | { | ||
106 | struct device_node *dn = op->node; | ||
107 | struct usb_hcd *hcd; | ||
108 | struct ehci_hcd *ehci; | ||
109 | struct resource res; | ||
110 | int irq; | ||
111 | int rv; | ||
112 | |||
113 | if (usb_disabled()) | ||
114 | return -ENODEV; | ||
115 | |||
116 | dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n"); | ||
117 | |||
118 | rv = of_address_to_resource(dn, 0, &res); | ||
119 | if (rv) | ||
120 | return rv; | ||
121 | |||
122 | hcd = usb_create_hcd(&ehci_ppc_of_hc_driver, &op->dev, "PPC-OF USB"); | ||
123 | if (!hcd) | ||
124 | return -ENOMEM; | ||
125 | |||
126 | hcd->rsrc_start = res.start; | ||
127 | hcd->rsrc_len = res.end - res.start + 1; | ||
128 | |||
129 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
130 | printk(KERN_ERR __FILE__ ": request_mem_region failed\n"); | ||
131 | rv = -EBUSY; | ||
132 | goto err_rmr; | ||
133 | } | ||
134 | |||
135 | irq = irq_of_parse_and_map(dn, 0); | ||
136 | if (irq == NO_IRQ) { | ||
137 | printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n"); | ||
138 | rv = -EBUSY; | ||
139 | goto err_irq; | ||
140 | } | ||
141 | |||
142 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
143 | if (!hcd->regs) { | ||
144 | printk(KERN_ERR __FILE__ ": ioremap failed\n"); | ||
145 | rv = -ENOMEM; | ||
146 | goto err_ioremap; | ||
147 | } | ||
148 | |||
149 | ehci = hcd_to_ehci(hcd); | ||
150 | |||
151 | if (of_get_property(dn, "big-endian", NULL)) { | ||
152 | ehci->big_endian_mmio = 1; | ||
153 | ehci->big_endian_desc = 1; | ||
154 | } | ||
155 | if (of_get_property(dn, "big-endian-regs", NULL)) | ||
156 | ehci->big_endian_mmio = 1; | ||
157 | if (of_get_property(dn, "big-endian-desc", NULL)) | ||
158 | ehci->big_endian_desc = 1; | ||
159 | |||
160 | ehci->caps = hcd->regs; | ||
161 | ehci->regs = hcd->regs + | ||
162 | HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
163 | |||
164 | /* cache this readonly data; minimize chip reads */ | ||
165 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
166 | |||
167 | if (of_device_is_compatible(dn, "ibm,usb-ehci-440epx")) { | ||
168 | rv = ppc44x_enable_bmt(dn); | ||
169 | ehci_dbg(ehci, "Break Memory Transfer (BMT) is %senabled!\n", | ||
170 | rv ? "NOT ": ""); | ||
171 | } | ||
172 | |||
173 | rv = usb_add_hcd(hcd, irq, 0); | ||
174 | if (rv == 0) | ||
175 | return 0; | ||
176 | |||
177 | iounmap(hcd->regs); | ||
178 | err_ioremap: | ||
179 | irq_dispose_mapping(irq); | ||
180 | err_irq: | ||
181 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
182 | err_rmr: | ||
183 | usb_put_hcd(hcd); | ||
184 | |||
185 | return rv; | ||
186 | } | ||
187 | |||
188 | |||
189 | static int ehci_hcd_ppc_of_remove(struct of_device *op) | ||
190 | { | ||
191 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | ||
192 | dev_set_drvdata(&op->dev, NULL); | ||
193 | |||
194 | dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n"); | ||
195 | |||
196 | usb_remove_hcd(hcd); | ||
197 | |||
198 | iounmap(hcd->regs); | ||
199 | irq_dispose_mapping(hcd->irq); | ||
200 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
201 | |||
202 | usb_put_hcd(hcd); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | |||
208 | static int ehci_hcd_ppc_of_shutdown(struct of_device *op) | ||
209 | { | ||
210 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | ||
211 | |||
212 | if (hcd->driver->shutdown) | ||
213 | hcd->driver->shutdown(hcd); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | |||
219 | static struct of_device_id ehci_hcd_ppc_of_match[] = { | ||
220 | { | ||
221 | .compatible = "usb-ehci", | ||
222 | }, | ||
223 | {}, | ||
224 | }; | ||
225 | MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match); | ||
226 | |||
227 | |||
228 | static struct of_platform_driver ehci_hcd_ppc_of_driver = { | ||
229 | .name = "ppc-of-ehci", | ||
230 | .match_table = ehci_hcd_ppc_of_match, | ||
231 | .probe = ehci_hcd_ppc_of_probe, | ||
232 | .remove = ehci_hcd_ppc_of_remove, | ||
233 | .shutdown = ehci_hcd_ppc_of_shutdown, | ||
234 | .driver = { | ||
235 | .name = "ppc-of-ehci", | ||
236 | .owner = THIS_MODULE, | ||
237 | }, | ||
238 | }; | ||
diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c index 452d4b1bc859..a3249078c808 100644 --- a/drivers/usb/host/ehci-ppc-soc.c +++ b/drivers/usb/host/ehci-ppc-soc.c | |||
@@ -162,6 +162,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = { | |||
162 | .hub_control = ehci_hub_control, | 162 | .hub_control = ehci_hub_control, |
163 | .bus_suspend = ehci_bus_suspend, | 163 | .bus_suspend = ehci_bus_suspend, |
164 | .bus_resume = ehci_bus_resume, | 164 | .bus_resume = ehci_bus_resume, |
165 | .relinquish_port = ehci_relinquish_port, | ||
165 | }; | 166 | }; |
166 | 167 | ||
167 | static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) | 168 | static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) |
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 03a6b2f4e6ed..bbda58eb8813 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c | |||
@@ -72,6 +72,7 @@ static const struct hc_driver ps3_ehci_hc_driver = { | |||
72 | .bus_suspend = ehci_bus_suspend, | 72 | .bus_suspend = ehci_bus_suspend, |
73 | .bus_resume = ehci_bus_resume, | 73 | .bus_resume = ehci_bus_resume, |
74 | #endif | 74 | #endif |
75 | .relinquish_port = ehci_relinquish_port, | ||
75 | }; | 76 | }; |
76 | 77 | ||
77 | static int ps3_ehci_probe(struct ps3_system_bus_device *dev) | 78 | static int ps3_ehci_probe(struct ps3_system_bus_device *dev) |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index b10f39c047e9..776a97f33914 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -198,7 +198,8 @@ static int qtd_copy_status ( | |||
198 | 198 | ||
199 | /* if async CSPLIT failed, try cleaning out the TT buffer */ | 199 | /* if async CSPLIT failed, try cleaning out the TT buffer */ |
200 | if (status != -EPIPE | 200 | if (status != -EPIPE |
201 | && urb->dev->tt && !usb_pipeint (urb->pipe) | 201 | && urb->dev->tt |
202 | && !usb_pipeint(urb->pipe) | ||
202 | && ((token & QTD_STS_MMF) != 0 | 203 | && ((token & QTD_STS_MMF) != 0 |
203 | || QTD_CERR(token) == 0) | 204 | || QTD_CERR(token) == 0) |
204 | && (!ehci_is_TDI(ehci) | 205 | && (!ehci_is_TDI(ehci) |
@@ -211,6 +212,9 @@ static int qtd_copy_status ( | |||
211 | urb->dev->ttport, urb->dev->devnum, | 212 | urb->dev->ttport, urb->dev->devnum, |
212 | usb_pipeendpoint (urb->pipe), token); | 213 | usb_pipeendpoint (urb->pipe), token); |
213 | #endif /* DEBUG */ | 214 | #endif /* DEBUG */ |
215 | /* REVISIT ARC-derived cores don't clear the root | ||
216 | * hub TT buffer in this way... | ||
217 | */ | ||
214 | usb_hub_tt_clear_buffer (urb->dev, urb->pipe); | 218 | usb_hub_tt_clear_buffer (urb->dev, urb->pipe); |
215 | } | 219 | } |
216 | } | 220 | } |
@@ -638,6 +642,7 @@ qh_make ( | |||
638 | u32 info1 = 0, info2 = 0; | 642 | u32 info1 = 0, info2 = 0; |
639 | int is_input, type; | 643 | int is_input, type; |
640 | int maxp = 0; | 644 | int maxp = 0; |
645 | struct usb_tt *tt = urb->dev->tt; | ||
641 | 646 | ||
642 | if (!qh) | 647 | if (!qh) |
643 | return qh; | 648 | return qh; |
@@ -661,8 +666,9 @@ qh_make ( | |||
661 | * For control/bulk requests, the HC or TT handles these. | 666 | * For control/bulk requests, the HC or TT handles these. |
662 | */ | 667 | */ |
663 | if (type == PIPE_INTERRUPT) { | 668 | if (type == PIPE_INTERRUPT) { |
664 | qh->usecs = NS_TO_US (usb_calc_bus_time (USB_SPEED_HIGH, is_input, 0, | 669 | qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH, |
665 | hb_mult (maxp) * max_packet (maxp))); | 670 | is_input, 0, |
671 | hb_mult(maxp) * max_packet(maxp))); | ||
666 | qh->start = NO_FRAME; | 672 | qh->start = NO_FRAME; |
667 | 673 | ||
668 | if (urb->dev->speed == USB_SPEED_HIGH) { | 674 | if (urb->dev->speed == USB_SPEED_HIGH) { |
@@ -680,7 +686,6 @@ qh_make ( | |||
680 | goto done; | 686 | goto done; |
681 | } | 687 | } |
682 | } else { | 688 | } else { |
683 | struct usb_tt *tt = urb->dev->tt; | ||
684 | int think_time; | 689 | int think_time; |
685 | 690 | ||
686 | /* gap is f(FS/LS transfer times) */ | 691 | /* gap is f(FS/LS transfer times) */ |
@@ -736,10 +741,8 @@ qh_make ( | |||
736 | /* set the address of the TT; for TDI's integrated | 741 | /* set the address of the TT; for TDI's integrated |
737 | * root hub tt, leave it zeroed. | 742 | * root hub tt, leave it zeroed. |
738 | */ | 743 | */ |
739 | if (!ehci_is_TDI(ehci) | 744 | if (tt && tt->hub != ehci_to_hcd(ehci)->self.root_hub) |
740 | || urb->dev->tt->hub != | 745 | info2 |= tt->hub->devnum << 16; |
741 | ehci_to_hcd(ehci)->self.root_hub) | ||
742 | info2 |= urb->dev->tt->hub->devnum << 16; | ||
743 | 746 | ||
744 | /* NOTE: if (PIPE_INTERRUPT) { scheduler sets c-mask } */ | 747 | /* NOTE: if (PIPE_INTERRUPT) { scheduler sets c-mask } */ |
745 | 748 | ||
@@ -973,7 +976,7 @@ static void end_unlink_async (struct ehci_hcd *ehci) | |||
973 | struct ehci_qh *qh = ehci->reclaim; | 976 | struct ehci_qh *qh = ehci->reclaim; |
974 | struct ehci_qh *next; | 977 | struct ehci_qh *next; |
975 | 978 | ||
976 | timer_action_done (ehci, TIMER_IAA_WATCHDOG); | 979 | iaa_watchdog_done(ehci); |
977 | 980 | ||
978 | // qh->hw_next = cpu_to_hc32(qh->qh_dma); | 981 | // qh->hw_next = cpu_to_hc32(qh->qh_dma); |
979 | qh->qh_state = QH_STATE_IDLE; | 982 | qh->qh_state = QH_STATE_IDLE; |
@@ -983,7 +986,6 @@ static void end_unlink_async (struct ehci_hcd *ehci) | |||
983 | /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */ | 986 | /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */ |
984 | next = qh->reclaim; | 987 | next = qh->reclaim; |
985 | ehci->reclaim = next; | 988 | ehci->reclaim = next; |
986 | ehci->reclaim_ready = 0; | ||
987 | qh->reclaim = NULL; | 989 | qh->reclaim = NULL; |
988 | 990 | ||
989 | qh_completions (ehci, qh); | 991 | qh_completions (ehci, qh); |
@@ -1059,11 +1061,10 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
1059 | return; | 1061 | return; |
1060 | } | 1062 | } |
1061 | 1063 | ||
1062 | ehci->reclaim_ready = 0; | ||
1063 | cmd |= CMD_IAAD; | 1064 | cmd |= CMD_IAAD; |
1064 | ehci_writel(ehci, cmd, &ehci->regs->command); | 1065 | ehci_writel(ehci, cmd, &ehci->regs->command); |
1065 | (void)ehci_readl(ehci, &ehci->regs->command); | 1066 | (void)ehci_readl(ehci, &ehci->regs->command); |
1066 | timer_action (ehci, TIMER_IAA_WATCHDOG); | 1067 | iaa_watchdog_start(ehci); |
1067 | } | 1068 | } |
1068 | 1069 | ||
1069 | /*-------------------------------------------------------------------------*/ | 1070 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 80d99bce2b38..8a8e08a51ba3 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -119,7 +119,8 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) | |||
119 | q = &q->fstn->fstn_next; | 119 | q = &q->fstn->fstn_next; |
120 | break; | 120 | break; |
121 | case Q_TYPE_ITD: | 121 | case Q_TYPE_ITD: |
122 | usecs += q->itd->usecs [uframe]; | 122 | if (q->itd->hw_transaction[uframe]) |
123 | usecs += q->itd->stream->usecs; | ||
123 | hw_p = &q->itd->hw_next; | 124 | hw_p = &q->itd->hw_next; |
124 | q = &q->itd->itd_next; | 125 | q = &q->itd->itd_next; |
125 | break; | 126 | break; |
@@ -211,7 +212,7 @@ static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) | |||
211 | * low/fullspeed transfer can "carry over" from one uframe to the next, | 212 | * low/fullspeed transfer can "carry over" from one uframe to the next, |
212 | * since the TT just performs downstream transfers in sequence. | 213 | * since the TT just performs downstream transfers in sequence. |
213 | * | 214 | * |
214 | * For example two seperate 100 usec transfers can start in the same uframe, | 215 | * For example two separate 100 usec transfers can start in the same uframe, |
215 | * and the second one would "carry over" 75 usecs into the next uframe. | 216 | * and the second one would "carry over" 75 usecs into the next uframe. |
216 | */ | 217 | */ |
217 | static void | 218 | static void |
@@ -1536,7 +1537,6 @@ itd_link_urb ( | |||
1536 | uframe = next_uframe & 0x07; | 1537 | uframe = next_uframe & 0x07; |
1537 | frame = next_uframe >> 3; | 1538 | frame = next_uframe >> 3; |
1538 | 1539 | ||
1539 | itd->usecs [uframe] = stream->usecs; | ||
1540 | itd_patch(ehci, itd, iso_sched, packet, uframe); | 1540 | itd_patch(ehci, itd, iso_sched, packet, uframe); |
1541 | 1541 | ||
1542 | next_uframe += stream->interval; | 1542 | next_uframe += stream->interval; |
@@ -1565,6 +1565,16 @@ itd_link_urb ( | |||
1565 | 1565 | ||
1566 | #define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR) | 1566 | #define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR) |
1567 | 1567 | ||
1568 | /* Process and recycle a completed ITD. Return true iff its urb completed, | ||
1569 | * and hence its completion callback probably added things to the hardware | ||
1570 | * schedule. | ||
1571 | * | ||
1572 | * Note that we carefully avoid recycling this descriptor until after any | ||
1573 | * completion callback runs, so that it won't be reused quickly. That is, | ||
1574 | * assuming (a) no more than two urbs per frame on this endpoint, and also | ||
1575 | * (b) only this endpoint's completions submit URBs. It seems some silicon | ||
1576 | * corrupts things if you reuse completed descriptors very quickly... | ||
1577 | */ | ||
1568 | static unsigned | 1578 | static unsigned |
1569 | itd_complete ( | 1579 | itd_complete ( |
1570 | struct ehci_hcd *ehci, | 1580 | struct ehci_hcd *ehci, |
@@ -1577,6 +1587,7 @@ itd_complete ( | |||
1577 | int urb_index = -1; | 1587 | int urb_index = -1; |
1578 | struct ehci_iso_stream *stream = itd->stream; | 1588 | struct ehci_iso_stream *stream = itd->stream; |
1579 | struct usb_device *dev; | 1589 | struct usb_device *dev; |
1590 | unsigned retval = false; | ||
1580 | 1591 | ||
1581 | /* for each uframe with a packet */ | 1592 | /* for each uframe with a packet */ |
1582 | for (uframe = 0; uframe < 8; uframe++) { | 1593 | for (uframe = 0; uframe < 8; uframe++) { |
@@ -1610,30 +1621,21 @@ itd_complete ( | |||
1610 | } | 1621 | } |
1611 | } | 1622 | } |
1612 | 1623 | ||
1613 | usb_put_urb (urb); | ||
1614 | itd->urb = NULL; | ||
1615 | itd->stream = NULL; | ||
1616 | list_move (&itd->itd_list, &stream->free_list); | ||
1617 | iso_stream_put (ehci, stream); | ||
1618 | |||
1619 | /* handle completion now? */ | 1624 | /* handle completion now? */ |
1620 | if (likely ((urb_index + 1) != urb->number_of_packets)) | 1625 | if (likely ((urb_index + 1) != urb->number_of_packets)) |
1621 | return 0; | 1626 | goto done; |
1622 | 1627 | ||
1623 | /* ASSERT: it's really the last itd for this urb | 1628 | /* ASSERT: it's really the last itd for this urb |
1624 | list_for_each_entry (itd, &stream->td_list, itd_list) | 1629 | list_for_each_entry (itd, &stream->td_list, itd_list) |
1625 | BUG_ON (itd->urb == urb); | 1630 | BUG_ON (itd->urb == urb); |
1626 | */ | 1631 | */ |
1627 | 1632 | ||
1628 | /* give urb back to the driver ... can be out-of-order */ | 1633 | /* give urb back to the driver; completion often (re)submits */ |
1629 | dev = urb->dev; | 1634 | dev = urb->dev; |
1630 | ehci_urb_done(ehci, urb, 0); | 1635 | ehci_urb_done(ehci, urb, 0); |
1636 | retval = true; | ||
1631 | urb = NULL; | 1637 | urb = NULL; |
1632 | |||
1633 | /* defer stopping schedule; completion can submit */ | ||
1634 | ehci->periodic_sched--; | 1638 | ehci->periodic_sched--; |
1635 | if (unlikely (!ehci->periodic_sched)) | ||
1636 | (void) disable_periodic (ehci); | ||
1637 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; | 1639 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; |
1638 | 1640 | ||
1639 | if (unlikely (list_empty (&stream->td_list))) { | 1641 | if (unlikely (list_empty (&stream->td_list))) { |
@@ -1645,8 +1647,15 @@ itd_complete ( | |||
1645 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); | 1647 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); |
1646 | } | 1648 | } |
1647 | iso_stream_put (ehci, stream); | 1649 | iso_stream_put (ehci, stream); |
1650 | /* OK to recycle this ITD now that its completion callback ran. */ | ||
1651 | done: | ||
1652 | usb_put_urb(urb); | ||
1653 | itd->urb = NULL; | ||
1654 | itd->stream = NULL; | ||
1655 | list_move(&itd->itd_list, &stream->free_list); | ||
1656 | iso_stream_put(ehci, stream); | ||
1648 | 1657 | ||
1649 | return 1; | 1658 | return retval; |
1650 | } | 1659 | } |
1651 | 1660 | ||
1652 | /*-------------------------------------------------------------------------*/ | 1661 | /*-------------------------------------------------------------------------*/ |
@@ -1712,8 +1721,6 @@ done: | |||
1712 | return status; | 1721 | return status; |
1713 | } | 1722 | } |
1714 | 1723 | ||
1715 | #ifdef CONFIG_USB_EHCI_SPLIT_ISO | ||
1716 | |||
1717 | /*-------------------------------------------------------------------------*/ | 1724 | /*-------------------------------------------------------------------------*/ |
1718 | 1725 | ||
1719 | /* | 1726 | /* |
@@ -1950,6 +1957,16 @@ sitd_link_urb ( | |||
1950 | #define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \ | 1957 | #define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \ |
1951 | | SITD_STS_XACT | SITD_STS_MMF) | 1958 | | SITD_STS_XACT | SITD_STS_MMF) |
1952 | 1959 | ||
1960 | /* Process and recycle a completed SITD. Return true iff its urb completed, | ||
1961 | * and hence its completion callback probably added things to the hardware | ||
1962 | * schedule. | ||
1963 | * | ||
1964 | * Note that we carefully avoid recycling this descriptor until after any | ||
1965 | * completion callback runs, so that it won't be reused quickly. That is, | ||
1966 | * assuming (a) no more than two urbs per frame on this endpoint, and also | ||
1967 | * (b) only this endpoint's completions submit URBs. It seems some silicon | ||
1968 | * corrupts things if you reuse completed descriptors very quickly... | ||
1969 | */ | ||
1953 | static unsigned | 1970 | static unsigned |
1954 | sitd_complete ( | 1971 | sitd_complete ( |
1955 | struct ehci_hcd *ehci, | 1972 | struct ehci_hcd *ehci, |
@@ -1961,6 +1978,7 @@ sitd_complete ( | |||
1961 | int urb_index = -1; | 1978 | int urb_index = -1; |
1962 | struct ehci_iso_stream *stream = sitd->stream; | 1979 | struct ehci_iso_stream *stream = sitd->stream; |
1963 | struct usb_device *dev; | 1980 | struct usb_device *dev; |
1981 | unsigned retval = false; | ||
1964 | 1982 | ||
1965 | urb_index = sitd->index; | 1983 | urb_index = sitd->index; |
1966 | desc = &urb->iso_frame_desc [urb_index]; | 1984 | desc = &urb->iso_frame_desc [urb_index]; |
@@ -1981,32 +1999,23 @@ sitd_complete ( | |||
1981 | desc->status = 0; | 1999 | desc->status = 0; |
1982 | desc->actual_length = desc->length - SITD_LENGTH (t); | 2000 | desc->actual_length = desc->length - SITD_LENGTH (t); |
1983 | } | 2001 | } |
1984 | |||
1985 | usb_put_urb (urb); | ||
1986 | sitd->urb = NULL; | ||
1987 | sitd->stream = NULL; | ||
1988 | list_move (&sitd->sitd_list, &stream->free_list); | ||
1989 | stream->depth -= stream->interval << 3; | 2002 | stream->depth -= stream->interval << 3; |
1990 | iso_stream_put (ehci, stream); | ||
1991 | 2003 | ||
1992 | /* handle completion now? */ | 2004 | /* handle completion now? */ |
1993 | if ((urb_index + 1) != urb->number_of_packets) | 2005 | if ((urb_index + 1) != urb->number_of_packets) |
1994 | return 0; | 2006 | goto done; |
1995 | 2007 | ||
1996 | /* ASSERT: it's really the last sitd for this urb | 2008 | /* ASSERT: it's really the last sitd for this urb |
1997 | list_for_each_entry (sitd, &stream->td_list, sitd_list) | 2009 | list_for_each_entry (sitd, &stream->td_list, sitd_list) |
1998 | BUG_ON (sitd->urb == urb); | 2010 | BUG_ON (sitd->urb == urb); |
1999 | */ | 2011 | */ |
2000 | 2012 | ||
2001 | /* give urb back to the driver */ | 2013 | /* give urb back to the driver; completion often (re)submits */ |
2002 | dev = urb->dev; | 2014 | dev = urb->dev; |
2003 | ehci_urb_done(ehci, urb, 0); | 2015 | ehci_urb_done(ehci, urb, 0); |
2016 | retval = true; | ||
2004 | urb = NULL; | 2017 | urb = NULL; |
2005 | |||
2006 | /* defer stopping schedule; completion can submit */ | ||
2007 | ehci->periodic_sched--; | 2018 | ehci->periodic_sched--; |
2008 | if (!ehci->periodic_sched) | ||
2009 | (void) disable_periodic (ehci); | ||
2010 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; | 2019 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; |
2011 | 2020 | ||
2012 | if (list_empty (&stream->td_list)) { | 2021 | if (list_empty (&stream->td_list)) { |
@@ -2018,8 +2027,15 @@ sitd_complete ( | |||
2018 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); | 2027 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); |
2019 | } | 2028 | } |
2020 | iso_stream_put (ehci, stream); | 2029 | iso_stream_put (ehci, stream); |
2030 | /* OK to recycle this SITD now that its completion callback ran. */ | ||
2031 | done: | ||
2032 | usb_put_urb(urb); | ||
2033 | sitd->urb = NULL; | ||
2034 | sitd->stream = NULL; | ||
2035 | list_move(&sitd->sitd_list, &stream->free_list); | ||
2036 | iso_stream_put(ehci, stream); | ||
2021 | 2037 | ||
2022 | return 1; | 2038 | return retval; |
2023 | } | 2039 | } |
2024 | 2040 | ||
2025 | 2041 | ||
@@ -2082,26 +2098,6 @@ done: | |||
2082 | return status; | 2098 | return status; |
2083 | } | 2099 | } |
2084 | 2100 | ||
2085 | #else | ||
2086 | |||
2087 | static inline int | ||
2088 | sitd_submit (struct ehci_hcd *ehci, struct urb *urb, gfp_t mem_flags) | ||
2089 | { | ||
2090 | ehci_dbg (ehci, "split iso support is disabled\n"); | ||
2091 | return -ENOSYS; | ||
2092 | } | ||
2093 | |||
2094 | static inline unsigned | ||
2095 | sitd_complete ( | ||
2096 | struct ehci_hcd *ehci, | ||
2097 | struct ehci_sitd *sitd | ||
2098 | ) { | ||
2099 | ehci_err (ehci, "sitd_complete %p?\n", sitd); | ||
2100 | return 0; | ||
2101 | } | ||
2102 | |||
2103 | #endif /* USB_EHCI_SPLIT_ISO */ | ||
2104 | |||
2105 | /*-------------------------------------------------------------------------*/ | 2101 | /*-------------------------------------------------------------------------*/ |
2106 | 2102 | ||
2107 | static void | 2103 | static void |
@@ -2127,17 +2123,9 @@ scan_periodic (struct ehci_hcd *ehci) | |||
2127 | for (;;) { | 2123 | for (;;) { |
2128 | union ehci_shadow q, *q_p; | 2124 | union ehci_shadow q, *q_p; |
2129 | __hc32 type, *hw_p; | 2125 | __hc32 type, *hw_p; |
2130 | unsigned uframes; | 2126 | unsigned incomplete = false; |
2131 | 2127 | ||
2132 | /* don't scan past the live uframe */ | ||
2133 | frame = now_uframe >> 3; | 2128 | frame = now_uframe >> 3; |
2134 | if (frame == (clock >> 3)) | ||
2135 | uframes = now_uframe & 0x07; | ||
2136 | else { | ||
2137 | /* safe to scan the whole frame at once */ | ||
2138 | now_uframe |= 0x07; | ||
2139 | uframes = 8; | ||
2140 | } | ||
2141 | 2129 | ||
2142 | restart: | 2130 | restart: |
2143 | /* scan each element in frame's queue for completions */ | 2131 | /* scan each element in frame's queue for completions */ |
@@ -2175,12 +2163,15 @@ restart: | |||
2175 | q = q.fstn->fstn_next; | 2163 | q = q.fstn->fstn_next; |
2176 | break; | 2164 | break; |
2177 | case Q_TYPE_ITD: | 2165 | case Q_TYPE_ITD: |
2178 | /* skip itds for later in the frame */ | 2166 | /* If this ITD is still active, leave it for |
2167 | * later processing ... check the next entry. | ||
2168 | */ | ||
2179 | rmb (); | 2169 | rmb (); |
2180 | for (uf = live ? uframes : 8; uf < 8; uf++) { | 2170 | for (uf = 0; uf < 8 && live; uf++) { |
2181 | if (0 == (q.itd->hw_transaction [uf] | 2171 | if (0 == (q.itd->hw_transaction [uf] |
2182 | & ITD_ACTIVE(ehci))) | 2172 | & ITD_ACTIVE(ehci))) |
2183 | continue; | 2173 | continue; |
2174 | incomplete = true; | ||
2184 | q_p = &q.itd->itd_next; | 2175 | q_p = &q.itd->itd_next; |
2185 | hw_p = &q.itd->hw_next; | 2176 | hw_p = &q.itd->hw_next; |
2186 | type = Q_NEXT_TYPE(ehci, | 2177 | type = Q_NEXT_TYPE(ehci, |
@@ -2188,10 +2179,12 @@ restart: | |||
2188 | q = *q_p; | 2179 | q = *q_p; |
2189 | break; | 2180 | break; |
2190 | } | 2181 | } |
2191 | if (uf != 8) | 2182 | if (uf < 8 && live) |
2192 | break; | 2183 | break; |
2193 | 2184 | ||
2194 | /* this one's ready ... HC won't cache the | 2185 | /* Take finished ITDs out of the schedule |
2186 | * and process them: recycle, maybe report | ||
2187 | * URB completion. HC won't cache the | ||
2195 | * pointer for much longer, if at all. | 2188 | * pointer for much longer, if at all. |
2196 | */ | 2189 | */ |
2197 | *q_p = q.itd->itd_next; | 2190 | *q_p = q.itd->itd_next; |
@@ -2202,8 +2195,12 @@ restart: | |||
2202 | q = *q_p; | 2195 | q = *q_p; |
2203 | break; | 2196 | break; |
2204 | case Q_TYPE_SITD: | 2197 | case Q_TYPE_SITD: |
2198 | /* If this SITD is still active, leave it for | ||
2199 | * later processing ... check the next entry. | ||
2200 | */ | ||
2205 | if ((q.sitd->hw_results & SITD_ACTIVE(ehci)) | 2201 | if ((q.sitd->hw_results & SITD_ACTIVE(ehci)) |
2206 | && live) { | 2202 | && live) { |
2203 | incomplete = true; | ||
2207 | q_p = &q.sitd->sitd_next; | 2204 | q_p = &q.sitd->sitd_next; |
2208 | hw_p = &q.sitd->hw_next; | 2205 | hw_p = &q.sitd->hw_next; |
2209 | type = Q_NEXT_TYPE(ehci, | 2206 | type = Q_NEXT_TYPE(ehci, |
@@ -2211,6 +2208,11 @@ restart: | |||
2211 | q = *q_p; | 2208 | q = *q_p; |
2212 | break; | 2209 | break; |
2213 | } | 2210 | } |
2211 | |||
2212 | /* Take finished SITDs out of the schedule | ||
2213 | * and process them: recycle, maybe report | ||
2214 | * URB completion. | ||
2215 | */ | ||
2214 | *q_p = q.sitd->sitd_next; | 2216 | *q_p = q.sitd->sitd_next; |
2215 | *hw_p = q.sitd->hw_next; | 2217 | *hw_p = q.sitd->hw_next; |
2216 | type = Q_NEXT_TYPE(ehci, q.sitd->hw_next); | 2218 | type = Q_NEXT_TYPE(ehci, q.sitd->hw_next); |
@@ -2226,11 +2228,24 @@ restart: | |||
2226 | } | 2228 | } |
2227 | 2229 | ||
2228 | /* assume completion callbacks modify the queue */ | 2230 | /* assume completion callbacks modify the queue */ |
2229 | if (unlikely (modified)) | 2231 | if (unlikely (modified)) { |
2230 | goto restart; | 2232 | if (likely(ehci->periodic_sched > 0)) |
2233 | goto restart; | ||
2234 | /* maybe we can short-circuit this scan! */ | ||
2235 | disable_periodic(ehci); | ||
2236 | now_uframe = clock; | ||
2237 | break; | ||
2238 | } | ||
2231 | } | 2239 | } |
2232 | 2240 | ||
2233 | /* stop when we catch up to the HC */ | 2241 | /* If we can tell we caught up to the hardware, stop now. |
2242 | * We can't advance our scan without collecting the ISO | ||
2243 | * transfers that are still pending in this frame. | ||
2244 | */ | ||
2245 | if (incomplete && HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { | ||
2246 | ehci->next_uframe = now_uframe; | ||
2247 | break; | ||
2248 | } | ||
2234 | 2249 | ||
2235 | // FIXME: this assumes we won't get lapped when | 2250 | // FIXME: this assumes we won't get lapped when |
2236 | // latencies climb; that should be rare, but... | 2251 | // latencies climb; that should be rare, but... |
@@ -2243,7 +2258,8 @@ restart: | |||
2243 | if (now_uframe == clock) { | 2258 | if (now_uframe == clock) { |
2244 | unsigned now; | 2259 | unsigned now; |
2245 | 2260 | ||
2246 | if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) | 2261 | if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) |
2262 | || ehci->periodic_sched == 0) | ||
2247 | break; | 2263 | break; |
2248 | ehci->next_uframe = now_uframe; | 2264 | ehci->next_uframe = now_uframe; |
2249 | now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; | 2265 | now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 951d69fec513..bf92d209a1a9 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -74,7 +74,6 @@ struct ehci_hcd { /* one per controller */ | |||
74 | /* async schedule support */ | 74 | /* async schedule support */ |
75 | struct ehci_qh *async; | 75 | struct ehci_qh *async; |
76 | struct ehci_qh *reclaim; | 76 | struct ehci_qh *reclaim; |
77 | unsigned reclaim_ready : 1; | ||
78 | unsigned scanning : 1; | 77 | unsigned scanning : 1; |
79 | 78 | ||
80 | /* periodic schedule support */ | 79 | /* periodic schedule support */ |
@@ -105,6 +104,7 @@ struct ehci_hcd { /* one per controller */ | |||
105 | struct dma_pool *itd_pool; /* itd per iso urb */ | 104 | struct dma_pool *itd_pool; /* itd per iso urb */ |
106 | struct dma_pool *sitd_pool; /* sitd per split iso urb */ | 105 | struct dma_pool *sitd_pool; /* sitd per split iso urb */ |
107 | 106 | ||
107 | struct timer_list iaa_watchdog; | ||
108 | struct timer_list watchdog; | 108 | struct timer_list watchdog; |
109 | unsigned long actions; | 109 | unsigned long actions; |
110 | unsigned stamp; | 110 | unsigned stamp; |
@@ -127,6 +127,14 @@ struct ehci_hcd { /* one per controller */ | |||
127 | #else | 127 | #else |
128 | # define COUNT(x) do {} while (0) | 128 | # define COUNT(x) do {} while (0) |
129 | #endif | 129 | #endif |
130 | |||
131 | /* debug files */ | ||
132 | #ifdef DEBUG | ||
133 | struct dentry *debug_dir; | ||
134 | struct dentry *debug_async; | ||
135 | struct dentry *debug_periodic; | ||
136 | struct dentry *debug_registers; | ||
137 | #endif | ||
130 | }; | 138 | }; |
131 | 139 | ||
132 | /* convert between an HCD pointer and the corresponding EHCI_HCD */ | 140 | /* convert between an HCD pointer and the corresponding EHCI_HCD */ |
@@ -140,9 +148,21 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci) | |||
140 | } | 148 | } |
141 | 149 | ||
142 | 150 | ||
151 | static inline void | ||
152 | iaa_watchdog_start(struct ehci_hcd *ehci) | ||
153 | { | ||
154 | WARN_ON(timer_pending(&ehci->iaa_watchdog)); | ||
155 | mod_timer(&ehci->iaa_watchdog, | ||
156 | jiffies + msecs_to_jiffies(EHCI_IAA_MSECS)); | ||
157 | } | ||
158 | |||
159 | static inline void iaa_watchdog_done(struct ehci_hcd *ehci) | ||
160 | { | ||
161 | del_timer(&ehci->iaa_watchdog); | ||
162 | } | ||
163 | |||
143 | enum ehci_timer_action { | 164 | enum ehci_timer_action { |
144 | TIMER_IO_WATCHDOG, | 165 | TIMER_IO_WATCHDOG, |
145 | TIMER_IAA_WATCHDOG, | ||
146 | TIMER_ASYNC_SHRINK, | 166 | TIMER_ASYNC_SHRINK, |
147 | TIMER_ASYNC_OFF, | 167 | TIMER_ASYNC_OFF, |
148 | }; | 168 | }; |
@@ -160,9 +180,6 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) | |||
160 | unsigned long t; | 180 | unsigned long t; |
161 | 181 | ||
162 | switch (action) { | 182 | switch (action) { |
163 | case TIMER_IAA_WATCHDOG: | ||
164 | t = EHCI_IAA_JIFFIES; | ||
165 | break; | ||
166 | case TIMER_IO_WATCHDOG: | 183 | case TIMER_IO_WATCHDOG: |
167 | t = EHCI_IO_JIFFIES; | 184 | t = EHCI_IO_JIFFIES; |
168 | break; | 185 | break; |
@@ -179,8 +196,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) | |||
179 | // async queue SHRINK often precedes IAA. while it's ready | 196 | // async queue SHRINK often precedes IAA. while it's ready |
180 | // to go OFF neither can matter, and afterwards the IO | 197 | // to go OFF neither can matter, and afterwards the IO |
181 | // watchdog stops unless there's still periodic traffic. | 198 | // watchdog stops unless there's still periodic traffic. |
182 | if (action != TIMER_IAA_WATCHDOG | 199 | if (time_before_eq(t, ehci->watchdog.expires) |
183 | && t > ehci->watchdog.expires | ||
184 | && timer_pending (&ehci->watchdog)) | 200 | && timer_pending (&ehci->watchdog)) |
185 | return; | 201 | return; |
186 | mod_timer (&ehci->watchdog, t); | 202 | mod_timer (&ehci->watchdog, t); |
@@ -534,8 +550,8 @@ struct ehci_iso_stream { | |||
534 | * trusting urb->interval == f(epdesc->bInterval) and | 550 | * trusting urb->interval == f(epdesc->bInterval) and |
535 | * including the extra info for hw_bufp[0..2] | 551 | * including the extra info for hw_bufp[0..2] |
536 | */ | 552 | */ |
537 | u8 interval; | ||
538 | u8 usecs, c_usecs; | 553 | u8 usecs, c_usecs; |
554 | u16 interval; | ||
539 | u16 tt_usecs; | 555 | u16 tt_usecs; |
540 | u16 maxp; | 556 | u16 maxp; |
541 | u16 raw_mask; | 557 | u16 raw_mask; |
@@ -586,7 +602,6 @@ struct ehci_itd { | |||
586 | unsigned frame; /* where scheduled */ | 602 | unsigned frame; /* where scheduled */ |
587 | unsigned pg; | 603 | unsigned pg; |
588 | unsigned index[8]; /* in urb->iso_frame_desc */ | 604 | unsigned index[8]; /* in urb->iso_frame_desc */ |
589 | u8 usecs[8]; | ||
590 | } __attribute__ ((aligned (32))); | 605 | } __attribute__ ((aligned (32))); |
591 | 606 | ||
592 | /*-------------------------------------------------------------------------*/ | 607 | /*-------------------------------------------------------------------------*/ |
@@ -725,11 +740,16 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) | |||
725 | * definition below can die once the 4xx support is | 740 | * definition below can die once the 4xx support is |
726 | * finally ported over. | 741 | * finally ported over. |
727 | */ | 742 | */ |
728 | #if defined(CONFIG_PPC) | 743 | #if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE) |
729 | #define readl_be(addr) in_be32((__force unsigned *)addr) | 744 | #define readl_be(addr) in_be32((__force unsigned *)addr) |
730 | #define writel_be(val, addr) out_be32((__force unsigned *)addr, val) | 745 | #define writel_be(val, addr) out_be32((__force unsigned *)addr, val) |
731 | #endif | 746 | #endif |
732 | 747 | ||
748 | #if defined(CONFIG_ARM) && defined(CONFIG_ARCH_IXP4XX) | ||
749 | #define readl_be(addr) __raw_readl((__force unsigned *)addr) | ||
750 | #define writel_be(val, addr) __raw_writel(val, (__force unsigned *)addr) | ||
751 | #endif | ||
752 | |||
733 | static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, | 753 | static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, |
734 | __u32 __iomem * regs) | 754 | __u32 __iomem * regs) |
735 | { | 755 | { |
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index c27417f5b9d8..0130fd8571e4 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -918,7 +918,6 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
918 | | RH_PS_OCIC | RH_PS_PRSC)) { | 918 | | RH_PS_OCIC | RH_PS_PRSC)) { |
919 | changed = 1; | 919 | changed = 1; |
920 | buf[0] |= 1 << (i + 1); | 920 | buf[0] |= 1 << (i + 1); |
921 | continue; | ||
922 | } | 921 | } |
923 | } | 922 | } |
924 | spin_unlock_irqrestore(&isp116x->lock, flags); | 923 | spin_unlock_irqrestore(&isp116x->lock, flags); |
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index d849c809acbd..126fcbdd6408 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c | |||
@@ -17,6 +17,8 @@ | |||
17 | 17 | ||
18 | #include <asm/mach-types.h> | 18 | #include <asm/mach-types.h> |
19 | #include <asm/hardware.h> | 19 | #include <asm/hardware.h> |
20 | #include <asm/gpio.h> | ||
21 | |||
20 | #include <asm/arch/board.h> | 22 | #include <asm/arch/board.h> |
21 | #include <asm/arch/cpu.h> | 23 | #include <asm/arch/cpu.h> |
22 | 24 | ||
@@ -271,12 +273,41 @@ static const struct hc_driver ohci_at91_hc_driver = { | |||
271 | 273 | ||
272 | static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) | 274 | static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) |
273 | { | 275 | { |
276 | struct at91_usbh_data *pdata = pdev->dev.platform_data; | ||
277 | int i; | ||
278 | |||
279 | if (pdata) { | ||
280 | /* REVISIT make the driver support per-port power switching, | ||
281 | * and also overcurrent detection. Here we assume the ports | ||
282 | * are always powered while this driver is active, and use | ||
283 | * active-low power switches. | ||
284 | */ | ||
285 | for (i = 0; i < pdata->ports; i++) { | ||
286 | if (pdata->vbus_pin[i] <= 0) | ||
287 | continue; | ||
288 | gpio_request(pdata->vbus_pin[i], "ohci_vbus"); | ||
289 | gpio_direction_output(pdata->vbus_pin[i], 0); | ||
290 | } | ||
291 | } | ||
292 | |||
274 | device_init_wakeup(&pdev->dev, 1); | 293 | device_init_wakeup(&pdev->dev, 1); |
275 | return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev); | 294 | return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev); |
276 | } | 295 | } |
277 | 296 | ||
278 | static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) | 297 | static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) |
279 | { | 298 | { |
299 | struct at91_usbh_data *pdata = pdev->dev.platform_data; | ||
300 | int i; | ||
301 | |||
302 | if (pdata) { | ||
303 | for (i = 0; i < pdata->ports; i++) { | ||
304 | if (pdata->vbus_pin[i] <= 0) | ||
305 | continue; | ||
306 | gpio_direction_output(pdata->vbus_pin[i], 1); | ||
307 | gpio_free(pdata->vbus_pin[i]); | ||
308 | } | ||
309 | } | ||
310 | |||
280 | device_init_wakeup(&pdev->dev, 0); | 311 | device_init_wakeup(&pdev->dev, 0); |
281 | return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev); | 312 | return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev); |
282 | } | 313 | } |
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index ebab5ce8f5ce..a22c30aa745d 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c | |||
@@ -401,6 +401,42 @@ static inline void remove_debug_files (struct ohci_hcd *bus) { } | |||
401 | 401 | ||
402 | #else | 402 | #else |
403 | 403 | ||
404 | static int debug_async_open(struct inode *, struct file *); | ||
405 | static int debug_periodic_open(struct inode *, struct file *); | ||
406 | static int debug_registers_open(struct inode *, struct file *); | ||
407 | static int debug_async_open(struct inode *, struct file *); | ||
408 | static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); | ||
409 | static int debug_close(struct inode *, struct file *); | ||
410 | |||
411 | static const struct file_operations debug_async_fops = { | ||
412 | .owner = THIS_MODULE, | ||
413 | .open = debug_async_open, | ||
414 | .read = debug_output, | ||
415 | .release = debug_close, | ||
416 | }; | ||
417 | static const struct file_operations debug_periodic_fops = { | ||
418 | .owner = THIS_MODULE, | ||
419 | .open = debug_periodic_open, | ||
420 | .read = debug_output, | ||
421 | .release = debug_close, | ||
422 | }; | ||
423 | static const struct file_operations debug_registers_fops = { | ||
424 | .owner = THIS_MODULE, | ||
425 | .open = debug_registers_open, | ||
426 | .read = debug_output, | ||
427 | .release = debug_close, | ||
428 | }; | ||
429 | |||
430 | static struct dentry *ohci_debug_root; | ||
431 | |||
432 | struct debug_buffer { | ||
433 | ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ | ||
434 | struct device *dev; | ||
435 | struct mutex mutex; /* protect filling of buffer */ | ||
436 | size_t count; /* number of characters filled into buffer */ | ||
437 | char *page; | ||
438 | }; | ||
439 | |||
404 | static ssize_t | 440 | static ssize_t |
405 | show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) | 441 | show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) |
406 | { | 442 | { |
@@ -467,8 +503,7 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed) | |||
467 | return count - size; | 503 | return count - size; |
468 | } | 504 | } |
469 | 505 | ||
470 | static ssize_t | 506 | static ssize_t fill_async_buffer(struct debug_buffer *buf) |
471 | show_async (struct class_device *class_dev, char *buf) | ||
472 | { | 507 | { |
473 | struct usb_bus *bus; | 508 | struct usb_bus *bus; |
474 | struct usb_hcd *hcd; | 509 | struct usb_hcd *hcd; |
@@ -476,25 +511,23 @@ show_async (struct class_device *class_dev, char *buf) | |||
476 | size_t temp; | 511 | size_t temp; |
477 | unsigned long flags; | 512 | unsigned long flags; |
478 | 513 | ||
479 | bus = class_get_devdata(class_dev); | 514 | bus = dev_get_drvdata(buf->dev); |
480 | hcd = bus_to_hcd(bus); | 515 | hcd = bus_to_hcd(bus); |
481 | ohci = hcd_to_ohci(hcd); | 516 | ohci = hcd_to_ohci(hcd); |
482 | 517 | ||
483 | /* display control and bulk lists together, for simplicity */ | 518 | /* display control and bulk lists together, for simplicity */ |
484 | spin_lock_irqsave (&ohci->lock, flags); | 519 | spin_lock_irqsave (&ohci->lock, flags); |
485 | temp = show_list (ohci, buf, PAGE_SIZE, ohci->ed_controltail); | 520 | temp = show_list(ohci, buf->page, buf->count, ohci->ed_controltail); |
486 | temp += show_list (ohci, buf + temp, PAGE_SIZE - temp, ohci->ed_bulktail); | 521 | temp += show_list(ohci, buf->page + temp, buf->count - temp, |
522 | ohci->ed_bulktail); | ||
487 | spin_unlock_irqrestore (&ohci->lock, flags); | 523 | spin_unlock_irqrestore (&ohci->lock, flags); |
488 | 524 | ||
489 | return temp; | 525 | return temp; |
490 | } | 526 | } |
491 | static CLASS_DEVICE_ATTR (async, S_IRUGO, show_async, NULL); | ||
492 | |||
493 | 527 | ||
494 | #define DBG_SCHED_LIMIT 64 | 528 | #define DBG_SCHED_LIMIT 64 |
495 | 529 | ||
496 | static ssize_t | 530 | static ssize_t fill_periodic_buffer(struct debug_buffer *buf) |
497 | show_periodic (struct class_device *class_dev, char *buf) | ||
498 | { | 531 | { |
499 | struct usb_bus *bus; | 532 | struct usb_bus *bus; |
500 | struct usb_hcd *hcd; | 533 | struct usb_hcd *hcd; |
@@ -509,10 +542,10 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
509 | return 0; | 542 | return 0; |
510 | seen_count = 0; | 543 | seen_count = 0; |
511 | 544 | ||
512 | bus = class_get_devdata(class_dev); | 545 | bus = (struct usb_bus *)dev_get_drvdata(buf->dev); |
513 | hcd = bus_to_hcd(bus); | 546 | hcd = bus_to_hcd(bus); |
514 | ohci = hcd_to_ohci(hcd); | 547 | ohci = hcd_to_ohci(hcd); |
515 | next = buf; | 548 | next = buf->page; |
516 | size = PAGE_SIZE; | 549 | size = PAGE_SIZE; |
517 | 550 | ||
518 | temp = scnprintf (next, size, "size = %d\n", NUM_INTS); | 551 | temp = scnprintf (next, size, "size = %d\n", NUM_INTS); |
@@ -589,13 +622,9 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
589 | 622 | ||
590 | return PAGE_SIZE - size; | 623 | return PAGE_SIZE - size; |
591 | } | 624 | } |
592 | static CLASS_DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL); | ||
593 | |||
594 | |||
595 | #undef DBG_SCHED_LIMIT | 625 | #undef DBG_SCHED_LIMIT |
596 | 626 | ||
597 | static ssize_t | 627 | static ssize_t fill_registers_buffer(struct debug_buffer *buf) |
598 | show_registers (struct class_device *class_dev, char *buf) | ||
599 | { | 628 | { |
600 | struct usb_bus *bus; | 629 | struct usb_bus *bus; |
601 | struct usb_hcd *hcd; | 630 | struct usb_hcd *hcd; |
@@ -606,11 +635,11 @@ show_registers (struct class_device *class_dev, char *buf) | |||
606 | char *next; | 635 | char *next; |
607 | u32 rdata; | 636 | u32 rdata; |
608 | 637 | ||
609 | bus = class_get_devdata(class_dev); | 638 | bus = (struct usb_bus *)dev_get_drvdata(buf->dev); |
610 | hcd = bus_to_hcd(bus); | 639 | hcd = bus_to_hcd(bus); |
611 | ohci = hcd_to_ohci(hcd); | 640 | ohci = hcd_to_ohci(hcd); |
612 | regs = ohci->regs; | 641 | regs = ohci->regs; |
613 | next = buf; | 642 | next = buf->page; |
614 | size = PAGE_SIZE; | 643 | size = PAGE_SIZE; |
615 | 644 | ||
616 | spin_lock_irqsave (&ohci->lock, flags); | 645 | spin_lock_irqsave (&ohci->lock, flags); |
@@ -677,29 +706,155 @@ show_registers (struct class_device *class_dev, char *buf) | |||
677 | 706 | ||
678 | done: | 707 | done: |
679 | spin_unlock_irqrestore (&ohci->lock, flags); | 708 | spin_unlock_irqrestore (&ohci->lock, flags); |
709 | |||
680 | return PAGE_SIZE - size; | 710 | return PAGE_SIZE - size; |
681 | } | 711 | } |
682 | static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL); | ||
683 | 712 | ||
713 | static struct debug_buffer *alloc_buffer(struct device *dev, | ||
714 | ssize_t (*fill_func)(struct debug_buffer *)) | ||
715 | { | ||
716 | struct debug_buffer *buf; | ||
717 | |||
718 | buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); | ||
684 | 719 | ||
720 | if (buf) { | ||
721 | buf->dev = dev; | ||
722 | buf->fill_func = fill_func; | ||
723 | mutex_init(&buf->mutex); | ||
724 | } | ||
725 | |||
726 | return buf; | ||
727 | } | ||
728 | |||
729 | static int fill_buffer(struct debug_buffer *buf) | ||
730 | { | ||
731 | int ret = 0; | ||
732 | |||
733 | if (!buf->page) | ||
734 | buf->page = (char *)get_zeroed_page(GFP_KERNEL); | ||
735 | |||
736 | if (!buf->page) { | ||
737 | ret = -ENOMEM; | ||
738 | goto out; | ||
739 | } | ||
740 | |||
741 | ret = buf->fill_func(buf); | ||
742 | |||
743 | if (ret >= 0) { | ||
744 | buf->count = ret; | ||
745 | ret = 0; | ||
746 | } | ||
747 | |||
748 | out: | ||
749 | return ret; | ||
750 | } | ||
751 | |||
752 | static ssize_t debug_output(struct file *file, char __user *user_buf, | ||
753 | size_t len, loff_t *offset) | ||
754 | { | ||
755 | struct debug_buffer *buf = file->private_data; | ||
756 | int ret = 0; | ||
757 | |||
758 | mutex_lock(&buf->mutex); | ||
759 | if (buf->count == 0) { | ||
760 | ret = fill_buffer(buf); | ||
761 | if (ret != 0) { | ||
762 | mutex_unlock(&buf->mutex); | ||
763 | goto out; | ||
764 | } | ||
765 | } | ||
766 | mutex_unlock(&buf->mutex); | ||
767 | |||
768 | ret = simple_read_from_buffer(user_buf, len, offset, | ||
769 | buf->page, buf->count); | ||
770 | |||
771 | out: | ||
772 | return ret; | ||
773 | |||
774 | } | ||
775 | |||
776 | static int debug_close(struct inode *inode, struct file *file) | ||
777 | { | ||
778 | struct debug_buffer *buf = file->private_data; | ||
779 | |||
780 | if (buf) { | ||
781 | if (buf->page) | ||
782 | free_page((unsigned long)buf->page); | ||
783 | kfree(buf); | ||
784 | } | ||
785 | |||
786 | return 0; | ||
787 | } | ||
788 | static int debug_async_open(struct inode *inode, struct file *file) | ||
789 | { | ||
790 | file->private_data = alloc_buffer(inode->i_private, fill_async_buffer); | ||
791 | |||
792 | return file->private_data ? 0 : -ENOMEM; | ||
793 | } | ||
794 | |||
795 | static int debug_periodic_open(struct inode *inode, struct file *file) | ||
796 | { | ||
797 | file->private_data = alloc_buffer(inode->i_private, | ||
798 | fill_periodic_buffer); | ||
799 | |||
800 | return file->private_data ? 0 : -ENOMEM; | ||
801 | } | ||
802 | |||
803 | static int debug_registers_open(struct inode *inode, struct file *file) | ||
804 | { | ||
805 | file->private_data = alloc_buffer(inode->i_private, | ||
806 | fill_registers_buffer); | ||
807 | |||
808 | return file->private_data ? 0 : -ENOMEM; | ||
809 | } | ||
685 | static inline void create_debug_files (struct ohci_hcd *ohci) | 810 | static inline void create_debug_files (struct ohci_hcd *ohci) |
686 | { | 811 | { |
687 | struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev; | 812 | struct usb_bus *bus = &ohci_to_hcd(ohci)->self; |
688 | int retval; | 813 | struct device *dev = bus->dev; |
814 | |||
815 | ohci->debug_dir = debugfs_create_dir(bus->bus_name, ohci_debug_root); | ||
816 | if (!ohci->debug_dir) | ||
817 | goto dir_error; | ||
818 | |||
819 | ohci->debug_async = debugfs_create_file("async", S_IRUGO, | ||
820 | ohci->debug_dir, dev, | ||
821 | &debug_async_fops); | ||
822 | if (!ohci->debug_async) | ||
823 | goto async_error; | ||
824 | |||
825 | ohci->debug_periodic = debugfs_create_file("periodic", S_IRUGO, | ||
826 | ohci->debug_dir, dev, | ||
827 | &debug_periodic_fops); | ||
828 | if (!ohci->debug_periodic) | ||
829 | goto periodic_error; | ||
830 | |||
831 | ohci->debug_registers = debugfs_create_file("registers", S_IRUGO, | ||
832 | ohci->debug_dir, dev, | ||
833 | &debug_registers_fops); | ||
834 | if (!ohci->debug_registers) | ||
835 | goto registers_error; | ||
689 | 836 | ||
690 | retval = class_device_create_file(cldev, &class_device_attr_async); | ||
691 | retval = class_device_create_file(cldev, &class_device_attr_periodic); | ||
692 | retval = class_device_create_file(cldev, &class_device_attr_registers); | ||
693 | ohci_dbg (ohci, "created debug files\n"); | 837 | ohci_dbg (ohci, "created debug files\n"); |
838 | return; | ||
839 | |||
840 | registers_error: | ||
841 | debugfs_remove(ohci->debug_periodic); | ||
842 | periodic_error: | ||
843 | debugfs_remove(ohci->debug_async); | ||
844 | async_error: | ||
845 | debugfs_remove(ohci->debug_dir); | ||
846 | dir_error: | ||
847 | ohci->debug_periodic = NULL; | ||
848 | ohci->debug_async = NULL; | ||
849 | ohci->debug_dir = NULL; | ||
694 | } | 850 | } |
695 | 851 | ||
696 | static inline void remove_debug_files (struct ohci_hcd *ohci) | 852 | static inline void remove_debug_files (struct ohci_hcd *ohci) |
697 | { | 853 | { |
698 | struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev; | 854 | debugfs_remove(ohci->debug_registers); |
699 | 855 | debugfs_remove(ohci->debug_periodic); | |
700 | class_device_remove_file(cldev, &class_device_attr_async); | 856 | debugfs_remove(ohci->debug_async); |
701 | class_device_remove_file(cldev, &class_device_attr_periodic); | 857 | debugfs_remove(ohci->debug_dir); |
702 | class_device_remove_file(cldev, &class_device_attr_registers); | ||
703 | } | 858 | } |
704 | 859 | ||
705 | #endif | 860 | #endif |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index ddd4ee1f2413..dd4798ee028e 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/dmapool.h> | 36 | #include <linux/dmapool.h> |
37 | #include <linux/reboot.h> | 37 | #include <linux/reboot.h> |
38 | #include <linux/workqueue.h> | 38 | #include <linux/workqueue.h> |
39 | #include <linux/debugfs.h> | ||
39 | 40 | ||
40 | #include <asm/io.h> | 41 | #include <asm/io.h> |
41 | #include <asm/irq.h> | 42 | #include <asm/irq.h> |
@@ -809,13 +810,9 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) | |||
809 | } | 810 | } |
810 | 811 | ||
811 | if (ints & OHCI_INTR_WDH) { | 812 | if (ints & OHCI_INTR_WDH) { |
812 | if (HC_IS_RUNNING(hcd->state)) | ||
813 | ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrdisable); | ||
814 | spin_lock (&ohci->lock); | 813 | spin_lock (&ohci->lock); |
815 | dl_done_list (ohci); | 814 | dl_done_list (ohci); |
816 | spin_unlock (&ohci->lock); | 815 | spin_unlock (&ohci->lock); |
817 | if (HC_IS_RUNNING(hcd->state)) | ||
818 | ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrenable); | ||
819 | } | 816 | } |
820 | 817 | ||
821 | if (quirk_zfmicro(ohci) && (ints & OHCI_INTR_SF)) { | 818 | if (quirk_zfmicro(ohci) && (ints & OHCI_INTR_SF)) { |
@@ -1032,6 +1029,13 @@ MODULE_LICENSE ("GPL"); | |||
1032 | #define PLATFORM_DRIVER usb_hcd_pnx4008_driver | 1029 | #define PLATFORM_DRIVER usb_hcd_pnx4008_driver |
1033 | #endif | 1030 | #endif |
1034 | 1031 | ||
1032 | #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | ||
1033 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ | ||
1034 | defined(CONFIG_CPU_SUBTYPE_SH7763) | ||
1035 | #include "ohci-sh.c" | ||
1036 | #define PLATFORM_DRIVER ohci_hcd_sh_driver | ||
1037 | #endif | ||
1038 | |||
1035 | 1039 | ||
1036 | #ifdef CONFIG_USB_OHCI_HCD_PPC_OF | 1040 | #ifdef CONFIG_USB_OHCI_HCD_PPC_OF |
1037 | #include "ohci-ppc-of.c" | 1041 | #include "ohci-ppc-of.c" |
@@ -1048,6 +1052,11 @@ MODULE_LICENSE ("GPL"); | |||
1048 | #define SSB_OHCI_DRIVER ssb_ohci_driver | 1052 | #define SSB_OHCI_DRIVER ssb_ohci_driver |
1049 | #endif | 1053 | #endif |
1050 | 1054 | ||
1055 | #ifdef CONFIG_MFD_SM501 | ||
1056 | #include "ohci-sm501.c" | ||
1057 | #define PLATFORM_DRIVER ohci_hcd_sm501_driver | ||
1058 | #endif | ||
1059 | |||
1051 | #if !defined(PCI_DRIVER) && \ | 1060 | #if !defined(PCI_DRIVER) && \ |
1052 | !defined(PLATFORM_DRIVER) && \ | 1061 | !defined(PLATFORM_DRIVER) && \ |
1053 | !defined(OF_PLATFORM_DRIVER) && \ | 1062 | !defined(OF_PLATFORM_DRIVER) && \ |
@@ -1068,6 +1077,14 @@ static int __init ohci_hcd_mod_init(void) | |||
1068 | pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, | 1077 | pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, |
1069 | sizeof (struct ed), sizeof (struct td)); | 1078 | sizeof (struct ed), sizeof (struct td)); |
1070 | 1079 | ||
1080 | #ifdef DEBUG | ||
1081 | ohci_debug_root = debugfs_create_dir("ohci", NULL); | ||
1082 | if (!ohci_debug_root) { | ||
1083 | retval = -ENOENT; | ||
1084 | goto error_debug; | ||
1085 | } | ||
1086 | #endif | ||
1087 | |||
1071 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1088 | #ifdef PS3_SYSTEM_BUS_DRIVER |
1072 | retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER); | 1089 | retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER); |
1073 | if (retval < 0) | 1090 | if (retval < 0) |
@@ -1130,6 +1147,12 @@ static int __init ohci_hcd_mod_init(void) | |||
1130 | ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | 1147 | ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); |
1131 | error_ps3: | 1148 | error_ps3: |
1132 | #endif | 1149 | #endif |
1150 | #ifdef DEBUG | ||
1151 | debugfs_remove(ohci_debug_root); | ||
1152 | ohci_debug_root = NULL; | ||
1153 | error_debug: | ||
1154 | #endif | ||
1155 | |||
1133 | return retval; | 1156 | return retval; |
1134 | } | 1157 | } |
1135 | module_init(ohci_hcd_mod_init); | 1158 | module_init(ohci_hcd_mod_init); |
@@ -1154,6 +1177,9 @@ static void __exit ohci_hcd_mod_exit(void) | |||
1154 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1177 | #ifdef PS3_SYSTEM_BUS_DRIVER |
1155 | ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | 1178 | ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); |
1156 | #endif | 1179 | #endif |
1180 | #ifdef DEBUG | ||
1181 | debugfs_remove(ohci_debug_root); | ||
1182 | #endif | ||
1157 | } | 1183 | } |
1158 | module_exit(ohci_hcd_mod_exit); | 1184 | module_exit(ohci_hcd_mod_exit); |
1159 | 1185 | ||
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c new file mode 100644 index 000000000000..5309ac039e15 --- /dev/null +++ b/drivers/usb/host/ohci-sh.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * OHCI HCD (Host Controller Driver) for USB. | ||
3 | * | ||
4 | * Copyright (C) 2008 Renesas Solutions Corp. | ||
5 | * | ||
6 | * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/platform_device.h> | ||
24 | |||
25 | static int ohci_sh_start(struct usb_hcd *hcd) | ||
26 | { | ||
27 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
28 | |||
29 | ohci_hcd_init(ohci); | ||
30 | ohci_init(ohci); | ||
31 | ohci_run(ohci); | ||
32 | hcd->state = HC_STATE_RUNNING; | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static const struct hc_driver ohci_sh_hc_driver = { | ||
37 | .description = hcd_name, | ||
38 | .product_desc = "SuperH OHCI", | ||
39 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
40 | |||
41 | /* | ||
42 | * generic hardware linkage | ||
43 | */ | ||
44 | .irq = ohci_irq, | ||
45 | .flags = HCD_USB11 | HCD_MEMORY, | ||
46 | |||
47 | /* | ||
48 | * basic lifecycle operations | ||
49 | */ | ||
50 | .start = ohci_sh_start, | ||
51 | .stop = ohci_stop, | ||
52 | .shutdown = ohci_shutdown, | ||
53 | |||
54 | /* | ||
55 | * managing i/o requests and associated device resources | ||
56 | */ | ||
57 | .urb_enqueue = ohci_urb_enqueue, | ||
58 | .urb_dequeue = ohci_urb_dequeue, | ||
59 | .endpoint_disable = ohci_endpoint_disable, | ||
60 | |||
61 | /* | ||
62 | * scheduling support | ||
63 | */ | ||
64 | .get_frame_number = ohci_get_frame, | ||
65 | |||
66 | /* | ||
67 | * root hub support | ||
68 | */ | ||
69 | .hub_status_data = ohci_hub_status_data, | ||
70 | .hub_control = ohci_hub_control, | ||
71 | .hub_irq_enable = ohci_rhsc_enable, | ||
72 | #ifdef CONFIG_PM | ||
73 | .bus_suspend = ohci_bus_suspend, | ||
74 | .bus_resume = ohci_bus_resume, | ||
75 | #endif | ||
76 | .start_port_reset = ohci_start_port_reset, | ||
77 | }; | ||
78 | |||
79 | /*-------------------------------------------------------------------------*/ | ||
80 | |||
81 | #define resource_len(r) (((r)->end - (r)->start) + 1) | ||
82 | static int ohci_hcd_sh_probe(struct platform_device *pdev) | ||
83 | { | ||
84 | struct resource *res = NULL; | ||
85 | struct usb_hcd *hcd = NULL; | ||
86 | int irq = -1; | ||
87 | int ret; | ||
88 | |||
89 | if (usb_disabled()) | ||
90 | return -ENODEV; | ||
91 | |||
92 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
93 | if (!res) { | ||
94 | err("platform_get_resource error."); | ||
95 | return -ENODEV; | ||
96 | } | ||
97 | |||
98 | irq = platform_get_irq(pdev, 0); | ||
99 | if (irq < 0) { | ||
100 | err("platform_get_irq error."); | ||
101 | return -ENODEV; | ||
102 | } | ||
103 | |||
104 | /* initialize hcd */ | ||
105 | hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name); | ||
106 | if (!hcd) { | ||
107 | err("Failed to create hcd"); | ||
108 | return -ENOMEM; | ||
109 | } | ||
110 | |||
111 | hcd->regs = (void __iomem *)res->start; | ||
112 | hcd->rsrc_start = res->start; | ||
113 | hcd->rsrc_len = resource_len(res); | ||
114 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); | ||
115 | if (ret != 0) { | ||
116 | err("Failed to add hcd"); | ||
117 | usb_put_hcd(hcd); | ||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | static int ohci_hcd_sh_remove(struct platform_device *pdev) | ||
125 | { | ||
126 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
127 | |||
128 | usb_remove_hcd(hcd); | ||
129 | usb_put_hcd(hcd); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static struct platform_driver ohci_hcd_sh_driver = { | ||
135 | .probe = ohci_hcd_sh_probe, | ||
136 | .remove = ohci_hcd_sh_remove, | ||
137 | .shutdown = usb_hcd_platform_shutdown, | ||
138 | .driver = { | ||
139 | .name = "sh_ohci", | ||
140 | .owner = THIS_MODULE, | ||
141 | }, | ||
142 | }; | ||
143 | |||
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c new file mode 100644 index 000000000000..a97070142869 --- /dev/null +++ b/drivers/usb/host/ohci-sm501.c | |||
@@ -0,0 +1,264 @@ | |||
1 | /* | ||
2 | * OHCI HCD (Host Controller Driver) for USB. | ||
3 | * | ||
4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | ||
5 | * (C) Copyright 2000-2005 David Brownell | ||
6 | * (C) Copyright 2002 Hewlett-Packard Company | ||
7 | * (C) Copyright 2008 Magnus Damm | ||
8 | * | ||
9 | * SM501 Bus Glue - based on ohci-omap.c | ||
10 | * | ||
11 | * This file is licenced under the GPL. | ||
12 | */ | ||
13 | |||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/jiffies.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/dma-mapping.h> | ||
18 | #include <linux/sm501.h> | ||
19 | #include <linux/sm501-regs.h> | ||
20 | |||
21 | static int ohci_sm501_init(struct usb_hcd *hcd) | ||
22 | { | ||
23 | return ohci_init(hcd_to_ohci(hcd)); | ||
24 | } | ||
25 | |||
26 | static int ohci_sm501_start(struct usb_hcd *hcd) | ||
27 | { | ||
28 | struct device *dev = hcd->self.controller; | ||
29 | int ret; | ||
30 | |||
31 | ret = ohci_run(hcd_to_ohci(hcd)); | ||
32 | if (ret < 0) { | ||
33 | dev_err(dev, "can't start %s", hcd->self.bus_name); | ||
34 | ohci_stop(hcd); | ||
35 | } | ||
36 | |||
37 | return ret; | ||
38 | } | ||
39 | |||
40 | /*-------------------------------------------------------------------------*/ | ||
41 | |||
42 | static const struct hc_driver ohci_sm501_hc_driver = { | ||
43 | .description = hcd_name, | ||
44 | .product_desc = "SM501 OHCI", | ||
45 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
46 | |||
47 | /* | ||
48 | * generic hardware linkage | ||
49 | */ | ||
50 | .irq = ohci_irq, | ||
51 | .flags = HCD_USB11 | HCD_MEMORY | HCD_LOCAL_MEM, | ||
52 | |||
53 | /* | ||
54 | * basic lifecycle operations | ||
55 | */ | ||
56 | .reset = ohci_sm501_init, | ||
57 | .start = ohci_sm501_start, | ||
58 | .stop = ohci_stop, | ||
59 | .shutdown = ohci_shutdown, | ||
60 | |||
61 | /* | ||
62 | * managing i/o requests and associated device resources | ||
63 | */ | ||
64 | .urb_enqueue = ohci_urb_enqueue, | ||
65 | .urb_dequeue = ohci_urb_dequeue, | ||
66 | .endpoint_disable = ohci_endpoint_disable, | ||
67 | |||
68 | /* | ||
69 | * scheduling support | ||
70 | */ | ||
71 | .get_frame_number = ohci_get_frame, | ||
72 | |||
73 | /* | ||
74 | * root hub support | ||
75 | */ | ||
76 | .hub_status_data = ohci_hub_status_data, | ||
77 | .hub_control = ohci_hub_control, | ||
78 | .hub_irq_enable = ohci_rhsc_enable, | ||
79 | #ifdef CONFIG_PM | ||
80 | .bus_suspend = ohci_bus_suspend, | ||
81 | .bus_resume = ohci_bus_resume, | ||
82 | #endif | ||
83 | .start_port_reset = ohci_start_port_reset, | ||
84 | }; | ||
85 | |||
86 | /*-------------------------------------------------------------------------*/ | ||
87 | |||
88 | static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev) | ||
89 | { | ||
90 | const struct hc_driver *driver = &ohci_sm501_hc_driver; | ||
91 | struct device *dev = &pdev->dev; | ||
92 | struct resource *res, *mem; | ||
93 | int retval, irq; | ||
94 | struct usb_hcd *hcd = 0; | ||
95 | |||
96 | irq = retval = platform_get_irq(pdev, 0); | ||
97 | if (retval < 0) | ||
98 | goto err0; | ||
99 | |||
100 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
101 | if (mem == NULL) { | ||
102 | dev_err(dev, "no resource definition for memory\n"); | ||
103 | retval = -ENOENT; | ||
104 | goto err0; | ||
105 | } | ||
106 | |||
107 | if (!request_mem_region(mem->start, mem->end - mem->start + 1, | ||
108 | pdev->name)) { | ||
109 | dev_err(dev, "request_mem_region failed\n"); | ||
110 | retval = -EBUSY; | ||
111 | goto err0; | ||
112 | } | ||
113 | |||
114 | /* The sm501 chip is equipped with local memory that may be used | ||
115 | * by on-chip devices such as the video controller and the usb host. | ||
116 | * This driver uses dma_declare_coherent_memory() to make sure | ||
117 | * usb allocations with dma_alloc_coherent() allocate from | ||
118 | * this local memory. The dma_handle returned by dma_alloc_coherent() | ||
119 | * will be an offset starting from 0 for the first local memory byte. | ||
120 | * | ||
121 | * So as long as data is allocated using dma_alloc_coherent() all is | ||
122 | * fine. This is however not always the case - buffers may be allocated | ||
123 | * using kmalloc() - so the usb core needs to be told that it must copy | ||
124 | * data into our local memory if the buffers happen to be placed in | ||
125 | * regular memory. The HCD_LOCAL_MEM flag does just that. | ||
126 | */ | ||
127 | |||
128 | if (!dma_declare_coherent_memory(dev, mem->start, | ||
129 | mem->start - mem->parent->start, | ||
130 | (mem->end - mem->start) + 1, | ||
131 | DMA_MEMORY_MAP | | ||
132 | DMA_MEMORY_EXCLUSIVE)) { | ||
133 | dev_err(dev, "cannot declare coherent memory\n"); | ||
134 | retval = -ENXIO; | ||
135 | goto err1; | ||
136 | } | ||
137 | |||
138 | /* allocate, reserve and remap resources for registers */ | ||
139 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
140 | if (res == NULL) { | ||
141 | dev_err(dev, "no resource definition for registers\n"); | ||
142 | retval = -ENOENT; | ||
143 | goto err2; | ||
144 | } | ||
145 | |||
146 | hcd = usb_create_hcd(driver, &pdev->dev, pdev->dev.bus_id); | ||
147 | if (!hcd) { | ||
148 | retval = -ENOMEM; | ||
149 | goto err2; | ||
150 | } | ||
151 | |||
152 | hcd->rsrc_start = res->start; | ||
153 | hcd->rsrc_len = res->end - res->start + 1; | ||
154 | |||
155 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, pdev->name)) { | ||
156 | dev_err(dev, "request_mem_region failed\n"); | ||
157 | retval = -EBUSY; | ||
158 | goto err3; | ||
159 | } | ||
160 | |||
161 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
162 | if (hcd->regs == NULL) { | ||
163 | dev_err(dev, "cannot remap registers\n"); | ||
164 | retval = -ENXIO; | ||
165 | goto err4; | ||
166 | } | ||
167 | |||
168 | ohci_hcd_init(hcd_to_ohci(hcd)); | ||
169 | |||
170 | retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | ||
171 | if (retval) | ||
172 | goto err4; | ||
173 | |||
174 | /* enable power and unmask interrupts */ | ||
175 | |||
176 | sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1); | ||
177 | sm501_modify_reg(dev->parent, SM501_IRQ_MASK, 1 << 6, 0); | ||
178 | |||
179 | return 0; | ||
180 | err4: | ||
181 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
182 | err3: | ||
183 | usb_put_hcd(hcd); | ||
184 | err2: | ||
185 | dma_release_declared_memory(dev); | ||
186 | err1: | ||
187 | release_mem_region(mem->start, mem->end - mem->start + 1); | ||
188 | err0: | ||
189 | return retval; | ||
190 | } | ||
191 | |||
192 | static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev) | ||
193 | { | ||
194 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
195 | struct resource *mem; | ||
196 | |||
197 | usb_remove_hcd(hcd); | ||
198 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
199 | usb_put_hcd(hcd); | ||
200 | dma_release_declared_memory(&pdev->dev); | ||
201 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
202 | release_mem_region(mem->start, mem->end - mem->start + 1); | ||
203 | |||
204 | /* mask interrupts and disable power */ | ||
205 | |||
206 | sm501_modify_reg(pdev->dev.parent, SM501_IRQ_MASK, 0, 1 << 6); | ||
207 | sm501_unit_power(pdev->dev.parent, SM501_GATE_USB_HOST, 0); | ||
208 | |||
209 | platform_set_drvdata(pdev, NULL); | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | /*-------------------------------------------------------------------------*/ | ||
214 | |||
215 | #ifdef CONFIG_PM | ||
216 | static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg) | ||
217 | { | ||
218 | struct device *dev = &pdev->dev; | ||
219 | struct ohci_hcd *ohci = hcd_to_ohci(platform_get_drvdata(pdev)); | ||
220 | |||
221 | if (time_before(jiffies, ohci->next_statechange)) | ||
222 | msleep(5); | ||
223 | ohci->next_statechange = jiffies; | ||
224 | |||
225 | sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0); | ||
226 | ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; | ||
227 | dev->power.power_state = PMSG_SUSPEND; | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int ohci_sm501_resume(struct platform_device *pdev) | ||
232 | { | ||
233 | struct device *dev = &pdev->dev; | ||
234 | struct ohci_hcd *ohci = hcd_to_ohci(platform_get_drvdata(pdev)); | ||
235 | |||
236 | if (time_before(jiffies, ohci->next_statechange)) | ||
237 | msleep(5); | ||
238 | ohci->next_statechange = jiffies; | ||
239 | |||
240 | sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1); | ||
241 | dev->power.power_state = PMSG_ON; | ||
242 | usb_hcd_resume_root_hub(platform_get_drvdata(pdev)); | ||
243 | return 0; | ||
244 | } | ||
245 | #endif | ||
246 | |||
247 | /*-------------------------------------------------------------------------*/ | ||
248 | |||
249 | /* | ||
250 | * Driver definition to register with the SM501 bus | ||
251 | */ | ||
252 | static struct platform_driver ohci_hcd_sm501_driver = { | ||
253 | .probe = ohci_hcd_sm501_drv_probe, | ||
254 | .remove = ohci_hcd_sm501_drv_remove, | ||
255 | .shutdown = usb_hcd_platform_shutdown, | ||
256 | #ifdef CONFIG_PM | ||
257 | .suspend = ohci_sm501_suspend, | ||
258 | .resume = ohci_sm501_resume, | ||
259 | #endif | ||
260 | .driver = { | ||
261 | .owner = THIS_MODULE, | ||
262 | .name = "sm501-usb", | ||
263 | }, | ||
264 | }; | ||
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 47c5c66a282c..dc544ddc7849 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
@@ -408,6 +408,13 @@ struct ohci_hcd { | |||
408 | unsigned eds_scheduled; | 408 | unsigned eds_scheduled; |
409 | struct ed *ed_to_check; | 409 | struct ed *ed_to_check; |
410 | unsigned zf_delay; | 410 | unsigned zf_delay; |
411 | |||
412 | #ifdef DEBUG | ||
413 | struct dentry *debug_dir; | ||
414 | struct dentry *debug_async; | ||
415 | struct dentry *debug_periodic; | ||
416 | struct dentry *debug_registers; | ||
417 | #endif | ||
411 | }; | 418 | }; |
412 | 419 | ||
413 | #ifdef CONFIG_PCI | 420 | #ifdef CONFIG_PCI |
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index fe9ceb077d9b..57388252b693 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h | |||
@@ -405,7 +405,7 @@ | |||
405 | 405 | ||
406 | struct r8a66597_pipe_info { | 406 | struct r8a66597_pipe_info { |
407 | u16 pipenum; | 407 | u16 pipenum; |
408 | u16 address; /* R8A66597 HCD usb addres */ | 408 | u16 address; /* R8A66597 HCD usb address */ |
409 | u16 epnum; | 409 | u16 epnum; |
410 | u16 maxpacket; | 410 | u16 maxpacket; |
411 | u16 type; | 411 | u16 type; |