aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
-rw-r--r--drivers/usb/host/ehci-hub.c109
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 */
475static 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 */
536static 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}
561static DEVICE_ATTR(companion, 0644, show_companion, store_companion);
562
563static 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
574static 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
585static int check_reset_complete ( 508static 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;