diff options
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 109 |
1 files changed, 19 insertions, 90 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index ea6184bf48d..25ed607aab9 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -27,7 +27,6 @@ | |||
27 | */ | 27 | */ |
28 | 28 | ||
29 | /*-------------------------------------------------------------------------*/ | 29 | /*-------------------------------------------------------------------------*/ |
30 | #include <linux/usb/otg.h> | ||
31 | 30 | ||
32 | #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) | 31 | #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) |
33 | 32 | ||
@@ -285,7 +284,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
285 | changed = 1; | 284 | changed = 1; |
286 | } | 285 | } |
287 | } | 286 | } |
288 | 287 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | |
289 | if (changed && ehci->has_hostpc) { | 288 | if (changed && ehci->has_hostpc) { |
290 | spin_unlock_irq(&ehci->lock); | 289 | spin_unlock_irq(&ehci->lock); |
291 | msleep(5); /* 5 ms for HCD to enter low-power mode */ | 290 | msleep(5); /* 5 ms for HCD to enter low-power mode */ |
@@ -306,7 +305,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
306 | "succeeded" : "failed"); | 305 | "succeeded" : "failed"); |
307 | } | 306 | } |
308 | } | 307 | } |
309 | 308 | #endif | |
310 | /* Apparently some devices need a >= 1-uframe delay here */ | 309 | /* Apparently some devices need a >= 1-uframe delay here */ |
311 | if (ehci->bus_suspended) | 310 | if (ehci->bus_suspended) |
312 | udelay(150); | 311 | udelay(150); |
@@ -343,7 +342,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
343 | u32 temp; | 342 | u32 temp; |
344 | u32 power_okay; | 343 | u32 power_okay; |
345 | int i; | 344 | int i; |
346 | u8 resume_needed = 0; | 345 | unsigned long resume_needed = 0; |
347 | 346 | ||
348 | if (time_before (jiffies, ehci->next_statechange)) | 347 | if (time_before (jiffies, ehci->next_statechange)) |
349 | msleep(5); | 348 | msleep(5); |
@@ -416,7 +415,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
416 | if (test_bit(i, &ehci->bus_suspended) && | 415 | if (test_bit(i, &ehci->bus_suspended) && |
417 | (temp & PORT_SUSPEND)) { | 416 | (temp & PORT_SUSPEND)) { |
418 | temp |= PORT_RESUME; | 417 | temp |= PORT_RESUME; |
419 | resume_needed = 1; | 418 | set_bit(i, &resume_needed); |
420 | } | 419 | } |
421 | ehci_writel(ehci, temp, &ehci->regs->port_status [i]); | 420 | ehci_writel(ehci, temp, &ehci->regs->port_status [i]); |
422 | } | 421 | } |
@@ -431,8 +430,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
431 | i = HCS_N_PORTS (ehci->hcs_params); | 430 | i = HCS_N_PORTS (ehci->hcs_params); |
432 | while (i--) { | 431 | while (i--) { |
433 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); | 432 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); |
434 | if (test_bit(i, &ehci->bus_suspended) && | 433 | if (test_bit(i, &resume_needed)) { |
435 | (temp & PORT_SUSPEND)) { | ||
436 | temp &= ~(PORT_RWC_BITS | PORT_RESUME); | 434 | temp &= ~(PORT_RWC_BITS | PORT_RESUME); |
437 | ehci_writel(ehci, temp, &ehci->regs->port_status [i]); | 435 | ehci_writel(ehci, temp, &ehci->regs->port_status [i]); |
438 | ehci_vdbg (ehci, "resumed port %d\n", i + 1); | 436 | ehci_vdbg (ehci, "resumed port %d\n", i + 1); |
@@ -471,29 +469,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
471 | 469 | ||
472 | /*-------------------------------------------------------------------------*/ | 470 | /*-------------------------------------------------------------------------*/ |
473 | 471 | ||
474 | /* Display the ports dedicated to the companion controller */ | ||
475 | static ssize_t show_companion(struct device *dev, | ||
476 | struct device_attribute *attr, | ||
477 | char *buf) | ||
478 | { | ||
479 | struct ehci_hcd *ehci; | ||
480 | int nports, index, n; | ||
481 | int count = PAGE_SIZE; | ||
482 | char *ptr = buf; | ||
483 | |||
484 | ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); | ||
485 | nports = HCS_N_PORTS(ehci->hcs_params); | ||
486 | |||
487 | for (index = 0; index < nports; ++index) { | ||
488 | if (test_bit(index, &ehci->companion_ports)) { | ||
489 | n = scnprintf(ptr, count, "%d\n", index + 1); | ||
490 | ptr += n; | ||
491 | count -= n; | ||
492 | } | ||
493 | } | ||
494 | return ptr - buf; | ||
495 | } | ||
496 | |||
497 | /* | 472 | /* |
498 | * Sets the owner of a port | 473 | * Sets the owner of a port |
499 | */ | 474 | */ |
@@ -528,58 +503,6 @@ static void set_owner(struct ehci_hcd *ehci, int portnum, int new_owner) | |||
528 | } | 503 | } |
529 | } | 504 | } |
530 | 505 | ||
531 | /* | ||
532 | * Dedicate or undedicate a port to the companion controller. | ||
533 | * Syntax is "[-]portnum", where a leading '-' sign means | ||
534 | * return control of the port to the EHCI controller. | ||
535 | */ | ||
536 | static ssize_t store_companion(struct device *dev, | ||
537 | struct device_attribute *attr, | ||
538 | const char *buf, size_t count) | ||
539 | { | ||
540 | struct ehci_hcd *ehci; | ||
541 | int portnum, new_owner; | ||
542 | |||
543 | ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); | ||
544 | new_owner = PORT_OWNER; /* Owned by companion */ | ||
545 | if (sscanf(buf, "%d", &portnum) != 1) | ||
546 | return -EINVAL; | ||
547 | if (portnum < 0) { | ||
548 | portnum = - portnum; | ||
549 | new_owner = 0; /* Owned by EHCI */ | ||
550 | } | ||
551 | if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params)) | ||
552 | return -ENOENT; | ||
553 | portnum--; | ||
554 | if (new_owner) | ||
555 | set_bit(portnum, &ehci->companion_ports); | ||
556 | else | ||
557 | clear_bit(portnum, &ehci->companion_ports); | ||
558 | set_owner(ehci, portnum, new_owner); | ||
559 | return count; | ||
560 | } | ||
561 | static DEVICE_ATTR(companion, 0644, show_companion, store_companion); | ||
562 | |||
563 | static inline int create_companion_file(struct ehci_hcd *ehci) | ||
564 | { | ||
565 | int i = 0; | ||
566 | |||
567 | /* with integrated TT there is no companion! */ | ||
568 | if (!ehci_is_TDI(ehci)) | ||
569 | i = device_create_file(ehci_to_hcd(ehci)->self.controller, | ||
570 | &dev_attr_companion); | ||
571 | return i; | ||
572 | } | ||
573 | |||
574 | static inline void remove_companion_file(struct ehci_hcd *ehci) | ||
575 | { | ||
576 | /* with integrated TT there is no companion! */ | ||
577 | if (!ehci_is_TDI(ehci)) | ||
578 | device_remove_file(ehci_to_hcd(ehci)->self.controller, | ||
579 | &dev_attr_companion); | ||
580 | } | ||
581 | |||
582 | |||
583 | /*-------------------------------------------------------------------------*/ | 506 | /*-------------------------------------------------------------------------*/ |
584 | 507 | ||
585 | static int check_reset_complete ( | 508 | static int check_reset_complete ( |
@@ -802,13 +725,6 @@ static int ehci_hub_control ( | |||
802 | goto error; | 725 | goto error; |
803 | if (ehci->no_selective_suspend) | 726 | if (ehci->no_selective_suspend) |
804 | break; | 727 | break; |
805 | #ifdef CONFIG_USB_OTG | ||
806 | if ((hcd->self.otg_port == (wIndex + 1)) | ||
807 | && hcd->self.b_hnp_enable) { | ||
808 | otg_start_hnp(ehci->transceiver); | ||
809 | break; | ||
810 | } | ||
811 | #endif | ||
812 | if (!(temp & PORT_SUSPEND)) | 728 | if (!(temp & PORT_SUSPEND)) |
813 | break; | 729 | break; |
814 | if ((temp & PORT_PE) == 0) | 730 | if ((temp & PORT_PE) == 0) |
@@ -891,10 +807,11 @@ static int ehci_hub_control ( | |||
891 | * power switching; they're allowed to just limit the | 807 | * power switching; they're allowed to just limit the |
892 | * current. khubd will turn the power back on. | 808 | * current. khubd will turn the power back on. |
893 | */ | 809 | */ |
894 | if (HCS_PPC (ehci->hcs_params)){ | 810 | if ((temp & PORT_OC) && HCS_PPC(ehci->hcs_params)) { |
895 | ehci_writel(ehci, | 811 | ehci_writel(ehci, |
896 | temp & ~(PORT_RWC_BITS | PORT_POWER), | 812 | temp & ~(PORT_RWC_BITS | PORT_POWER), |
897 | status_reg); | 813 | status_reg); |
814 | temp = ehci_readl(ehci, status_reg); | ||
898 | } | 815 | } |
899 | } | 816 | } |
900 | 817 | ||
@@ -1120,7 +1037,19 @@ static int ehci_hub_control ( | |||
1120 | if (!selector || selector > 5) | 1037 | if (!selector || selector > 5) |
1121 | goto error; | 1038 | goto error; |
1122 | ehci_quiesce(ehci); | 1039 | ehci_quiesce(ehci); |
1040 | |||
1041 | /* Put all enabled ports into suspend */ | ||
1042 | while (ports--) { | ||
1043 | u32 __iomem *sreg = | ||
1044 | &ehci->regs->port_status[ports]; | ||
1045 | |||
1046 | temp = ehci_readl(ehci, sreg) & ~PORT_RWC_BITS; | ||
1047 | if (temp & PORT_PE) | ||
1048 | ehci_writel(ehci, temp | PORT_SUSPEND, | ||
1049 | sreg); | ||
1050 | } | ||
1123 | ehci_halt(ehci); | 1051 | ehci_halt(ehci); |
1052 | temp = ehci_readl(ehci, status_reg); | ||
1124 | temp |= selector << 16; | 1053 | temp |= selector << 16; |
1125 | ehci_writel(ehci, temp, status_reg); | 1054 | ehci_writel(ehci, temp, status_reg); |
1126 | break; | 1055 | break; |