diff options
Diffstat (limited to 'drivers/usb/host')
37 files changed, 2203 insertions, 901 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index cc60759083bf..62711870f8ee 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -67,6 +67,11 @@ config USB_EHCI_TT_NEWSCHED | |||
67 | 67 | ||
68 | If unsure, say N. | 68 | If unsure, say N. |
69 | 69 | ||
70 | config USB_EHCI_BIG_ENDIAN_MMIO | ||
71 | bool | ||
72 | depends on USB_EHCI_HCD | ||
73 | default n | ||
74 | |||
70 | config USB_ISP116X_HCD | 75 | config USB_ISP116X_HCD |
71 | tristate "ISP116X HCD support" | 76 | tristate "ISP116X HCD support" |
72 | depends on USB | 77 | depends on USB |
@@ -101,21 +106,48 @@ config USB_OHCI_HCD_PPC_SOC | |||
101 | bool "OHCI support for on-chip PPC USB controller" | 106 | bool "OHCI support for on-chip PPC USB controller" |
102 | depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx) | 107 | depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx) |
103 | default y | 108 | default y |
104 | select USB_OHCI_BIG_ENDIAN | 109 | select USB_OHCI_BIG_ENDIAN_DESC |
110 | select USB_OHCI_BIG_ENDIAN_MMIO | ||
105 | ---help--- | 111 | ---help--- |
106 | Enables support for the USB controller on the MPC52xx or | 112 | Enables support for the USB controller on the MPC52xx or |
107 | STB03xxx processor chip. If unsure, say Y. | 113 | STB03xxx processor chip. If unsure, say Y. |
108 | 114 | ||
115 | config USB_OHCI_HCD_PPC_OF | ||
116 | bool "OHCI support for PPC USB controller on OF platform bus" | ||
117 | depends on USB_OHCI_HCD && PPC_OF | ||
118 | default y | ||
119 | ---help--- | ||
120 | Enables support for the USB controller PowerPC present on the | ||
121 | OpenFirmware platform bus. | ||
122 | |||
123 | config USB_OHCI_HCD_PPC_OF_BE | ||
124 | bool "Support big endian HC" | ||
125 | depends on USB_OHCI_HCD_PPC_OF | ||
126 | default y | ||
127 | select USB_OHCI_BIG_ENDIAN_DESC | ||
128 | select USB_OHCI_BIG_ENDIAN_MMIO | ||
129 | |||
130 | config USB_OHCI_HCD_PPC_OF_LE | ||
131 | bool "Support little endian HC" | ||
132 | depends on USB_OHCI_HCD_PPC_OF | ||
133 | default n | ||
134 | select USB_OHCI_LITTLE_ENDIAN | ||
135 | |||
109 | config USB_OHCI_HCD_PCI | 136 | config USB_OHCI_HCD_PCI |
110 | bool "OHCI support for PCI-bus USB controllers" | 137 | bool "OHCI support for PCI-bus USB controllers" |
111 | depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx) | 138 | depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF) |
112 | default y | 139 | default y |
113 | select USB_OHCI_LITTLE_ENDIAN | 140 | select USB_OHCI_LITTLE_ENDIAN |
114 | ---help--- | 141 | ---help--- |
115 | Enables support for PCI-bus plug-in USB controller cards. | 142 | Enables support for PCI-bus plug-in USB controller cards. |
116 | If unsure, say Y. | 143 | If unsure, say Y. |
117 | 144 | ||
118 | config USB_OHCI_BIG_ENDIAN | 145 | config USB_OHCI_BIG_ENDIAN_DESC |
146 | bool | ||
147 | depends on USB_OHCI_HCD | ||
148 | default n | ||
149 | |||
150 | config USB_OHCI_BIG_ENDIAN_MMIO | ||
119 | bool | 151 | bool |
120 | depends on USB_OHCI_HCD | 152 | depends on USB_OHCI_HCD |
121 | default n | 153 | default n |
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 56349d21e6ea..246afea9e83b 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
@@ -43,7 +43,7 @@ | |||
43 | */ | 43 | */ |
44 | static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) | 44 | static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) |
45 | { | 45 | { |
46 | u32 params = readl (&ehci->caps->hcs_params); | 46 | u32 params = ehci_readl(ehci, &ehci->caps->hcs_params); |
47 | 47 | ||
48 | ehci_dbg (ehci, | 48 | ehci_dbg (ehci, |
49 | "%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d\n", | 49 | "%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d\n", |
@@ -87,7 +87,7 @@ static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {} | |||
87 | * */ | 87 | * */ |
88 | static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) | 88 | static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) |
89 | { | 89 | { |
90 | u32 params = readl (&ehci->caps->hcc_params); | 90 | u32 params = ehci_readl(ehci, &ehci->caps->hcc_params); |
91 | 91 | ||
92 | if (HCC_ISOC_CACHE (params)) { | 92 | if (HCC_ISOC_CACHE (params)) { |
93 | ehci_dbg (ehci, | 93 | ehci_dbg (ehci, |
@@ -653,7 +653,7 @@ show_registers (struct class_device *class_dev, char *buf) | |||
653 | } | 653 | } |
654 | 654 | ||
655 | /* Capability Registers */ | 655 | /* Capability Registers */ |
656 | i = HC_VERSION(readl (&ehci->caps->hc_capbase)); | 656 | i = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); |
657 | temp = scnprintf (next, size, | 657 | temp = scnprintf (next, size, |
658 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" | 658 | "bus %s, device %s (driver " DRIVER_VERSION ")\n" |
659 | "%s\n" | 659 | "%s\n" |
@@ -673,7 +673,7 @@ show_registers (struct class_device *class_dev, char *buf) | |||
673 | unsigned count = 256/4; | 673 | unsigned count = 256/4; |
674 | 674 | ||
675 | pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); | 675 | pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); |
676 | offset = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params)); | 676 | offset = HCC_EXT_CAPS (ehci_readl(ehci, &ehci->caps->hcc_params)); |
677 | while (offset && count--) { | 677 | while (offset && count--) { |
678 | pci_read_config_dword (pdev, offset, &cap); | 678 | pci_read_config_dword (pdev, offset, &cap); |
679 | switch (cap & 0xff) { | 679 | switch (cap & 0xff) { |
@@ -704,50 +704,50 @@ show_registers (struct class_device *class_dev, char *buf) | |||
704 | #endif | 704 | #endif |
705 | 705 | ||
706 | // FIXME interpret both types of params | 706 | // FIXME interpret both types of params |
707 | i = readl (&ehci->caps->hcs_params); | 707 | i = ehci_readl(ehci, &ehci->caps->hcs_params); |
708 | temp = scnprintf (next, size, "structural params 0x%08x\n", i); | 708 | temp = scnprintf (next, size, "structural params 0x%08x\n", i); |
709 | size -= temp; | 709 | size -= temp; |
710 | next += temp; | 710 | next += temp; |
711 | 711 | ||
712 | i = readl (&ehci->caps->hcc_params); | 712 | i = ehci_readl(ehci, &ehci->caps->hcc_params); |
713 | temp = scnprintf (next, size, "capability params 0x%08x\n", i); | 713 | temp = scnprintf (next, size, "capability params 0x%08x\n", i); |
714 | size -= temp; | 714 | size -= temp; |
715 | next += temp; | 715 | next += temp; |
716 | 716 | ||
717 | /* Operational Registers */ | 717 | /* Operational Registers */ |
718 | temp = dbg_status_buf (scratch, sizeof scratch, label, | 718 | temp = dbg_status_buf (scratch, sizeof scratch, label, |
719 | readl (&ehci->regs->status)); | 719 | ehci_readl(ehci, &ehci->regs->status)); |
720 | temp = scnprintf (next, size, fmt, temp, scratch); | 720 | temp = scnprintf (next, size, fmt, temp, scratch); |
721 | size -= temp; | 721 | size -= temp; |
722 | next += temp; | 722 | next += temp; |
723 | 723 | ||
724 | temp = dbg_command_buf (scratch, sizeof scratch, label, | 724 | temp = dbg_command_buf (scratch, sizeof scratch, label, |
725 | readl (&ehci->regs->command)); | 725 | ehci_readl(ehci, &ehci->regs->command)); |
726 | temp = scnprintf (next, size, fmt, temp, scratch); | 726 | temp = scnprintf (next, size, fmt, temp, scratch); |
727 | size -= temp; | 727 | size -= temp; |
728 | next += temp; | 728 | next += temp; |
729 | 729 | ||
730 | temp = dbg_intr_buf (scratch, sizeof scratch, label, | 730 | temp = dbg_intr_buf (scratch, sizeof scratch, label, |
731 | readl (&ehci->regs->intr_enable)); | 731 | ehci_readl(ehci, &ehci->regs->intr_enable)); |
732 | temp = scnprintf (next, size, fmt, temp, scratch); | 732 | temp = scnprintf (next, size, fmt, temp, scratch); |
733 | size -= temp; | 733 | size -= temp; |
734 | next += temp; | 734 | next += temp; |
735 | 735 | ||
736 | temp = scnprintf (next, size, "uframe %04x\n", | 736 | temp = scnprintf (next, size, "uframe %04x\n", |
737 | readl (&ehci->regs->frame_index)); | 737 | ehci_readl(ehci, &ehci->regs->frame_index)); |
738 | size -= temp; | 738 | size -= temp; |
739 | next += temp; | 739 | next += temp; |
740 | 740 | ||
741 | for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) { | 741 | for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) { |
742 | temp = dbg_port_buf (scratch, sizeof scratch, label, i, | 742 | temp = dbg_port_buf (scratch, sizeof scratch, label, i, |
743 | readl (&ehci->regs->port_status [i - 1])); | 743 | ehci_readl(ehci, &ehci->regs->port_status [i - 1])); |
744 | temp = scnprintf (next, size, fmt, temp, scratch); | 744 | temp = scnprintf (next, size, fmt, temp, scratch); |
745 | size -= temp; | 745 | size -= temp; |
746 | next += temp; | 746 | next += temp; |
747 | if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) { | 747 | if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) { |
748 | temp = scnprintf (next, size, | 748 | temp = scnprintf (next, size, |
749 | " debug control %08x\n", | 749 | " debug control %08x\n", |
750 | readl (&ehci->debug->control)); | 750 | ehci_readl(ehci, &ehci->debug->control)); |
751 | size -= temp; | 751 | size -= temp; |
752 | next += temp; | 752 | next += temp; |
753 | } | 753 | } |
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 1a915e982c1c..a52480505f78 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -177,7 +177,7 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci, | |||
177 | case FSL_USB2_PHY_NONE: | 177 | case FSL_USB2_PHY_NONE: |
178 | break; | 178 | break; |
179 | } | 179 | } |
180 | writel(portsc, &ehci->regs->port_status[port_offset]); | 180 | ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); |
181 | } | 181 | } |
182 | 182 | ||
183 | static void mpc83xx_usb_setup(struct usb_hcd *hcd) | 183 | static void mpc83xx_usb_setup(struct usb_hcd *hcd) |
@@ -214,7 +214,7 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd) | |||
214 | } | 214 | } |
215 | 215 | ||
216 | /* put controller in host mode. */ | 216 | /* put controller in host mode. */ |
217 | writel(0x00000003, non_ehci + FSL_SOC_USB_USBMODE); | 217 | ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMODE); |
218 | out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); | 218 | out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); |
219 | out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); | 219 | out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); |
220 | out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); | 220 | out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); |
@@ -238,12 +238,12 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) | |||
238 | /* EHCI registers start at offset 0x100 */ | 238 | /* EHCI registers start at offset 0x100 */ |
239 | ehci->caps = hcd->regs + 0x100; | 239 | ehci->caps = hcd->regs + 0x100; |
240 | ehci->regs = hcd->regs + 0x100 + | 240 | ehci->regs = hcd->regs + 0x100 + |
241 | HC_LENGTH(readl(&ehci->caps->hc_capbase)); | 241 | HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); |
242 | dbg_hcs_params(ehci, "reset"); | 242 | dbg_hcs_params(ehci, "reset"); |
243 | dbg_hcc_params(ehci, "reset"); | 243 | dbg_hcc_params(ehci, "reset"); |
244 | 244 | ||
245 | /* cache this readonly data; minimize chip reads */ | 245 | /* cache this readonly data; minimize chip reads */ |
246 | ehci->hcs_params = readl(&ehci->caps->hcs_params); | 246 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); |
247 | 247 | ||
248 | retval = ehci_halt(ehci); | 248 | retval = ehci_halt(ehci); |
249 | if (retval) | 249 | if (retval) |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 025d33313681..185721dba42b 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -157,12 +157,13 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); | |||
157 | * before driver shutdown. But it also seems to be caused by bugs in cardbus | 157 | * before driver shutdown. But it also seems to be caused by bugs in cardbus |
158 | * bridge shutdown: shutting down the bridge before the devices using it. | 158 | * bridge shutdown: shutting down the bridge before the devices using it. |
159 | */ | 159 | */ |
160 | static int handshake (void __iomem *ptr, u32 mask, u32 done, int usec) | 160 | static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, |
161 | u32 mask, u32 done, int usec) | ||
161 | { | 162 | { |
162 | u32 result; | 163 | u32 result; |
163 | 164 | ||
164 | do { | 165 | do { |
165 | result = readl (ptr); | 166 | result = ehci_readl(ehci, ptr); |
166 | if (result == ~(u32)0) /* card removed */ | 167 | if (result == ~(u32)0) /* card removed */ |
167 | return -ENODEV; | 168 | return -ENODEV; |
168 | result &= mask; | 169 | result &= mask; |
@@ -177,18 +178,19 @@ static int handshake (void __iomem *ptr, u32 mask, u32 done, int usec) | |||
177 | /* force HC to halt state from unknown (EHCI spec section 2.3) */ | 178 | /* force HC to halt state from unknown (EHCI spec section 2.3) */ |
178 | static int ehci_halt (struct ehci_hcd *ehci) | 179 | static int ehci_halt (struct ehci_hcd *ehci) |
179 | { | 180 | { |
180 | u32 temp = readl (&ehci->regs->status); | 181 | u32 temp = ehci_readl(ehci, &ehci->regs->status); |
181 | 182 | ||
182 | /* disable any irqs left enabled by previous code */ | 183 | /* disable any irqs left enabled by previous code */ |
183 | writel (0, &ehci->regs->intr_enable); | 184 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
184 | 185 | ||
185 | if ((temp & STS_HALT) != 0) | 186 | if ((temp & STS_HALT) != 0) |
186 | return 0; | 187 | return 0; |
187 | 188 | ||
188 | temp = readl (&ehci->regs->command); | 189 | temp = ehci_readl(ehci, &ehci->regs->command); |
189 | temp &= ~CMD_RUN; | 190 | temp &= ~CMD_RUN; |
190 | writel (temp, &ehci->regs->command); | 191 | ehci_writel(ehci, temp, &ehci->regs->command); |
191 | return handshake (&ehci->regs->status, STS_HALT, STS_HALT, 16 * 125); | 192 | return handshake (ehci, &ehci->regs->status, |
193 | STS_HALT, STS_HALT, 16 * 125); | ||
192 | } | 194 | } |
193 | 195 | ||
194 | /* put TDI/ARC silicon into EHCI mode */ | 196 | /* put TDI/ARC silicon into EHCI mode */ |
@@ -198,23 +200,24 @@ static void tdi_reset (struct ehci_hcd *ehci) | |||
198 | u32 tmp; | 200 | u32 tmp; |
199 | 201 | ||
200 | reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x68); | 202 | reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x68); |
201 | tmp = readl (reg_ptr); | 203 | tmp = ehci_readl(ehci, reg_ptr); |
202 | tmp |= 0x3; | 204 | tmp |= 0x3; |
203 | writel (tmp, reg_ptr); | 205 | ehci_writel(ehci, tmp, reg_ptr); |
204 | } | 206 | } |
205 | 207 | ||
206 | /* reset a non-running (STS_HALT == 1) controller */ | 208 | /* reset a non-running (STS_HALT == 1) controller */ |
207 | static int ehci_reset (struct ehci_hcd *ehci) | 209 | static int ehci_reset (struct ehci_hcd *ehci) |
208 | { | 210 | { |
209 | int retval; | 211 | int retval; |
210 | u32 command = readl (&ehci->regs->command); | 212 | u32 command = ehci_readl(ehci, &ehci->regs->command); |
211 | 213 | ||
212 | command |= CMD_RESET; | 214 | command |= CMD_RESET; |
213 | dbg_cmd (ehci, "reset", command); | 215 | dbg_cmd (ehci, "reset", command); |
214 | writel (command, &ehci->regs->command); | 216 | ehci_writel(ehci, command, &ehci->regs->command); |
215 | ehci_to_hcd(ehci)->state = HC_STATE_HALT; | 217 | ehci_to_hcd(ehci)->state = HC_STATE_HALT; |
216 | ehci->next_statechange = jiffies; | 218 | ehci->next_statechange = jiffies; |
217 | retval = handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000); | 219 | retval = handshake (ehci, &ehci->regs->command, |
220 | CMD_RESET, 0, 250 * 1000); | ||
218 | 221 | ||
219 | if (retval) | 222 | if (retval) |
220 | return retval; | 223 | return retval; |
@@ -236,21 +239,21 @@ static void ehci_quiesce (struct ehci_hcd *ehci) | |||
236 | #endif | 239 | #endif |
237 | 240 | ||
238 | /* wait for any schedule enables/disables to take effect */ | 241 | /* wait for any schedule enables/disables to take effect */ |
239 | temp = readl (&ehci->regs->command) << 10; | 242 | temp = ehci_readl(ehci, &ehci->regs->command) << 10; |
240 | temp &= STS_ASS | STS_PSS; | 243 | temp &= STS_ASS | STS_PSS; |
241 | if (handshake (&ehci->regs->status, STS_ASS | STS_PSS, | 244 | if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS, |
242 | temp, 16 * 125) != 0) { | 245 | temp, 16 * 125) != 0) { |
243 | ehci_to_hcd(ehci)->state = HC_STATE_HALT; | 246 | ehci_to_hcd(ehci)->state = HC_STATE_HALT; |
244 | return; | 247 | return; |
245 | } | 248 | } |
246 | 249 | ||
247 | /* then disable anything that's still active */ | 250 | /* then disable anything that's still active */ |
248 | temp = readl (&ehci->regs->command); | 251 | temp = ehci_readl(ehci, &ehci->regs->command); |
249 | temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE); | 252 | temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE); |
250 | writel (temp, &ehci->regs->command); | 253 | ehci_writel(ehci, temp, &ehci->regs->command); |
251 | 254 | ||
252 | /* hardware can take 16 microframes to turn off ... */ | 255 | /* hardware can take 16 microframes to turn off ... */ |
253 | if (handshake (&ehci->regs->status, STS_ASS | STS_PSS, | 256 | if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS, |
254 | 0, 16 * 125) != 0) { | 257 | 0, 16 * 125) != 0) { |
255 | ehci_to_hcd(ehci)->state = HC_STATE_HALT; | 258 | ehci_to_hcd(ehci)->state = HC_STATE_HALT; |
256 | return; | 259 | return; |
@@ -277,11 +280,11 @@ static void ehci_watchdog (unsigned long param) | |||
277 | 280 | ||
278 | /* lost IAA irqs wedge things badly; seen with a vt8235 */ | 281 | /* lost IAA irqs wedge things badly; seen with a vt8235 */ |
279 | if (ehci->reclaim) { | 282 | if (ehci->reclaim) { |
280 | u32 status = readl (&ehci->regs->status); | 283 | u32 status = ehci_readl(ehci, &ehci->regs->status); |
281 | if (status & STS_IAA) { | 284 | if (status & STS_IAA) { |
282 | ehci_vdbg (ehci, "lost IAA\n"); | 285 | ehci_vdbg (ehci, "lost IAA\n"); |
283 | COUNT (ehci->stats.lost_iaa); | 286 | COUNT (ehci->stats.lost_iaa); |
284 | writel (STS_IAA, &ehci->regs->status); | 287 | ehci_writel(ehci, STS_IAA, &ehci->regs->status); |
285 | ehci->reclaim_ready = 1; | 288 | ehci->reclaim_ready = 1; |
286 | } | 289 | } |
287 | } | 290 | } |
@@ -309,7 +312,7 @@ ehci_shutdown (struct usb_hcd *hcd) | |||
309 | (void) ehci_halt (ehci); | 312 | (void) ehci_halt (ehci); |
310 | 313 | ||
311 | /* make BIOS/etc use companion controller during reboot */ | 314 | /* make BIOS/etc use companion controller during reboot */ |
312 | writel (0, &ehci->regs->configured_flag); | 315 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); |
313 | } | 316 | } |
314 | 317 | ||
315 | static void ehci_port_power (struct ehci_hcd *ehci, int is_on) | 318 | static void ehci_port_power (struct ehci_hcd *ehci, int is_on) |
@@ -379,12 +382,13 @@ static void ehci_stop (struct usb_hcd *hcd) | |||
379 | ehci_quiesce (ehci); | 382 | ehci_quiesce (ehci); |
380 | 383 | ||
381 | ehci_reset (ehci); | 384 | ehci_reset (ehci); |
382 | writel (0, &ehci->regs->intr_enable); | 385 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
383 | spin_unlock_irq(&ehci->lock); | 386 | spin_unlock_irq(&ehci->lock); |
384 | 387 | ||
385 | /* let companion controllers work when we aren't */ | 388 | /* let companion controllers work when we aren't */ |
386 | writel (0, &ehci->regs->configured_flag); | 389 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); |
387 | 390 | ||
391 | remove_companion_file(ehci); | ||
388 | remove_debug_files (ehci); | 392 | remove_debug_files (ehci); |
389 | 393 | ||
390 | /* root hub is shut down separately (first, when possible) */ | 394 | /* root hub is shut down separately (first, when possible) */ |
@@ -402,7 +406,8 @@ static void ehci_stop (struct usb_hcd *hcd) | |||
402 | ehci->stats.complete, ehci->stats.unlink); | 406 | ehci->stats.complete, ehci->stats.unlink); |
403 | #endif | 407 | #endif |
404 | 408 | ||
405 | dbg_status (ehci, "ehci_stop completed", readl (&ehci->regs->status)); | 409 | dbg_status (ehci, "ehci_stop completed", |
410 | ehci_readl(ehci, &ehci->regs->status)); | ||
406 | } | 411 | } |
407 | 412 | ||
408 | /* one-time init, only for memory state */ | 413 | /* one-time init, only for memory state */ |
@@ -428,7 +433,7 @@ static int ehci_init(struct usb_hcd *hcd) | |||
428 | return retval; | 433 | return retval; |
429 | 434 | ||
430 | /* controllers may cache some of the periodic schedule ... */ | 435 | /* controllers may cache some of the periodic schedule ... */ |
431 | hcc_params = readl(&ehci->caps->hcc_params); | 436 | hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); |
432 | if (HCC_ISOC_CACHE(hcc_params)) // full frame cache | 437 | if (HCC_ISOC_CACHE(hcc_params)) // full frame cache |
433 | ehci->i_thresh = 8; | 438 | ehci->i_thresh = 8; |
434 | else // N microframes cached | 439 | else // N microframes cached |
@@ -496,13 +501,16 @@ static int ehci_run (struct usb_hcd *hcd) | |||
496 | u32 temp; | 501 | u32 temp; |
497 | u32 hcc_params; | 502 | u32 hcc_params; |
498 | 503 | ||
504 | hcd->uses_new_polling = 1; | ||
505 | hcd->poll_rh = 0; | ||
506 | |||
499 | /* EHCI spec section 4.1 */ | 507 | /* EHCI spec section 4.1 */ |
500 | if ((retval = ehci_reset(ehci)) != 0) { | 508 | if ((retval = ehci_reset(ehci)) != 0) { |
501 | ehci_mem_cleanup(ehci); | 509 | ehci_mem_cleanup(ehci); |
502 | return retval; | 510 | return retval; |
503 | } | 511 | } |
504 | writel(ehci->periodic_dma, &ehci->regs->frame_list); | 512 | ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); |
505 | writel((u32)ehci->async->qh_dma, &ehci->regs->async_next); | 513 | ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next); |
506 | 514 | ||
507 | /* | 515 | /* |
508 | * hcc_params controls whether ehci->regs->segment must (!!!) | 516 | * hcc_params controls whether ehci->regs->segment must (!!!) |
@@ -516,9 +524,9 @@ static int ehci_run (struct usb_hcd *hcd) | |||
516 | * Scsi_Host.highmem_io, and so forth. It's readonly to all | 524 | * Scsi_Host.highmem_io, and so forth. It's readonly to all |
517 | * host side drivers though. | 525 | * host side drivers though. |
518 | */ | 526 | */ |
519 | hcc_params = readl(&ehci->caps->hcc_params); | 527 | hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); |
520 | if (HCC_64BIT_ADDR(hcc_params)) { | 528 | if (HCC_64BIT_ADDR(hcc_params)) { |
521 | writel(0, &ehci->regs->segment); | 529 | ehci_writel(ehci, 0, &ehci->regs->segment); |
522 | #if 0 | 530 | #if 0 |
523 | // this is deeply broken on almost all architectures | 531 | // this is deeply broken on almost all architectures |
524 | if (!dma_set_mask(hcd->self.controller, DMA_64BIT_MASK)) | 532 | if (!dma_set_mask(hcd->self.controller, DMA_64BIT_MASK)) |
@@ -531,7 +539,7 @@ static int ehci_run (struct usb_hcd *hcd) | |||
531 | // root hub will detect new devices (why?); NEC doesn't | 539 | // root hub will detect new devices (why?); NEC doesn't |
532 | ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); | 540 | ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); |
533 | ehci->command |= CMD_RUN; | 541 | ehci->command |= CMD_RUN; |
534 | writel (ehci->command, &ehci->regs->command); | 542 | ehci_writel(ehci, ehci->command, &ehci->regs->command); |
535 | dbg_cmd (ehci, "init", ehci->command); | 543 | dbg_cmd (ehci, "init", ehci->command); |
536 | 544 | ||
537 | /* | 545 | /* |
@@ -541,23 +549,25 @@ static int ehci_run (struct usb_hcd *hcd) | |||
541 | * and there's no companion controller unless maybe for USB OTG.) | 549 | * and there's no companion controller unless maybe for USB OTG.) |
542 | */ | 550 | */ |
543 | hcd->state = HC_STATE_RUNNING; | 551 | hcd->state = HC_STATE_RUNNING; |
544 | writel (FLAG_CF, &ehci->regs->configured_flag); | 552 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); |
545 | readl (&ehci->regs->command); /* unblock posted writes */ | 553 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ |
546 | 554 | ||
547 | temp = HC_VERSION(readl (&ehci->caps->hc_capbase)); | 555 | temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); |
548 | ehci_info (ehci, | 556 | ehci_info (ehci, |
549 | "USB %x.%x started, EHCI %x.%02x, driver %s%s\n", | 557 | "USB %x.%x started, EHCI %x.%02x, driver %s%s\n", |
550 | ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), | 558 | ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), |
551 | temp >> 8, temp & 0xff, DRIVER_VERSION, | 559 | temp >> 8, temp & 0xff, DRIVER_VERSION, |
552 | ignore_oc ? ", overcurrent ignored" : ""); | 560 | ignore_oc ? ", overcurrent ignored" : ""); |
553 | 561 | ||
554 | writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ | 562 | ehci_writel(ehci, INTR_MASK, |
563 | &ehci->regs->intr_enable); /* Turn On Interrupts */ | ||
555 | 564 | ||
556 | /* GRR this is run-once init(), being done every time the HC starts. | 565 | /* GRR this is run-once init(), being done every time the HC starts. |
557 | * So long as they're part of class devices, we can't do it init() | 566 | * So long as they're part of class devices, we can't do it init() |
558 | * since the class device isn't created that early. | 567 | * since the class device isn't created that early. |
559 | */ | 568 | */ |
560 | create_debug_files(ehci); | 569 | create_debug_files(ehci); |
570 | create_companion_file(ehci); | ||
561 | 571 | ||
562 | return 0; | 572 | return 0; |
563 | } | 573 | } |
@@ -567,12 +577,12 @@ static int ehci_run (struct usb_hcd *hcd) | |||
567 | static irqreturn_t ehci_irq (struct usb_hcd *hcd) | 577 | static irqreturn_t ehci_irq (struct usb_hcd *hcd) |
568 | { | 578 | { |
569 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 579 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
570 | u32 status; | 580 | u32 status, pcd_status = 0; |
571 | int bh; | 581 | int bh; |
572 | 582 | ||
573 | spin_lock (&ehci->lock); | 583 | spin_lock (&ehci->lock); |
574 | 584 | ||
575 | status = readl (&ehci->regs->status); | 585 | status = ehci_readl(ehci, &ehci->regs->status); |
576 | 586 | ||
577 | /* e.g. cardbus physical eject */ | 587 | /* e.g. cardbus physical eject */ |
578 | if (status == ~(u32) 0) { | 588 | if (status == ~(u32) 0) { |
@@ -587,8 +597,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
587 | } | 597 | } |
588 | 598 | ||
589 | /* clear (just) interrupts */ | 599 | /* clear (just) interrupts */ |
590 | writel (status, &ehci->regs->status); | 600 | ehci_writel(ehci, status, &ehci->regs->status); |
591 | readl (&ehci->regs->command); /* unblock posted write */ | 601 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted write */ |
592 | bh = 0; | 602 | bh = 0; |
593 | 603 | ||
594 | #ifdef EHCI_VERBOSE_DEBUG | 604 | #ifdef EHCI_VERBOSE_DEBUG |
@@ -617,13 +627,15 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
617 | /* remote wakeup [4.3.1] */ | 627 | /* remote wakeup [4.3.1] */ |
618 | if (status & STS_PCD) { | 628 | if (status & STS_PCD) { |
619 | unsigned i = HCS_N_PORTS (ehci->hcs_params); | 629 | unsigned i = HCS_N_PORTS (ehci->hcs_params); |
630 | pcd_status = status; | ||
620 | 631 | ||
621 | /* resume root hub? */ | 632 | /* resume root hub? */ |
622 | if (!(readl(&ehci->regs->command) & CMD_RUN)) | 633 | if (!(ehci_readl(ehci, &ehci->regs->command) & CMD_RUN)) |
623 | usb_hcd_resume_root_hub(hcd); | 634 | usb_hcd_resume_root_hub(hcd); |
624 | 635 | ||
625 | while (i--) { | 636 | while (i--) { |
626 | int pstatus = readl (&ehci->regs->port_status [i]); | 637 | int pstatus = ehci_readl(ehci, |
638 | &ehci->regs->port_status [i]); | ||
627 | 639 | ||
628 | if (pstatus & PORT_OWNER) | 640 | if (pstatus & PORT_OWNER) |
629 | continue; | 641 | continue; |
@@ -643,14 +655,15 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
643 | /* PCI errors [4.15.2.4] */ | 655 | /* PCI errors [4.15.2.4] */ |
644 | if (unlikely ((status & STS_FATAL) != 0)) { | 656 | if (unlikely ((status & STS_FATAL) != 0)) { |
645 | /* bogus "fatal" IRQs appear on some chips... why? */ | 657 | /* bogus "fatal" IRQs appear on some chips... why? */ |
646 | status = readl (&ehci->regs->status); | 658 | status = ehci_readl(ehci, &ehci->regs->status); |
647 | dbg_cmd (ehci, "fatal", readl (&ehci->regs->command)); | 659 | dbg_cmd (ehci, "fatal", ehci_readl(ehci, |
660 | &ehci->regs->command)); | ||
648 | dbg_status (ehci, "fatal", status); | 661 | dbg_status (ehci, "fatal", status); |
649 | if (status & STS_HALT) { | 662 | if (status & STS_HALT) { |
650 | ehci_err (ehci, "fatal error\n"); | 663 | ehci_err (ehci, "fatal error\n"); |
651 | dead: | 664 | dead: |
652 | ehci_reset (ehci); | 665 | ehci_reset (ehci); |
653 | writel (0, &ehci->regs->configured_flag); | 666 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); |
654 | /* generic layer kills/unlinks all urbs, then | 667 | /* generic layer kills/unlinks all urbs, then |
655 | * uses ehci_stop to clean up the rest | 668 | * uses ehci_stop to clean up the rest |
656 | */ | 669 | */ |
@@ -661,6 +674,8 @@ dead: | |||
661 | if (bh) | 674 | if (bh) |
662 | ehci_work (ehci); | 675 | ehci_work (ehci); |
663 | spin_unlock (&ehci->lock); | 676 | spin_unlock (&ehci->lock); |
677 | if (pcd_status & STS_PCD) | ||
678 | usb_hcd_poll_rh_status(hcd); | ||
664 | return IRQ_HANDLED; | 679 | return IRQ_HANDLED; |
665 | } | 680 | } |
666 | 681 | ||
@@ -873,7 +888,8 @@ done: | |||
873 | static int ehci_get_frame (struct usb_hcd *hcd) | 888 | static int ehci_get_frame (struct usb_hcd *hcd) |
874 | { | 889 | { |
875 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 890 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
876 | return (readl (&ehci->regs->frame_index) >> 3) % ehci->periodic_size; | 891 | return (ehci_readl(ehci, &ehci->regs->frame_index) >> 3) % |
892 | ehci->periodic_size; | ||
877 | } | 893 | } |
878 | 894 | ||
879 | /*-------------------------------------------------------------------------*/ | 895 | /*-------------------------------------------------------------------------*/ |
@@ -899,7 +915,13 @@ MODULE_LICENSE ("GPL"); | |||
899 | #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver | 915 | #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver |
900 | #endif | 916 | #endif |
901 | 917 | ||
902 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) | 918 | #ifdef CONFIG_PPC_PS3 |
919 | #include "ehci-ps3.c" | ||
920 | #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_sb_driver | ||
921 | #endif | ||
922 | |||
923 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ | ||
924 | !defined(PS3_SYSTEM_BUS_DRIVER) | ||
903 | #error "missing bus glue for ehci-hcd" | 925 | #error "missing bus glue for ehci-hcd" |
904 | #endif | 926 | #endif |
905 | 927 | ||
@@ -924,6 +946,20 @@ static int __init ehci_hcd_init(void) | |||
924 | #ifdef PLATFORM_DRIVER | 946 | #ifdef PLATFORM_DRIVER |
925 | platform_driver_unregister(&PLATFORM_DRIVER); | 947 | platform_driver_unregister(&PLATFORM_DRIVER); |
926 | #endif | 948 | #endif |
949 | return retval; | ||
950 | } | ||
951 | #endif | ||
952 | |||
953 | #ifdef PS3_SYSTEM_BUS_DRIVER | ||
954 | retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER); | ||
955 | if (retval < 0) { | ||
956 | #ifdef PLATFORM_DRIVER | ||
957 | platform_driver_unregister(&PLATFORM_DRIVER); | ||
958 | #endif | ||
959 | #ifdef PCI_DRIVER | ||
960 | pci_unregister_driver(&PCI_DRIVER); | ||
961 | #endif | ||
962 | return retval; | ||
927 | } | 963 | } |
928 | #endif | 964 | #endif |
929 | 965 | ||
@@ -939,6 +975,9 @@ static void __exit ehci_hcd_cleanup(void) | |||
939 | #ifdef PCI_DRIVER | 975 | #ifdef PCI_DRIVER |
940 | pci_unregister_driver(&PCI_DRIVER); | 976 | pci_unregister_driver(&PCI_DRIVER); |
941 | #endif | 977 | #endif |
978 | #ifdef PS3_SYSTEM_BUS_DRIVER | ||
979 | ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | ||
980 | #endif | ||
942 | } | 981 | } |
943 | module_exit(ehci_hcd_cleanup); | 982 | module_exit(ehci_hcd_cleanup); |
944 | 983 | ||
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index bfe5f307cba6..0d83c6df1a3b 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -47,7 +47,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
47 | ehci_quiesce (ehci); | 47 | ehci_quiesce (ehci); |
48 | hcd->state = HC_STATE_QUIESCING; | 48 | hcd->state = HC_STATE_QUIESCING; |
49 | } | 49 | } |
50 | ehci->command = readl (&ehci->regs->command); | 50 | ehci->command = ehci_readl(ehci, &ehci->regs->command); |
51 | if (ehci->reclaim) | 51 | if (ehci->reclaim) |
52 | ehci->reclaim_ready = 1; | 52 | ehci->reclaim_ready = 1; |
53 | ehci_work(ehci); | 53 | ehci_work(ehci); |
@@ -60,7 +60,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
60 | ehci->bus_suspended = 0; | 60 | ehci->bus_suspended = 0; |
61 | while (port--) { | 61 | while (port--) { |
62 | u32 __iomem *reg = &ehci->regs->port_status [port]; | 62 | u32 __iomem *reg = &ehci->regs->port_status [port]; |
63 | u32 t1 = readl (reg) & ~PORT_RWC_BITS; | 63 | u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; |
64 | u32 t2 = t1; | 64 | u32 t2 = t1; |
65 | 65 | ||
66 | /* keep track of which ports we suspend */ | 66 | /* keep track of which ports we suspend */ |
@@ -79,7 +79,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
79 | if (t1 != t2) { | 79 | if (t1 != t2) { |
80 | ehci_vdbg (ehci, "port %d, %08x -> %08x\n", | 80 | ehci_vdbg (ehci, "port %d, %08x -> %08x\n", |
81 | port + 1, t1, t2); | 81 | port + 1, t1, t2); |
82 | writel (t2, reg); | 82 | ehci_writel(ehci, t2, reg); |
83 | } | 83 | } |
84 | } | 84 | } |
85 | 85 | ||
@@ -92,8 +92,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
92 | mask = INTR_MASK; | 92 | mask = INTR_MASK; |
93 | if (!device_may_wakeup(&hcd->self.root_hub->dev)) | 93 | if (!device_may_wakeup(&hcd->self.root_hub->dev)) |
94 | mask &= ~STS_PCD; | 94 | mask &= ~STS_PCD; |
95 | writel(mask, &ehci->regs->intr_enable); | 95 | ehci_writel(ehci, mask, &ehci->regs->intr_enable); |
96 | readl(&ehci->regs->intr_enable); | 96 | ehci_readl(ehci, &ehci->regs->intr_enable); |
97 | 97 | ||
98 | ehci->next_statechange = jiffies + msecs_to_jiffies(10); | 98 | ehci->next_statechange = jiffies + msecs_to_jiffies(10); |
99 | spin_unlock_irq (&ehci->lock); | 99 | spin_unlock_irq (&ehci->lock); |
@@ -118,26 +118,26 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
118 | * the last user of the controller, not reset/pm hardware keeping | 118 | * the last user of the controller, not reset/pm hardware keeping |
119 | * state we gave to it. | 119 | * state we gave to it. |
120 | */ | 120 | */ |
121 | temp = readl(&ehci->regs->intr_enable); | 121 | temp = ehci_readl(ehci, &ehci->regs->intr_enable); |
122 | ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss"); | 122 | ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss"); |
123 | 123 | ||
124 | /* at least some APM implementations will try to deliver | 124 | /* at least some APM implementations will try to deliver |
125 | * IRQs right away, so delay them until we're ready. | 125 | * IRQs right away, so delay them until we're ready. |
126 | */ | 126 | */ |
127 | writel(0, &ehci->regs->intr_enable); | 127 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
128 | 128 | ||
129 | /* re-init operational registers */ | 129 | /* re-init operational registers */ |
130 | writel(0, &ehci->regs->segment); | 130 | ehci_writel(ehci, 0, &ehci->regs->segment); |
131 | writel(ehci->periodic_dma, &ehci->regs->frame_list); | 131 | ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); |
132 | writel((u32) ehci->async->qh_dma, &ehci->regs->async_next); | 132 | ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next); |
133 | 133 | ||
134 | /* restore CMD_RUN, framelist size, and irq threshold */ | 134 | /* restore CMD_RUN, framelist size, and irq threshold */ |
135 | writel (ehci->command, &ehci->regs->command); | 135 | ehci_writel(ehci, ehci->command, &ehci->regs->command); |
136 | 136 | ||
137 | /* manually resume the ports we suspended during bus_suspend() */ | 137 | /* manually resume the ports we suspended during bus_suspend() */ |
138 | i = HCS_N_PORTS (ehci->hcs_params); | 138 | i = HCS_N_PORTS (ehci->hcs_params); |
139 | while (i--) { | 139 | while (i--) { |
140 | temp = readl (&ehci->regs->port_status [i]); | 140 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); |
141 | temp &= ~(PORT_RWC_BITS | 141 | temp &= ~(PORT_RWC_BITS |
142 | | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E); | 142 | | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E); |
143 | if (test_bit(i, &ehci->bus_suspended) && | 143 | if (test_bit(i, &ehci->bus_suspended) && |
@@ -145,20 +145,20 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
145 | ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); | 145 | ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); |
146 | temp |= PORT_RESUME; | 146 | temp |= PORT_RESUME; |
147 | } | 147 | } |
148 | writel (temp, &ehci->regs->port_status [i]); | 148 | ehci_writel(ehci, temp, &ehci->regs->port_status [i]); |
149 | } | 149 | } |
150 | i = HCS_N_PORTS (ehci->hcs_params); | 150 | i = HCS_N_PORTS (ehci->hcs_params); |
151 | mdelay (20); | 151 | mdelay (20); |
152 | while (i--) { | 152 | while (i--) { |
153 | temp = readl (&ehci->regs->port_status [i]); | 153 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); |
154 | if (test_bit(i, &ehci->bus_suspended) && | 154 | if (test_bit(i, &ehci->bus_suspended) && |
155 | (temp & PORT_SUSPEND)) { | 155 | (temp & PORT_SUSPEND)) { |
156 | temp &= ~(PORT_RWC_BITS | PORT_RESUME); | 156 | temp &= ~(PORT_RWC_BITS | PORT_RESUME); |
157 | writel (temp, &ehci->regs->port_status [i]); | 157 | ehci_writel(ehci, temp, &ehci->regs->port_status [i]); |
158 | ehci_vdbg (ehci, "resumed port %d\n", i + 1); | 158 | ehci_vdbg (ehci, "resumed port %d\n", i + 1); |
159 | } | 159 | } |
160 | } | 160 | } |
161 | (void) readl (&ehci->regs->command); | 161 | (void) ehci_readl(ehci, &ehci->regs->command); |
162 | 162 | ||
163 | /* maybe re-activate the schedule(s) */ | 163 | /* maybe re-activate the schedule(s) */ |
164 | temp = 0; | 164 | temp = 0; |
@@ -168,14 +168,14 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
168 | temp |= CMD_PSE; | 168 | temp |= CMD_PSE; |
169 | if (temp) { | 169 | if (temp) { |
170 | ehci->command |= temp; | 170 | ehci->command |= temp; |
171 | writel (ehci->command, &ehci->regs->command); | 171 | ehci_writel(ehci, ehci->command, &ehci->regs->command); |
172 | } | 172 | } |
173 | 173 | ||
174 | ehci->next_statechange = jiffies + msecs_to_jiffies(5); | 174 | ehci->next_statechange = jiffies + msecs_to_jiffies(5); |
175 | hcd->state = HC_STATE_RUNNING; | 175 | hcd->state = HC_STATE_RUNNING; |
176 | 176 | ||
177 | /* Now we can safely re-enable irqs */ | 177 | /* Now we can safely re-enable irqs */ |
178 | writel(INTR_MASK, &ehci->regs->intr_enable); | 178 | ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); |
179 | 179 | ||
180 | spin_unlock_irq (&ehci->lock); | 180 | spin_unlock_irq (&ehci->lock); |
181 | return 0; | 181 | return 0; |
@@ -190,9 +190,107 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
190 | 190 | ||
191 | /*-------------------------------------------------------------------------*/ | 191 | /*-------------------------------------------------------------------------*/ |
192 | 192 | ||
193 | /* Display the ports dedicated to the companion controller */ | ||
194 | static ssize_t show_companion(struct class_device *class_dev, char *buf) | ||
195 | { | ||
196 | struct ehci_hcd *ehci; | ||
197 | int nports, index, n; | ||
198 | int count = PAGE_SIZE; | ||
199 | char *ptr = buf; | ||
200 | |||
201 | ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev))); | ||
202 | nports = HCS_N_PORTS(ehci->hcs_params); | ||
203 | |||
204 | for (index = 0; index < nports; ++index) { | ||
205 | if (test_bit(index, &ehci->companion_ports)) { | ||
206 | n = scnprintf(ptr, count, "%d\n", index + 1); | ||
207 | ptr += n; | ||
208 | count -= n; | ||
209 | } | ||
210 | } | ||
211 | return ptr - buf; | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * Dedicate or undedicate a port to the companion controller. | ||
216 | * Syntax is "[-]portnum", where a leading '-' sign means | ||
217 | * return control of the port to the EHCI controller. | ||
218 | */ | ||
219 | static ssize_t store_companion(struct class_device *class_dev, | ||
220 | const char *buf, size_t count) | ||
221 | { | ||
222 | struct ehci_hcd *ehci; | ||
223 | int portnum, new_owner, try; | ||
224 | u32 __iomem *status_reg; | ||
225 | u32 port_status; | ||
226 | |||
227 | ehci = hcd_to_ehci(bus_to_hcd(class_get_devdata(class_dev))); | ||
228 | new_owner = PORT_OWNER; /* Owned by companion */ | ||
229 | if (sscanf(buf, "%d", &portnum) != 1) | ||
230 | return -EINVAL; | ||
231 | if (portnum < 0) { | ||
232 | portnum = - portnum; | ||
233 | new_owner = 0; /* Owned by EHCI */ | ||
234 | } | ||
235 | if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params)) | ||
236 | return -ENOENT; | ||
237 | status_reg = &ehci->regs->port_status[--portnum]; | ||
238 | if (new_owner) | ||
239 | set_bit(portnum, &ehci->companion_ports); | ||
240 | else | ||
241 | clear_bit(portnum, &ehci->companion_ports); | ||
242 | |||
243 | /* | ||
244 | * The controller won't set the OWNER bit if the port is | ||
245 | * enabled, so this loop will sometimes require at least two | ||
246 | * iterations: one to disable the port and one to set OWNER. | ||
247 | */ | ||
248 | |||
249 | for (try = 4; try > 0; --try) { | ||
250 | spin_lock_irq(&ehci->lock); | ||
251 | port_status = ehci_readl(ehci, status_reg); | ||
252 | if ((port_status & PORT_OWNER) == new_owner | ||
253 | || (port_status & (PORT_OWNER | PORT_CONNECT)) | ||
254 | == 0) | ||
255 | try = 0; | ||
256 | else { | ||
257 | port_status ^= PORT_OWNER; | ||
258 | port_status &= ~(PORT_PE | PORT_RWC_BITS); | ||
259 | ehci_writel(ehci, port_status, status_reg); | ||
260 | } | ||
261 | spin_unlock_irq(&ehci->lock); | ||
262 | if (try > 1) | ||
263 | msleep(5); | ||
264 | } | ||
265 | return count; | ||
266 | } | ||
267 | static CLASS_DEVICE_ATTR(companion, 0644, show_companion, store_companion); | ||
268 | |||
269 | static inline void create_companion_file(struct ehci_hcd *ehci) | ||
270 | { | ||
271 | int i; | ||
272 | |||
273 | /* with integrated TT there is no companion! */ | ||
274 | if (!ehci_is_TDI(ehci)) | ||
275 | i = class_device_create_file(ehci_to_hcd(ehci)->self.class_dev, | ||
276 | &class_device_attr_companion); | ||
277 | } | ||
278 | |||
279 | static inline void remove_companion_file(struct ehci_hcd *ehci) | ||
280 | { | ||
281 | /* with integrated TT there is no companion! */ | ||
282 | if (!ehci_is_TDI(ehci)) | ||
283 | class_device_remove_file(ehci_to_hcd(ehci)->self.class_dev, | ||
284 | &class_device_attr_companion); | ||
285 | } | ||
286 | |||
287 | |||
288 | /*-------------------------------------------------------------------------*/ | ||
289 | |||
193 | static int check_reset_complete ( | 290 | static int check_reset_complete ( |
194 | struct ehci_hcd *ehci, | 291 | struct ehci_hcd *ehci, |
195 | int index, | 292 | int index, |
293 | u32 __iomem *status_reg, | ||
196 | int port_status | 294 | int port_status |
197 | ) { | 295 | ) { |
198 | if (!(port_status & PORT_CONNECT)) { | 296 | if (!(port_status & PORT_CONNECT)) { |
@@ -217,7 +315,7 @@ static int check_reset_complete ( | |||
217 | // what happens if HCS_N_CC(params) == 0 ? | 315 | // what happens if HCS_N_CC(params) == 0 ? |
218 | port_status |= PORT_OWNER; | 316 | port_status |= PORT_OWNER; |
219 | port_status &= ~PORT_RWC_BITS; | 317 | port_status &= ~PORT_RWC_BITS; |
220 | writel (port_status, &ehci->regs->port_status [index]); | 318 | ehci_writel(ehci, port_status, status_reg); |
221 | 319 | ||
222 | } else | 320 | } else |
223 | ehci_dbg (ehci, "port %d high speed\n", index + 1); | 321 | ehci_dbg (ehci, "port %d high speed\n", index + 1); |
@@ -268,22 +366,21 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
268 | /* port N changes (bit N)? */ | 366 | /* port N changes (bit N)? */ |
269 | spin_lock_irqsave (&ehci->lock, flags); | 367 | spin_lock_irqsave (&ehci->lock, flags); |
270 | for (i = 0; i < ports; i++) { | 368 | for (i = 0; i < ports; i++) { |
271 | temp = readl (&ehci->regs->port_status [i]); | 369 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); |
272 | if (temp & PORT_OWNER) { | 370 | |
273 | /* don't report this in GetPortStatus */ | 371 | /* |
274 | if (temp & PORT_CSC) { | 372 | * Return status information even for ports with OWNER set. |
275 | temp &= ~PORT_RWC_BITS; | 373 | * Otherwise khubd wouldn't see the disconnect event when a |
276 | temp |= PORT_CSC; | 374 | * high-speed device is switched over to the companion |
277 | writel (temp, &ehci->regs->port_status [i]); | 375 | * controller by the user. |
278 | } | 376 | */ |
279 | continue; | 377 | |
280 | } | ||
281 | if (!(temp & PORT_CONNECT)) | 378 | if (!(temp & PORT_CONNECT)) |
282 | ehci->reset_done [i] = 0; | 379 | ehci->reset_done [i] = 0; |
283 | if ((temp & mask) != 0 | 380 | if ((temp & mask) != 0 |
284 | || ((temp & PORT_RESUME) != 0 | 381 | || ((temp & PORT_RESUME) != 0 |
285 | && time_after (jiffies, | 382 | && time_after_eq(jiffies, |
286 | ehci->reset_done [i]))) { | 383 | ehci->reset_done[i]))) { |
287 | if (i < 7) | 384 | if (i < 7) |
288 | buf [0] |= 1 << (i + 1); | 385 | buf [0] |= 1 << (i + 1); |
289 | else | 386 | else |
@@ -345,6 +442,7 @@ static int ehci_hub_control ( | |||
345 | ) { | 442 | ) { |
346 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 443 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
347 | int ports = HCS_N_PORTS (ehci->hcs_params); | 444 | int ports = HCS_N_PORTS (ehci->hcs_params); |
445 | u32 __iomem *status_reg = &ehci->regs->port_status[wIndex - 1]; | ||
348 | u32 temp, status; | 446 | u32 temp, status; |
349 | unsigned long flags; | 447 | unsigned long flags; |
350 | int retval = 0; | 448 | int retval = 0; |
@@ -373,18 +471,22 @@ static int ehci_hub_control ( | |||
373 | if (!wIndex || wIndex > ports) | 471 | if (!wIndex || wIndex > ports) |
374 | goto error; | 472 | goto error; |
375 | wIndex--; | 473 | wIndex--; |
376 | temp = readl (&ehci->regs->port_status [wIndex]); | 474 | temp = ehci_readl(ehci, status_reg); |
377 | if (temp & PORT_OWNER) | 475 | |
378 | break; | 476 | /* |
477 | * Even if OWNER is set, so the port is owned by the | ||
478 | * companion controller, khubd needs to be able to clear | ||
479 | * the port-change status bits (especially | ||
480 | * USB_PORT_FEAT_C_CONNECTION). | ||
481 | */ | ||
379 | 482 | ||
380 | switch (wValue) { | 483 | switch (wValue) { |
381 | case USB_PORT_FEAT_ENABLE: | 484 | case USB_PORT_FEAT_ENABLE: |
382 | writel (temp & ~PORT_PE, | 485 | ehci_writel(ehci, temp & ~PORT_PE, status_reg); |
383 | &ehci->regs->port_status [wIndex]); | ||
384 | break; | 486 | break; |
385 | case USB_PORT_FEAT_C_ENABLE: | 487 | case USB_PORT_FEAT_C_ENABLE: |
386 | writel((temp & ~PORT_RWC_BITS) | PORT_PEC, | 488 | ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_PEC, |
387 | &ehci->regs->port_status [wIndex]); | 489 | status_reg); |
388 | break; | 490 | break; |
389 | case USB_PORT_FEAT_SUSPEND: | 491 | case USB_PORT_FEAT_SUSPEND: |
390 | if (temp & PORT_RESET) | 492 | if (temp & PORT_RESET) |
@@ -396,8 +498,8 @@ static int ehci_hub_control ( | |||
396 | goto error; | 498 | goto error; |
397 | /* resume signaling for 20 msec */ | 499 | /* resume signaling for 20 msec */ |
398 | temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); | 500 | temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); |
399 | writel (temp | PORT_RESUME, | 501 | ehci_writel(ehci, temp | PORT_RESUME, |
400 | &ehci->regs->port_status [wIndex]); | 502 | status_reg); |
401 | ehci->reset_done [wIndex] = jiffies | 503 | ehci->reset_done [wIndex] = jiffies |
402 | + msecs_to_jiffies (20); | 504 | + msecs_to_jiffies (20); |
403 | } | 505 | } |
@@ -407,16 +509,17 @@ static int ehci_hub_control ( | |||
407 | break; | 509 | break; |
408 | case USB_PORT_FEAT_POWER: | 510 | case USB_PORT_FEAT_POWER: |
409 | if (HCS_PPC (ehci->hcs_params)) | 511 | if (HCS_PPC (ehci->hcs_params)) |
410 | writel (temp & ~(PORT_RWC_BITS | PORT_POWER), | 512 | ehci_writel(ehci, |
411 | &ehci->regs->port_status [wIndex]); | 513 | temp & ~(PORT_RWC_BITS | PORT_POWER), |
514 | status_reg); | ||
412 | break; | 515 | break; |
413 | case USB_PORT_FEAT_C_CONNECTION: | 516 | case USB_PORT_FEAT_C_CONNECTION: |
414 | writel((temp & ~PORT_RWC_BITS) | PORT_CSC, | 517 | ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC, |
415 | &ehci->regs->port_status [wIndex]); | 518 | status_reg); |
416 | break; | 519 | break; |
417 | case USB_PORT_FEAT_C_OVER_CURRENT: | 520 | case USB_PORT_FEAT_C_OVER_CURRENT: |
418 | writel((temp & ~PORT_RWC_BITS) | PORT_OCC, | 521 | ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_OCC, |
419 | &ehci->regs->port_status [wIndex]); | 522 | status_reg); |
420 | break; | 523 | break; |
421 | case USB_PORT_FEAT_C_RESET: | 524 | case USB_PORT_FEAT_C_RESET: |
422 | /* GetPortStatus clears reset */ | 525 | /* GetPortStatus clears reset */ |
@@ -424,7 +527,7 @@ static int ehci_hub_control ( | |||
424 | default: | 527 | default: |
425 | goto error; | 528 | goto error; |
426 | } | 529 | } |
427 | readl (&ehci->regs->command); /* unblock posted write */ | 530 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted write */ |
428 | break; | 531 | break; |
429 | case GetHubDescriptor: | 532 | case GetHubDescriptor: |
430 | ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *) | 533 | ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *) |
@@ -440,7 +543,7 @@ static int ehci_hub_control ( | |||
440 | goto error; | 543 | goto error; |
441 | wIndex--; | 544 | wIndex--; |
442 | status = 0; | 545 | status = 0; |
443 | temp = readl (&ehci->regs->port_status [wIndex]); | 546 | temp = ehci_readl(ehci, status_reg); |
444 | 547 | ||
445 | // wPortChange bits | 548 | // wPortChange bits |
446 | if (temp & PORT_CSC) | 549 | if (temp & PORT_CSC) |
@@ -451,42 +554,55 @@ static int ehci_hub_control ( | |||
451 | status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; | 554 | status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; |
452 | 555 | ||
453 | /* whoever resumes must GetPortStatus to complete it!! */ | 556 | /* whoever resumes must GetPortStatus to complete it!! */ |
454 | if ((temp & PORT_RESUME) | 557 | if (temp & PORT_RESUME) { |
455 | && time_after (jiffies, | ||
456 | ehci->reset_done [wIndex])) { | ||
457 | status |= 1 << USB_PORT_FEAT_C_SUSPEND; | ||
458 | ehci->reset_done [wIndex] = 0; | ||
459 | 558 | ||
460 | /* stop resume signaling */ | 559 | /* Remote Wakeup received? */ |
461 | temp = readl (&ehci->regs->port_status [wIndex]); | 560 | if (!ehci->reset_done[wIndex]) { |
462 | writel (temp & ~(PORT_RWC_BITS | PORT_RESUME), | 561 | /* resume signaling for 20 msec */ |
463 | &ehci->regs->port_status [wIndex]); | 562 | ehci->reset_done[wIndex] = jiffies |
464 | retval = handshake ( | 563 | + msecs_to_jiffies(20); |
465 | &ehci->regs->port_status [wIndex], | 564 | /* check the port again */ |
466 | PORT_RESUME, 0, 2000 /* 2msec */); | 565 | mod_timer(&ehci_to_hcd(ehci)->rh_timer, |
467 | if (retval != 0) { | 566 | ehci->reset_done[wIndex]); |
468 | ehci_err (ehci, "port %d resume error %d\n", | 567 | } |
469 | wIndex + 1, retval); | 568 | |
470 | goto error; | 569 | /* resume completed? */ |
570 | else if (time_after_eq(jiffies, | ||
571 | ehci->reset_done[wIndex])) { | ||
572 | status |= 1 << USB_PORT_FEAT_C_SUSPEND; | ||
573 | ehci->reset_done[wIndex] = 0; | ||
574 | |||
575 | /* stop resume signaling */ | ||
576 | temp = ehci_readl(ehci, status_reg); | ||
577 | ehci_writel(ehci, | ||
578 | temp & ~(PORT_RWC_BITS | PORT_RESUME), | ||
579 | status_reg); | ||
580 | retval = handshake(ehci, status_reg, | ||
581 | PORT_RESUME, 0, 2000 /* 2msec */); | ||
582 | if (retval != 0) { | ||
583 | ehci_err(ehci, | ||
584 | "port %d resume error %d\n", | ||
585 | wIndex + 1, retval); | ||
586 | goto error; | ||
587 | } | ||
588 | temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); | ||
471 | } | 589 | } |
472 | temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); | ||
473 | } | 590 | } |
474 | 591 | ||
475 | /* whoever resets must GetPortStatus to complete it!! */ | 592 | /* whoever resets must GetPortStatus to complete it!! */ |
476 | if ((temp & PORT_RESET) | 593 | if ((temp & PORT_RESET) |
477 | && time_after (jiffies, | 594 | && time_after_eq(jiffies, |
478 | ehci->reset_done [wIndex])) { | 595 | ehci->reset_done[wIndex])) { |
479 | status |= 1 << USB_PORT_FEAT_C_RESET; | 596 | status |= 1 << USB_PORT_FEAT_C_RESET; |
480 | ehci->reset_done [wIndex] = 0; | 597 | ehci->reset_done [wIndex] = 0; |
481 | 598 | ||
482 | /* force reset to complete */ | 599 | /* force reset to complete */ |
483 | writel (temp & ~(PORT_RWC_BITS | PORT_RESET), | 600 | ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET), |
484 | &ehci->regs->port_status [wIndex]); | 601 | status_reg); |
485 | /* REVISIT: some hardware needs 550+ usec to clear | 602 | /* REVISIT: some hardware needs 550+ usec to clear |
486 | * this bit; seems too long to spin routinely... | 603 | * this bit; seems too long to spin routinely... |
487 | */ | 604 | */ |
488 | retval = handshake ( | 605 | retval = handshake(ehci, status_reg, |
489 | &ehci->regs->port_status [wIndex], | ||
490 | PORT_RESET, 0, 750); | 606 | PORT_RESET, 0, 750); |
491 | if (retval != 0) { | 607 | if (retval != 0) { |
492 | ehci_err (ehci, "port %d reset error %d\n", | 608 | ehci_err (ehci, "port %d reset error %d\n", |
@@ -495,28 +611,41 @@ static int ehci_hub_control ( | |||
495 | } | 611 | } |
496 | 612 | ||
497 | /* see what we found out */ | 613 | /* see what we found out */ |
498 | temp = check_reset_complete (ehci, wIndex, | 614 | temp = check_reset_complete (ehci, wIndex, status_reg, |
499 | readl (&ehci->regs->port_status [wIndex])); | 615 | ehci_readl(ehci, status_reg)); |
500 | } | 616 | } |
501 | 617 | ||
502 | // don't show wPortStatus if it's owned by a companion hc | 618 | /* transfer dedicated ports to the companion hc */ |
503 | if (!(temp & PORT_OWNER)) { | 619 | if ((temp & PORT_CONNECT) && |
504 | if (temp & PORT_CONNECT) { | 620 | test_bit(wIndex, &ehci->companion_ports)) { |
505 | status |= 1 << USB_PORT_FEAT_CONNECTION; | 621 | temp &= ~PORT_RWC_BITS; |
506 | // status may be from integrated TT | 622 | temp |= PORT_OWNER; |
507 | status |= ehci_port_speed(ehci, temp); | 623 | ehci_writel(ehci, temp, status_reg); |
508 | } | 624 | ehci_dbg(ehci, "port %d --> companion\n", wIndex + 1); |
509 | if (temp & PORT_PE) | 625 | temp = ehci_readl(ehci, status_reg); |
510 | status |= 1 << USB_PORT_FEAT_ENABLE; | 626 | } |
511 | if (temp & (PORT_SUSPEND|PORT_RESUME)) | 627 | |
512 | status |= 1 << USB_PORT_FEAT_SUSPEND; | 628 | /* |
513 | if (temp & PORT_OC) | 629 | * Even if OWNER is set, there's no harm letting khubd |
514 | status |= 1 << USB_PORT_FEAT_OVER_CURRENT; | 630 | * see the wPortStatus values (they should all be 0 except |
515 | if (temp & PORT_RESET) | 631 | * for PORT_POWER anyway). |
516 | status |= 1 << USB_PORT_FEAT_RESET; | 632 | */ |
517 | if (temp & PORT_POWER) | 633 | |
518 | status |= 1 << USB_PORT_FEAT_POWER; | 634 | if (temp & PORT_CONNECT) { |
635 | status |= 1 << USB_PORT_FEAT_CONNECTION; | ||
636 | // status may be from integrated TT | ||
637 | status |= ehci_port_speed(ehci, temp); | ||
519 | } | 638 | } |
639 | if (temp & PORT_PE) | ||
640 | status |= 1 << USB_PORT_FEAT_ENABLE; | ||
641 | if (temp & (PORT_SUSPEND|PORT_RESUME)) | ||
642 | status |= 1 << USB_PORT_FEAT_SUSPEND; | ||
643 | if (temp & PORT_OC) | ||
644 | status |= 1 << USB_PORT_FEAT_OVER_CURRENT; | ||
645 | if (temp & PORT_RESET) | ||
646 | status |= 1 << USB_PORT_FEAT_RESET; | ||
647 | if (temp & PORT_POWER) | ||
648 | status |= 1 << USB_PORT_FEAT_POWER; | ||
520 | 649 | ||
521 | #ifndef EHCI_VERBOSE_DEBUG | 650 | #ifndef EHCI_VERBOSE_DEBUG |
522 | if (status & ~0xffff) /* only if wPortChange is interesting */ | 651 | if (status & ~0xffff) /* only if wPortChange is interesting */ |
@@ -541,7 +670,7 @@ static int ehci_hub_control ( | |||
541 | if (!wIndex || wIndex > ports) | 670 | if (!wIndex || wIndex > ports) |
542 | goto error; | 671 | goto error; |
543 | wIndex--; | 672 | wIndex--; |
544 | temp = readl (&ehci->regs->port_status [wIndex]); | 673 | temp = ehci_readl(ehci, status_reg); |
545 | if (temp & PORT_OWNER) | 674 | if (temp & PORT_OWNER) |
546 | break; | 675 | break; |
547 | 676 | ||
@@ -555,13 +684,12 @@ static int ehci_hub_control ( | |||
555 | goto error; | 684 | goto error; |
556 | if (device_may_wakeup(&hcd->self.root_hub->dev)) | 685 | if (device_may_wakeup(&hcd->self.root_hub->dev)) |
557 | temp |= PORT_WAKE_BITS; | 686 | temp |= PORT_WAKE_BITS; |
558 | writel (temp | PORT_SUSPEND, | 687 | ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); |
559 | &ehci->regs->port_status [wIndex]); | ||
560 | break; | 688 | break; |
561 | case USB_PORT_FEAT_POWER: | 689 | case USB_PORT_FEAT_POWER: |
562 | if (HCS_PPC (ehci->hcs_params)) | 690 | if (HCS_PPC (ehci->hcs_params)) |
563 | writel (temp | PORT_POWER, | 691 | ehci_writel(ehci, temp | PORT_POWER, |
564 | &ehci->regs->port_status [wIndex]); | 692 | status_reg); |
565 | break; | 693 | break; |
566 | case USB_PORT_FEAT_RESET: | 694 | case USB_PORT_FEAT_RESET: |
567 | if (temp & PORT_RESUME) | 695 | if (temp & PORT_RESUME) |
@@ -589,7 +717,7 @@ static int ehci_hub_control ( | |||
589 | ehci->reset_done [wIndex] = jiffies | 717 | ehci->reset_done [wIndex] = jiffies |
590 | + msecs_to_jiffies (50); | 718 | + msecs_to_jiffies (50); |
591 | } | 719 | } |
592 | writel (temp, &ehci->regs->port_status [wIndex]); | 720 | ehci_writel(ehci, temp, status_reg); |
593 | break; | 721 | break; |
594 | 722 | ||
595 | /* For downstream facing ports (these): one hub port is put | 723 | /* For downstream facing ports (these): one hub port is put |
@@ -604,13 +732,13 @@ static int ehci_hub_control ( | |||
604 | ehci_quiesce(ehci); | 732 | ehci_quiesce(ehci); |
605 | ehci_halt(ehci); | 733 | ehci_halt(ehci); |
606 | temp |= selector << 16; | 734 | temp |= selector << 16; |
607 | writel (temp, &ehci->regs->port_status [wIndex]); | 735 | ehci_writel(ehci, temp, status_reg); |
608 | break; | 736 | break; |
609 | 737 | ||
610 | default: | 738 | default: |
611 | goto error; | 739 | goto error; |
612 | } | 740 | } |
613 | readl (&ehci->regs->command); /* unblock posted writes */ | 741 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ |
614 | break; | 742 | break; |
615 | 743 | ||
616 | default: | 744 | default: |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 4bc7970ba3ef..12edc723ec73 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -38,7 +38,7 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) | |||
38 | if ((temp & (3 << 13)) == (1 << 13)) { | 38 | if ((temp & (3 << 13)) == (1 << 13)) { |
39 | temp &= 0x1fff; | 39 | temp &= 0x1fff; |
40 | ehci->debug = ehci_to_hcd(ehci)->regs + temp; | 40 | ehci->debug = ehci_to_hcd(ehci)->regs + temp; |
41 | temp = readl(&ehci->debug->control); | 41 | temp = ehci_readl(ehci, &ehci->debug->control); |
42 | ehci_info(ehci, "debug port %d%s\n", | 42 | ehci_info(ehci, "debug port %d%s\n", |
43 | HCS_DEBUG_PORT(ehci->hcs_params), | 43 | HCS_DEBUG_PORT(ehci->hcs_params), |
44 | (temp & DBGP_ENABLED) | 44 | (temp & DBGP_ENABLED) |
@@ -71,8 +71,24 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
71 | u32 temp; | 71 | u32 temp; |
72 | int retval; | 72 | int retval; |
73 | 73 | ||
74 | switch (pdev->vendor) { | ||
75 | case PCI_VENDOR_ID_TOSHIBA_2: | ||
76 | /* celleb's companion chip */ | ||
77 | if (pdev->device == 0x01b5) { | ||
78 | #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO | ||
79 | ehci->big_endian_mmio = 1; | ||
80 | #else | ||
81 | ehci_warn(ehci, | ||
82 | "unsupported big endian Toshiba quirk\n"); | ||
83 | #endif | ||
84 | } | ||
85 | break; | ||
86 | } | ||
87 | |||
74 | ehci->caps = hcd->regs; | 88 | ehci->caps = hcd->regs; |
75 | ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase)); | 89 | ehci->regs = hcd->regs + |
90 | HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
91 | |||
76 | dbg_hcs_params(ehci, "reset"); | 92 | dbg_hcs_params(ehci, "reset"); |
77 | dbg_hcc_params(ehci, "reset"); | 93 | dbg_hcc_params(ehci, "reset"); |
78 | 94 | ||
@@ -101,7 +117,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
101 | } | 117 | } |
102 | 118 | ||
103 | /* cache this readonly data; minimize chip reads */ | 119 | /* cache this readonly data; minimize chip reads */ |
104 | ehci->hcs_params = readl(&ehci->caps->hcs_params); | 120 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); |
105 | 121 | ||
106 | retval = ehci_halt(ehci); | 122 | retval = ehci_halt(ehci); |
107 | if (retval) | 123 | if (retval) |
@@ -235,8 +251,8 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) | |||
235 | rc = -EINVAL; | 251 | rc = -EINVAL; |
236 | goto bail; | 252 | goto bail; |
237 | } | 253 | } |
238 | writel (0, &ehci->regs->intr_enable); | 254 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
239 | (void)readl(&ehci->regs->intr_enable); | 255 | (void)ehci_readl(ehci, &ehci->regs->intr_enable); |
240 | 256 | ||
241 | /* make sure snapshot being resumed re-enumerates everything */ | 257 | /* make sure snapshot being resumed re-enumerates everything */ |
242 | if (message.event == PM_EVENT_PRETHAW) { | 258 | if (message.event == PM_EVENT_PRETHAW) { |
@@ -270,13 +286,13 @@ static int ehci_pci_resume(struct usb_hcd *hcd) | |||
270 | /* If CF is still set, we maintained PCI Vaux power. | 286 | /* If CF is still set, we maintained PCI Vaux power. |
271 | * Just undo the effect of ehci_pci_suspend(). | 287 | * Just undo the effect of ehci_pci_suspend(). |
272 | */ | 288 | */ |
273 | if (readl(&ehci->regs->configured_flag) == FLAG_CF) { | 289 | if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { |
274 | int mask = INTR_MASK; | 290 | int mask = INTR_MASK; |
275 | 291 | ||
276 | if (!device_may_wakeup(&hcd->self.root_hub->dev)) | 292 | if (!device_may_wakeup(&hcd->self.root_hub->dev)) |
277 | mask &= ~STS_PCD; | 293 | mask &= ~STS_PCD; |
278 | writel(mask, &ehci->regs->intr_enable); | 294 | ehci_writel(ehci, mask, &ehci->regs->intr_enable); |
279 | readl(&ehci->regs->intr_enable); | 295 | ehci_readl(ehci, &ehci->regs->intr_enable); |
280 | return 0; | 296 | return 0; |
281 | } | 297 | } |
282 | 298 | ||
@@ -300,9 +316,9 @@ static int ehci_pci_resume(struct usb_hcd *hcd) | |||
300 | /* here we "know" root ports should always stay powered */ | 316 | /* here we "know" root ports should always stay powered */ |
301 | ehci_port_power(ehci, 1); | 317 | ehci_port_power(ehci, 1); |
302 | 318 | ||
303 | writel(ehci->command, &ehci->regs->command); | 319 | ehci_writel(ehci, ehci->command, &ehci->regs->command); |
304 | writel(FLAG_CF, &ehci->regs->configured_flag); | 320 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); |
305 | readl(&ehci->regs->command); /* unblock posted writes */ | 321 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ |
306 | 322 | ||
307 | hcd->state = HC_STATE_SUSPENDED; | 323 | hcd->state = HC_STATE_SUSPENDED; |
308 | return 0; | 324 | return 0; |
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c new file mode 100644 index 000000000000..4d781a2a9807 --- /dev/null +++ b/drivers/usb/host/ehci-ps3.c | |||
@@ -0,0 +1,193 @@ | |||
1 | /* | ||
2 | * PS3 EHCI Host Controller driver | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <asm/ps3.h> | ||
22 | |||
23 | static int ps3_ehci_hc_reset(struct usb_hcd *hcd) | ||
24 | { | ||
25 | int result; | ||
26 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
27 | |||
28 | ehci->big_endian_mmio = 1; | ||
29 | |||
30 | ehci->caps = hcd->regs; | ||
31 | ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, | ||
32 | &ehci->caps->hc_capbase)); | ||
33 | |||
34 | dbg_hcs_params(ehci, "reset"); | ||
35 | dbg_hcc_params(ehci, "reset"); | ||
36 | |||
37 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
38 | |||
39 | result = ehci_halt(ehci); | ||
40 | |||
41 | if (result) | ||
42 | return result; | ||
43 | |||
44 | result = ehci_init(hcd); | ||
45 | |||
46 | if (result) | ||
47 | return result; | ||
48 | |||
49 | ehci_port_power(ehci, 0); | ||
50 | |||
51 | return result; | ||
52 | } | ||
53 | |||
54 | static const struct hc_driver ps3_ehci_hc_driver = { | ||
55 | .description = hcd_name, | ||
56 | .product_desc = "PS3 EHCI Host Controller", | ||
57 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
58 | .irq = ehci_irq, | ||
59 | .flags = HCD_MEMORY | HCD_USB2, | ||
60 | .reset = ps3_ehci_hc_reset, | ||
61 | .start = ehci_run, | ||
62 | .stop = ehci_stop, | ||
63 | .shutdown = ehci_shutdown, | ||
64 | .urb_enqueue = ehci_urb_enqueue, | ||
65 | .urb_dequeue = ehci_urb_dequeue, | ||
66 | .endpoint_disable = ehci_endpoint_disable, | ||
67 | .get_frame_number = ehci_get_frame, | ||
68 | .hub_status_data = ehci_hub_status_data, | ||
69 | .hub_control = ehci_hub_control, | ||
70 | #if defined(CONFIG_PM) | ||
71 | .bus_suspend = ehci_bus_suspend, | ||
72 | .bus_resume = ehci_bus_resume, | ||
73 | #endif | ||
74 | }; | ||
75 | |||
76 | #if !defined(DEBUG) | ||
77 | #undef dev_dbg | ||
78 | static inline int __attribute__ ((format (printf, 2, 3))) dev_dbg( | ||
79 | const struct device *_dev, const char *fmt, ...) {return 0;} | ||
80 | #endif | ||
81 | |||
82 | |||
83 | static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev) | ||
84 | { | ||
85 | int result; | ||
86 | struct usb_hcd *hcd; | ||
87 | unsigned int virq; | ||
88 | static u64 dummy_mask = DMA_32BIT_MASK; | ||
89 | |||
90 | if (usb_disabled()) { | ||
91 | result = -ENODEV; | ||
92 | goto fail_start; | ||
93 | } | ||
94 | |||
95 | result = ps3_mmio_region_create(dev->m_region); | ||
96 | |||
97 | if (result) { | ||
98 | dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n", | ||
99 | __func__, __LINE__); | ||
100 | result = -EPERM; | ||
101 | goto fail_mmio; | ||
102 | } | ||
103 | |||
104 | dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__, | ||
105 | __LINE__, dev->m_region->lpar_addr); | ||
106 | |||
107 | result = ps3_alloc_io_irq(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq); | ||
108 | |||
109 | if (result) { | ||
110 | dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n", | ||
111 | __func__, __LINE__, virq); | ||
112 | result = -EPERM; | ||
113 | goto fail_irq; | ||
114 | } | ||
115 | |||
116 | dev->core.power.power_state = PMSG_ON; | ||
117 | dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */ | ||
118 | |||
119 | hcd = usb_create_hcd(&ps3_ehci_hc_driver, &dev->core, dev->core.bus_id); | ||
120 | |||
121 | if (!hcd) { | ||
122 | dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__, | ||
123 | __LINE__); | ||
124 | result = -ENOMEM; | ||
125 | goto fail_create_hcd; | ||
126 | } | ||
127 | |||
128 | hcd->rsrc_start = dev->m_region->lpar_addr; | ||
129 | hcd->rsrc_len = dev->m_region->len; | ||
130 | hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len); | ||
131 | |||
132 | if (!hcd->regs) { | ||
133 | dev_dbg(&dev->core, "%s:%d: ioremap failed\n", __func__, | ||
134 | __LINE__); | ||
135 | result = -EPERM; | ||
136 | goto fail_ioremap; | ||
137 | } | ||
138 | |||
139 | dev_dbg(&dev->core, "%s:%d: hcd->rsrc_start %lxh\n", __func__, __LINE__, | ||
140 | (unsigned long)hcd->rsrc_start); | ||
141 | dev_dbg(&dev->core, "%s:%d: hcd->rsrc_len %lxh\n", __func__, __LINE__, | ||
142 | (unsigned long)hcd->rsrc_len); | ||
143 | dev_dbg(&dev->core, "%s:%d: hcd->regs %lxh\n", __func__, __LINE__, | ||
144 | (unsigned long)hcd->regs); | ||
145 | dev_dbg(&dev->core, "%s:%d: virq %lu\n", __func__, __LINE__, | ||
146 | (unsigned long)virq); | ||
147 | |||
148 | ps3_system_bus_set_driver_data(dev, hcd); | ||
149 | |||
150 | result = usb_add_hcd(hcd, virq, IRQF_DISABLED); | ||
151 | |||
152 | if (result) { | ||
153 | dev_dbg(&dev->core, "%s:%d: usb_add_hcd failed (%d)\n", | ||
154 | __func__, __LINE__, result); | ||
155 | goto fail_add_hcd; | ||
156 | } | ||
157 | |||
158 | return result; | ||
159 | |||
160 | fail_add_hcd: | ||
161 | iounmap(hcd->regs); | ||
162 | fail_ioremap: | ||
163 | usb_put_hcd(hcd); | ||
164 | fail_create_hcd: | ||
165 | ps3_free_io_irq(virq); | ||
166 | fail_irq: | ||
167 | ps3_free_mmio_region(dev->m_region); | ||
168 | fail_mmio: | ||
169 | fail_start: | ||
170 | return result; | ||
171 | } | ||
172 | |||
173 | static int ps3_ehci_sb_remove(struct ps3_system_bus_device *dev) | ||
174 | { | ||
175 | struct usb_hcd *hcd = | ||
176 | (struct usb_hcd *)ps3_system_bus_get_driver_data(dev); | ||
177 | |||
178 | usb_put_hcd(hcd); | ||
179 | ps3_system_bus_set_driver_data(dev, NULL); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | MODULE_ALIAS("ps3-ehci"); | ||
185 | |||
186 | static struct ps3_system_bus_driver ps3_ehci_sb_driver = { | ||
187 | .match_id = PS3_MATCH_ID_EHCI, | ||
188 | .core = { | ||
189 | .name = "ps3-ehci-driver", | ||
190 | }, | ||
191 | .probe = ps3_ehci_sb_probe, | ||
192 | .remove = ps3_ehci_sb_remove, | ||
193 | }; | ||
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 62e46dc60e86..e7fbbd00e7cd 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -789,13 +789,14 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
789 | head = ehci->async; | 789 | head = ehci->async; |
790 | timer_action_done (ehci, TIMER_ASYNC_OFF); | 790 | timer_action_done (ehci, TIMER_ASYNC_OFF); |
791 | if (!head->qh_next.qh) { | 791 | if (!head->qh_next.qh) { |
792 | u32 cmd = readl (&ehci->regs->command); | 792 | u32 cmd = ehci_readl(ehci, &ehci->regs->command); |
793 | 793 | ||
794 | if (!(cmd & CMD_ASE)) { | 794 | if (!(cmd & CMD_ASE)) { |
795 | /* in case a clear of CMD_ASE didn't take yet */ | 795 | /* in case a clear of CMD_ASE didn't take yet */ |
796 | (void) handshake (&ehci->regs->status, STS_ASS, 0, 150); | 796 | (void)handshake(ehci, &ehci->regs->status, |
797 | STS_ASS, 0, 150); | ||
797 | cmd |= CMD_ASE | CMD_RUN; | 798 | cmd |= CMD_ASE | CMD_RUN; |
798 | writel (cmd, &ehci->regs->command); | 799 | ehci_writel(ehci, cmd, &ehci->regs->command); |
799 | ehci_to_hcd(ehci)->state = HC_STATE_RUNNING; | 800 | ehci_to_hcd(ehci)->state = HC_STATE_RUNNING; |
800 | /* posted write need not be known to HC yet ... */ | 801 | /* posted write need not be known to HC yet ... */ |
801 | } | 802 | } |
@@ -1007,7 +1008,7 @@ static void end_unlink_async (struct ehci_hcd *ehci) | |||
1007 | 1008 | ||
1008 | static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | 1009 | static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) |
1009 | { | 1010 | { |
1010 | int cmd = readl (&ehci->regs->command); | 1011 | int cmd = ehci_readl(ehci, &ehci->regs->command); |
1011 | struct ehci_qh *prev; | 1012 | struct ehci_qh *prev; |
1012 | 1013 | ||
1013 | #ifdef DEBUG | 1014 | #ifdef DEBUG |
@@ -1025,7 +1026,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
1025 | if (ehci_to_hcd(ehci)->state != HC_STATE_HALT | 1026 | if (ehci_to_hcd(ehci)->state != HC_STATE_HALT |
1026 | && !ehci->reclaim) { | 1027 | && !ehci->reclaim) { |
1027 | /* ... and CMD_IAAD clear */ | 1028 | /* ... and CMD_IAAD clear */ |
1028 | writel (cmd & ~CMD_ASE, &ehci->regs->command); | 1029 | ehci_writel(ehci, cmd & ~CMD_ASE, |
1030 | &ehci->regs->command); | ||
1029 | wmb (); | 1031 | wmb (); |
1030 | // handshake later, if we need to | 1032 | // handshake later, if we need to |
1031 | timer_action_done (ehci, TIMER_ASYNC_OFF); | 1033 | timer_action_done (ehci, TIMER_ASYNC_OFF); |
@@ -1054,8 +1056,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
1054 | 1056 | ||
1055 | ehci->reclaim_ready = 0; | 1057 | ehci->reclaim_ready = 0; |
1056 | cmd |= CMD_IAAD; | 1058 | cmd |= CMD_IAAD; |
1057 | writel (cmd, &ehci->regs->command); | 1059 | ehci_writel(ehci, cmd, &ehci->regs->command); |
1058 | (void) readl (&ehci->regs->command); | 1060 | (void)ehci_readl(ehci, &ehci->regs->command); |
1059 | timer_action (ehci, TIMER_IAA_WATCHDOG); | 1061 | timer_action (ehci, TIMER_IAA_WATCHDOG); |
1060 | } | 1062 | } |
1061 | 1063 | ||
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 65c402a0fa7a..7b5ae7111f23 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -433,20 +433,20 @@ static int enable_periodic (struct ehci_hcd *ehci) | |||
433 | /* did clearing PSE did take effect yet? | 433 | /* did clearing PSE did take effect yet? |
434 | * takes effect only at frame boundaries... | 434 | * takes effect only at frame boundaries... |
435 | */ | 435 | */ |
436 | status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125); | 436 | status = handshake(ehci, &ehci->regs->status, STS_PSS, 0, 9 * 125); |
437 | if (status != 0) { | 437 | if (status != 0) { |
438 | ehci_to_hcd(ehci)->state = HC_STATE_HALT; | 438 | ehci_to_hcd(ehci)->state = HC_STATE_HALT; |
439 | return status; | 439 | return status; |
440 | } | 440 | } |
441 | 441 | ||
442 | cmd = readl (&ehci->regs->command) | CMD_PSE; | 442 | cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE; |
443 | writel (cmd, &ehci->regs->command); | 443 | ehci_writel(ehci, cmd, &ehci->regs->command); |
444 | /* posted write ... PSS happens later */ | 444 | /* posted write ... PSS happens later */ |
445 | ehci_to_hcd(ehci)->state = HC_STATE_RUNNING; | 445 | ehci_to_hcd(ehci)->state = HC_STATE_RUNNING; |
446 | 446 | ||
447 | /* make sure ehci_work scans these */ | 447 | /* make sure ehci_work scans these */ |
448 | ehci->next_uframe = readl (&ehci->regs->frame_index) | 448 | ehci->next_uframe = ehci_readl(ehci, &ehci->regs->frame_index) |
449 | % (ehci->periodic_size << 3); | 449 | % (ehci->periodic_size << 3); |
450 | return 0; | 450 | return 0; |
451 | } | 451 | } |
452 | 452 | ||
@@ -458,14 +458,14 @@ static int disable_periodic (struct ehci_hcd *ehci) | |||
458 | /* did setting PSE not take effect yet? | 458 | /* did setting PSE not take effect yet? |
459 | * takes effect only at frame boundaries... | 459 | * takes effect only at frame boundaries... |
460 | */ | 460 | */ |
461 | status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125); | 461 | status = handshake(ehci, &ehci->regs->status, STS_PSS, STS_PSS, 9 * 125); |
462 | if (status != 0) { | 462 | if (status != 0) { |
463 | ehci_to_hcd(ehci)->state = HC_STATE_HALT; | 463 | ehci_to_hcd(ehci)->state = HC_STATE_HALT; |
464 | return status; | 464 | return status; |
465 | } | 465 | } |
466 | 466 | ||
467 | cmd = readl (&ehci->regs->command) & ~CMD_PSE; | 467 | cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE; |
468 | writel (cmd, &ehci->regs->command); | 468 | ehci_writel(ehci, cmd, &ehci->regs->command); |
469 | /* posted write ... */ | 469 | /* posted write ... */ |
470 | 470 | ||
471 | ehci->next_uframe = -1; | 471 | ehci->next_uframe = -1; |
@@ -1336,7 +1336,7 @@ iso_stream_schedule ( | |||
1336 | goto fail; | 1336 | goto fail; |
1337 | } | 1337 | } |
1338 | 1338 | ||
1339 | now = readl (&ehci->regs->frame_index) % mod; | 1339 | now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; |
1340 | 1340 | ||
1341 | /* when's the last uframe this urb could start? */ | 1341 | /* when's the last uframe this urb could start? */ |
1342 | max = now + mod; | 1342 | max = now + mod; |
@@ -2088,7 +2088,7 @@ scan_periodic (struct ehci_hcd *ehci) | |||
2088 | */ | 2088 | */ |
2089 | now_uframe = ehci->next_uframe; | 2089 | now_uframe = ehci->next_uframe; |
2090 | if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) | 2090 | if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) |
2091 | clock = readl (&ehci->regs->frame_index); | 2091 | clock = ehci_readl(ehci, &ehci->regs->frame_index); |
2092 | else | 2092 | else |
2093 | clock = now_uframe + mod - 1; | 2093 | clock = now_uframe + mod - 1; |
2094 | clock %= mod; | 2094 | clock %= mod; |
@@ -2213,7 +2213,7 @@ restart: | |||
2213 | if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) | 2213 | if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) |
2214 | break; | 2214 | break; |
2215 | ehci->next_uframe = now_uframe; | 2215 | ehci->next_uframe = now_uframe; |
2216 | now = readl (&ehci->regs->frame_index) % mod; | 2216 | now = ehci_readl(ehci, &ehci->regs->frame_index) % mod; |
2217 | if (now_uframe == now) | 2217 | if (now_uframe == now) |
2218 | break; | 2218 | break; |
2219 | 2219 | ||
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 74dbc6c8228f..46fa57a520d0 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -74,7 +74,11 @@ struct ehci_hcd { /* one per controller */ | |||
74 | 74 | ||
75 | /* per root hub port */ | 75 | /* per root hub port */ |
76 | unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; | 76 | unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; |
77 | unsigned long bus_suspended; | 77 | /* bit vectors (one bit per port) */ |
78 | unsigned long bus_suspended; /* which ports were | ||
79 | already suspended at the start of a bus suspend */ | ||
80 | unsigned long companion_ports; /* which ports are | ||
81 | dedicated to the companion controller */ | ||
78 | 82 | ||
79 | /* per-HC memory pools (could be per-bus, but ...) */ | 83 | /* per-HC memory pools (could be per-bus, but ...) */ |
80 | struct dma_pool *qh_pool; /* qh per active urb */ | 84 | struct dma_pool *qh_pool; /* qh per active urb */ |
@@ -92,6 +96,7 @@ struct ehci_hcd { /* one per controller */ | |||
92 | unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */ | 96 | unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */ |
93 | unsigned no_selective_suspend:1; | 97 | unsigned no_selective_suspend:1; |
94 | unsigned has_fsl_port_bug:1; /* FreeScale */ | 98 | unsigned has_fsl_port_bug:1; /* FreeScale */ |
99 | unsigned big_endian_mmio:1; | ||
95 | 100 | ||
96 | u8 sbrn; /* packed release number */ | 101 | u8 sbrn; /* packed release number */ |
97 | 102 | ||
@@ -651,6 +656,45 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) | |||
651 | #define ehci_has_fsl_portno_bug(e) (0) | 656 | #define ehci_has_fsl_portno_bug(e) (0) |
652 | #endif | 657 | #endif |
653 | 658 | ||
659 | /* | ||
660 | * While most USB host controllers implement their registers in | ||
661 | * little-endian format, a minority (celleb companion chip) implement | ||
662 | * them in big endian format. | ||
663 | * | ||
664 | * This attempts to support either format at compile time without a | ||
665 | * runtime penalty, or both formats with the additional overhead | ||
666 | * of checking a flag bit. | ||
667 | */ | ||
668 | |||
669 | #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO | ||
670 | #define ehci_big_endian_mmio(e) ((e)->big_endian_mmio) | ||
671 | #else | ||
672 | #define ehci_big_endian_mmio(e) 0 | ||
673 | #endif | ||
674 | |||
675 | static inline unsigned int ehci_readl (const struct ehci_hcd *ehci, | ||
676 | __u32 __iomem * regs) | ||
677 | { | ||
678 | #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO | ||
679 | return ehci_big_endian_mmio(ehci) ? | ||
680 | readl_be(regs) : | ||
681 | readl(regs); | ||
682 | #else | ||
683 | return readl(regs); | ||
684 | #endif | ||
685 | } | ||
686 | |||
687 | static inline void ehci_writel (const struct ehci_hcd *ehci, | ||
688 | const unsigned int val, __u32 __iomem *regs) | ||
689 | { | ||
690 | #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO | ||
691 | ehci_big_endian_mmio(ehci) ? | ||
692 | writel_be(val, regs) : | ||
693 | writel(val, regs); | ||
694 | #else | ||
695 | writel(val, regs); | ||
696 | #endif | ||
697 | } | ||
654 | 698 | ||
655 | /*-------------------------------------------------------------------------*/ | 699 | /*-------------------------------------------------------------------------*/ |
656 | 700 | ||
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c index 9325e46a68c0..282d82efc0b0 100644 --- a/drivers/usb/host/hc_crisv10.c +++ b/drivers/usb/host/hc_crisv10.c | |||
@@ -365,7 +365,7 @@ static inline struct urb *urb_list_first(int epid) | |||
365 | /* Adds an urb_entry last in the list for this epid. */ | 365 | /* Adds an urb_entry last in the list for this epid. */ |
366 | static inline void urb_list_add(struct urb *urb, int epid) | 366 | static inline void urb_list_add(struct urb *urb, int epid) |
367 | { | 367 | { |
368 | urb_entry_t *urb_entry = (urb_entry_t *)kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG); | 368 | urb_entry_t *urb_entry = kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG); |
369 | assert(urb_entry); | 369 | assert(urb_entry); |
370 | 370 | ||
371 | urb_entry->urb = urb; | 371 | urb_entry->urb = urb; |
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index b466581beb4a..930346487278 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c | |||
@@ -170,7 +170,6 @@ static int usb_hcd_at91_remove(struct usb_hcd *hcd, | |||
170 | at91_stop_hc(pdev); | 170 | at91_stop_hc(pdev); |
171 | iounmap(hcd->regs); | 171 | iounmap(hcd->regs); |
172 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 172 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
173 | disable_irq_wake(hcd->irq); | ||
174 | 173 | ||
175 | clk_put(fclk); | 174 | clk_put(fclk); |
176 | clk_put(iclk); | 175 | clk_put(iclk); |
@@ -187,7 +186,6 @@ ohci_at91_start (struct usb_hcd *hcd) | |||
187 | { | 186 | { |
188 | struct at91_usbh_data *board = hcd->self.controller->platform_data; | 187 | struct at91_usbh_data *board = hcd->self.controller->platform_data; |
189 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 188 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
190 | struct usb_device *root = hcd->self.root_hub; | ||
191 | int ret; | 189 | int ret; |
192 | 190 | ||
193 | if ((ret = ohci_init(ohci)) < 0) | 191 | if ((ret = ohci_init(ohci)) < 0) |
@@ -221,7 +219,7 @@ static const struct hc_driver ohci_at91_hc_driver = { | |||
221 | */ | 219 | */ |
222 | .start = ohci_at91_start, | 220 | .start = ohci_at91_start, |
223 | .stop = ohci_stop, | 221 | .stop = ohci_stop, |
224 | .shutdown = ohci_shutdown, | 222 | .shutdown = ohci_shutdown, |
225 | 223 | ||
226 | /* | 224 | /* |
227 | * managing i/o requests and associated device resources | 225 | * managing i/o requests and associated device resources |
@@ -272,8 +270,6 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
272 | 270 | ||
273 | if (device_may_wakeup(&pdev->dev)) | 271 | if (device_may_wakeup(&pdev->dev)) |
274 | enable_irq_wake(hcd->irq); | 272 | enable_irq_wake(hcd->irq); |
275 | else | ||
276 | disable_irq_wake(hcd->irq); | ||
277 | 273 | ||
278 | /* | 274 | /* |
279 | * The integrated transceivers seem unable to notice disconnect, | 275 | * The integrated transceivers seem unable to notice disconnect, |
@@ -294,6 +290,11 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
294 | 290 | ||
295 | static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) | 291 | static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) |
296 | { | 292 | { |
293 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
294 | |||
295 | if (device_may_wakeup(&pdev->dev)) | ||
296 | disable_irq_wake(hcd->irq); | ||
297 | |||
297 | if (!clocked) { | 298 | if (!clocked) { |
298 | clk_enable(iclk); | 299 | clk_enable(iclk); |
299 | clk_enable(fclk); | 300 | clk_enable(fclk); |
@@ -321,18 +322,3 @@ static struct platform_driver ohci_hcd_at91_driver = { | |||
321 | }, | 322 | }, |
322 | }; | 323 | }; |
323 | 324 | ||
324 | static int __init ohci_hcd_at91_init (void) | ||
325 | { | ||
326 | if (usb_disabled()) | ||
327 | return -ENODEV; | ||
328 | |||
329 | return platform_driver_register(&ohci_hcd_at91_driver); | ||
330 | } | ||
331 | |||
332 | static void __exit ohci_hcd_at91_cleanup (void) | ||
333 | { | ||
334 | platform_driver_unregister(&ohci_hcd_at91_driver); | ||
335 | } | ||
336 | |||
337 | module_init (ohci_hcd_at91_init); | ||
338 | module_exit (ohci_hcd_at91_cleanup); | ||
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index 24e23c5783d8..663a0600b6e7 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c | |||
@@ -269,7 +269,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = { | |||
269 | */ | 269 | */ |
270 | .start = ohci_au1xxx_start, | 270 | .start = ohci_au1xxx_start, |
271 | .stop = ohci_stop, | 271 | .stop = ohci_stop, |
272 | .shutdown = ohci_shutdown, | 272 | .shutdown = ohci_shutdown, |
273 | 273 | ||
274 | /* | 274 | /* |
275 | * managing i/o requests and associated device resources | 275 | * managing i/o requests and associated device resources |
@@ -336,7 +336,7 @@ static int ohci_hcd_au1xxx_drv_resume(struct platform_device *dev) | |||
336 | static struct platform_driver ohci_hcd_au1xxx_driver = { | 336 | static struct platform_driver ohci_hcd_au1xxx_driver = { |
337 | .probe = ohci_hcd_au1xxx_drv_probe, | 337 | .probe = ohci_hcd_au1xxx_drv_probe, |
338 | .remove = ohci_hcd_au1xxx_drv_remove, | 338 | .remove = ohci_hcd_au1xxx_drv_remove, |
339 | .shutdown = usb_hcd_platform_shutdown, | 339 | .shutdown = usb_hcd_platform_shutdown, |
340 | /*.suspend = ohci_hcd_au1xxx_drv_suspend, */ | 340 | /*.suspend = ohci_hcd_au1xxx_drv_suspend, */ |
341 | /*.resume = ohci_hcd_au1xxx_drv_resume, */ | 341 | /*.resume = ohci_hcd_au1xxx_drv_resume, */ |
342 | .driver = { | 342 | .driver = { |
@@ -345,19 +345,3 @@ static struct platform_driver ohci_hcd_au1xxx_driver = { | |||
345 | }, | 345 | }, |
346 | }; | 346 | }; |
347 | 347 | ||
348 | static int __init ohci_hcd_au1xxx_init (void) | ||
349 | { | ||
350 | pr_debug (DRIVER_INFO " (Au1xxx)"); | ||
351 | pr_debug ("block sizes: ed %d td %d\n", | ||
352 | sizeof (struct ed), sizeof (struct td)); | ||
353 | |||
354 | return platform_driver_register(&ohci_hcd_au1xxx_driver); | ||
355 | } | ||
356 | |||
357 | static void __exit ohci_hcd_au1xxx_cleanup (void) | ||
358 | { | ||
359 | platform_driver_unregister(&ohci_hcd_au1xxx_driver); | ||
360 | } | ||
361 | |||
362 | module_init (ohci_hcd_au1xxx_init); | ||
363 | module_exit (ohci_hcd_au1xxx_cleanup); | ||
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 0f47a57dac28..273d5ddb72be 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c | |||
@@ -16,7 +16,7 @@ | |||
16 | case PIPE_CONTROL: temp = "ctrl"; break; \ | 16 | case PIPE_CONTROL: temp = "ctrl"; break; \ |
17 | case PIPE_BULK: temp = "bulk"; break; \ | 17 | case PIPE_BULK: temp = "bulk"; break; \ |
18 | case PIPE_INTERRUPT: temp = "intr"; break; \ | 18 | case PIPE_INTERRUPT: temp = "intr"; break; \ |
19 | default: temp = "isoc"; break; \ | 19 | default: temp = "isoc"; break; \ |
20 | }; temp;}) | 20 | }; temp;}) |
21 | #define pipestring(pipe) edstring(usb_pipetype(pipe)) | 21 | #define pipestring(pipe) edstring(usb_pipetype(pipe)) |
22 | 22 | ||
@@ -205,13 +205,13 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) | |||
205 | (temp & RH_PS_PSSC) ? " PSSC" : "", \ | 205 | (temp & RH_PS_PSSC) ? " PSSC" : "", \ |
206 | (temp & RH_PS_PESC) ? " PESC" : "", \ | 206 | (temp & RH_PS_PESC) ? " PESC" : "", \ |
207 | (temp & RH_PS_CSC) ? " CSC" : "", \ | 207 | (temp & RH_PS_CSC) ? " CSC" : "", \ |
208 | \ | 208 | \ |
209 | (temp & RH_PS_LSDA) ? " LSDA" : "", \ | 209 | (temp & RH_PS_LSDA) ? " LSDA" : "", \ |
210 | (temp & RH_PS_PPS) ? " PPS" : "", \ | 210 | (temp & RH_PS_PPS) ? " PPS" : "", \ |
211 | (temp & RH_PS_PRS) ? " PRS" : "", \ | 211 | (temp & RH_PS_PRS) ? " PRS" : "", \ |
212 | (temp & RH_PS_POCI) ? " POCI" : "", \ | 212 | (temp & RH_PS_POCI) ? " POCI" : "", \ |
213 | (temp & RH_PS_PSS) ? " PSS" : "", \ | 213 | (temp & RH_PS_PSS) ? " PSS" : "", \ |
214 | \ | 214 | \ |
215 | (temp & RH_PS_PES) ? " PES" : "", \ | 215 | (temp & RH_PS_PES) ? " PES" : "", \ |
216 | (temp & RH_PS_CCS) ? " CCS" : "" \ | 216 | (temp & RH_PS_CCS) ? " CCS" : "" \ |
217 | ); | 217 | ); |
@@ -563,7 +563,7 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
563 | (info & ED_SKIP) ? " K" : "", | 563 | (info & ED_SKIP) ? " K" : "", |
564 | (ed->hwHeadP & | 564 | (ed->hwHeadP & |
565 | cpu_to_hc32(ohci, ED_H)) ? | 565 | cpu_to_hc32(ohci, ED_H)) ? |
566 | " H" : ""); | 566 | " H" : ""); |
567 | size -= temp; | 567 | size -= temp; |
568 | next += temp; | 568 | next += temp; |
569 | 569 | ||
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 1bf5e7a4e735..44c60fba76e1 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c | |||
@@ -169,7 +169,7 @@ static int ohci_hcd_ep93xx_drv_remove(struct platform_device *pdev) | |||
169 | static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_t state) | 169 | static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_t state) |
170 | { | 170 | { |
171 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 171 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
172 | struct ochi_hcd *ohci = hcd_to_ohci(hcd); | 172 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); |
173 | 173 | ||
174 | if (time_before(jiffies, ohci->next_statechange)) | 174 | if (time_before(jiffies, ohci->next_statechange)) |
175 | msleep(5); | 175 | msleep(5); |
@@ -204,7 +204,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev) | |||
204 | static struct platform_driver ohci_hcd_ep93xx_driver = { | 204 | static struct platform_driver ohci_hcd_ep93xx_driver = { |
205 | .probe = ohci_hcd_ep93xx_drv_probe, | 205 | .probe = ohci_hcd_ep93xx_drv_probe, |
206 | .remove = ohci_hcd_ep93xx_drv_remove, | 206 | .remove = ohci_hcd_ep93xx_drv_remove, |
207 | .shutdown = usb_hcd_platform_shutdown, | 207 | .shutdown = usb_hcd_platform_shutdown, |
208 | #ifdef CONFIG_PM | 208 | #ifdef CONFIG_PM |
209 | .suspend = ohci_hcd_ep93xx_drv_suspend, | 209 | .suspend = ohci_hcd_ep93xx_drv_suspend, |
210 | .resume = ohci_hcd_ep93xx_drv_resume, | 210 | .resume = ohci_hcd_ep93xx_drv_resume, |
@@ -214,15 +214,3 @@ static struct platform_driver ohci_hcd_ep93xx_driver = { | |||
214 | }, | 214 | }, |
215 | }; | 215 | }; |
216 | 216 | ||
217 | static int __init ohci_hcd_ep93xx_init(void) | ||
218 | { | ||
219 | return platform_driver_register(&ohci_hcd_ep93xx_driver); | ||
220 | } | ||
221 | |||
222 | static void __exit ohci_hcd_ep93xx_cleanup(void) | ||
223 | { | ||
224 | platform_driver_unregister(&ohci_hcd_ep93xx_driver); | ||
225 | } | ||
226 | |||
227 | module_init(ohci_hcd_ep93xx_init); | ||
228 | module_exit(ohci_hcd_ep93xx_cleanup); | ||
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index b28a9b602066..fa6a7ceaa0db 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -3,77 +3,21 @@ | |||
3 | * | 3 | * |
4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | 4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> |
5 | * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net> | 5 | * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net> |
6 | * | 6 | * |
7 | * [ Initialisation is based on Linus' ] | 7 | * [ Initialisation is based on Linus' ] |
8 | * [ uhci code and gregs ohci fragments ] | 8 | * [ uhci code and gregs ohci fragments ] |
9 | * [ (C) Copyright 1999 Linus Torvalds ] | 9 | * [ (C) Copyright 1999 Linus Torvalds ] |
10 | * [ (C) Copyright 1999 Gregory P. Smith] | 10 | * [ (C) Copyright 1999 Gregory P. Smith] |
11 | * | 11 | * |
12 | * | 12 | * |
13 | * OHCI is the main "non-Intel/VIA" standard for USB 1.1 host controller | 13 | * OHCI is the main "non-Intel/VIA" standard for USB 1.1 host controller |
14 | * interfaces (though some non-x86 Intel chips use it). It supports | 14 | * interfaces (though some non-x86 Intel chips use it). It supports |
15 | * smarter hardware than UHCI. A download link for the spec available | 15 | * smarter hardware than UHCI. A download link for the spec available |
16 | * through the http://www.usb.org website. | 16 | * through the http://www.usb.org website. |
17 | * | 17 | * |
18 | * History: | ||
19 | * | ||
20 | * 2004/03/24 LH7A404 support (Durgesh Pattamatta & Marc Singer) | ||
21 | * 2004/02/04 use generic dma_* functions instead of pci_* (dsaxena@plexity.net) | ||
22 | * 2003/02/24 show registers in sysfs (Kevin Brosius) | ||
23 | * | ||
24 | * 2002/09/03 get rid of ed hashtables, rework periodic scheduling and | ||
25 | * bandwidth accounting; if debugging, show schedules in driverfs | ||
26 | * 2002/07/19 fixes to management of ED and schedule state. | ||
27 | * 2002/06/09 SA-1111 support (Christopher Hoover) | ||
28 | * 2002/06/01 remember frame when HC won't see EDs any more; use that info | ||
29 | * to fix urb unlink races caused by interrupt latency assumptions; | ||
30 | * minor ED field and function naming updates | ||
31 | * 2002/01/18 package as a patch for 2.5.3; this should match the | ||
32 | * 2.4.17 kernel modulo some bugs being fixed. | ||
33 | * | ||
34 | * 2001/10/18 merge pmac cleanup (Benjamin Herrenschmidt) and bugfixes | ||
35 | * from post-2.4.5 patches. | ||
36 | * 2001/09/20 URB_ZERO_PACKET support; hcca_dma portability, OPTi warning | ||
37 | * 2001/09/07 match PCI PM changes, errnos from Linus' tree | ||
38 | * 2001/05/05 fork 2.4.5 version into "hcd" framework, cleanup, simplify; | ||
39 | * pbook pci quirks gone (please fix pbook pci sw!) (db) | ||
40 | * | ||
41 | * 2001/04/08 Identify version on module load (gb) | ||
42 | * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam); | ||
43 | pci_map_single (db) | ||
44 | * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db) | ||
45 | * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam) | ||
46 | * | ||
47 | * 2000/09/26 fixed races in removing the private portion of the urb | ||
48 | * 2000/09/07 disable bulk and control lists when unlinking the last | ||
49 | * endpoint descriptor in order to avoid unrecoverable errors on | ||
50 | * the Lucent chips. (rwc@sgi) | ||
51 | * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some | ||
52 | * urb unlink probs, indentation fixes | ||
53 | * 2000/08/11 various oops fixes mostly affecting iso and cleanup from | ||
54 | * device unplugs. | ||
55 | * 2000/06/28 use PCI hotplug framework, for better power management | ||
56 | * and for Cardbus support (David Brownell) | ||
57 | * 2000/earlier: fixes for NEC/Lucent chips; suspend/resume handling | ||
58 | * when the controller loses power; handle UE; cleanup; ... | ||
59 | * | ||
60 | * v5.2 1999/12/07 URB 3rd preview, | ||
61 | * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi) | ||
62 | * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume | ||
63 | * i386: HUB, Keyboard, Mouse, Printer | ||
64 | * | ||
65 | * v4.3 1999/10/27 multiple HCs, bulk_request | ||
66 | * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes | ||
67 | * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl. | ||
68 | * v4.0 1999/08/18 | ||
69 | * v3.0 1999/06/25 | ||
70 | * v2.1 1999/05/09 code clean up | ||
71 | * v2.0 1999/05/04 | ||
72 | * v1.0 1999/04/27 initial release | ||
73 | * | ||
74 | * This file is licenced under the GPL. | 18 | * This file is licenced under the GPL. |
75 | */ | 19 | */ |
76 | 20 | ||
77 | #include <linux/module.h> | 21 | #include <linux/module.h> |
78 | #include <linux/moduleparam.h> | 22 | #include <linux/moduleparam.h> |
79 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
@@ -89,7 +33,7 @@ | |||
89 | #include <linux/list.h> | 33 | #include <linux/list.h> |
90 | #include <linux/usb.h> | 34 | #include <linux/usb.h> |
91 | #include <linux/usb/otg.h> | 35 | #include <linux/usb/otg.h> |
92 | #include <linux/dma-mapping.h> | 36 | #include <linux/dma-mapping.h> |
93 | #include <linux/dmapool.h> | 37 | #include <linux/dmapool.h> |
94 | #include <linux/reboot.h> | 38 | #include <linux/reboot.h> |
95 | 39 | ||
@@ -183,11 +127,11 @@ static int ohci_urb_enqueue ( | |||
183 | int i, size = 0; | 127 | int i, size = 0; |
184 | unsigned long flags; | 128 | unsigned long flags; |
185 | int retval = 0; | 129 | int retval = 0; |
186 | 130 | ||
187 | #ifdef OHCI_VERBOSE_DEBUG | 131 | #ifdef OHCI_VERBOSE_DEBUG |
188 | urb_print (urb, "SUB", usb_pipein (pipe)); | 132 | urb_print (urb, "SUB", usb_pipein (pipe)); |
189 | #endif | 133 | #endif |
190 | 134 | ||
191 | /* every endpoint has a ed, locate and maybe (re)initialize it */ | 135 | /* every endpoint has a ed, locate and maybe (re)initialize it */ |
192 | if (! (ed = ed_get (ohci, ep, urb->dev, pipe, urb->interval))) | 136 | if (! (ed = ed_get (ohci, ep, urb->dev, pipe, urb->interval))) |
193 | return -ENOMEM; | 137 | return -ENOMEM; |
@@ -232,7 +176,7 @@ static int ohci_urb_enqueue ( | |||
232 | memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *)); | 176 | memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *)); |
233 | INIT_LIST_HEAD (&urb_priv->pending); | 177 | INIT_LIST_HEAD (&urb_priv->pending); |
234 | urb_priv->length = size; | 178 | urb_priv->length = size; |
235 | urb_priv->ed = ed; | 179 | urb_priv->ed = ed; |
236 | 180 | ||
237 | /* allocate the TDs (deferring hash chain updates) */ | 181 | /* allocate the TDs (deferring hash chain updates) */ |
238 | for (i = 0; i < size; i++) { | 182 | for (i = 0; i < size; i++) { |
@@ -242,7 +186,7 @@ static int ohci_urb_enqueue ( | |||
242 | urb_free_priv (ohci, urb_priv); | 186 | urb_free_priv (ohci, urb_priv); |
243 | return -ENOMEM; | 187 | return -ENOMEM; |
244 | } | 188 | } |
245 | } | 189 | } |
246 | 190 | ||
247 | spin_lock_irqsave (&ohci->lock, flags); | 191 | spin_lock_irqsave (&ohci->lock, flags); |
248 | 192 | ||
@@ -313,13 +257,13 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | |||
313 | { | 257 | { |
314 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 258 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
315 | unsigned long flags; | 259 | unsigned long flags; |
316 | 260 | ||
317 | #ifdef OHCI_VERBOSE_DEBUG | 261 | #ifdef OHCI_VERBOSE_DEBUG |
318 | urb_print (urb, "UNLINK", 1); | 262 | urb_print (urb, "UNLINK", 1); |
319 | #endif | 263 | #endif |
320 | 264 | ||
321 | spin_lock_irqsave (&ohci->lock, flags); | 265 | spin_lock_irqsave (&ohci->lock, flags); |
322 | if (HC_IS_RUNNING(hcd->state)) { | 266 | if (HC_IS_RUNNING(hcd->state)) { |
323 | urb_priv_t *urb_priv; | 267 | urb_priv_t *urb_priv; |
324 | 268 | ||
325 | /* Unless an IRQ completed the unlink while it was being | 269 | /* Unless an IRQ completed the unlink while it was being |
@@ -512,11 +456,11 @@ static int ohci_init (struct ohci_hcd *ohci) | |||
512 | 456 | ||
513 | /* Start an OHCI controller, set the BUS operational | 457 | /* Start an OHCI controller, set the BUS operational |
514 | * resets USB and controller | 458 | * resets USB and controller |
515 | * enable interrupts | 459 | * enable interrupts |
516 | */ | 460 | */ |
517 | static int ohci_run (struct ohci_hcd *ohci) | 461 | static int ohci_run (struct ohci_hcd *ohci) |
518 | { | 462 | { |
519 | u32 mask, temp; | 463 | u32 mask, temp; |
520 | int first = ohci->fminterval == 0; | 464 | int first = ohci->fminterval == 0; |
521 | struct usb_hcd *hcd = ohci_to_hcd(ohci); | 465 | struct usb_hcd *hcd = ohci_to_hcd(ohci); |
522 | 466 | ||
@@ -534,7 +478,7 @@ static int ohci_run (struct ohci_hcd *ohci) | |||
534 | /* also: power/overcurrent flags in roothub.a */ | 478 | /* also: power/overcurrent flags in roothub.a */ |
535 | } | 479 | } |
536 | 480 | ||
537 | /* Reset USB nearly "by the book". RemoteWakeupConnected was | 481 | /* Reset USB nearly "by the book". RemoteWakeupConnected was |
538 | * saved if boot firmware (BIOS/SMM/...) told us it's connected, | 482 | * saved if boot firmware (BIOS/SMM/...) told us it's connected, |
539 | * or if bus glue did the same (e.g. for PCI add-in cards with | 483 | * or if bus glue did the same (e.g. for PCI add-in cards with |
540 | * PCI PM support). | 484 | * PCI PM support). |
@@ -765,9 +709,9 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) | |||
765 | dl_done_list (ohci); | 709 | dl_done_list (ohci); |
766 | spin_unlock (&ohci->lock); | 710 | spin_unlock (&ohci->lock); |
767 | if (HC_IS_RUNNING(hcd->state)) | 711 | if (HC_IS_RUNNING(hcd->state)) |
768 | ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrenable); | 712 | ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrenable); |
769 | } | 713 | } |
770 | 714 | ||
771 | /* could track INTR_SO to reduce available PCI/... bandwidth */ | 715 | /* could track INTR_SO to reduce available PCI/... bandwidth */ |
772 | 716 | ||
773 | /* handle any pending URB/ED unlinks, leaving INTR_SF enabled | 717 | /* handle any pending URB/ED unlinks, leaving INTR_SF enabled |
@@ -778,12 +722,12 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) | |||
778 | finish_unlinks (ohci, ohci_frame_no(ohci)); | 722 | finish_unlinks (ohci, ohci_frame_no(ohci)); |
779 | if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list | 723 | if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list |
780 | && HC_IS_RUNNING(hcd->state)) | 724 | && HC_IS_RUNNING(hcd->state)) |
781 | ohci_writel (ohci, OHCI_INTR_SF, ®s->intrdisable); | 725 | ohci_writel (ohci, OHCI_INTR_SF, ®s->intrdisable); |
782 | spin_unlock (&ohci->lock); | 726 | spin_unlock (&ohci->lock); |
783 | 727 | ||
784 | if (HC_IS_RUNNING(hcd->state)) { | 728 | if (HC_IS_RUNNING(hcd->state)) { |
785 | ohci_writel (ohci, ints, ®s->intrstatus); | 729 | ohci_writel (ohci, ints, ®s->intrstatus); |
786 | ohci_writel (ohci, OHCI_INTR_MIE, ®s->intrenable); | 730 | ohci_writel (ohci, OHCI_INTR_MIE, ®s->intrenable); |
787 | // flush those writes | 731 | // flush those writes |
788 | (void) ohci_readl (ohci, &ohci->regs->control); | 732 | (void) ohci_readl (ohci, &ohci->regs->control); |
789 | } | 733 | } |
@@ -794,7 +738,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) | |||
794 | /*-------------------------------------------------------------------------*/ | 738 | /*-------------------------------------------------------------------------*/ |
795 | 739 | ||
796 | static void ohci_stop (struct usb_hcd *hcd) | 740 | static void ohci_stop (struct usb_hcd *hcd) |
797 | { | 741 | { |
798 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 742 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
799 | 743 | ||
800 | ohci_dbg (ohci, "stop %s controller (state 0x%02x)\n", | 744 | ohci_dbg (ohci, "stop %s controller (state 0x%02x)\n", |
@@ -812,8 +756,8 @@ static void ohci_stop (struct usb_hcd *hcd) | |||
812 | remove_debug_files (ohci); | 756 | remove_debug_files (ohci); |
813 | ohci_mem_cleanup (ohci); | 757 | ohci_mem_cleanup (ohci); |
814 | if (ohci->hcca) { | 758 | if (ohci->hcca) { |
815 | dma_free_coherent (hcd->self.controller, | 759 | dma_free_coherent (hcd->self.controller, |
816 | sizeof *ohci->hcca, | 760 | sizeof *ohci->hcca, |
817 | ohci->hcca, ohci->hcca_dma); | 761 | ohci->hcca, ohci->hcca_dma); |
818 | ohci->hcca = NULL; | 762 | ohci->hcca = NULL; |
819 | ohci->hcca_dma = 0; | 763 | ohci->hcca_dma = 0; |
@@ -836,7 +780,7 @@ static int ohci_restart (struct ohci_hcd *ohci) | |||
836 | * recycle any "live" eds/tds (and urbs) right away. | 780 | * recycle any "live" eds/tds (and urbs) right away. |
837 | * later, khubd disconnect processing will recycle the other state, | 781 | * later, khubd disconnect processing will recycle the other state, |
838 | * (either as disconnect/reconnect, or maybe someday as a reset). | 782 | * (either as disconnect/reconnect, or maybe someday as a reset). |
839 | */ | 783 | */ |
840 | spin_lock_irq(&ohci->lock); | 784 | spin_lock_irq(&ohci->lock); |
841 | disable (ohci); | 785 | disable (ohci); |
842 | usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub); | 786 | usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub); |
@@ -875,11 +819,11 @@ static int ohci_restart (struct ohci_hcd *ohci) | |||
875 | /* empty the interrupt branches */ | 819 | /* empty the interrupt branches */ |
876 | for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0; | 820 | for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0; |
877 | for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0; | 821 | for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0; |
878 | 822 | ||
879 | /* no EDs to remove */ | 823 | /* no EDs to remove */ |
880 | ohci->ed_rm_list = NULL; | 824 | ohci->ed_rm_list = NULL; |
881 | 825 | ||
882 | /* empty control and bulk lists */ | 826 | /* empty control and bulk lists */ |
883 | ohci->ed_controltail = NULL; | 827 | ohci->ed_controltail = NULL; |
884 | ohci->ed_bulktail = NULL; | 828 | ohci->ed_bulktail = NULL; |
885 | 829 | ||
@@ -911,59 +855,167 @@ MODULE_LICENSE ("GPL"); | |||
911 | 855 | ||
912 | #ifdef CONFIG_PCI | 856 | #ifdef CONFIG_PCI |
913 | #include "ohci-pci.c" | 857 | #include "ohci-pci.c" |
858 | #define PCI_DRIVER ohci_pci_driver | ||
914 | #endif | 859 | #endif |
915 | 860 | ||
916 | #ifdef CONFIG_SA1111 | 861 | #ifdef CONFIG_SA1111 |
917 | #include "ohci-sa1111.c" | 862 | #include "ohci-sa1111.c" |
863 | #define SA1111_DRIVER ohci_hcd_sa1111_driver | ||
918 | #endif | 864 | #endif |
919 | 865 | ||
920 | #ifdef CONFIG_ARCH_S3C2410 | 866 | #ifdef CONFIG_ARCH_S3C2410 |
921 | #include "ohci-s3c2410.c" | 867 | #include "ohci-s3c2410.c" |
868 | #define PLATFORM_DRIVER ohci_hcd_s3c2410_driver | ||
922 | #endif | 869 | #endif |
923 | 870 | ||
924 | #ifdef CONFIG_ARCH_OMAP | 871 | #ifdef CONFIG_ARCH_OMAP |
925 | #include "ohci-omap.c" | 872 | #include "ohci-omap.c" |
873 | #define PLATFORM_DRIVER ohci_hcd_omap_driver | ||
926 | #endif | 874 | #endif |
927 | 875 | ||
928 | #ifdef CONFIG_ARCH_LH7A404 | 876 | #ifdef CONFIG_ARCH_LH7A404 |
929 | #include "ohci-lh7a404.c" | 877 | #include "ohci-lh7a404.c" |
878 | #define PLATFORM_DRIVER ohci_hcd_lh7a404_driver | ||
930 | #endif | 879 | #endif |
931 | 880 | ||
932 | #ifdef CONFIG_PXA27x | 881 | #ifdef CONFIG_PXA27x |
933 | #include "ohci-pxa27x.c" | 882 | #include "ohci-pxa27x.c" |
883 | #define PLATFORM_DRIVER ohci_hcd_pxa27x_driver | ||
934 | #endif | 884 | #endif |
935 | 885 | ||
936 | #ifdef CONFIG_ARCH_EP93XX | 886 | #ifdef CONFIG_ARCH_EP93XX |
937 | #include "ohci-ep93xx.c" | 887 | #include "ohci-ep93xx.c" |
888 | #define PLATFORM_DRIVER ohci_hcd_ep93xx_driver | ||
938 | #endif | 889 | #endif |
939 | 890 | ||
940 | #ifdef CONFIG_SOC_AU1X00 | 891 | #ifdef CONFIG_SOC_AU1X00 |
941 | #include "ohci-au1xxx.c" | 892 | #include "ohci-au1xxx.c" |
893 | #define PLATFORM_DRIVER ohci_hcd_au1xxx_driver | ||
894 | #endif | ||
895 | |||
896 | #ifdef CONFIG_PNX8550 | ||
897 | #include "ohci-pnx8550.c" | ||
898 | #define PLATFORM_DRIVER ohci_hcd_pnx8550_driver | ||
942 | #endif | 899 | #endif |
943 | 900 | ||
944 | #ifdef CONFIG_USB_OHCI_HCD_PPC_SOC | 901 | #ifdef CONFIG_USB_OHCI_HCD_PPC_SOC |
945 | #include "ohci-ppc-soc.c" | 902 | #include "ohci-ppc-soc.c" |
903 | #define PLATFORM_DRIVER ohci_hcd_ppc_soc_driver | ||
946 | #endif | 904 | #endif |
947 | 905 | ||
948 | #ifdef CONFIG_ARCH_AT91 | 906 | #ifdef CONFIG_ARCH_AT91 |
949 | #include "ohci-at91.c" | 907 | #include "ohci-at91.c" |
908 | #define PLATFORM_DRIVER ohci_hcd_at91_driver | ||
950 | #endif | 909 | #endif |
951 | 910 | ||
952 | #ifdef CONFIG_ARCH_PNX4008 | 911 | #ifdef CONFIG_ARCH_PNX4008 |
953 | #include "ohci-pnx4008.c" | 912 | #include "ohci-pnx4008.c" |
913 | #define PLATFORM_DRIVER usb_hcd_pnx4008_driver | ||
954 | #endif | 914 | #endif |
955 | 915 | ||
956 | #if !(defined(CONFIG_PCI) \ | 916 | |
957 | || defined(CONFIG_SA1111) \ | 917 | #ifdef CONFIG_USB_OHCI_HCD_PPC_OF |
958 | || defined(CONFIG_ARCH_S3C2410) \ | 918 | #include "ohci-ppc-of.c" |
959 | || defined(CONFIG_ARCH_OMAP) \ | 919 | #define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver |
960 | || defined (CONFIG_ARCH_LH7A404) \ | 920 | #endif |
961 | || defined (CONFIG_PXA27x) \ | 921 | |
962 | || defined (CONFIG_ARCH_EP93XX) \ | 922 | #ifdef CONFIG_PPC_PS3 |
963 | || defined (CONFIG_SOC_AU1X00) \ | 923 | #include "ohci-ps3.c" |
964 | || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ | 924 | #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_sb_driver |
965 | || defined (CONFIG_ARCH_AT91) \ | 925 | #endif |
966 | || defined (CONFIG_ARCH_PNX4008) \ | 926 | |
967 | ) | 927 | #if !defined(PCI_DRIVER) && \ |
928 | !defined(PLATFORM_DRIVER) && \ | ||
929 | !defined(OF_PLATFORM_DRIVER) && \ | ||
930 | !defined(SA1111_DRIVER) && \ | ||
931 | !defined(PS3_SYSTEM_BUS_DRIVER) | ||
968 | #error "missing bus glue for ohci-hcd" | 932 | #error "missing bus glue for ohci-hcd" |
969 | #endif | 933 | #endif |
934 | |||
935 | static int __init ohci_hcd_mod_init(void) | ||
936 | { | ||
937 | int retval = 0; | ||
938 | |||
939 | if (usb_disabled()) | ||
940 | return -ENODEV; | ||
941 | |||
942 | printk (KERN_DEBUG "%s: " DRIVER_INFO "\n", hcd_name); | ||
943 | pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, | ||
944 | sizeof (struct ed), sizeof (struct td)); | ||
945 | |||
946 | #ifdef PS3_SYSTEM_BUS_DRIVER | ||
947 | retval = ps3_system_bus_driver_register(&PS3_SYSTEM_BUS_DRIVER); | ||
948 | if (retval < 0) | ||
949 | goto error_ps3; | ||
950 | #endif | ||
951 | |||
952 | #ifdef PLATFORM_DRIVER | ||
953 | retval = platform_driver_register(&PLATFORM_DRIVER); | ||
954 | if (retval < 0) | ||
955 | goto error_platform; | ||
956 | #endif | ||
957 | |||
958 | #ifdef OF_PLATFORM_DRIVER | ||
959 | retval = of_register_platform_driver(&OF_PLATFORM_DRIVER); | ||
960 | if (retval < 0) | ||
961 | goto error_of_platform; | ||
962 | #endif | ||
963 | |||
964 | #ifdef SA1111_DRIVER | ||
965 | retval = sa1111_driver_register(&SA1111_DRIVER); | ||
966 | if (retval < 0) | ||
967 | goto error_sa1111; | ||
968 | #endif | ||
969 | |||
970 | #ifdef PCI_DRIVER | ||
971 | retval = pci_register_driver(&PCI_DRIVER); | ||
972 | if (retval < 0) | ||
973 | goto error_pci; | ||
974 | #endif | ||
975 | |||
976 | return retval; | ||
977 | |||
978 | /* Error path */ | ||
979 | #ifdef PCI_DRIVER | ||
980 | error_pci: | ||
981 | #endif | ||
982 | #ifdef SA1111_DRIVER | ||
983 | sa1111_driver_unregister(&SA1111_DRIVER); | ||
984 | error_sa1111: | ||
985 | #endif | ||
986 | #ifdef OF_PLATFORM_DRIVER | ||
987 | of_unregister_platform_driver(&OF_PLATFORM_DRIVER); | ||
988 | error_of_platform: | ||
989 | #endif | ||
990 | #ifdef PLATFORM_DRIVER | ||
991 | platform_driver_unregister(&PLATFORM_DRIVER); | ||
992 | error_platform: | ||
993 | #endif | ||
994 | #ifdef PS3_SYSTEM_BUS_DRIVER | ||
995 | ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | ||
996 | error_ps3: | ||
997 | #endif | ||
998 | return retval; | ||
999 | } | ||
1000 | module_init(ohci_hcd_mod_init); | ||
1001 | |||
1002 | static void __exit ohci_hcd_mod_exit(void) | ||
1003 | { | ||
1004 | #ifdef PCI_DRIVER | ||
1005 | pci_unregister_driver(&PCI_DRIVER); | ||
1006 | #endif | ||
1007 | #ifdef SA1111_DRIVER | ||
1008 | sa1111_driver_unregister(&SA1111_DRIVER); | ||
1009 | #endif | ||
1010 | #ifdef OF_PLATFORM_DRIVER | ||
1011 | of_unregister_platform_driver(&OF_PLATFORM_DRIVER); | ||
1012 | #endif | ||
1013 | #ifdef PLATFORM_DRIVER | ||
1014 | platform_driver_unregister(&PLATFORM_DRIVER); | ||
1015 | #endif | ||
1016 | #ifdef PS3_SYSTEM_BUS_DRIVER | ||
1017 | ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | ||
1018 | #endif | ||
1019 | } | ||
1020 | module_exit(ohci_hcd_mod_exit); | ||
1021 | |||
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 2441642cb7b4..216c9c9d4d6d 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * OHCI HCD (Host Controller Driver) for USB. | 2 | * OHCI HCD (Host Controller Driver) for USB. |
3 | * | 3 | * |
4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | 4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> |
5 | * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net> | 5 | * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net> |
6 | * | 6 | * |
7 | * This file is licenced under GPL | 7 | * This file is licenced under GPL |
8 | */ | 8 | */ |
9 | 9 | ||
@@ -23,13 +23,13 @@ | |||
23 | (temp & RH_PS_PSSC) ? " PSSC" : "", \ | 23 | (temp & RH_PS_PSSC) ? " PSSC" : "", \ |
24 | (temp & RH_PS_PESC) ? " PESC" : "", \ | 24 | (temp & RH_PS_PESC) ? " PESC" : "", \ |
25 | (temp & RH_PS_CSC) ? " CSC" : "", \ | 25 | (temp & RH_PS_CSC) ? " CSC" : "", \ |
26 | \ | 26 | \ |
27 | (temp & RH_PS_LSDA) ? " LSDA" : "", \ | 27 | (temp & RH_PS_LSDA) ? " LSDA" : "", \ |
28 | (temp & RH_PS_PPS) ? " PPS" : "", \ | 28 | (temp & RH_PS_PPS) ? " PPS" : "", \ |
29 | (temp & RH_PS_PRS) ? " PRS" : "", \ | 29 | (temp & RH_PS_PRS) ? " PRS" : "", \ |
30 | (temp & RH_PS_POCI) ? " POCI" : "", \ | 30 | (temp & RH_PS_POCI) ? " POCI" : "", \ |
31 | (temp & RH_PS_PSS) ? " PSS" : "", \ | 31 | (temp & RH_PS_PSS) ? " PSS" : "", \ |
32 | \ | 32 | \ |
33 | (temp & RH_PS_PES) ? " PES" : "", \ | 33 | (temp & RH_PS_PES) ? " PES" : "", \ |
34 | (temp & RH_PS_CCS) ? " CCS" : "" \ | 34 | (temp & RH_PS_CCS) ? " CCS" : "" \ |
35 | ); | 35 | ); |
@@ -484,7 +484,7 @@ ohci_hub_descriptor ( | |||
484 | temp = 0; | 484 | temp = 0; |
485 | if (rh & RH_A_NPS) /* no power switching? */ | 485 | if (rh & RH_A_NPS) /* no power switching? */ |
486 | temp |= 0x0002; | 486 | temp |= 0x0002; |
487 | if (rh & RH_A_PSM) /* per-port power switching? */ | 487 | if (rh & RH_A_PSM) /* per-port power switching? */ |
488 | temp |= 0x0001; | 488 | temp |= 0x0001; |
489 | if (rh & RH_A_NOCP) /* no overcurrent reporting? */ | 489 | if (rh & RH_A_NOCP) /* no overcurrent reporting? */ |
490 | temp |= 0x0010; | 490 | temp |= 0x0010; |
@@ -555,7 +555,7 @@ static void start_hnp(struct ohci_hcd *ohci); | |||
555 | #define tick_before(t1,t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0) | 555 | #define tick_before(t1,t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0) |
556 | 556 | ||
557 | /* called from some task, normally khubd */ | 557 | /* called from some task, normally khubd */ |
558 | static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port) | 558 | static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port) |
559 | { | 559 | { |
560 | __hc32 __iomem *portstat = &ohci->regs->roothub.portstatus [port]; | 560 | __hc32 __iomem *portstat = &ohci->regs->roothub.portstatus [port]; |
561 | u32 temp; | 561 | u32 temp; |
@@ -570,10 +570,13 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port) | |||
570 | /* spin until any current reset finishes */ | 570 | /* spin until any current reset finishes */ |
571 | for (;;) { | 571 | for (;;) { |
572 | temp = ohci_readl (ohci, portstat); | 572 | temp = ohci_readl (ohci, portstat); |
573 | /* handle e.g. CardBus eject */ | ||
574 | if (temp == ~(u32)0) | ||
575 | return -ESHUTDOWN; | ||
573 | if (!(temp & RH_PS_PRS)) | 576 | if (!(temp & RH_PS_PRS)) |
574 | break; | 577 | break; |
575 | udelay (500); | 578 | udelay (500); |
576 | } | 579 | } |
577 | 580 | ||
578 | if (!(temp & RH_PS_CCS)) | 581 | if (!(temp & RH_PS_CCS)) |
579 | break; | 582 | break; |
@@ -586,6 +589,8 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port) | |||
586 | now = ohci_readl(ohci, &ohci->regs->fmnumber); | 589 | now = ohci_readl(ohci, &ohci->regs->fmnumber); |
587 | } while (tick_before(now, reset_done)); | 590 | } while (tick_before(now, reset_done)); |
588 | /* caller synchronizes using PRSC */ | 591 | /* caller synchronizes using PRSC */ |
592 | |||
593 | return 0; | ||
589 | } | 594 | } |
590 | 595 | ||
591 | static int ohci_hub_control ( | 596 | static int ohci_hub_control ( |
@@ -702,7 +707,7 @@ static int ohci_hub_control ( | |||
702 | &ohci->regs->roothub.portstatus [wIndex]); | 707 | &ohci->regs->roothub.portstatus [wIndex]); |
703 | break; | 708 | break; |
704 | case USB_PORT_FEAT_RESET: | 709 | case USB_PORT_FEAT_RESET: |
705 | root_port_reset (ohci, wIndex); | 710 | retval = root_port_reset (ohci, wIndex); |
706 | break; | 711 | break; |
707 | default: | 712 | default: |
708 | goto error; | 713 | goto error; |
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index e121d97ed91c..4a043abd85ea 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c | |||
@@ -38,7 +38,7 @@ static void lh7a404_start_hc(struct platform_device *dev) | |||
38 | CSC_PWRCNT |= CSC_PWRCNT_USBH_EN; /* Enable clock */ | 38 | CSC_PWRCNT |= CSC_PWRCNT_USBH_EN; /* Enable clock */ |
39 | udelay(1000); | 39 | udelay(1000); |
40 | USBH_CMDSTATUS = OHCI_HCR; | 40 | USBH_CMDSTATUS = OHCI_HCR; |
41 | 41 | ||
42 | printk(KERN_DEBUG __FILE__ | 42 | printk(KERN_DEBUG __FILE__ |
43 | ": Clock to USB host has been enabled \n"); | 43 | ": Clock to USB host has been enabled \n"); |
44 | } | 44 | } |
@@ -89,7 +89,7 @@ int usb_hcd_lh7a404_probe (const struct hc_driver *driver, | |||
89 | retval = -EBUSY; | 89 | retval = -EBUSY; |
90 | goto err1; | 90 | goto err1; |
91 | } | 91 | } |
92 | 92 | ||
93 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | 93 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); |
94 | if (!hcd->regs) { | 94 | if (!hcd->regs) { |
95 | pr_debug("ioremap failed"); | 95 | pr_debug("ioremap failed"); |
@@ -174,7 +174,7 @@ static const struct hc_driver ohci_lh7a404_hc_driver = { | |||
174 | */ | 174 | */ |
175 | .start = ohci_lh7a404_start, | 175 | .start = ohci_lh7a404_start, |
176 | .stop = ohci_stop, | 176 | .stop = ohci_stop, |
177 | .shutdown = ohci_shutdown, | 177 | .shutdown = ohci_shutdown, |
178 | 178 | ||
179 | /* | 179 | /* |
180 | * managing i/o requests and associated device resources | 180 | * managing i/o requests and associated device resources |
@@ -242,7 +242,7 @@ static int ohci_hcd_lh7a404_drv_resume(struct platform_device *dev) | |||
242 | static struct platform_driver ohci_hcd_lh7a404_driver = { | 242 | static struct platform_driver ohci_hcd_lh7a404_driver = { |
243 | .probe = ohci_hcd_lh7a404_drv_probe, | 243 | .probe = ohci_hcd_lh7a404_drv_probe, |
244 | .remove = ohci_hcd_lh7a404_drv_remove, | 244 | .remove = ohci_hcd_lh7a404_drv_remove, |
245 | .shutdown = usb_hcd_platform_shutdown, | 245 | .shutdown = usb_hcd_platform_shutdown, |
246 | /*.suspend = ohci_hcd_lh7a404_drv_suspend, */ | 246 | /*.suspend = ohci_hcd_lh7a404_drv_suspend, */ |
247 | /*.resume = ohci_hcd_lh7a404_drv_resume, */ | 247 | /*.resume = ohci_hcd_lh7a404_drv_resume, */ |
248 | .driver = { | 248 | .driver = { |
@@ -251,19 +251,3 @@ static struct platform_driver ohci_hcd_lh7a404_driver = { | |||
251 | }, | 251 | }, |
252 | }; | 252 | }; |
253 | 253 | ||
254 | static int __init ohci_hcd_lh7a404_init (void) | ||
255 | { | ||
256 | pr_debug (DRIVER_INFO " (LH7A404)"); | ||
257 | pr_debug ("block sizes: ed %d td %d\n", | ||
258 | sizeof (struct ed), sizeof (struct td)); | ||
259 | |||
260 | return platform_driver_register(&ohci_hcd_lh7a404_driver); | ||
261 | } | ||
262 | |||
263 | static void __exit ohci_hcd_lh7a404_cleanup (void) | ||
264 | { | ||
265 | platform_driver_unregister(&ohci_hcd_lh7a404_driver); | ||
266 | } | ||
267 | |||
268 | module_init (ohci_hcd_lh7a404_init); | ||
269 | module_exit (ohci_hcd_lh7a404_cleanup); | ||
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index d976614eebd3..2f20d3dc895b 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c | |||
@@ -1,24 +1,24 @@ | |||
1 | /* | 1 | /* |
2 | * OHCI HCD (Host Controller Driver) for USB. | 2 | * OHCI HCD (Host Controller Driver) for USB. |
3 | * | 3 | * |
4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | 4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> |
5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> | 5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> |
6 | * | 6 | * |
7 | * This file is licenced under the GPL. | 7 | * This file is licenced under the GPL. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | /*-------------------------------------------------------------------------*/ | 10 | /*-------------------------------------------------------------------------*/ |
11 | 11 | ||
12 | /* | 12 | /* |
13 | * There's basically three types of memory: | 13 | * OHCI deals with three types of memory: |
14 | * - data used only by the HCD ... kmalloc is fine | 14 | * - data used only by the HCD ... kmalloc is fine |
15 | * - async and periodic schedules, shared by HC and HCD ... these | 15 | * - async and periodic schedules, shared by HC and HCD ... these |
16 | * need to use dma_pool or dma_alloc_coherent | 16 | * need to use dma_pool or dma_alloc_coherent |
17 | * - driver buffers, read/written by HC ... the hcd glue or the | 17 | * - driver buffers, read/written by HC ... the hcd glue or the |
18 | * device driver provides us with dma addresses | 18 | * device driver provides us with dma addresses |
19 | * | 19 | * |
20 | * There's also PCI "register" data, which is memory mapped. | 20 | * There's also "register" data, which is memory mapped. |
21 | * No memory seen by this driver is pagable. | 21 | * No memory seen by this driver (or any HCD) may be paged out. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | /*-------------------------------------------------------------------------*/ | 24 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 9c02177de50a..5cfa3d1c4413 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c | |||
@@ -447,7 +447,7 @@ static const struct hc_driver ohci_omap_hc_driver = { | |||
447 | .reset = ohci_omap_init, | 447 | .reset = ohci_omap_init, |
448 | .start = ohci_omap_start, | 448 | .start = ohci_omap_start, |
449 | .stop = ohci_omap_stop, | 449 | .stop = ohci_omap_stop, |
450 | .shutdown = ohci_shutdown, | 450 | .shutdown = ohci_shutdown, |
451 | 451 | ||
452 | /* | 452 | /* |
453 | * managing i/o requests and associated device resources | 453 | * managing i/o requests and associated device resources |
@@ -533,7 +533,7 @@ static int ohci_omap_resume(struct platform_device *dev) | |||
533 | static struct platform_driver ohci_hcd_omap_driver = { | 533 | static struct platform_driver ohci_hcd_omap_driver = { |
534 | .probe = ohci_hcd_omap_drv_probe, | 534 | .probe = ohci_hcd_omap_drv_probe, |
535 | .remove = ohci_hcd_omap_drv_remove, | 535 | .remove = ohci_hcd_omap_drv_remove, |
536 | .shutdown = usb_hcd_platform_shutdown, | 536 | .shutdown = usb_hcd_platform_shutdown, |
537 | #ifdef CONFIG_PM | 537 | #ifdef CONFIG_PM |
538 | .suspend = ohci_omap_suspend, | 538 | .suspend = ohci_omap_suspend, |
539 | .resume = ohci_omap_resume, | 539 | .resume = ohci_omap_resume, |
@@ -544,22 +544,3 @@ static struct platform_driver ohci_hcd_omap_driver = { | |||
544 | }, | 544 | }, |
545 | }; | 545 | }; |
546 | 546 | ||
547 | static int __init ohci_hcd_omap_init (void) | ||
548 | { | ||
549 | printk (KERN_DEBUG "%s: " DRIVER_INFO " (OMAP)\n", hcd_name); | ||
550 | if (usb_disabled()) | ||
551 | return -ENODEV; | ||
552 | |||
553 | pr_debug("%s: block sizes: ed %Zd td %Zd\n", hcd_name, | ||
554 | sizeof (struct ed), sizeof (struct td)); | ||
555 | |||
556 | return platform_driver_register(&ohci_hcd_omap_driver); | ||
557 | } | ||
558 | |||
559 | static void __exit ohci_hcd_omap_cleanup (void) | ||
560 | { | ||
561 | platform_driver_unregister(&ohci_hcd_omap_driver); | ||
562 | } | ||
563 | |||
564 | module_init (ohci_hcd_omap_init); | ||
565 | module_exit (ohci_hcd_omap_cleanup); | ||
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 874418552789..b331ac4d0d62 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -3,96 +3,171 @@ | |||
3 | * | 3 | * |
4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | 4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> |
5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> | 5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> |
6 | * | 6 | * |
7 | * [ Initialisation is based on Linus' ] | 7 | * [ Initialisation is based on Linus' ] |
8 | * [ uhci code and gregs ohci fragments ] | 8 | * [ uhci code and gregs ohci fragments ] |
9 | * [ (C) Copyright 1999 Linus Torvalds ] | 9 | * [ (C) Copyright 1999 Linus Torvalds ] |
10 | * [ (C) Copyright 1999 Gregory P. Smith] | 10 | * [ (C) Copyright 1999 Gregory P. Smith] |
11 | * | 11 | * |
12 | * PCI Bus Glue | 12 | * PCI Bus Glue |
13 | * | 13 | * |
14 | * This file is licenced under the GPL. | 14 | * This file is licenced under the GPL. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef CONFIG_PCI | 17 | #ifndef CONFIG_PCI |
18 | #error "This file is PCI bus glue. CONFIG_PCI must be defined." | 18 | #error "This file is PCI bus glue. CONFIG_PCI must be defined." |
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | /*-------------------------------------------------------------------------*/ | 21 | /*-------------------------------------------------------------------------*/ |
22 | 22 | ||
23 | static int | 23 | /* AMD 756, for most chips (early revs), corrupts register |
24 | ohci_pci_reset (struct usb_hcd *hcd) | 24 | * values on read ... so enable the vendor workaround. |
25 | */ | ||
26 | static int __devinit ohci_quirk_amd756(struct usb_hcd *hcd) | ||
25 | { | 27 | { |
26 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 28 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
27 | 29 | ||
28 | ohci_hcd_init (ohci); | 30 | ohci->flags = OHCI_QUIRK_AMD756; |
29 | return ohci_init (ohci); | 31 | ohci_dbg (ohci, "AMD756 erratum 4 workaround\n"); |
32 | |||
33 | /* also erratum 10 (suspend/resume issues) */ | ||
34 | device_init_wakeup(&hcd->self.root_hub->dev, 0); | ||
35 | |||
36 | return 0; | ||
30 | } | 37 | } |
31 | 38 | ||
32 | static int __devinit | 39 | /* Apple's OHCI driver has a lot of bizarre workarounds |
33 | ohci_pci_start (struct usb_hcd *hcd) | 40 | * for this chip. Evidently control and bulk lists |
41 | * can get confused. (B&W G3 models, and ...) | ||
42 | */ | ||
43 | static int __devinit ohci_quirk_opti(struct usb_hcd *hcd) | ||
34 | { | 44 | { |
35 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 45 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
36 | int ret; | ||
37 | 46 | ||
38 | /* REVISIT this whole block should move to reset(), which handles | 47 | ohci_dbg (ohci, "WARNING: OPTi workarounds unavailable\n"); |
39 | * all the other one-time init. | 48 | |
49 | return 0; | ||
50 | } | ||
51 | |||
52 | /* Check for NSC87560. We have to look at the bridge (fn1) to | ||
53 | * identify the USB (fn2). This quirk might apply to more or | ||
54 | * even all NSC stuff. | ||
55 | */ | ||
56 | static int __devinit ohci_quirk_ns(struct usb_hcd *hcd) | ||
57 | { | ||
58 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | ||
59 | struct pci_dev *b; | ||
60 | |||
61 | b = pci_get_slot (pdev->bus, PCI_DEVFN (PCI_SLOT (pdev->devfn), 1)); | ||
62 | if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO | ||
63 | && b->vendor == PCI_VENDOR_ID_NS) { | ||
64 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
65 | |||
66 | ohci->flags |= OHCI_QUIRK_SUPERIO; | ||
67 | ohci_dbg (ohci, "Using NSC SuperIO setup\n"); | ||
68 | } | ||
69 | pci_dev_put(b); | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | /* Check for Compaq's ZFMicro chipset, which needs short | ||
75 | * delays before control or bulk queues get re-activated | ||
76 | * in finish_unlinks() | ||
77 | */ | ||
78 | static int __devinit ohci_quirk_zfmicro(struct usb_hcd *hcd) | ||
79 | { | ||
80 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
81 | |||
82 | ohci->flags |= OHCI_QUIRK_ZFMICRO; | ||
83 | ohci_dbg (ohci, "enabled Compaq ZFMicro chipset quirk\n"); | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | /* Check for Toshiba SCC OHCI which has big endian registers | ||
89 | * and little endian in memory data structures | ||
90 | */ | ||
91 | static int __devinit ohci_quirk_toshiba_scc(struct usb_hcd *hcd) | ||
92 | { | ||
93 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
94 | |||
95 | /* That chip is only present in the southbridge of some | ||
96 | * cell based platforms which are supposed to select | ||
97 | * CONFIG_USB_OHCI_BIG_ENDIAN_MMIO. We verify here if | ||
98 | * that was the case though. | ||
40 | */ | 99 | */ |
100 | #ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO | ||
101 | ohci->flags |= OHCI_QUIRK_BE_MMIO; | ||
102 | ohci_dbg (ohci, "enabled big endian Toshiba quirk\n"); | ||
103 | return 0; | ||
104 | #else | ||
105 | ohci_err (ohci, "unsupported big endian Toshiba quirk\n"); | ||
106 | return -ENXIO; | ||
107 | #endif | ||
108 | } | ||
109 | |||
110 | /* List of quirks for OHCI */ | ||
111 | static const struct pci_device_id ohci_pci_quirks[] = { | ||
112 | { | ||
113 | PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x740c), | ||
114 | .driver_data = (unsigned long)ohci_quirk_amd756, | ||
115 | }, | ||
116 | { | ||
117 | PCI_DEVICE(PCI_VENDOR_ID_OPTI, 0xc861), | ||
118 | .driver_data = (unsigned long)ohci_quirk_opti, | ||
119 | }, | ||
120 | { | ||
121 | PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_ANY_ID), | ||
122 | .driver_data = (unsigned long)ohci_quirk_ns, | ||
123 | }, | ||
124 | { | ||
125 | PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xa0f8), | ||
126 | .driver_data = (unsigned long)ohci_quirk_zfmicro, | ||
127 | }, | ||
128 | { | ||
129 | PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, 0x01b6), | ||
130 | .driver_data = (unsigned long)ohci_quirk_toshiba_scc, | ||
131 | }, | ||
132 | /* FIXME for some of the early AMD 760 southbridges, OHCI | ||
133 | * won't work at all. blacklist them. | ||
134 | */ | ||
135 | |||
136 | {}, | ||
137 | }; | ||
138 | |||
139 | static int ohci_pci_reset (struct usb_hcd *hcd) | ||
140 | { | ||
141 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
142 | int ret = 0; | ||
143 | |||
41 | if (hcd->self.controller) { | 144 | if (hcd->self.controller) { |
42 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | 145 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); |
146 | const struct pci_device_id *quirk_id; | ||
43 | 147 | ||
44 | /* AMD 756, for most chips (early revs), corrupts register | 148 | quirk_id = pci_match_id(ohci_pci_quirks, pdev); |
45 | * values on read ... so enable the vendor workaround. | 149 | if (quirk_id != NULL) { |
46 | */ | 150 | int (*quirk)(struct usb_hcd *ohci); |
47 | if (pdev->vendor == PCI_VENDOR_ID_AMD | 151 | quirk = (void *)quirk_id->driver_data; |
48 | && pdev->device == 0x740c) { | 152 | ret = quirk(hcd); |
49 | ohci->flags = OHCI_QUIRK_AMD756; | ||
50 | ohci_dbg (ohci, "AMD756 erratum 4 workaround\n"); | ||
51 | /* also erratum 10 (suspend/resume issues) */ | ||
52 | device_init_wakeup(&hcd->self.root_hub->dev, 0); | ||
53 | } | 153 | } |
154 | } | ||
155 | if (ret == 0) { | ||
156 | ohci_hcd_init (ohci); | ||
157 | return ohci_init (ohci); | ||
158 | } | ||
159 | return ret; | ||
160 | } | ||
54 | 161 | ||
55 | /* FIXME for some of the early AMD 760 southbridges, OHCI | ||
56 | * won't work at all. blacklist them. | ||
57 | */ | ||
58 | |||
59 | /* Apple's OHCI driver has a lot of bizarre workarounds | ||
60 | * for this chip. Evidently control and bulk lists | ||
61 | * can get confused. (B&W G3 models, and ...) | ||
62 | */ | ||
63 | else if (pdev->vendor == PCI_VENDOR_ID_OPTI | ||
64 | && pdev->device == 0xc861) { | ||
65 | ohci_dbg (ohci, | ||
66 | "WARNING: OPTi workarounds unavailable\n"); | ||
67 | } | ||
68 | 162 | ||
69 | /* Check for NSC87560. We have to look at the bridge (fn1) to | 163 | static int __devinit ohci_pci_start (struct usb_hcd *hcd) |
70 | * identify the USB (fn2). This quirk might apply to more or | 164 | { |
71 | * even all NSC stuff. | 165 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
72 | */ | 166 | int ret; |
73 | else if (pdev->vendor == PCI_VENDOR_ID_NS) { | ||
74 | struct pci_dev *b; | ||
75 | |||
76 | b = pci_get_slot (pdev->bus, | ||
77 | PCI_DEVFN (PCI_SLOT (pdev->devfn), 1)); | ||
78 | if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO | ||
79 | && b->vendor == PCI_VENDOR_ID_NS) { | ||
80 | ohci->flags |= OHCI_QUIRK_SUPERIO; | ||
81 | ohci_dbg (ohci, "Using NSC SuperIO setup\n"); | ||
82 | } | ||
83 | pci_dev_put(b); | ||
84 | } | ||
85 | 167 | ||
86 | /* Check for Compaq's ZFMicro chipset, which needs short | 168 | #ifdef CONFIG_PM /* avoid warnings about unused pdev */ |
87 | * delays before control or bulk queues get re-activated | 169 | if (hcd->self.controller) { |
88 | * in finish_unlinks() | 170 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); |
89 | */ | ||
90 | else if (pdev->vendor == PCI_VENDOR_ID_COMPAQ | ||
91 | && pdev->device == 0xa0f8) { | ||
92 | ohci->flags |= OHCI_QUIRK_ZFMICRO; | ||
93 | ohci_dbg (ohci, | ||
94 | "enabled Compaq ZFMicro chipset quirk\n"); | ||
95 | } | ||
96 | 171 | ||
97 | /* RWC may not be set for add-in PCI cards, since boot | 172 | /* RWC may not be set for add-in PCI cards, since boot |
98 | * firmware probably ignored them. This transfers PCI | 173 | * firmware probably ignored them. This transfers PCI |
@@ -101,16 +176,14 @@ ohci_pci_start (struct usb_hcd *hcd) | |||
101 | if (device_may_wakeup(&pdev->dev)) | 176 | if (device_may_wakeup(&pdev->dev)) |
102 | ohci->hc_control |= OHCI_CTRL_RWC; | 177 | ohci->hc_control |= OHCI_CTRL_RWC; |
103 | } | 178 | } |
179 | #endif /* CONFIG_PM */ | ||
104 | 180 | ||
105 | /* NOTE: there may have already been a first reset, to | 181 | ret = ohci_run (ohci); |
106 | * keep bios/smm irqs from making trouble | 182 | if (ret < 0) { |
107 | */ | ||
108 | if ((ret = ohci_run (ohci)) < 0) { | ||
109 | ohci_err (ohci, "can't start\n"); | 183 | ohci_err (ohci, "can't start\n"); |
110 | ohci_stop (hcd); | 184 | ohci_stop (hcd); |
111 | return ret; | ||
112 | } | 185 | } |
113 | return 0; | 186 | return ret; |
114 | } | 187 | } |
115 | 188 | ||
116 | #ifdef CONFIG_PM | 189 | #ifdef CONFIG_PM |
@@ -238,23 +311,3 @@ static struct pci_driver ohci_pci_driver = { | |||
238 | .shutdown = usb_hcd_pci_shutdown, | 311 | .shutdown = usb_hcd_pci_shutdown, |
239 | }; | 312 | }; |
240 | 313 | ||
241 | |||
242 | static int __init ohci_hcd_pci_init (void) | ||
243 | { | ||
244 | printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name); | ||
245 | if (usb_disabled()) | ||
246 | return -ENODEV; | ||
247 | |||
248 | pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, | ||
249 | sizeof (struct ed), sizeof (struct td)); | ||
250 | return pci_register_driver (&ohci_pci_driver); | ||
251 | } | ||
252 | module_init (ohci_hcd_pci_init); | ||
253 | |||
254 | /*-------------------------------------------------------------------------*/ | ||
255 | |||
256 | static void __exit ohci_hcd_pci_cleanup (void) | ||
257 | { | ||
258 | pci_unregister_driver (&ohci_pci_driver); | ||
259 | } | ||
260 | module_exit (ohci_hcd_pci_cleanup); | ||
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index 7f26f9bdbaf1..893b172384da 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * driver for Philips PNX4008 USB Host | 4 | * driver for Philips PNX4008 USB Host |
5 | * | 5 | * |
6 | * Authors: Dmitry Chigirev <source@mvista.com> | 6 | * Authors: Dmitry Chigirev <source@mvista.com> |
7 | * Vitaly Wool <vitalywool@gmail.com> | 7 | * Vitaly Wool <vitalywool@gmail.com> |
8 | * | 8 | * |
9 | * register initialization is based on code examples provided by Philips | 9 | * register initialization is based on code examples provided by Philips |
10 | * Copyright (c) 2005 Koninklijke Philips Electronics N.V. | 10 | * Copyright (c) 2005 Koninklijke Philips Electronics N.V. |
@@ -29,7 +29,7 @@ | |||
29 | #include <asm/arch/irqs.h> | 29 | #include <asm/arch/irqs.h> |
30 | #include <asm/arch/gpio.h> | 30 | #include <asm/arch/gpio.h> |
31 | 31 | ||
32 | #define USB_CTRL IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64) | 32 | #define USB_CTRL IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64) |
33 | 33 | ||
34 | /* USB_CTRL bit defines */ | 34 | /* USB_CTRL bit defines */ |
35 | #define USB_SLAVE_HCLK_EN (1 << 24) | 35 | #define USB_SLAVE_HCLK_EN (1 << 24) |
@@ -465,15 +465,3 @@ static struct platform_driver usb_hcd_pnx4008_driver = { | |||
465 | .remove = usb_hcd_pnx4008_remove, | 465 | .remove = usb_hcd_pnx4008_remove, |
466 | }; | 466 | }; |
467 | 467 | ||
468 | static int __init usb_hcd_pnx4008_init(void) | ||
469 | { | ||
470 | return platform_driver_register(&usb_hcd_pnx4008_driver); | ||
471 | } | ||
472 | |||
473 | static void __exit usb_hcd_pnx4008_cleanup(void) | ||
474 | { | ||
475 | return platform_driver_unregister(&usb_hcd_pnx4008_driver); | ||
476 | } | ||
477 | |||
478 | module_init(usb_hcd_pnx4008_init); | ||
479 | module_exit(usb_hcd_pnx4008_cleanup); | ||
diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c new file mode 100644 index 000000000000..de45eb0051a7 --- /dev/null +++ b/drivers/usb/host/ohci-pnx8550.c | |||
@@ -0,0 +1,242 @@ | |||
1 | /* | ||
2 | * OHCI HCD (Host Controller Driver) for USB. | ||
3 | * | ||
4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | ||
5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> | ||
6 | * (C) Copyright 2002 Hewlett-Packard Company | ||
7 | * (C) Copyright 2005 Embedded Alley Solutions, Inc. | ||
8 | * | ||
9 | * Bus Glue for PNX8550 | ||
10 | * | ||
11 | * Written by Christopher Hoover <ch@hpl.hp.com> | ||
12 | * Based on fragments of previous driver by Russell King et al. | ||
13 | * | ||
14 | * Modified for LH7A404 from ohci-sa1111.c | ||
15 | * by Durgesh Pattamatta <pattamattad@sharpsec.com> | ||
16 | * | ||
17 | * Modified for PNX8550 from ohci-sa1111.c and sa-omap.c | ||
18 | * by Vitaly Wool <vitalywool@gmail.com> | ||
19 | * | ||
20 | * This file is licenced under the GPL. | ||
21 | */ | ||
22 | |||
23 | #include <linux/device.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <asm/mach-pnx8550/usb.h> | ||
26 | #include <asm/mach-pnx8550/int.h> | ||
27 | #include <asm/mach-pnx8550/pci.h> | ||
28 | |||
29 | #ifndef CONFIG_PNX8550 | ||
30 | #error "This file is PNX8550 bus glue. CONFIG_PNX8550 must be defined." | ||
31 | #endif | ||
32 | |||
33 | extern int usb_disabled(void); | ||
34 | |||
35 | /*-------------------------------------------------------------------------*/ | ||
36 | |||
37 | static void pnx8550_start_hc(struct platform_device *dev) | ||
38 | { | ||
39 | /* | ||
40 | * Set register CLK48CTL to enable and 48MHz | ||
41 | */ | ||
42 | outl(0x00000003, PCI_BASE | 0x0004770c); | ||
43 | |||
44 | /* | ||
45 | * Set register CLK12CTL to enable and 48MHz | ||
46 | */ | ||
47 | outl(0x00000003, PCI_BASE | 0x00047710); | ||
48 | |||
49 | udelay(100); | ||
50 | } | ||
51 | |||
52 | static void pnx8550_stop_hc(struct platform_device *dev) | ||
53 | { | ||
54 | udelay(10); | ||
55 | } | ||
56 | |||
57 | |||
58 | /*-------------------------------------------------------------------------*/ | ||
59 | |||
60 | /* configure so an HC device and id are always provided */ | ||
61 | /* always called with process context; sleeping is OK */ | ||
62 | |||
63 | |||
64 | /** | ||
65 | * usb_hcd_pnx8550_probe - initialize pnx8550-based HCDs | ||
66 | * Context: !in_interrupt() | ||
67 | * | ||
68 | * Allocates basic resources for this USB host controller, and | ||
69 | * then invokes the start() method for the HCD associated with it | ||
70 | * through the hotplug entry's driver_data. | ||
71 | * | ||
72 | */ | ||
73 | int usb_hcd_pnx8550_probe (const struct hc_driver *driver, | ||
74 | struct platform_device *dev) | ||
75 | { | ||
76 | int retval; | ||
77 | struct usb_hcd *hcd; | ||
78 | |||
79 | if (dev->resource[0].flags != IORESOURCE_MEM || | ||
80 | dev->resource[1].flags != IORESOURCE_IRQ) { | ||
81 | dev_err (&dev->dev,"invalid resource type\n"); | ||
82 | return -ENOMEM; | ||
83 | } | ||
84 | |||
85 | hcd = usb_create_hcd (driver, &dev->dev, "pnx8550"); | ||
86 | if (!hcd) | ||
87 | return -ENOMEM; | ||
88 | hcd->rsrc_start = dev->resource[0].start; | ||
89 | hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; | ||
90 | |||
91 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
92 | dev_err(&dev->dev, "request_mem_region [0x%08llx, 0x%08llx] " | ||
93 | "failed\n", hcd->rsrc_start, hcd->rsrc_len); | ||
94 | retval = -EBUSY; | ||
95 | goto err1; | ||
96 | } | ||
97 | |||
98 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
99 | if (!hcd->regs) { | ||
100 | dev_err(&dev->dev, "ioremap [[0x%08llx, 0x%08llx] failed\n", | ||
101 | hcd->rsrc_start, hcd->rsrc_len); | ||
102 | retval = -ENOMEM; | ||
103 | goto err2; | ||
104 | } | ||
105 | |||
106 | pnx8550_start_hc(dev); | ||
107 | |||
108 | ohci_hcd_init(hcd_to_ohci(hcd)); | ||
109 | |||
110 | retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT); | ||
111 | if (retval == 0) | ||
112 | return retval; | ||
113 | |||
114 | pnx8550_stop_hc(dev); | ||
115 | iounmap(hcd->regs); | ||
116 | err2: | ||
117 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
118 | err1: | ||
119 | usb_put_hcd(hcd); | ||
120 | return retval; | ||
121 | } | ||
122 | |||
123 | |||
124 | /* may be called without controller electrically present */ | ||
125 | /* may be called with controller, bus, and devices active */ | ||
126 | |||
127 | /** | ||
128 | * usb_hcd_pnx8550_remove - shutdown processing for pnx8550-based HCDs | ||
129 | * @dev: USB Host Controller being removed | ||
130 | * Context: !in_interrupt() | ||
131 | * | ||
132 | * Reverses the effect of usb_hcd_pnx8550_probe(), first invoking | ||
133 | * the HCD's stop() method. It is always called from a thread | ||
134 | * context, normally "rmmod", "apmd", or something similar. | ||
135 | * | ||
136 | */ | ||
137 | void usb_hcd_pnx8550_remove (struct usb_hcd *hcd, struct platform_device *dev) | ||
138 | { | ||
139 | usb_remove_hcd(hcd); | ||
140 | pnx8550_stop_hc(dev); | ||
141 | iounmap(hcd->regs); | ||
142 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
143 | usb_put_hcd(hcd); | ||
144 | } | ||
145 | |||
146 | /*-------------------------------------------------------------------------*/ | ||
147 | |||
148 | static int __devinit | ||
149 | ohci_pnx8550_start (struct usb_hcd *hcd) | ||
150 | { | ||
151 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
152 | int ret; | ||
153 | |||
154 | ohci_dbg (ohci, "ohci_pnx8550_start, ohci:%p", ohci); | ||
155 | |||
156 | if ((ret = ohci_init(ohci)) < 0) | ||
157 | return ret; | ||
158 | |||
159 | if ((ret = ohci_run (ohci)) < 0) { | ||
160 | err ("can't start %s", hcd->self.bus_name); | ||
161 | ohci_stop (hcd); | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | /*-------------------------------------------------------------------------*/ | ||
169 | |||
170 | static const struct hc_driver ohci_pnx8550_hc_driver = { | ||
171 | .description = hcd_name, | ||
172 | .product_desc = "PNX8550 OHCI", | ||
173 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
174 | |||
175 | /* | ||
176 | * generic hardware linkage | ||
177 | */ | ||
178 | .irq = ohci_irq, | ||
179 | .flags = HCD_USB11 | HCD_MEMORY, | ||
180 | |||
181 | /* | ||
182 | * basic lifecycle operations | ||
183 | */ | ||
184 | .start = ohci_pnx8550_start, | ||
185 | .stop = ohci_stop, | ||
186 | |||
187 | /* | ||
188 | * managing i/o requests and associated device resources | ||
189 | */ | ||
190 | .urb_enqueue = ohci_urb_enqueue, | ||
191 | .urb_dequeue = ohci_urb_dequeue, | ||
192 | .endpoint_disable = ohci_endpoint_disable, | ||
193 | |||
194 | /* | ||
195 | * scheduling support | ||
196 | */ | ||
197 | .get_frame_number = ohci_get_frame, | ||
198 | |||
199 | /* | ||
200 | * root hub support | ||
201 | */ | ||
202 | .hub_status_data = ohci_hub_status_data, | ||
203 | .hub_control = ohci_hub_control, | ||
204 | .hub_irq_enable = ohci_rhsc_enable, | ||
205 | #ifdef CONFIG_PM | ||
206 | .bus_suspend = ohci_bus_suspend, | ||
207 | .bus_resume = ohci_bus_resume, | ||
208 | #endif | ||
209 | .start_port_reset = ohci_start_port_reset, | ||
210 | }; | ||
211 | |||
212 | /*-------------------------------------------------------------------------*/ | ||
213 | |||
214 | static int ohci_hcd_pnx8550_drv_probe(struct platform_device *pdev) | ||
215 | { | ||
216 | int ret; | ||
217 | |||
218 | if (usb_disabled()) | ||
219 | return -ENODEV; | ||
220 | |||
221 | ret = usb_hcd_pnx8550_probe(&ohci_pnx8550_hc_driver, pdev); | ||
222 | return ret; | ||
223 | } | ||
224 | |||
225 | static int ohci_hcd_pnx8550_drv_remove(struct platform_device *pdev) | ||
226 | { | ||
227 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
228 | |||
229 | usb_hcd_pnx8550_remove(hcd, pdev); | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | MODULE_ALIAS("pnx8550-ohci"); | ||
234 | |||
235 | static struct platform_driver ohci_hcd_pnx8550_driver = { | ||
236 | .driver = { | ||
237 | .name = "pnx8550-ohci", | ||
238 | }, | ||
239 | .probe = ohci_hcd_pnx8550_drv_probe, | ||
240 | .remove = ohci_hcd_pnx8550_drv_remove, | ||
241 | }; | ||
242 | |||
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c new file mode 100644 index 000000000000..08e237c7bc43 --- /dev/null +++ b/drivers/usb/host/ohci-ppc-of.c | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * OHCI HCD (Host Controller Driver) for USB. | ||
3 | * | ||
4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | ||
5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> | ||
6 | * (C) Copyright 2002 Hewlett-Packard Company | ||
7 | * (C) Copyright 2006 Sylvain Munaut <tnt@246tNt.com> | ||
8 | * | ||
9 | * Bus glue for OHCI HC on the of_platform bus | ||
10 | * | ||
11 | * Modified for of_platform bus from ohci-sa1111.c | ||
12 | * | ||
13 | * This file is licenced under the GPL. | ||
14 | */ | ||
15 | |||
16 | #include <linux/signal.h> | ||
17 | |||
18 | #include <asm/of_platform.h> | ||
19 | #include <asm/prom.h> | ||
20 | |||
21 | |||
22 | static int __devinit | ||
23 | ohci_ppc_of_start(struct usb_hcd *hcd) | ||
24 | { | ||
25 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
26 | int ret; | ||
27 | |||
28 | if ((ret = ohci_init(ohci)) < 0) | ||
29 | return ret; | ||
30 | |||
31 | if ((ret = ohci_run(ohci)) < 0) { | ||
32 | err("can't start %s", ohci_to_hcd(ohci)->self.bus_name); | ||
33 | ohci_stop(hcd); | ||
34 | return ret; | ||
35 | } | ||
36 | |||
37 | return 0; | ||
38 | } | ||
39 | |||
40 | static const struct hc_driver ohci_ppc_of_hc_driver = { | ||
41 | .description = hcd_name, | ||
42 | .product_desc = "OF OHCI", | ||
43 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
44 | |||
45 | /* | ||
46 | * generic hardware linkage | ||
47 | */ | ||
48 | .irq = ohci_irq, | ||
49 | .flags = HCD_USB11 | HCD_MEMORY, | ||
50 | |||
51 | /* | ||
52 | * basic lifecycle operations | ||
53 | */ | ||
54 | .start = ohci_ppc_of_start, | ||
55 | .stop = ohci_stop, | ||
56 | .shutdown = ohci_shutdown, | ||
57 | |||
58 | /* | ||
59 | * managing i/o requests and associated device resources | ||
60 | */ | ||
61 | .urb_enqueue = ohci_urb_enqueue, | ||
62 | .urb_dequeue = ohci_urb_dequeue, | ||
63 | .endpoint_disable = ohci_endpoint_disable, | ||
64 | |||
65 | /* | ||
66 | * scheduling support | ||
67 | */ | ||
68 | .get_frame_number = ohci_get_frame, | ||
69 | |||
70 | /* | ||
71 | * root hub support | ||
72 | */ | ||
73 | .hub_status_data = ohci_hub_status_data, | ||
74 | .hub_control = ohci_hub_control, | ||
75 | .hub_irq_enable = ohci_rhsc_enable, | ||
76 | #ifdef CONFIG_PM | ||
77 | .bus_suspend = ohci_bus_suspend, | ||
78 | .bus_resume = ohci_bus_resume, | ||
79 | #endif | ||
80 | .start_port_reset = ohci_start_port_reset, | ||
81 | }; | ||
82 | |||
83 | |||
84 | static int __devinit | ||
85 | ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) | ||
86 | { | ||
87 | struct device_node *dn = op->node; | ||
88 | struct usb_hcd *hcd; | ||
89 | struct ohci_hcd *ohci; | ||
90 | struct resource res; | ||
91 | int irq; | ||
92 | |||
93 | int rv; | ||
94 | int is_bigendian; | ||
95 | |||
96 | if (usb_disabled()) | ||
97 | return -ENODEV; | ||
98 | |||
99 | is_bigendian = | ||
100 | device_is_compatible(dn, "ohci-bigendian") || | ||
101 | device_is_compatible(dn, "ohci-be"); | ||
102 | |||
103 | dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n"); | ||
104 | |||
105 | rv = of_address_to_resource(dn, 0, &res); | ||
106 | if (rv) | ||
107 | return rv; | ||
108 | |||
109 | hcd = usb_create_hcd(&ohci_ppc_of_hc_driver, &op->dev, "PPC-OF USB"); | ||
110 | if (!hcd) | ||
111 | return -ENOMEM; | ||
112 | |||
113 | hcd->rsrc_start = res.start; | ||
114 | hcd->rsrc_len = res.end - res.start + 1; | ||
115 | |||
116 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
117 | printk(KERN_ERR __FILE__ ": request_mem_region failed\n"); | ||
118 | rv = -EBUSY; | ||
119 | goto err_rmr; | ||
120 | } | ||
121 | |||
122 | irq = irq_of_parse_and_map(dn, 0); | ||
123 | if (irq == NO_IRQ) { | ||
124 | printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n"); | ||
125 | rv = -EBUSY; | ||
126 | goto err_irq; | ||
127 | } | ||
128 | |||
129 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
130 | if (!hcd->regs) { | ||
131 | printk(KERN_ERR __FILE__ ": ioremap failed\n"); | ||
132 | rv = -ENOMEM; | ||
133 | goto err_ioremap; | ||
134 | } | ||
135 | |||
136 | ohci = hcd_to_ohci(hcd); | ||
137 | if (is_bigendian) | ||
138 | ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; | ||
139 | |||
140 | ohci_hcd_init(ohci); | ||
141 | |||
142 | rv = usb_add_hcd(hcd, irq, 0); | ||
143 | if (rv == 0) | ||
144 | return 0; | ||
145 | |||
146 | iounmap(hcd->regs); | ||
147 | err_ioremap: | ||
148 | irq_dispose_mapping(irq); | ||
149 | err_irq: | ||
150 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
151 | err_rmr: | ||
152 | usb_put_hcd(hcd); | ||
153 | |||
154 | return rv; | ||
155 | } | ||
156 | |||
157 | static int ohci_hcd_ppc_of_remove(struct of_device *op) | ||
158 | { | ||
159 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | ||
160 | dev_set_drvdata(&op->dev, NULL); | ||
161 | |||
162 | dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n"); | ||
163 | |||
164 | usb_remove_hcd(hcd); | ||
165 | |||
166 | iounmap(hcd->regs); | ||
167 | irq_dispose_mapping(hcd->irq); | ||
168 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
169 | |||
170 | usb_put_hcd(hcd); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int ohci_hcd_ppc_of_shutdown(struct of_device *op) | ||
176 | { | ||
177 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | ||
178 | |||
179 | if (hcd->driver->shutdown) | ||
180 | hcd->driver->shutdown(hcd); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | |||
186 | static struct of_device_id ohci_hcd_ppc_of_match[] = { | ||
187 | #ifdef CONFIG_USB_OHCI_HCD_PPC_OF_BE | ||
188 | { | ||
189 | .name = "usb", | ||
190 | .compatible = "ohci-bigendian", | ||
191 | }, | ||
192 | { | ||
193 | .name = "usb", | ||
194 | .compatible = "ohci-be", | ||
195 | }, | ||
196 | #endif | ||
197 | #ifdef CONFIG_USB_OHCI_HCD_PPC_OF_LE | ||
198 | { | ||
199 | .name = "usb", | ||
200 | .compatible = "ohci-littledian", | ||
201 | }, | ||
202 | { | ||
203 | .name = "usb", | ||
204 | .compatible = "ohci-le", | ||
205 | }, | ||
206 | #endif | ||
207 | {}, | ||
208 | }; | ||
209 | MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match); | ||
210 | |||
211 | #if !defined(CONFIG_USB_OHCI_HCD_PPC_OF_BE) && \ | ||
212 | !defined(CONFIG_USB_OHCI_HCD_PPC_OF_LE) | ||
213 | #error "No endianess selected for ppc-of-ohci" | ||
214 | #endif | ||
215 | |||
216 | |||
217 | static struct of_platform_driver ohci_hcd_ppc_of_driver = { | ||
218 | .name = "ppc-of-ohci", | ||
219 | .match_table = ohci_hcd_ppc_of_match, | ||
220 | .probe = ohci_hcd_ppc_of_probe, | ||
221 | .remove = ohci_hcd_ppc_of_remove, | ||
222 | .shutdown = ohci_hcd_ppc_of_shutdown, | ||
223 | #ifdef CONFIG_PM | ||
224 | /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/ | ||
225 | /*.resume = ohci_hcd_ppc_soc_drv_resume,*/ | ||
226 | #endif | ||
227 | .driver = { | ||
228 | .name = "ppc-of-ohci", | ||
229 | .owner = THIS_MODULE, | ||
230 | }, | ||
231 | }; | ||
232 | |||
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c index d9d1ae236bd5..1a2e1777ca61 100644 --- a/drivers/usb/host/ohci-ppc-soc.c +++ b/drivers/usb/host/ohci-ppc-soc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> | 5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> |
6 | * (C) Copyright 2002 Hewlett-Packard Company | 6 | * (C) Copyright 2002 Hewlett-Packard Company |
7 | * (C) Copyright 2003-2005 MontaVista Software Inc. | 7 | * (C) Copyright 2003-2005 MontaVista Software Inc. |
8 | * | 8 | * |
9 | * Bus Glue for PPC On-Chip OHCI driver | 9 | * Bus Glue for PPC On-Chip OHCI driver |
10 | * Tested on Freescale MPC5200 and IBM STB04xxx | 10 | * Tested on Freescale MPC5200 and IBM STB04xxx |
11 | * | 11 | * |
@@ -72,7 +72,7 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver, | |||
72 | } | 72 | } |
73 | 73 | ||
74 | ohci = hcd_to_ohci(hcd); | 74 | ohci = hcd_to_ohci(hcd); |
75 | ohci->flags |= OHCI_BIG_ENDIAN; | 75 | ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; |
76 | ohci_hcd_init(ohci); | 76 | ohci_hcd_init(ohci); |
77 | 77 | ||
78 | retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); | 78 | retval = usb_add_hcd(hcd, irq, IRQF_DISABLED); |
@@ -85,7 +85,7 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver, | |||
85 | err2: | 85 | err2: |
86 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 86 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
87 | err1: | 87 | err1: |
88 | usb_put_hcd(hcd); | 88 | usb_put_hcd(hcd); |
89 | return retval; | 89 | return retval; |
90 | } | 90 | } |
91 | 91 | ||
@@ -148,7 +148,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = { | |||
148 | */ | 148 | */ |
149 | .start = ohci_ppc_soc_start, | 149 | .start = ohci_ppc_soc_start, |
150 | .stop = ohci_stop, | 150 | .stop = ohci_stop, |
151 | .shutdown = ohci_shutdown, | 151 | .shutdown = ohci_shutdown, |
152 | 152 | ||
153 | /* | 153 | /* |
154 | * managing i/o requests and associated device resources | 154 | * managing i/o requests and associated device resources |
@@ -197,7 +197,7 @@ static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev) | |||
197 | static struct platform_driver ohci_hcd_ppc_soc_driver = { | 197 | static struct platform_driver ohci_hcd_ppc_soc_driver = { |
198 | .probe = ohci_hcd_ppc_soc_drv_probe, | 198 | .probe = ohci_hcd_ppc_soc_drv_probe, |
199 | .remove = ohci_hcd_ppc_soc_drv_remove, | 199 | .remove = ohci_hcd_ppc_soc_drv_remove, |
200 | .shutdown = usb_hcd_platform_shutdown, | 200 | .shutdown = usb_hcd_platform_shutdown, |
201 | #ifdef CONFIG_PM | 201 | #ifdef CONFIG_PM |
202 | /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/ | 202 | /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/ |
203 | /*.resume = ohci_hcd_ppc_soc_drv_resume,*/ | 203 | /*.resume = ohci_hcd_ppc_soc_drv_resume,*/ |
@@ -208,19 +208,3 @@ static struct platform_driver ohci_hcd_ppc_soc_driver = { | |||
208 | }, | 208 | }, |
209 | }; | 209 | }; |
210 | 210 | ||
211 | static int __init ohci_hcd_ppc_soc_init(void) | ||
212 | { | ||
213 | pr_debug(DRIVER_INFO " (PPC SOC)\n"); | ||
214 | pr_debug("block sizes: ed %d td %d\n", sizeof(struct ed), | ||
215 | sizeof(struct td)); | ||
216 | |||
217 | return platform_driver_register(&ohci_hcd_ppc_soc_driver); | ||
218 | } | ||
219 | |||
220 | static void __exit ohci_hcd_ppc_soc_cleanup(void) | ||
221 | { | ||
222 | platform_driver_unregister(&ohci_hcd_ppc_soc_driver); | ||
223 | } | ||
224 | |||
225 | module_init(ohci_hcd_ppc_soc_init); | ||
226 | module_exit(ohci_hcd_ppc_soc_cleanup); | ||
diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c new file mode 100644 index 000000000000..62283a3926de --- /dev/null +++ b/drivers/usb/host/ohci-ps3.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * PS3 OHCI Host Controller driver | ||
3 | * | ||
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | ||
5 | * Copyright 2006 Sony Corp. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <asm/ps3.h> | ||
22 | |||
23 | static int ps3_ohci_hc_reset(struct usb_hcd *hcd) | ||
24 | { | ||
25 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
26 | |||
27 | ohci->flags |= OHCI_QUIRK_BE_MMIO; | ||
28 | ohci_hcd_init(ohci); | ||
29 | return ohci_init(ohci); | ||
30 | } | ||
31 | |||
32 | static int __devinit ps3_ohci_hc_start(struct usb_hcd *hcd) | ||
33 | { | ||
34 | int result; | ||
35 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
36 | |||
37 | /* Handle root hub init quirk in spider south bridge. */ | ||
38 | /* Also set PwrOn2PwrGood to 0x7f (254ms). */ | ||
39 | |||
40 | ohci_writel(ohci, 0x7f000000 | RH_A_PSM | RH_A_OCPM, | ||
41 | &ohci->regs->roothub.a); | ||
42 | ohci_writel(ohci, 0x00060000, &ohci->regs->roothub.b); | ||
43 | |||
44 | result = ohci_run(ohci); | ||
45 | |||
46 | if (result < 0) { | ||
47 | err("can't start %s", hcd->self.bus_name); | ||
48 | ohci_stop(hcd); | ||
49 | } | ||
50 | |||
51 | return result; | ||
52 | } | ||
53 | |||
54 | static const struct hc_driver ps3_ohci_hc_driver = { | ||
55 | .description = hcd_name, | ||
56 | .product_desc = "PS3 OHCI Host Controller", | ||
57 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
58 | .irq = ohci_irq, | ||
59 | .flags = HCD_MEMORY | HCD_USB11, | ||
60 | .reset = ps3_ohci_hc_reset, | ||
61 | .start = ps3_ohci_hc_start, | ||
62 | .stop = ohci_stop, | ||
63 | .shutdown = ohci_shutdown, | ||
64 | .urb_enqueue = ohci_urb_enqueue, | ||
65 | .urb_dequeue = ohci_urb_dequeue, | ||
66 | .endpoint_disable = ohci_endpoint_disable, | ||
67 | .get_frame_number = ohci_get_frame, | ||
68 | .hub_status_data = ohci_hub_status_data, | ||
69 | .hub_control = ohci_hub_control, | ||
70 | .hub_irq_enable = ohci_rhsc_enable, | ||
71 | .start_port_reset = ohci_start_port_reset, | ||
72 | #if defined(CONFIG_PM) | ||
73 | .bus_suspend = ohci_bus_suspend, | ||
74 | .bus_resume = ohci_bus_resume, | ||
75 | #endif | ||
76 | }; | ||
77 | |||
78 | /* redefine dev_dbg to do a syntax check */ | ||
79 | |||
80 | #if !defined(DEBUG) | ||
81 | #undef dev_dbg | ||
82 | static inline int __attribute__ ((format (printf, 2, 3))) dev_dbg( | ||
83 | const struct device *_dev, const char *fmt, ...) {return 0;} | ||
84 | #endif | ||
85 | |||
86 | static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev) | ||
87 | { | ||
88 | int result; | ||
89 | struct usb_hcd *hcd; | ||
90 | unsigned int virq; | ||
91 | static u64 dummy_mask = DMA_32BIT_MASK; | ||
92 | |||
93 | if (usb_disabled()) { | ||
94 | result = -ENODEV; | ||
95 | goto fail_start; | ||
96 | } | ||
97 | |||
98 | result = ps3_mmio_region_create(dev->m_region); | ||
99 | |||
100 | if (result) { | ||
101 | dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n", | ||
102 | __func__, __LINE__); | ||
103 | result = -EPERM; | ||
104 | goto fail_mmio; | ||
105 | } | ||
106 | |||
107 | dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__, | ||
108 | __LINE__, dev->m_region->lpar_addr); | ||
109 | |||
110 | result = ps3_alloc_io_irq(PS3_BINDING_CPU_ANY, dev->interrupt_id, &virq); | ||
111 | |||
112 | if (result) { | ||
113 | dev_dbg(&dev->core, "%s:%d: ps3_construct_io_irq(%d) failed.\n", | ||
114 | __func__, __LINE__, virq); | ||
115 | result = -EPERM; | ||
116 | goto fail_irq; | ||
117 | } | ||
118 | |||
119 | dev->core.power.power_state = PMSG_ON; | ||
120 | dev->core.dma_mask = &dummy_mask; /* FIXME: for improper usb code */ | ||
121 | |||
122 | hcd = usb_create_hcd(&ps3_ohci_hc_driver, &dev->core, dev->core.bus_id); | ||
123 | |||
124 | if (!hcd) { | ||
125 | dev_dbg(&dev->core, "%s:%d: usb_create_hcd failed\n", __func__, | ||
126 | __LINE__); | ||
127 | result = -ENOMEM; | ||
128 | goto fail_create_hcd; | ||
129 | } | ||
130 | |||
131 | hcd->rsrc_start = dev->m_region->lpar_addr; | ||
132 | hcd->rsrc_len = dev->m_region->len; | ||
133 | hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len); | ||
134 | |||
135 | if (!hcd->regs) { | ||
136 | dev_dbg(&dev->core, "%s:%d: ioremap failed\n", __func__, | ||
137 | __LINE__); | ||
138 | result = -EPERM; | ||
139 | goto fail_ioremap; | ||
140 | } | ||
141 | |||
142 | dev_dbg(&dev->core, "%s:%d: hcd->rsrc_start %lxh\n", __func__, __LINE__, | ||
143 | (unsigned long)hcd->rsrc_start); | ||
144 | dev_dbg(&dev->core, "%s:%d: hcd->rsrc_len %lxh\n", __func__, __LINE__, | ||
145 | (unsigned long)hcd->rsrc_len); | ||
146 | dev_dbg(&dev->core, "%s:%d: hcd->regs %lxh\n", __func__, __LINE__, | ||
147 | (unsigned long)hcd->regs); | ||
148 | dev_dbg(&dev->core, "%s:%d: virq %lu\n", __func__, __LINE__, | ||
149 | (unsigned long)virq); | ||
150 | |||
151 | ps3_system_bus_set_driver_data(dev, hcd); | ||
152 | |||
153 | result = usb_add_hcd(hcd, virq, IRQF_DISABLED); | ||
154 | |||
155 | if (result) { | ||
156 | dev_dbg(&dev->core, "%s:%d: usb_add_hcd failed (%d)\n", | ||
157 | __func__, __LINE__, result); | ||
158 | goto fail_add_hcd; | ||
159 | } | ||
160 | |||
161 | return result; | ||
162 | |||
163 | fail_add_hcd: | ||
164 | iounmap(hcd->regs); | ||
165 | fail_ioremap: | ||
166 | usb_put_hcd(hcd); | ||
167 | fail_create_hcd: | ||
168 | ps3_free_io_irq(virq); | ||
169 | fail_irq: | ||
170 | ps3_free_mmio_region(dev->m_region); | ||
171 | fail_mmio: | ||
172 | fail_start: | ||
173 | return result; | ||
174 | } | ||
175 | |||
176 | static int ps3_ohci_sb_remove (struct ps3_system_bus_device *dev) | ||
177 | { | ||
178 | struct usb_hcd *hcd = | ||
179 | (struct usb_hcd *)ps3_system_bus_get_driver_data(dev); | ||
180 | |||
181 | usb_put_hcd(hcd); | ||
182 | ps3_system_bus_set_driver_data(dev, NULL); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | MODULE_ALIAS("ps3-ohci"); | ||
188 | |||
189 | static struct ps3_system_bus_driver ps3_ohci_sb_driver = { | ||
190 | .match_id = PS3_MATCH_ID_OHCI, | ||
191 | .core = { | ||
192 | .name = "ps3-ohci-driver", | ||
193 | }, | ||
194 | .probe = ps3_ohci_sb_probe, | ||
195 | .remove = ps3_ohci_sb_remove, | ||
196 | }; | ||
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index e176b04d7aeb..f1563dc319d3 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c | |||
@@ -47,7 +47,7 @@ static int pxa27x_ohci_select_pmm( int mode ) | |||
47 | switch ( mode ) { | 47 | switch ( mode ) { |
48 | case PMM_NPS_MODE: | 48 | case PMM_NPS_MODE: |
49 | UHCRHDA |= RH_A_NPS; | 49 | UHCRHDA |= RH_A_NPS; |
50 | break; | 50 | break; |
51 | case PMM_GLOBAL_MODE: | 51 | case PMM_GLOBAL_MODE: |
52 | UHCRHDA &= ~(RH_A_NPS & RH_A_PSM); | 52 | UHCRHDA &= ~(RH_A_NPS & RH_A_PSM); |
53 | break; | 53 | break; |
@@ -60,7 +60,7 @@ static int pxa27x_ohci_select_pmm( int mode ) | |||
60 | break; | 60 | break; |
61 | default: | 61 | default: |
62 | printk( KERN_ERR | 62 | printk( KERN_ERR |
63 | "Invalid mode %d, set to non-power switch mode.\n", | 63 | "Invalid mode %d, set to non-power switch mode.\n", |
64 | mode ); | 64 | mode ); |
65 | 65 | ||
66 | UHCRHDA |= RH_A_NPS; | 66 | UHCRHDA |= RH_A_NPS; |
@@ -270,7 +270,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = { | |||
270 | */ | 270 | */ |
271 | .start = ohci_pxa27x_start, | 271 | .start = ohci_pxa27x_start, |
272 | .stop = ohci_stop, | 272 | .stop = ohci_stop, |
273 | .shutdown = ohci_shutdown, | 273 | .shutdown = ohci_shutdown, |
274 | 274 | ||
275 | /* | 275 | /* |
276 | * managing i/o requests and associated device resources | 276 | * managing i/o requests and associated device resources |
@@ -359,9 +359,9 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev) | |||
359 | static struct platform_driver ohci_hcd_pxa27x_driver = { | 359 | static struct platform_driver ohci_hcd_pxa27x_driver = { |
360 | .probe = ohci_hcd_pxa27x_drv_probe, | 360 | .probe = ohci_hcd_pxa27x_drv_probe, |
361 | .remove = ohci_hcd_pxa27x_drv_remove, | 361 | .remove = ohci_hcd_pxa27x_drv_remove, |
362 | .shutdown = usb_hcd_platform_shutdown, | 362 | .shutdown = usb_hcd_platform_shutdown, |
363 | #ifdef CONFIG_PM | 363 | #ifdef CONFIG_PM |
364 | .suspend = ohci_hcd_pxa27x_drv_suspend, | 364 | .suspend = ohci_hcd_pxa27x_drv_suspend, |
365 | .resume = ohci_hcd_pxa27x_drv_resume, | 365 | .resume = ohci_hcd_pxa27x_drv_resume, |
366 | #endif | 366 | #endif |
367 | .driver = { | 367 | .driver = { |
@@ -369,19 +369,3 @@ static struct platform_driver ohci_hcd_pxa27x_driver = { | |||
369 | }, | 369 | }, |
370 | }; | 370 | }; |
371 | 371 | ||
372 | static int __init ohci_hcd_pxa27x_init (void) | ||
373 | { | ||
374 | pr_debug (DRIVER_INFO " (pxa27x)"); | ||
375 | pr_debug ("block sizes: ed %d td %d\n", | ||
376 | sizeof (struct ed), sizeof (struct td)); | ||
377 | |||
378 | return platform_driver_register(&ohci_hcd_pxa27x_driver); | ||
379 | } | ||
380 | |||
381 | static void __exit ohci_hcd_pxa27x_cleanup (void) | ||
382 | { | ||
383 | platform_driver_unregister(&ohci_hcd_pxa27x_driver); | ||
384 | } | ||
385 | |||
386 | module_init (ohci_hcd_pxa27x_init); | ||
387 | module_exit (ohci_hcd_pxa27x_cleanup); | ||
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index fe1fe2f97cb5..830a3fe8615e 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * OHCI HCD (Host Controller Driver) for USB. | 2 | * OHCI HCD (Host Controller Driver) for USB. |
3 | * | 3 | * |
4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | 4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> |
5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> | 5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> |
6 | * | 6 | * |
7 | * This file is licenced under the GPL. | 7 | * This file is licenced under the GPL. |
8 | */ | 8 | */ |
9 | 9 | ||
@@ -89,7 +89,7 @@ __acquires(ohci->lock) | |||
89 | 89 | ||
90 | /*-------------------------------------------------------------------------* | 90 | /*-------------------------------------------------------------------------* |
91 | * ED handling functions | 91 | * ED handling functions |
92 | *-------------------------------------------------------------------------*/ | 92 | *-------------------------------------------------------------------------*/ |
93 | 93 | ||
94 | /* search for the right schedule branch to use for a periodic ed. | 94 | /* search for the right schedule branch to use for a periodic ed. |
95 | * does some load balancing; returns the branch, or negative errno. | 95 | * does some load balancing; returns the branch, or negative errno. |
@@ -107,7 +107,6 @@ static int balance (struct ohci_hcd *ohci, int interval, int load) | |||
107 | */ | 107 | */ |
108 | for (i = 0; i < interval ; i++) { | 108 | for (i = 0; i < interval ; i++) { |
109 | if (branch < 0 || ohci->load [branch] > ohci->load [i]) { | 109 | if (branch < 0 || ohci->load [branch] > ohci->load [i]) { |
110 | #if 1 /* CONFIG_USB_BANDWIDTH */ | ||
111 | int j; | 110 | int j; |
112 | 111 | ||
113 | /* usb 1.1 says 90% of one frame */ | 112 | /* usb 1.1 says 90% of one frame */ |
@@ -117,8 +116,7 @@ static int balance (struct ohci_hcd *ohci, int interval, int load) | |||
117 | } | 116 | } |
118 | if (j < NUM_INTS) | 117 | if (j < NUM_INTS) |
119 | continue; | 118 | continue; |
120 | #endif | 119 | branch = i; |
121 | branch = i; | ||
122 | } | 120 | } |
123 | } | 121 | } |
124 | return branch; | 122 | return branch; |
@@ -171,7 +169,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed) | |||
171 | /* link an ed into one of the HC chains */ | 169 | /* link an ed into one of the HC chains */ |
172 | 170 | ||
173 | static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) | 171 | static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) |
174 | { | 172 | { |
175 | int branch; | 173 | int branch; |
176 | 174 | ||
177 | if (ohci_to_hcd(ohci)->state == HC_STATE_QUIESCING) | 175 | if (ohci_to_hcd(ohci)->state == HC_STATE_QUIESCING) |
@@ -248,7 +246,7 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) | |||
248 | } | 246 | } |
249 | ed->branch = branch; | 247 | ed->branch = branch; |
250 | periodic_link (ohci, ed); | 248 | periodic_link (ohci, ed); |
251 | } | 249 | } |
252 | 250 | ||
253 | /* the HC may not see the schedule updates yet, but if it does | 251 | /* the HC may not see the schedule updates yet, but if it does |
254 | * then they'll be properly ordered. | 252 | * then they'll be properly ordered. |
@@ -277,7 +275,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) | |||
277 | *prev = ed->ed_next; | 275 | *prev = ed->ed_next; |
278 | } | 276 | } |
279 | ohci->load [i] -= ed->load; | 277 | ohci->load [i] -= ed->load; |
280 | } | 278 | } |
281 | ohci_to_hcd(ohci)->self.bandwidth_allocated -= ed->load / ed->interval; | 279 | ohci_to_hcd(ohci)->self.bandwidth_allocated -= ed->load / ed->interval; |
282 | 280 | ||
283 | ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n", | 281 | ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n", |
@@ -285,7 +283,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) | |||
285 | ed, ed->branch, ed->load, ed->interval); | 283 | ed, ed->branch, ed->load, ed->interval); |
286 | } | 284 | } |
287 | 285 | ||
288 | /* unlink an ed from one of the HC chains. | 286 | /* unlink an ed from one of the HC chains. |
289 | * just the link to the ed is unlinked. | 287 | * just the link to the ed is unlinked. |
290 | * the link from the ed still points to another operational ed or 0 | 288 | * the link from the ed still points to another operational ed or 0 |
291 | * so the HC can eventually finish the processing of the unlinked ed | 289 | * so the HC can eventually finish the processing of the unlinked ed |
@@ -307,7 +305,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed) | |||
307 | * When finish_unlinks() runs later, after SOF interrupt, it will often | 305 | * When finish_unlinks() runs later, after SOF interrupt, it will often |
308 | * complete one or more URB unlinks before making that state change. | 306 | * complete one or more URB unlinks before making that state change. |
309 | */ | 307 | */ |
310 | static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) | 308 | static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) |
311 | { | 309 | { |
312 | ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP); | 310 | ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP); |
313 | wmb (); | 311 | wmb (); |
@@ -397,7 +395,7 @@ static struct ed *ed_get ( | |||
397 | unsigned int pipe, | 395 | unsigned int pipe, |
398 | int interval | 396 | int interval |
399 | ) { | 397 | ) { |
400 | struct ed *ed; | 398 | struct ed *ed; |
401 | unsigned long flags; | 399 | unsigned long flags; |
402 | 400 | ||
403 | spin_lock_irqsave (&ohci->lock, flags); | 401 | spin_lock_irqsave (&ohci->lock, flags); |
@@ -413,9 +411,9 @@ static struct ed *ed_get ( | |||
413 | goto done; | 411 | goto done; |
414 | } | 412 | } |
415 | 413 | ||
416 | /* dummy td; end of td list for ed */ | 414 | /* dummy td; end of td list for ed */ |
417 | td = td_alloc (ohci, GFP_ATOMIC); | 415 | td = td_alloc (ohci, GFP_ATOMIC); |
418 | if (!td) { | 416 | if (!td) { |
419 | /* out of memory */ | 417 | /* out of memory */ |
420 | ed_free (ohci, ed); | 418 | ed_free (ohci, ed); |
421 | ed = NULL; | 419 | ed = NULL; |
@@ -462,7 +460,7 @@ static struct ed *ed_get ( | |||
462 | 460 | ||
463 | done: | 461 | done: |
464 | spin_unlock_irqrestore (&ohci->lock, flags); | 462 | spin_unlock_irqrestore (&ohci->lock, flags); |
465 | return ed; | 463 | return ed; |
466 | } | 464 | } |
467 | 465 | ||
468 | /*-------------------------------------------------------------------------*/ | 466 | /*-------------------------------------------------------------------------*/ |
@@ -474,7 +472,7 @@ done: | |||
474 | * and that ed->state is ED_OPER | 472 | * and that ed->state is ED_OPER |
475 | */ | 473 | */ |
476 | static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed) | 474 | static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed) |
477 | { | 475 | { |
478 | ed->hwINFO |= cpu_to_hc32 (ohci, ED_DEQUEUE); | 476 | ed->hwINFO |= cpu_to_hc32 (ohci, ED_DEQUEUE); |
479 | ed_deschedule (ohci, ed); | 477 | ed_deschedule (ohci, ed); |
480 | 478 | ||
@@ -541,7 +539,7 @@ td_fill (struct ohci_hcd *ohci, u32 info, | |||
541 | td->ed = urb_priv->ed; | 539 | td->ed = urb_priv->ed; |
542 | td->next_dl_td = NULL; | 540 | td->next_dl_td = NULL; |
543 | td->index = index; | 541 | td->index = index; |
544 | td->urb = urb; | 542 | td->urb = urb; |
545 | td->data_dma = data; | 543 | td->data_dma = data; |
546 | if (!len) | 544 | if (!len) |
547 | data = 0; | 545 | data = 0; |
@@ -553,8 +551,8 @@ td_fill (struct ohci_hcd *ohci, u32 info, | |||
553 | (data & 0x0FFF) | 0xE000); | 551 | (data & 0x0FFF) | 0xE000); |
554 | td->ed->last_iso = info & 0xffff; | 552 | td->ed->last_iso = info & 0xffff; |
555 | } else { | 553 | } else { |
556 | td->hwCBP = cpu_to_hc32 (ohci, data); | 554 | td->hwCBP = cpu_to_hc32 (ohci, data); |
557 | } | 555 | } |
558 | if (data) | 556 | if (data) |
559 | td->hwBE = cpu_to_hc32 (ohci, data + len - 1); | 557 | td->hwBE = cpu_to_hc32 (ohci, data + len - 1); |
560 | else | 558 | else |
@@ -597,7 +595,7 @@ static void td_submit_urb ( | |||
597 | * use the device toggle bits for resetting, and rely on the fact | 595 | * use the device toggle bits for resetting, and rely on the fact |
598 | * that resetting toggle is meaningless if the endpoint is active. | 596 | * that resetting toggle is meaningless if the endpoint is active. |
599 | */ | 597 | */ |
600 | if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) { | 598 | if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) { |
601 | usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), | 599 | usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), |
602 | is_out, 1); | 600 | is_out, 1); |
603 | urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C); | 601 | urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C); |
@@ -721,16 +719,16 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) | |||
721 | list_del (&td->td_list); | 719 | list_del (&td->td_list); |
722 | 720 | ||
723 | /* ISO ... drivers see per-TD length/status */ | 721 | /* ISO ... drivers see per-TD length/status */ |
724 | if (tdINFO & TD_ISO) { | 722 | if (tdINFO & TD_ISO) { |
725 | u16 tdPSW = ohci_hwPSW (ohci, td, 0); | 723 | u16 tdPSW = ohci_hwPSW (ohci, td, 0); |
726 | int dlen = 0; | 724 | int dlen = 0; |
727 | 725 | ||
728 | /* NOTE: assumes FC in tdINFO == 0, and that | 726 | /* NOTE: assumes FC in tdINFO == 0, and that |
729 | * only the first of 0..MAXPSW psws is used. | 727 | * only the first of 0..MAXPSW psws is used. |
730 | */ | 728 | */ |
731 | 729 | ||
732 | cc = (tdPSW >> 12) & 0xF; | 730 | cc = (tdPSW >> 12) & 0xF; |
733 | if (tdINFO & TD_CC) /* hc didn't touch? */ | 731 | if (tdINFO & TD_CC) /* hc didn't touch? */ |
734 | return; | 732 | return; |
735 | 733 | ||
736 | if (usb_pipeout (urb->pipe)) | 734 | if (usb_pipeout (urb->pipe)) |
@@ -758,7 +756,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) | |||
758 | int type = usb_pipetype (urb->pipe); | 756 | int type = usb_pipetype (urb->pipe); |
759 | u32 tdBE = hc32_to_cpup (ohci, &td->hwBE); | 757 | u32 tdBE = hc32_to_cpup (ohci, &td->hwBE); |
760 | 758 | ||
761 | cc = TD_CC_GET (tdINFO); | 759 | cc = TD_CC_GET (tdINFO); |
762 | 760 | ||
763 | /* update packet status if needed (short is normally ok) */ | 761 | /* update packet status if needed (short is normally ok) */ |
764 | if (cc == TD_DATAUNDERRUN | 762 | if (cc == TD_DATAUNDERRUN |
@@ -787,7 +785,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) | |||
787 | urb, td, 1 + td->index, cc, | 785 | urb, td, 1 + td->index, cc, |
788 | urb->actual_length, | 786 | urb->actual_length, |
789 | urb->transfer_buffer_length); | 787 | urb->transfer_buffer_length); |
790 | } | 788 | } |
791 | } | 789 | } |
792 | 790 | ||
793 | /*-------------------------------------------------------------------------*/ | 791 | /*-------------------------------------------------------------------------*/ |
@@ -795,7 +793,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td) | |||
795 | static inline struct td * | 793 | static inline struct td * |
796 | ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) | 794 | ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) |
797 | { | 795 | { |
798 | struct urb *urb = td->urb; | 796 | struct urb *urb = td->urb; |
799 | struct ed *ed = td->ed; | 797 | struct ed *ed = td->ed; |
800 | struct list_head *tmp = td->td_list.next; | 798 | struct list_head *tmp = td->td_list.next; |
801 | __hc32 toggle = ed->hwHeadP & cpu_to_hc32 (ohci, ED_C); | 799 | __hc32 toggle = ed->hwHeadP & cpu_to_hc32 (ohci, ED_C); |
@@ -805,7 +803,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) | |||
805 | */ | 803 | */ |
806 | ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP); | 804 | ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP); |
807 | wmb (); | 805 | wmb (); |
808 | ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_H); | 806 | ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_H); |
809 | 807 | ||
810 | /* put any later tds from this urb onto the donelist, after 'td', | 808 | /* put any later tds from this urb onto the donelist, after 'td', |
811 | * order won't matter here: no errors, and nothing was transferred. | 809 | * order won't matter here: no errors, and nothing was transferred. |
@@ -833,7 +831,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev) | |||
833 | info &= ~cpu_to_hc32 (ohci, TD_CC); | 831 | info &= ~cpu_to_hc32 (ohci, TD_CC); |
834 | next->hwINFO = info; | 832 | next->hwINFO = info; |
835 | 833 | ||
836 | next->next_dl_td = rev; | 834 | next->next_dl_td = rev; |
837 | rev = next; | 835 | rev = next; |
838 | 836 | ||
839 | ed->hwHeadP = next->hwNextTD | toggle; | 837 | ed->hwHeadP = next->hwNextTD | toggle; |
@@ -881,8 +879,8 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) | |||
881 | /* get TD from hc's singly linked list, and | 879 | /* get TD from hc's singly linked list, and |
882 | * prepend to ours. ed->td_list changes later. | 880 | * prepend to ours. ed->td_list changes later. |
883 | */ | 881 | */ |
884 | while (td_dma) { | 882 | while (td_dma) { |
885 | int cc; | 883 | int cc; |
886 | 884 | ||
887 | td = dma_to_td (ohci, td_dma); | 885 | td = dma_to_td (ohci, td_dma); |
888 | if (!td) { | 886 | if (!td) { |
@@ -901,10 +899,10 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) | |||
901 | && (td->ed->hwHeadP & cpu_to_hc32 (ohci, ED_H))) | 899 | && (td->ed->hwHeadP & cpu_to_hc32 (ohci, ED_H))) |
902 | td_rev = ed_halted (ohci, td, cc, td_rev); | 900 | td_rev = ed_halted (ohci, td, cc, td_rev); |
903 | 901 | ||
904 | td->next_dl_td = td_rev; | 902 | td->next_dl_td = td_rev; |
905 | td_rev = td; | 903 | td_rev = td; |
906 | td_dma = hc32_to_cpup (ohci, &td->hwNextTD); | 904 | td_dma = hc32_to_cpup (ohci, &td->hwNextTD); |
907 | } | 905 | } |
908 | return td_rev; | 906 | return td_rev; |
909 | } | 907 | } |
910 | 908 | ||
@@ -1013,9 +1011,9 @@ rescan_this: | |||
1013 | 1011 | ||
1014 | if (modified) | 1012 | if (modified) |
1015 | goto rescan_all; | 1013 | goto rescan_all; |
1016 | } | 1014 | } |
1017 | 1015 | ||
1018 | /* maybe reenable control and bulk lists */ | 1016 | /* maybe reenable control and bulk lists */ |
1019 | if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state) | 1017 | if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state) |
1020 | && ohci_to_hcd(ohci)->state != HC_STATE_QUIESCING | 1018 | && ohci_to_hcd(ohci)->state != HC_STATE_QUIESCING |
1021 | && !ohci->ed_rm_list) { | 1019 | && !ohci->ed_rm_list) { |
@@ -1041,20 +1039,20 @@ rescan_this: | |||
1041 | &ohci->regs->ed_bulkcurrent); | 1039 | &ohci->regs->ed_bulkcurrent); |
1042 | } | 1040 | } |
1043 | } | 1041 | } |
1044 | 1042 | ||
1045 | /* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */ | 1043 | /* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */ |
1046 | if (control) { | 1044 | if (control) { |
1047 | ohci->hc_control |= control; | 1045 | ohci->hc_control |= control; |
1048 | if (ohci->flags & OHCI_QUIRK_ZFMICRO) | 1046 | if (ohci->flags & OHCI_QUIRK_ZFMICRO) |
1049 | mdelay(1); | 1047 | mdelay(1); |
1050 | ohci_writel (ohci, ohci->hc_control, | 1048 | ohci_writel (ohci, ohci->hc_control, |
1051 | &ohci->regs->control); | 1049 | &ohci->regs->control); |
1052 | } | 1050 | } |
1053 | if (command) { | 1051 | if (command) { |
1054 | if (ohci->flags & OHCI_QUIRK_ZFMICRO) | 1052 | if (ohci->flags & OHCI_QUIRK_ZFMICRO) |
1055 | mdelay(1); | 1053 | mdelay(1); |
1056 | ohci_writel (ohci, command, &ohci->regs->cmdstatus); | 1054 | ohci_writel (ohci, command, &ohci->regs->cmdstatus); |
1057 | } | 1055 | } |
1058 | } | 1056 | } |
1059 | } | 1057 | } |
1060 | 1058 | ||
@@ -1074,19 +1072,19 @@ dl_done_list (struct ohci_hcd *ohci) | |||
1074 | { | 1072 | { |
1075 | struct td *td = dl_reverse_done_list (ohci); | 1073 | struct td *td = dl_reverse_done_list (ohci); |
1076 | 1074 | ||
1077 | while (td) { | 1075 | while (td) { |
1078 | struct td *td_next = td->next_dl_td; | 1076 | struct td *td_next = td->next_dl_td; |
1079 | struct urb *urb = td->urb; | 1077 | struct urb *urb = td->urb; |
1080 | urb_priv_t *urb_priv = urb->hcpriv; | 1078 | urb_priv_t *urb_priv = urb->hcpriv; |
1081 | struct ed *ed = td->ed; | 1079 | struct ed *ed = td->ed; |
1082 | 1080 | ||
1083 | /* update URB's length and status from TD */ | 1081 | /* update URB's length and status from TD */ |
1084 | td_done (ohci, urb, td); | 1082 | td_done (ohci, urb, td); |
1085 | urb_priv->td_cnt++; | 1083 | urb_priv->td_cnt++; |
1086 | 1084 | ||
1087 | /* If all this urb's TDs are done, call complete() */ | 1085 | /* If all this urb's TDs are done, call complete() */ |
1088 | if (urb_priv->td_cnt == urb_priv->length) | 1086 | if (urb_priv->td_cnt == urb_priv->length) |
1089 | finish_urb (ohci, urb); | 1087 | finish_urb (ohci, urb); |
1090 | 1088 | ||
1091 | /* clean schedule: unlink EDs that are no longer busy */ | 1089 | /* clean schedule: unlink EDs that are no longer busy */ |
1092 | if (list_empty (&ed->td_list)) { | 1090 | if (list_empty (&ed->td_list)) { |
@@ -1094,25 +1092,26 @@ dl_done_list (struct ohci_hcd *ohci) | |||
1094 | start_ed_unlink (ohci, ed); | 1092 | start_ed_unlink (ohci, ed); |
1095 | 1093 | ||
1096 | /* ... reenabling halted EDs only after fault cleanup */ | 1094 | /* ... reenabling halted EDs only after fault cleanup */ |
1097 | } else if ((ed->hwINFO & cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE)) | 1095 | } else if ((ed->hwINFO & cpu_to_hc32 (ohci, |
1096 | ED_SKIP | ED_DEQUEUE)) | ||
1098 | == cpu_to_hc32 (ohci, ED_SKIP)) { | 1097 | == cpu_to_hc32 (ohci, ED_SKIP)) { |
1099 | td = list_entry (ed->td_list.next, struct td, td_list); | 1098 | td = list_entry (ed->td_list.next, struct td, td_list); |
1100 | if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) { | 1099 | if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) { |
1101 | ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP); | 1100 | ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP); |
1102 | /* ... hc may need waking-up */ | 1101 | /* ... hc may need waking-up */ |
1103 | switch (ed->type) { | 1102 | switch (ed->type) { |
1104 | case PIPE_CONTROL: | 1103 | case PIPE_CONTROL: |
1105 | ohci_writel (ohci, OHCI_CLF, | 1104 | ohci_writel (ohci, OHCI_CLF, |
1106 | &ohci->regs->cmdstatus); | 1105 | &ohci->regs->cmdstatus); |
1107 | break; | 1106 | break; |
1108 | case PIPE_BULK: | 1107 | case PIPE_BULK: |
1109 | ohci_writel (ohci, OHCI_BLF, | 1108 | ohci_writel (ohci, OHCI_BLF, |
1110 | &ohci->regs->cmdstatus); | 1109 | &ohci->regs->cmdstatus); |
1111 | break; | 1110 | break; |
1112 | } | 1111 | } |
1113 | } | 1112 | } |
1114 | } | 1113 | } |
1115 | 1114 | ||
1116 | td = td_next; | 1115 | td = td_next; |
1117 | } | 1116 | } |
1118 | } | 1117 | } |
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 59e436424d41..6829814b7aaf 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c | |||
@@ -447,7 +447,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = { | |||
447 | */ | 447 | */ |
448 | .start = ohci_s3c2410_start, | 448 | .start = ohci_s3c2410_start, |
449 | .stop = ohci_stop, | 449 | .stop = ohci_stop, |
450 | .shutdown = ohci_shutdown, | 450 | .shutdown = ohci_shutdown, |
451 | 451 | ||
452 | /* | 452 | /* |
453 | * managing i/o requests and associated device resources | 453 | * managing i/o requests and associated device resources |
@@ -492,7 +492,7 @@ static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev) | |||
492 | static struct platform_driver ohci_hcd_s3c2410_driver = { | 492 | static struct platform_driver ohci_hcd_s3c2410_driver = { |
493 | .probe = ohci_hcd_s3c2410_drv_probe, | 493 | .probe = ohci_hcd_s3c2410_drv_probe, |
494 | .remove = ohci_hcd_s3c2410_drv_remove, | 494 | .remove = ohci_hcd_s3c2410_drv_remove, |
495 | .shutdown = usb_hcd_platform_shutdown, | 495 | .shutdown = usb_hcd_platform_shutdown, |
496 | /*.suspend = ohci_hcd_s3c2410_drv_suspend, */ | 496 | /*.suspend = ohci_hcd_s3c2410_drv_suspend, */ |
497 | /*.resume = ohci_hcd_s3c2410_drv_resume, */ | 497 | /*.resume = ohci_hcd_s3c2410_drv_resume, */ |
498 | .driver = { | 498 | .driver = { |
@@ -501,15 +501,3 @@ static struct platform_driver ohci_hcd_s3c2410_driver = { | |||
501 | }, | 501 | }, |
502 | }; | 502 | }; |
503 | 503 | ||
504 | static int __init ohci_hcd_s3c2410_init (void) | ||
505 | { | ||
506 | return platform_driver_register(&ohci_hcd_s3c2410_driver); | ||
507 | } | ||
508 | |||
509 | static void __exit ohci_hcd_s3c2410_cleanup (void) | ||
510 | { | ||
511 | platform_driver_unregister(&ohci_hcd_s3c2410_driver); | ||
512 | } | ||
513 | |||
514 | module_init (ohci_hcd_s3c2410_init); | ||
515 | module_exit (ohci_hcd_s3c2410_cleanup); | ||
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index 71371de32ada..0f48f2d99226 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | 4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> |
5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> | 5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> |
6 | * (C) Copyright 2002 Hewlett-Packard Company | 6 | * (C) Copyright 2002 Hewlett-Packard Company |
7 | * | 7 | * |
8 | * SA1111 Bus Glue | 8 | * SA1111 Bus Glue |
9 | * | 9 | * |
10 | * Written by Christopher Hoover <ch@hpl.hp.com> | 10 | * Written by Christopher Hoover <ch@hpl.hp.com> |
@@ -12,7 +12,7 @@ | |||
12 | * | 12 | * |
13 | * This file is licenced under the GPL. | 13 | * This file is licenced under the GPL. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <asm/hardware.h> | 16 | #include <asm/hardware.h> |
17 | #include <asm/mach-types.h> | 17 | #include <asm/mach-types.h> |
18 | #include <asm/arch/assabet.h> | 18 | #include <asm/arch/assabet.h> |
@@ -31,7 +31,7 @@ static void sa1111_start_hc(struct sa1111_dev *dev) | |||
31 | { | 31 | { |
32 | unsigned int usb_rst = 0; | 32 | unsigned int usb_rst = 0; |
33 | 33 | ||
34 | printk(KERN_DEBUG __FILE__ | 34 | printk(KERN_DEBUG __FILE__ |
35 | ": starting SA-1111 OHCI USB Controller\n"); | 35 | ": starting SA-1111 OHCI USB Controller\n"); |
36 | 36 | ||
37 | #ifdef CONFIG_SA1100_BADGE4 | 37 | #ifdef CONFIG_SA1100_BADGE4 |
@@ -65,7 +65,7 @@ static void sa1111_start_hc(struct sa1111_dev *dev) | |||
65 | static void sa1111_stop_hc(struct sa1111_dev *dev) | 65 | static void sa1111_stop_hc(struct sa1111_dev *dev) |
66 | { | 66 | { |
67 | unsigned int usb_rst; | 67 | unsigned int usb_rst; |
68 | printk(KERN_DEBUG __FILE__ | 68 | printk(KERN_DEBUG __FILE__ |
69 | ": stopping SA-1111 OHCI USB Controller\n"); | 69 | ": stopping SA-1111 OHCI USB Controller\n"); |
70 | 70 | ||
71 | /* | 71 | /* |
@@ -269,19 +269,3 @@ static struct sa1111_driver ohci_hcd_sa1111_driver = { | |||
269 | .remove = ohci_hcd_sa1111_drv_remove, | 269 | .remove = ohci_hcd_sa1111_drv_remove, |
270 | }; | 270 | }; |
271 | 271 | ||
272 | static int __init ohci_hcd_sa1111_init (void) | ||
273 | { | ||
274 | dbg (DRIVER_INFO " (SA-1111)"); | ||
275 | dbg ("block sizes: ed %d td %d", | ||
276 | sizeof (struct ed), sizeof (struct td)); | ||
277 | |||
278 | return sa1111_driver_register(&ohci_hcd_sa1111_driver); | ||
279 | } | ||
280 | |||
281 | static void __exit ohci_hcd_sa1111_cleanup (void) | ||
282 | { | ||
283 | sa1111_driver_unregister(&ohci_hcd_sa1111_driver); | ||
284 | } | ||
285 | |||
286 | module_init (ohci_hcd_sa1111_init); | ||
287 | module_exit (ohci_hcd_sa1111_cleanup); | ||
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index a2f42a2f47c6..c2b5ecfe5e9f 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * OHCI HCD (Host Controller Driver) for USB. | 2 | * OHCI HCD (Host Controller Driver) for USB. |
3 | * | 3 | * |
4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> | 4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> |
5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> | 5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> |
6 | * | 6 | * |
7 | * This file is licenced under the GPL. | 7 | * This file is licenced under the GPL. |
8 | */ | 8 | */ |
9 | 9 | ||
@@ -14,7 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | typedef __u32 __bitwise __hc32; | 15 | typedef __u32 __bitwise __hc32; |
16 | typedef __u16 __bitwise __hc16; | 16 | typedef __u16 __bitwise __hc16; |
17 | 17 | ||
18 | /* | 18 | /* |
19 | * OHCI Endpoint Descriptor (ED) ... holds TD queue | 19 | * OHCI Endpoint Descriptor (ED) ... holds TD queue |
20 | * See OHCI spec, section 4.2 | 20 | * See OHCI spec, section 4.2 |
@@ -24,7 +24,7 @@ typedef __u16 __bitwise __hc16; | |||
24 | */ | 24 | */ |
25 | struct ed { | 25 | struct ed { |
26 | /* first fields are hardware-specified */ | 26 | /* first fields are hardware-specified */ |
27 | __hc32 hwINFO; /* endpoint config bitmap */ | 27 | __hc32 hwINFO; /* endpoint config bitmap */ |
28 | /* info bits defined by hcd */ | 28 | /* info bits defined by hcd */ |
29 | #define ED_DEQUEUE (1 << 27) | 29 | #define ED_DEQUEUE (1 << 27) |
30 | /* info bits defined by the hardware */ | 30 | /* info bits defined by the hardware */ |
@@ -52,11 +52,11 @@ struct ed { | |||
52 | * usually: OPER --> UNLINK --> (IDLE | OPER) --> ... | 52 | * usually: OPER --> UNLINK --> (IDLE | OPER) --> ... |
53 | */ | 53 | */ |
54 | u8 state; /* ED_{IDLE,UNLINK,OPER} */ | 54 | u8 state; /* ED_{IDLE,UNLINK,OPER} */ |
55 | #define ED_IDLE 0x00 /* NOT linked to HC */ | 55 | #define ED_IDLE 0x00 /* NOT linked to HC */ |
56 | #define ED_UNLINK 0x01 /* being unlinked from hc */ | 56 | #define ED_UNLINK 0x01 /* being unlinked from hc */ |
57 | #define ED_OPER 0x02 /* IS linked to hc */ | 57 | #define ED_OPER 0x02 /* IS linked to hc */ |
58 | 58 | ||
59 | u8 type; /* PIPE_{BULK,...} */ | 59 | u8 type; /* PIPE_{BULK,...} */ |
60 | 60 | ||
61 | /* periodic scheduling params (for intr and iso) */ | 61 | /* periodic scheduling params (for intr and iso) */ |
62 | u8 branch; | 62 | u8 branch; |
@@ -70,7 +70,7 @@ struct ed { | |||
70 | 70 | ||
71 | #define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */ | 71 | #define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */ |
72 | 72 | ||
73 | 73 | ||
74 | /* | 74 | /* |
75 | * OHCI Transfer Descriptor (TD) ... one per transfer segment | 75 | * OHCI Transfer Descriptor (TD) ... one per transfer segment |
76 | * See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt) | 76 | * See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt) |
@@ -107,22 +107,22 @@ struct td { | |||
107 | 107 | ||
108 | /* (no hwINFO #defines yet for iso tds) */ | 108 | /* (no hwINFO #defines yet for iso tds) */ |
109 | 109 | ||
110 | __hc32 hwCBP; /* Current Buffer Pointer (or 0) */ | 110 | __hc32 hwCBP; /* Current Buffer Pointer (or 0) */ |
111 | __hc32 hwNextTD; /* Next TD Pointer */ | 111 | __hc32 hwNextTD; /* Next TD Pointer */ |
112 | __hc32 hwBE; /* Memory Buffer End Pointer */ | 112 | __hc32 hwBE; /* Memory Buffer End Pointer */ |
113 | 113 | ||
114 | /* PSW is only for ISO. Only 1 PSW entry is used, but on | 114 | /* PSW is only for ISO. Only 1 PSW entry is used, but on |
115 | * big-endian PPC hardware that's the second entry. | 115 | * big-endian PPC hardware that's the second entry. |
116 | */ | 116 | */ |
117 | #define MAXPSW 2 | 117 | #define MAXPSW 2 |
118 | __hc16 hwPSW [MAXPSW]; | 118 | __hc16 hwPSW [MAXPSW]; |
119 | 119 | ||
120 | /* rest are purely for the driver's use */ | 120 | /* rest are purely for the driver's use */ |
121 | __u8 index; | 121 | __u8 index; |
122 | struct ed *ed; | 122 | struct ed *ed; |
123 | struct td *td_hash; /* dma-->td hashtable */ | 123 | struct td *td_hash; /* dma-->td hashtable */ |
124 | struct td *next_dl_td; | 124 | struct td *next_dl_td; |
125 | struct urb *urb; | 125 | struct urb *urb; |
126 | 126 | ||
127 | dma_addr_t td_dma; /* addr of this TD */ | 127 | dma_addr_t td_dma; /* addr of this TD */ |
128 | dma_addr_t data_dma; /* addr of data it points to */ | 128 | dma_addr_t data_dma; /* addr of data it points to */ |
@@ -152,8 +152,8 @@ struct td { | |||
152 | #define TD_NOTACCESSED 0x0F | 152 | #define TD_NOTACCESSED 0x0F |
153 | 153 | ||
154 | 154 | ||
155 | /* map OHCI TD status codes (CC) to errno values */ | 155 | /* map OHCI TD status codes (CC) to errno values */ |
156 | static const int cc_to_error [16] = { | 156 | static const int cc_to_error [16] = { |
157 | /* No Error */ 0, | 157 | /* No Error */ 0, |
158 | /* CRC Error */ -EILSEQ, | 158 | /* CRC Error */ -EILSEQ, |
159 | /* Bit Stuff */ -EPROTO, | 159 | /* Bit Stuff */ -EPROTO, |
@@ -169,7 +169,7 @@ static const int cc_to_error [16] = { | |||
169 | /* BufferOver */ -ECOMM, | 169 | /* BufferOver */ -ECOMM, |
170 | /* BuffUnder */ -ENOSR, | 170 | /* BuffUnder */ -ENOSR, |
171 | /* (for HCD) */ -EALREADY, | 171 | /* (for HCD) */ -EALREADY, |
172 | /* (for HCD) */ -EALREADY | 172 | /* (for HCD) */ -EALREADY |
173 | }; | 173 | }; |
174 | 174 | ||
175 | 175 | ||
@@ -182,7 +182,7 @@ struct ohci_hcca { | |||
182 | #define NUM_INTS 32 | 182 | #define NUM_INTS 32 |
183 | __hc32 int_table [NUM_INTS]; /* periodic schedule */ | 183 | __hc32 int_table [NUM_INTS]; /* periodic schedule */ |
184 | 184 | ||
185 | /* | 185 | /* |
186 | * OHCI defines u16 frame_no, followed by u16 zero pad. | 186 | * OHCI defines u16 frame_no, followed by u16 zero pad. |
187 | * Since some processors can't do 16 bit bus accesses, | 187 | * Since some processors can't do 16 bit bus accesses, |
188 | * portable access must be a 32 bits wide. | 188 | * portable access must be a 32 bits wide. |
@@ -262,10 +262,10 @@ struct ohci_regs { | |||
262 | * HcCommandStatus (cmdstatus) register masks | 262 | * HcCommandStatus (cmdstatus) register masks |
263 | */ | 263 | */ |
264 | #define OHCI_HCR (1 << 0) /* host controller reset */ | 264 | #define OHCI_HCR (1 << 0) /* host controller reset */ |
265 | #define OHCI_CLF (1 << 1) /* control list filled */ | 265 | #define OHCI_CLF (1 << 1) /* control list filled */ |
266 | #define OHCI_BLF (1 << 2) /* bulk list filled */ | 266 | #define OHCI_BLF (1 << 2) /* bulk list filled */ |
267 | #define OHCI_OCR (1 << 3) /* ownership change request */ | 267 | #define OHCI_OCR (1 << 3) /* ownership change request */ |
268 | #define OHCI_SOC (3 << 16) /* scheduling overrun count */ | 268 | #define OHCI_SOC (3 << 16) /* scheduling overrun count */ |
269 | 269 | ||
270 | /* | 270 | /* |
271 | * masks used with interrupt registers: | 271 | * masks used with interrupt registers: |
@@ -285,20 +285,20 @@ struct ohci_regs { | |||
285 | 285 | ||
286 | 286 | ||
287 | /* OHCI ROOT HUB REGISTER MASKS */ | 287 | /* OHCI ROOT HUB REGISTER MASKS */ |
288 | 288 | ||
289 | /* roothub.portstatus [i] bits */ | 289 | /* roothub.portstatus [i] bits */ |
290 | #define RH_PS_CCS 0x00000001 /* current connect status */ | 290 | #define RH_PS_CCS 0x00000001 /* current connect status */ |
291 | #define RH_PS_PES 0x00000002 /* port enable status*/ | 291 | #define RH_PS_PES 0x00000002 /* port enable status*/ |
292 | #define RH_PS_PSS 0x00000004 /* port suspend status */ | 292 | #define RH_PS_PSS 0x00000004 /* port suspend status */ |
293 | #define RH_PS_POCI 0x00000008 /* port over current indicator */ | 293 | #define RH_PS_POCI 0x00000008 /* port over current indicator */ |
294 | #define RH_PS_PRS 0x00000010 /* port reset status */ | 294 | #define RH_PS_PRS 0x00000010 /* port reset status */ |
295 | #define RH_PS_PPS 0x00000100 /* port power status */ | 295 | #define RH_PS_PPS 0x00000100 /* port power status */ |
296 | #define RH_PS_LSDA 0x00000200 /* low speed device attached */ | 296 | #define RH_PS_LSDA 0x00000200 /* low speed device attached */ |
297 | #define RH_PS_CSC 0x00010000 /* connect status change */ | 297 | #define RH_PS_CSC 0x00010000 /* connect status change */ |
298 | #define RH_PS_PESC 0x00020000 /* port enable status change */ | 298 | #define RH_PS_PESC 0x00020000 /* port enable status change */ |
299 | #define RH_PS_PSSC 0x00040000 /* port suspend status change */ | 299 | #define RH_PS_PSSC 0x00040000 /* port suspend status change */ |
300 | #define RH_PS_OCIC 0x00080000 /* over current indicator change */ | 300 | #define RH_PS_OCIC 0x00080000 /* over current indicator change */ |
301 | #define RH_PS_PRSC 0x00100000 /* port reset status change */ | 301 | #define RH_PS_PRSC 0x00100000 /* port reset status change */ |
302 | 302 | ||
303 | /* roothub.status bits */ | 303 | /* roothub.status bits */ |
304 | #define RH_HS_LPS 0x00000001 /* local power status */ | 304 | #define RH_HS_LPS 0x00000001 /* local power status */ |
@@ -333,7 +333,7 @@ typedef struct urb_priv { | |||
333 | } urb_priv_t; | 333 | } urb_priv_t; |
334 | 334 | ||
335 | #define TD_HASH_SIZE 64 /* power'o'two */ | 335 | #define TD_HASH_SIZE 64 /* power'o'two */ |
336 | // sizeof (struct td) ~= 64 == 2^6 ... | 336 | // sizeof (struct td) ~= 64 == 2^6 ... |
337 | #define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE) | 337 | #define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE) |
338 | 338 | ||
339 | 339 | ||
@@ -364,11 +364,11 @@ struct ohci_hcd { | |||
364 | 364 | ||
365 | struct ed *ed_bulktail; /* last in bulk list */ | 365 | struct ed *ed_bulktail; /* last in bulk list */ |
366 | struct ed *ed_controltail; /* last in ctrl list */ | 366 | struct ed *ed_controltail; /* last in ctrl list */ |
367 | struct ed *periodic [NUM_INTS]; /* shadow int_table */ | 367 | struct ed *periodic [NUM_INTS]; /* shadow int_table */ |
368 | 368 | ||
369 | /* | 369 | /* |
370 | * OTG controllers and transceivers need software interaction; | 370 | * OTG controllers and transceivers need software interaction; |
371 | * other external transceivers should be software-transparent | 371 | * other external transceivers should be software-transparent |
372 | */ | 372 | */ |
373 | struct otg_transceiver *transceiver; | 373 | struct otg_transceiver *transceiver; |
374 | 374 | ||
@@ -385,7 +385,7 @@ struct ohci_hcd { | |||
385 | */ | 385 | */ |
386 | int num_ports; | 386 | int num_ports; |
387 | int load [NUM_INTS]; | 387 | int load [NUM_INTS]; |
388 | u32 hc_control; /* copy of hc control reg */ | 388 | u32 hc_control; /* copy of hc control reg */ |
389 | unsigned long next_statechange; /* suspend/resume */ | 389 | unsigned long next_statechange; /* suspend/resume */ |
390 | u32 fminterval; /* saved register */ | 390 | u32 fminterval; /* saved register */ |
391 | unsigned autostop:1; /* rh auto stopping/stopped */ | 391 | unsigned autostop:1; /* rh auto stopping/stopped */ |
@@ -394,8 +394,9 @@ struct ohci_hcd { | |||
394 | #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ | 394 | #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ |
395 | #define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */ | 395 | #define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */ |
396 | #define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi, ... */ | 396 | #define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi, ... */ |
397 | #define OHCI_BIG_ENDIAN 0x08 /* big endian HC */ | 397 | #define OHCI_QUIRK_BE_DESC 0x08 /* BE descriptors */ |
398 | #define OHCI_QUIRK_ZFMICRO 0x10 /* Compaq ZFMicro chipset*/ | 398 | #define OHCI_QUIRK_BE_MMIO 0x10 /* BE registers */ |
399 | #define OHCI_QUIRK_ZFMICRO 0x20 /* Compaq ZFMicro chipset*/ | ||
399 | // there are also chip quirks/bugs in init logic | 400 | // there are also chip quirks/bugs in init logic |
400 | 401 | ||
401 | }; | 402 | }; |
@@ -439,117 +440,164 @@ static inline struct usb_hcd *ohci_to_hcd (const struct ohci_hcd *ohci) | |||
439 | * a minority (notably the IBM STB04XXX and the Motorola MPC5200 | 440 | * a minority (notably the IBM STB04XXX and the Motorola MPC5200 |
440 | * processors) implement them in big endian format. | 441 | * processors) implement them in big endian format. |
441 | * | 442 | * |
443 | * In addition some more exotic implementations like the Toshiba | ||
444 | * Spider (aka SCC) cell southbridge are "mixed" endian, that is, | ||
445 | * they have a different endianness for registers vs. in-memory | ||
446 | * descriptors. | ||
447 | * | ||
442 | * This attempts to support either format at compile time without a | 448 | * This attempts to support either format at compile time without a |
443 | * runtime penalty, or both formats with the additional overhead | 449 | * runtime penalty, or both formats with the additional overhead |
444 | * of checking a flag bit. | 450 | * of checking a flag bit. |
451 | * | ||
452 | * That leads to some tricky Kconfig rules howevber. There are | ||
453 | * different defaults based on some arch/ppc platforms, though | ||
454 | * the basic rules are: | ||
455 | * | ||
456 | * Controller type Kconfig options needed | ||
457 | * --------------- ---------------------- | ||
458 | * little endian CONFIG_USB_OHCI_LITTLE_ENDIAN | ||
459 | * | ||
460 | * fully big endian CONFIG_USB_OHCI_BIG_ENDIAN_DESC _and_ | ||
461 | * CONFIG_USB_OHCI_BIG_ENDIAN_MMIO | ||
462 | * | ||
463 | * mixed endian CONFIG_USB_OHCI_LITTLE_ENDIAN _and_ | ||
464 | * CONFIG_USB_OHCI_BIG_ENDIAN_{MMIO,DESC} | ||
465 | * | ||
466 | * (If you have a mixed endian controller, you -must- also define | ||
467 | * CONFIG_USB_OHCI_LITTLE_ENDIAN or things will not work when building | ||
468 | * both your mixed endian and a fully big endian controller support in | ||
469 | * the same kernel image). | ||
445 | */ | 470 | */ |
446 | 471 | ||
447 | #ifdef CONFIG_USB_OHCI_BIG_ENDIAN | 472 | #ifdef CONFIG_USB_OHCI_BIG_ENDIAN_DESC |
473 | #ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN | ||
474 | #define big_endian_desc(ohci) (ohci->flags & OHCI_QUIRK_BE_DESC) | ||
475 | #else | ||
476 | #define big_endian_desc(ohci) 1 /* only big endian */ | ||
477 | #endif | ||
478 | #else | ||
479 | #define big_endian_desc(ohci) 0 /* only little endian */ | ||
480 | #endif | ||
448 | 481 | ||
482 | #ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO | ||
449 | #ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN | 483 | #ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN |
450 | #define big_endian(ohci) (ohci->flags & OHCI_BIG_ENDIAN) /* either */ | 484 | #define big_endian_mmio(ohci) (ohci->flags & OHCI_QUIRK_BE_MMIO) |
485 | #else | ||
486 | #define big_endian_mmio(ohci) 1 /* only big endian */ | ||
487 | #endif | ||
451 | #else | 488 | #else |
452 | #define big_endian(ohci) 1 /* only big endian */ | 489 | #define big_endian_mmio(ohci) 0 /* only little endian */ |
453 | #endif | 490 | #endif |
454 | 491 | ||
455 | /* | 492 | /* |
456 | * Big-endian read/write functions are arch-specific. | 493 | * Big-endian read/write functions are arch-specific. |
457 | * Other arches can be added if/when they're needed. | 494 | * Other arches can be added if/when they're needed. |
495 | * | ||
496 | * REVISIT: arch/powerpc now has readl/writel_be, so the | ||
497 | * definition below can die once the STB04xxx support is | ||
498 | * finally ported over. | ||
458 | */ | 499 | */ |
459 | #if defined(CONFIG_PPC) | 500 | #if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE) |
460 | #define readl_be(addr) in_be32((__force unsigned *)addr) | 501 | #define readl_be(addr) in_be32((__force unsigned *)addr) |
461 | #define writel_be(val, addr) out_be32((__force unsigned *)addr, val) | 502 | #define writel_be(val, addr) out_be32((__force unsigned *)addr, val) |
462 | #endif | 503 | #endif |
463 | 504 | ||
464 | static inline unsigned int ohci_readl (const struct ohci_hcd *ohci, | 505 | static inline unsigned int _ohci_readl (const struct ohci_hcd *ohci, |
465 | __hc32 __iomem * regs) | 506 | __hc32 __iomem * regs) |
466 | { | 507 | { |
467 | return big_endian(ohci) ? readl_be (regs) : readl ((__force u32 *)regs); | 508 | #ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO |
509 | return big_endian_mmio(ohci) ? | ||
510 | readl_be (regs) : | ||
511 | readl (regs); | ||
512 | #else | ||
513 | return readl (regs); | ||
514 | #endif | ||
468 | } | 515 | } |
469 | 516 | ||
470 | static inline void ohci_writel (const struct ohci_hcd *ohci, | 517 | static inline void _ohci_writel (const struct ohci_hcd *ohci, |
471 | const unsigned int val, __hc32 __iomem *regs) | 518 | const unsigned int val, __hc32 __iomem *regs) |
472 | { | 519 | { |
473 | big_endian(ohci) ? writel_be (val, regs) : | 520 | #ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO |
474 | writel (val, (__force u32 *)regs); | 521 | big_endian_mmio(ohci) ? |
522 | writel_be (val, regs) : | ||
523 | writel (val, regs); | ||
524 | #else | ||
525 | writel (val, regs); | ||
526 | #endif | ||
475 | } | 527 | } |
476 | 528 | ||
477 | #else /* !CONFIG_USB_OHCI_BIG_ENDIAN */ | ||
478 | |||
479 | #define big_endian(ohci) 0 /* only little endian */ | ||
480 | |||
481 | #ifdef CONFIG_ARCH_LH7A404 | 529 | #ifdef CONFIG_ARCH_LH7A404 |
482 | /* Marc Singer: at the time this code was written, the LH7A404 | 530 | /* Marc Singer: at the time this code was written, the LH7A404 |
483 | * had a problem reading the USB host registers. This | 531 | * had a problem reading the USB host registers. This |
484 | * implementation of the ohci_readl function performs the read | 532 | * implementation of the ohci_readl function performs the read |
485 | * twice as a work-around. | 533 | * twice as a work-around. |
486 | */ | 534 | */ |
487 | static inline unsigned int | 535 | #define ohci_readl(o,r) (_ohci_readl(o,r),_ohci_readl(o,r)) |
488 | ohci_readl (const struct ohci_hcd *ohci, const __hc32 *regs) | 536 | #define ohci_writel(o,v,r) _ohci_writel(o,v,r) |
489 | { | ||
490 | *(volatile __force unsigned int*) regs; | ||
491 | return *(volatile __force unsigned int*) regs; | ||
492 | } | ||
493 | #else | 537 | #else |
494 | /* Standard version of ohci_readl uses standard, platform | 538 | #define ohci_readl(o,r) _ohci_readl(o,r) |
495 | * specific implementation. */ | 539 | #define ohci_writel(o,v,r) _ohci_writel(o,v,r) |
496 | static inline unsigned int | ||
497 | ohci_readl (const struct ohci_hcd *ohci, __hc32 __iomem * regs) | ||
498 | { | ||
499 | return readl(regs); | ||
500 | } | ||
501 | #endif | 540 | #endif |
502 | 541 | ||
503 | static inline void ohci_writel (const struct ohci_hcd *ohci, | ||
504 | const unsigned int val, __hc32 __iomem *regs) | ||
505 | { | ||
506 | writel (val, regs); | ||
507 | } | ||
508 | |||
509 | #endif /* !CONFIG_USB_OHCI_BIG_ENDIAN */ | ||
510 | 542 | ||
511 | /*-------------------------------------------------------------------------*/ | 543 | /*-------------------------------------------------------------------------*/ |
512 | 544 | ||
513 | /* cpu to ohci */ | 545 | /* cpu to ohci */ |
514 | static inline __hc16 cpu_to_hc16 (const struct ohci_hcd *ohci, const u16 x) | 546 | static inline __hc16 cpu_to_hc16 (const struct ohci_hcd *ohci, const u16 x) |
515 | { | 547 | { |
516 | return big_endian(ohci) ? (__force __hc16)cpu_to_be16(x) : (__force __hc16)cpu_to_le16(x); | 548 | return big_endian_desc(ohci) ? |
549 | (__force __hc16)cpu_to_be16(x) : | ||
550 | (__force __hc16)cpu_to_le16(x); | ||
517 | } | 551 | } |
518 | 552 | ||
519 | static inline __hc16 cpu_to_hc16p (const struct ohci_hcd *ohci, const u16 *x) | 553 | static inline __hc16 cpu_to_hc16p (const struct ohci_hcd *ohci, const u16 *x) |
520 | { | 554 | { |
521 | return big_endian(ohci) ? cpu_to_be16p(x) : cpu_to_le16p(x); | 555 | return big_endian_desc(ohci) ? |
556 | cpu_to_be16p(x) : | ||
557 | cpu_to_le16p(x); | ||
522 | } | 558 | } |
523 | 559 | ||
524 | static inline __hc32 cpu_to_hc32 (const struct ohci_hcd *ohci, const u32 x) | 560 | static inline __hc32 cpu_to_hc32 (const struct ohci_hcd *ohci, const u32 x) |
525 | { | 561 | { |
526 | return big_endian(ohci) ? (__force __hc32)cpu_to_be32(x) : (__force __hc32)cpu_to_le32(x); | 562 | return big_endian_desc(ohci) ? |
563 | (__force __hc32)cpu_to_be32(x) : | ||
564 | (__force __hc32)cpu_to_le32(x); | ||
527 | } | 565 | } |
528 | 566 | ||
529 | static inline __hc32 cpu_to_hc32p (const struct ohci_hcd *ohci, const u32 *x) | 567 | static inline __hc32 cpu_to_hc32p (const struct ohci_hcd *ohci, const u32 *x) |
530 | { | 568 | { |
531 | return big_endian(ohci) ? cpu_to_be32p(x) : cpu_to_le32p(x); | 569 | return big_endian_desc(ohci) ? |
570 | cpu_to_be32p(x) : | ||
571 | cpu_to_le32p(x); | ||
532 | } | 572 | } |
533 | 573 | ||
534 | /* ohci to cpu */ | 574 | /* ohci to cpu */ |
535 | static inline u16 hc16_to_cpu (const struct ohci_hcd *ohci, const __hc16 x) | 575 | static inline u16 hc16_to_cpu (const struct ohci_hcd *ohci, const __hc16 x) |
536 | { | 576 | { |
537 | return big_endian(ohci) ? be16_to_cpu((__force __be16)x) : le16_to_cpu((__force __le16)x); | 577 | return big_endian_desc(ohci) ? |
578 | be16_to_cpu((__force __be16)x) : | ||
579 | le16_to_cpu((__force __le16)x); | ||
538 | } | 580 | } |
539 | 581 | ||
540 | static inline u16 hc16_to_cpup (const struct ohci_hcd *ohci, const __hc16 *x) | 582 | static inline u16 hc16_to_cpup (const struct ohci_hcd *ohci, const __hc16 *x) |
541 | { | 583 | { |
542 | return big_endian(ohci) ? be16_to_cpup((__force __be16 *)x) : le16_to_cpup((__force __le16 *)x); | 584 | return big_endian_desc(ohci) ? |
585 | be16_to_cpup((__force __be16 *)x) : | ||
586 | le16_to_cpup((__force __le16 *)x); | ||
543 | } | 587 | } |
544 | 588 | ||
545 | static inline u32 hc32_to_cpu (const struct ohci_hcd *ohci, const __hc32 x) | 589 | static inline u32 hc32_to_cpu (const struct ohci_hcd *ohci, const __hc32 x) |
546 | { | 590 | { |
547 | return big_endian(ohci) ? be32_to_cpu((__force __be32)x) : le32_to_cpu((__force __le32)x); | 591 | return big_endian_desc(ohci) ? |
592 | be32_to_cpu((__force __be32)x) : | ||
593 | le32_to_cpu((__force __le32)x); | ||
548 | } | 594 | } |
549 | 595 | ||
550 | static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x) | 596 | static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x) |
551 | { | 597 | { |
552 | return big_endian(ohci) ? be32_to_cpup((__force __be32 *)x) : le32_to_cpup((__force __le32 *)x); | 598 | return big_endian_desc(ohci) ? |
599 | be32_to_cpup((__force __be32 *)x) : | ||
600 | le32_to_cpup((__force __le32 *)x); | ||
553 | } | 601 | } |
554 | 602 | ||
555 | /*-------------------------------------------------------------------------*/ | 603 | /*-------------------------------------------------------------------------*/ |
@@ -557,6 +605,9 @@ static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x) | |||
557 | /* HCCA frame number is 16 bits, but is accessed as 32 bits since not all | 605 | /* HCCA frame number is 16 bits, but is accessed as 32 bits since not all |
558 | * hardware handles 16 bit reads. That creates a different confusion on | 606 | * hardware handles 16 bit reads. That creates a different confusion on |
559 | * some big-endian SOC implementations. Same thing happens with PSW access. | 607 | * some big-endian SOC implementations. Same thing happens with PSW access. |
608 | * | ||
609 | * FIXME: Deal with that as a runtime quirk when STB03xxx is ported over | ||
610 | * to arch/powerpc | ||
560 | */ | 611 | */ |
561 | 612 | ||
562 | #ifdef CONFIG_STB03xxx | 613 | #ifdef CONFIG_STB03xxx |
@@ -568,7 +619,7 @@ static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x) | |||
568 | static inline u16 ohci_frame_no(const struct ohci_hcd *ohci) | 619 | static inline u16 ohci_frame_no(const struct ohci_hcd *ohci) |
569 | { | 620 | { |
570 | u32 tmp; | 621 | u32 tmp; |
571 | if (big_endian(ohci)) { | 622 | if (big_endian_desc(ohci)) { |
572 | tmp = be32_to_cpup((__force __be32 *)&ohci->hcca->frame_no); | 623 | tmp = be32_to_cpup((__force __be32 *)&ohci->hcca->frame_no); |
573 | tmp >>= OHCI_BE_FRAME_NO_SHIFT; | 624 | tmp >>= OHCI_BE_FRAME_NO_SHIFT; |
574 | } else | 625 | } else |
@@ -580,7 +631,7 @@ static inline u16 ohci_frame_no(const struct ohci_hcd *ohci) | |||
580 | static inline __hc16 *ohci_hwPSWp(const struct ohci_hcd *ohci, | 631 | static inline __hc16 *ohci_hwPSWp(const struct ohci_hcd *ohci, |
581 | const struct td *td, int index) | 632 | const struct td *td, int index) |
582 | { | 633 | { |
583 | return (__hc16 *)(big_endian(ohci) ? | 634 | return (__hc16 *)(big_endian_desc(ohci) ? |
584 | &td->hwPSW[index ^ 1] : &td->hwPSW[index]); | 635 | &td->hwPSW[index ^ 1] : &td->hwPSW[index]); |
585 | } | 636 | } |
586 | 637 | ||
@@ -598,11 +649,11 @@ static inline void disable (struct ohci_hcd *ohci) | |||
598 | } | 649 | } |
599 | 650 | ||
600 | #define FI 0x2edf /* 12000 bits per frame (-1) */ | 651 | #define FI 0x2edf /* 12000 bits per frame (-1) */ |
601 | #define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7)) | 652 | #define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7)) |
602 | #define FIT (1 << 31) | 653 | #define FIT (1 << 31) |
603 | #define LSTHRESH 0x628 /* lowspeed bit threshold */ | 654 | #define LSTHRESH 0x628 /* lowspeed bit threshold */ |
604 | 655 | ||
605 | static void periodic_reinit (struct ohci_hcd *ohci) | 656 | static inline void periodic_reinit (struct ohci_hcd *ohci) |
606 | { | 657 | { |
607 | u32 fi = ohci->fminterval & 0x03fff; | 658 | u32 fi = ohci->fminterval & 0x03fff; |
608 | u32 fit = ohci_readl(ohci, &ohci->regs->fminterval) & FIT; | 659 | u32 fit = ohci_readl(ohci, &ohci->regs->fminterval) & FIT; |
@@ -626,11 +677,11 @@ static void periodic_reinit (struct ohci_hcd *ohci) | |||
626 | temp = ohci_readl (hc, &hc->regs->roothub.register); \ | 677 | temp = ohci_readl (hc, &hc->regs->roothub.register); \ |
627 | temp; }) | 678 | temp; }) |
628 | 679 | ||
629 | static u32 roothub_a (struct ohci_hcd *hc) | 680 | static inline u32 roothub_a (struct ohci_hcd *hc) |
630 | { return read_roothub (hc, a, 0xfc0fe000); } | 681 | { return read_roothub (hc, a, 0xfc0fe000); } |
631 | static inline u32 roothub_b (struct ohci_hcd *hc) | 682 | static inline u32 roothub_b (struct ohci_hcd *hc) |
632 | { return ohci_readl (hc, &hc->regs->roothub.b); } | 683 | { return ohci_readl (hc, &hc->regs->roothub.b); } |
633 | static inline u32 roothub_status (struct ohci_hcd *hc) | 684 | static inline u32 roothub_status (struct ohci_hcd *hc) |
634 | { return ohci_readl (hc, &hc->regs->roothub.status); } | 685 | { return ohci_readl (hc, &hc->regs->roothub.status); } |
635 | static u32 roothub_portstatus (struct ohci_hcd *hc, int i) | 686 | static inline u32 roothub_portstatus (struct ohci_hcd *hc, int i) |
636 | { return read_roothub (hc, portstatus [i], 0xffe0fce0); } | 687 | { return read_roothub (hc, portstatus [i], 0xffe0fce0); } |
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index a9d7119e3176..a7fa0d75567d 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/moduleparam.h> | 40 | #include <linux/moduleparam.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/ioport.h> | 42 | #include <linux/ioport.h> |
43 | #include <linux/pci_ids.h> | ||
43 | #include <linux/sched.h> | 44 | #include <linux/sched.h> |
44 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
45 | #include <linux/smp_lock.h> | 46 | #include <linux/smp_lock.h> |
@@ -210,15 +211,16 @@ struct u132 { | |||
210 | * these cannot be inlines because we need the structure offset!! | 211 | * these cannot be inlines because we need the structure offset!! |
211 | * Does anyone have a better way????? | 212 | * Does anyone have a better way????? |
212 | */ | 213 | */ |
214 | #define ftdi_read_pcimem(pdev, member, data) usb_ftdi_elan_read_pcimem(pdev, \ | ||
215 | offsetof(struct ohci_regs, member), 0, data); | ||
216 | #define ftdi_write_pcimem(pdev, member, data) usb_ftdi_elan_write_pcimem(pdev, \ | ||
217 | offsetof(struct ohci_regs, member), 0, data); | ||
213 | #define u132_read_pcimem(u132, member, data) \ | 218 | #define u132_read_pcimem(u132, member, data) \ |
214 | usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \ | 219 | usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \ |
215 | ohci_regs, member), 0, data); | 220 | ohci_regs, member), 0, data); |
216 | #define u132_write_pcimem(u132, member, data) \ | 221 | #define u132_write_pcimem(u132, member, data) \ |
217 | usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \ | 222 | usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \ |
218 | ohci_regs, member), 0, data); | 223 | ohci_regs, member), 0, data); |
219 | #define u132_write_pcimem_byte(u132, member, data) \ | ||
220 | usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \ | ||
221 | ohci_regs, member), 0x0e, data); | ||
222 | static inline struct u132 *udev_to_u132(struct u132_udev *udev) | 224 | static inline struct u132 *udev_to_u132(struct u132_udev *udev) |
223 | { | 225 | { |
224 | u8 udev_number = udev->udev_number; | 226 | u8 udev_number = udev->udev_number; |
@@ -1574,59 +1576,12 @@ static char *hcfs2string(int state) | |||
1574 | return "?"; | 1576 | return "?"; |
1575 | } | 1577 | } |
1576 | 1578 | ||
1577 | static int u132_usb_reset(struct u132 *u132) | ||
1578 | { | ||
1579 | int retval; | ||
1580 | retval = u132_read_pcimem(u132, control, &u132->hc_control); | ||
1581 | if (retval) | ||
1582 | return retval; | ||
1583 | u132->hc_control &= OHCI_CTRL_RWC; | ||
1584 | retval = u132_write_pcimem(u132, control, u132->hc_control); | ||
1585 | if (retval) | ||
1586 | return retval; | ||
1587 | return 0; | ||
1588 | } | ||
1589 | |||
1590 | static int u132_init(struct u132 *u132) | 1579 | static int u132_init(struct u132 *u132) |
1591 | { | 1580 | { |
1592 | int retval; | 1581 | int retval; |
1593 | u32 control; | 1582 | u32 control; |
1594 | u132_disable(u132); | 1583 | u132_disable(u132); |
1595 | u132->next_statechange = | 1584 | u132->next_statechange = jiffies; |
1596 | jiffies; /* SMM owns the HC? not for long! */ { | ||
1597 | u32 control; | ||
1598 | retval = u132_read_pcimem(u132, control, &control); | ||
1599 | if (retval) | ||
1600 | return retval; | ||
1601 | if (control & OHCI_CTRL_IR) { | ||
1602 | u32 temp = 50; | ||
1603 | retval = u132_write_pcimem(u132, intrenable, | ||
1604 | OHCI_INTR_OC); | ||
1605 | if (retval) | ||
1606 | return retval; | ||
1607 | retval = u132_write_pcimem_byte(u132, cmdstatus, | ||
1608 | OHCI_OCR); | ||
1609 | if (retval) | ||
1610 | return retval; | ||
1611 | check:{ | ||
1612 | retval = u132_read_pcimem(u132, control, | ||
1613 | &control); | ||
1614 | if (retval) | ||
1615 | return retval; | ||
1616 | } | ||
1617 | if (control & OHCI_CTRL_IR) { | ||
1618 | msleep(10); | ||
1619 | if (--temp == 0) { | ||
1620 | dev_err(&u132->platform_dev->dev, "USB " | ||
1621 | "HC takeover failed!(BIOS/SMM b" | ||
1622 | "ug) control=%08X\n", control); | ||
1623 | return -EBUSY; | ||
1624 | } | ||
1625 | goto check; | ||
1626 | } | ||
1627 | u132_usb_reset(u132); | ||
1628 | } | ||
1629 | } | ||
1630 | retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE); | 1585 | retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE); |
1631 | if (retval) | 1586 | if (retval) |
1632 | return retval; | 1587 | return retval; |
@@ -1725,7 +1680,7 @@ static int u132_run(struct u132 *u132) | |||
1725 | retry:retval = u132_read_pcimem(u132, cmdstatus, &status); | 1680 | retry:retval = u132_read_pcimem(u132, cmdstatus, &status); |
1726 | if (retval) | 1681 | if (retval) |
1727 | return retval; | 1682 | return retval; |
1728 | retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_HCR); | 1683 | retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR); |
1729 | if (retval) | 1684 | if (retval) |
1730 | return retval; | 1685 | return retval; |
1731 | extra:{ | 1686 | extra:{ |
@@ -1782,7 +1737,7 @@ static int u132_run(struct u132 *u132) | |||
1782 | retval = u132_write_pcimem(u132, control, u132->hc_control); | 1737 | retval = u132_write_pcimem(u132, control, u132->hc_control); |
1783 | if (retval) | 1738 | if (retval) |
1784 | return retval; | 1739 | return retval; |
1785 | retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_BLF); | 1740 | retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF); |
1786 | if (retval) | 1741 | if (retval) |
1787 | return retval; | 1742 | return retval; |
1788 | retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus); | 1743 | retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus); |
@@ -1839,8 +1794,8 @@ static void u132_hcd_stop(struct usb_hcd *hcd) | |||
1839 | { | 1794 | { |
1840 | struct u132 *u132 = hcd_to_u132(hcd); | 1795 | struct u132 *u132 = hcd_to_u132(hcd); |
1841 | if (u132->going > 1) { | 1796 | if (u132->going > 1) { |
1842 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 1797 | dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b" |
1843 | , u132->going); | 1798 | "een removed %d\n", u132, hcd, u132->going); |
1844 | } else if (u132->going > 0) { | 1799 | } else if (u132->going > 0) { |
1845 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" | 1800 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" |
1846 | "ed\n", hcd); | 1801 | "ed\n", hcd); |
@@ -2545,8 +2500,9 @@ static void u132_endpoint_disable(struct usb_hcd *hcd, | |||
2545 | { | 2500 | { |
2546 | struct u132 *u132 = hcd_to_u132(hcd); | 2501 | struct u132 *u132 = hcd_to_u132(hcd); |
2547 | if (u132->going > 2) { | 2502 | if (u132->going > 2) { |
2548 | dev_err(&u132->platform_dev->dev, "device has been removed %d\n" | 2503 | dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p" |
2549 | , u132->going); | 2504 | ") has been removed %d\n", u132, hcd, hep, |
2505 | u132->going); | ||
2550 | } else { | 2506 | } else { |
2551 | struct u132_endp *endp = hep->hcpriv; | 2507 | struct u132_endp *endp = hep->hcpriv; |
2552 | if (endp) | 2508 | if (endp) |
@@ -2790,7 +2746,6 @@ static int u132_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
2790 | } else if (u132->going > 0) { | 2746 | } else if (u132->going > 0) { |
2791 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" | 2747 | dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov" |
2792 | "ed\n", hcd); | 2748 | "ed\n", hcd); |
2793 | dump_stack(); | ||
2794 | return -ESHUTDOWN; | 2749 | return -ESHUTDOWN; |
2795 | } else { | 2750 | } else { |
2796 | int i, changed = 0, length = 1; | 2751 | int i, changed = 0, length = 1; |
@@ -3034,12 +2989,15 @@ static int __devexit u132_remove(struct platform_device *pdev) | |||
3034 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 2989 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
3035 | if (hcd) { | 2990 | if (hcd) { |
3036 | struct u132 *u132 = hcd_to_u132(hcd); | 2991 | struct u132 *u132 = hcd_to_u132(hcd); |
3037 | dump_stack(); | ||
3038 | if (u132->going++ > 1) { | 2992 | if (u132->going++ > 1) { |
2993 | dev_err(&u132->platform_dev->dev, "already being remove" | ||
2994 | "d\n"); | ||
3039 | return -ENODEV; | 2995 | return -ENODEV; |
3040 | } else { | 2996 | } else { |
3041 | int rings = MAX_U132_RINGS; | 2997 | int rings = MAX_U132_RINGS; |
3042 | int endps = MAX_U132_ENDPS; | 2998 | int endps = MAX_U132_ENDPS; |
2999 | dev_err(&u132->platform_dev->dev, "removing device u132" | ||
3000 | ".%d\n", u132->sequence_num); | ||
3043 | msleep(100); | 3001 | msleep(100); |
3044 | down(&u132->sw_lock); | 3002 | down(&u132->sw_lock); |
3045 | u132_monitor_cancel_work(u132); | 3003 | u132_monitor_cancel_work(u132); |
@@ -3121,10 +3079,24 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev) | |||
3121 | static int __devinit u132_probe(struct platform_device *pdev) | 3079 | static int __devinit u132_probe(struct platform_device *pdev) |
3122 | { | 3080 | { |
3123 | struct usb_hcd *hcd; | 3081 | struct usb_hcd *hcd; |
3082 | int retval; | ||
3083 | u32 control; | ||
3084 | u32 rh_a = -1; | ||
3085 | u32 num_ports; | ||
3124 | msleep(100); | 3086 | msleep(100); |
3125 | if (u132_exiting > 0) { | 3087 | if (u132_exiting > 0) { |
3126 | return -ENODEV; | 3088 | return -ENODEV; |
3127 | } /* refuse to confuse usbcore */ | 3089 | } |
3090 | retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE); | ||
3091 | if (retval) | ||
3092 | return retval; | ||
3093 | retval = ftdi_read_pcimem(pdev, control, &control); | ||
3094 | if (retval) | ||
3095 | return retval; | ||
3096 | retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a); | ||
3097 | if (retval) | ||
3098 | return retval; | ||
3099 | num_ports = rh_a & RH_A_NDP; /* refuse to confuse usbcore */ | ||
3128 | if (pdev->dev.dma_mask) { | 3100 | if (pdev->dev.dma_mask) { |
3129 | return -EINVAL; | 3101 | return -EINVAL; |
3130 | } | 3102 | } |
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index e345f15b7d87..5d6c06bc4524 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c | |||
@@ -168,9 +168,13 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) | |||
168 | space, "", qh, qtype, | 168 | space, "", qh, qtype, |
169 | le32_to_cpu(qh->link), le32_to_cpu(element)); | 169 | le32_to_cpu(qh->link), le32_to_cpu(element)); |
170 | if (qh->type == USB_ENDPOINT_XFER_ISOC) | 170 | if (qh->type == USB_ENDPOINT_XFER_ISOC) |
171 | out += sprintf(out, "%*s period %d frame %x desc [%p]\n", | 171 | out += sprintf(out, "%*s period %d phase %d load %d us, " |
172 | space, "", qh->period, qh->iso_frame, | 172 | "frame %x desc [%p]\n", |
173 | qh->iso_packet_desc); | 173 | space, "", qh->period, qh->phase, qh->load, |
174 | qh->iso_frame, qh->iso_packet_desc); | ||
175 | else if (qh->type == USB_ENDPOINT_XFER_INT) | ||
176 | out += sprintf(out, "%*s period %d phase %d load %d us\n", | ||
177 | space, "", qh->period, qh->phase, qh->load); | ||
174 | 178 | ||
175 | if (element & UHCI_PTR_QH) | 179 | if (element & UHCI_PTR_QH) |
176 | out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); | 180 | out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); |
@@ -208,7 +212,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space) | |||
208 | space, "", nurbs); | 212 | space, "", nurbs); |
209 | } | 213 | } |
210 | 214 | ||
211 | if (qh->udev) { | 215 | if (qh->dummy_td) { |
212 | out += sprintf(out, "%*s Dummy TD\n", space, ""); | 216 | out += sprintf(out, "%*s Dummy TD\n", space, ""); |
213 | out += uhci_show_td(qh->dummy_td, out, len - (out - buf), 0); | 217 | out += uhci_show_td(qh->dummy_td, out, len - (out - buf), 0); |
214 | } | 218 | } |
@@ -347,31 +351,80 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) | |||
347 | struct uhci_qh *qh; | 351 | struct uhci_qh *qh; |
348 | struct uhci_td *td; | 352 | struct uhci_td *td; |
349 | struct list_head *tmp, *head; | 353 | struct list_head *tmp, *head; |
354 | int nframes, nerrs; | ||
350 | 355 | ||
351 | out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); | 356 | out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); |
352 | out += sprintf(out, "HC status\n"); | 357 | out += sprintf(out, "HC status\n"); |
353 | out += uhci_show_status(uhci, out, len - (out - buf)); | 358 | out += uhci_show_status(uhci, out, len - (out - buf)); |
359 | |||
360 | out += sprintf(out, "Periodic load table\n"); | ||
361 | for (i = 0; i < MAX_PHASE; ++i) { | ||
362 | out += sprintf(out, "\t%d", uhci->load[i]); | ||
363 | if (i % 8 == 7) | ||
364 | *out++ = '\n'; | ||
365 | } | ||
366 | out += sprintf(out, "Total: %d, #INT: %d, #ISO: %d\n", | ||
367 | uhci->total_load, | ||
368 | uhci_to_hcd(uhci)->self.bandwidth_int_reqs, | ||
369 | uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs); | ||
354 | if (debug <= 1) | 370 | if (debug <= 1) |
355 | return out - buf; | 371 | return out - buf; |
356 | 372 | ||
357 | out += sprintf(out, "Frame List\n"); | 373 | out += sprintf(out, "Frame List\n"); |
374 | nframes = 10; | ||
375 | nerrs = 0; | ||
358 | for (i = 0; i < UHCI_NUMFRAMES; ++i) { | 376 | for (i = 0; i < UHCI_NUMFRAMES; ++i) { |
377 | __le32 link, qh_dma; | ||
378 | |||
379 | j = 0; | ||
359 | td = uhci->frame_cpu[i]; | 380 | td = uhci->frame_cpu[i]; |
381 | link = uhci->frame[i]; | ||
360 | if (!td) | 382 | if (!td) |
361 | continue; | 383 | goto check_link; |
362 | 384 | ||
363 | out += sprintf(out, "- Frame %d\n", i); \ | 385 | if (nframes > 0) { |
364 | if (td->dma_handle != (dma_addr_t)uhci->frame[i]) | 386 | out += sprintf(out, "- Frame %d -> (%08x)\n", |
365 | out += sprintf(out, " frame list does not match td->dma_handle!\n"); | 387 | i, le32_to_cpu(link)); |
388 | j = 1; | ||
389 | } | ||
366 | 390 | ||
367 | head = &td->fl_list; | 391 | head = &td->fl_list; |
368 | tmp = head; | 392 | tmp = head; |
369 | do { | 393 | do { |
370 | td = list_entry(tmp, struct uhci_td, fl_list); | 394 | td = list_entry(tmp, struct uhci_td, fl_list); |
371 | tmp = tmp->next; | 395 | tmp = tmp->next; |
372 | out += uhci_show_td(td, out, len - (out - buf), 4); | 396 | if (cpu_to_le32(td->dma_handle) != link) { |
397 | if (nframes > 0) | ||
398 | out += sprintf(out, " link does " | ||
399 | "not match list entry!\n"); | ||
400 | else | ||
401 | ++nerrs; | ||
402 | } | ||
403 | if (nframes > 0) | ||
404 | out += uhci_show_td(td, out, | ||
405 | len - (out - buf), 4); | ||
406 | link = td->link; | ||
373 | } while (tmp != head); | 407 | } while (tmp != head); |
408 | |||
409 | check_link: | ||
410 | qh_dma = uhci_frame_skel_link(uhci, i); | ||
411 | if (link != qh_dma) { | ||
412 | if (nframes > 0) { | ||
413 | if (!j) { | ||
414 | out += sprintf(out, | ||
415 | "- Frame %d -> (%08x)\n", | ||
416 | i, le32_to_cpu(link)); | ||
417 | j = 1; | ||
418 | } | ||
419 | out += sprintf(out, " link does not match " | ||
420 | "QH (%08x)!\n", le32_to_cpu(qh_dma)); | ||
421 | } else | ||
422 | ++nerrs; | ||
423 | } | ||
424 | nframes -= j; | ||
374 | } | 425 | } |
426 | if (nerrs > 0) | ||
427 | out += sprintf(out, "Skipped %d bad links\n", nerrs); | ||
375 | 428 | ||
376 | out += sprintf(out, "Skeleton QHs\n"); | 429 | out += sprintf(out, "Skeleton QHs\n"); |
377 | 430 | ||
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index e87692c31be4..49b9d390b95f 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -60,6 +60,11 @@ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \ | |||
60 | Alan Stern" | 60 | Alan Stern" |
61 | #define DRIVER_DESC "USB Universal Host Controller Interface driver" | 61 | #define DRIVER_DESC "USB Universal Host Controller Interface driver" |
62 | 62 | ||
63 | /* for flakey hardware, ignore overcurrent indicators */ | ||
64 | static int ignore_oc; | ||
65 | module_param(ignore_oc, bool, S_IRUGO); | ||
66 | MODULE_PARM_DESC(ignore_oc, "ignore hardware overcurrent indications"); | ||
67 | |||
63 | /* | 68 | /* |
64 | * debug = 0, no debugging messages | 69 | * debug = 0, no debugging messages |
65 | * debug = 1, dump failed URBs except for stalls | 70 | * debug = 1, dump failed URBs except for stalls |
@@ -87,6 +92,34 @@ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state); | |||
87 | static void wakeup_rh(struct uhci_hcd *uhci); | 92 | static void wakeup_rh(struct uhci_hcd *uhci); |
88 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci); | 93 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci); |
89 | 94 | ||
95 | /* | ||
96 | * Calculate the link pointer DMA value for the first Skeleton QH in a frame. | ||
97 | */ | ||
98 | static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame) | ||
99 | { | ||
100 | int skelnum; | ||
101 | |||
102 | /* | ||
103 | * The interrupt queues will be interleaved as evenly as possible. | ||
104 | * There's not much to be done about period-1 interrupts; they have | ||
105 | * to occur in every frame. But we can schedule period-2 interrupts | ||
106 | * in odd-numbered frames, period-4 interrupts in frames congruent | ||
107 | * to 2 (mod 4), and so on. This way each frame only has two | ||
108 | * interrupt QHs, which will help spread out bandwidth utilization. | ||
109 | * | ||
110 | * ffs (Find First bit Set) does exactly what we need: | ||
111 | * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8], | ||
112 | * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc. | ||
113 | * ffs >= 7 => not on any high-period queue, so use | ||
114 | * skel_int1_qh = skelqh[9]. | ||
115 | * Add in UHCI_NUMFRAMES to insure at least one bit is set. | ||
116 | */ | ||
117 | skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES); | ||
118 | if (skelnum <= 1) | ||
119 | skelnum = 9; | ||
120 | return UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[skelnum]->dma_handle); | ||
121 | } | ||
122 | |||
90 | #include "uhci-debug.c" | 123 | #include "uhci-debug.c" |
91 | #include "uhci-q.c" | 124 | #include "uhci-q.c" |
92 | #include "uhci-hub.c" | 125 | #include "uhci-hub.c" |
@@ -169,6 +202,11 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci) | |||
169 | { | 202 | { |
170 | int port; | 203 | int port; |
171 | 204 | ||
205 | /* If we have to ignore overcurrent events then almost by definition | ||
206 | * we can't depend on resume-detect interrupts. */ | ||
207 | if (ignore_oc) | ||
208 | return 1; | ||
209 | |||
172 | switch (to_pci_dev(uhci_dev(uhci))->vendor) { | 210 | switch (to_pci_dev(uhci_dev(uhci))->vendor) { |
173 | default: | 211 | default: |
174 | break; | 212 | break; |
@@ -199,24 +237,16 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci) | |||
199 | 237 | ||
200 | static int remote_wakeup_is_broken(struct uhci_hcd *uhci) | 238 | static int remote_wakeup_is_broken(struct uhci_hcd *uhci) |
201 | { | 239 | { |
202 | static struct dmi_system_id broken_wakeup_table[] = { | ||
203 | { | ||
204 | .ident = "Asus A7V8X", | ||
205 | .matches = { | ||
206 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK"), | ||
207 | DMI_MATCH(DMI_BOARD_NAME, "A7V8X"), | ||
208 | DMI_MATCH(DMI_BOARD_VERSION, "REV 1.xx"), | ||
209 | } | ||
210 | }, | ||
211 | { } | ||
212 | }; | ||
213 | int port; | 240 | int port; |
241 | char *sys_info; | ||
242 | static char bad_Asus_board[] = "A7V8X"; | ||
214 | 243 | ||
215 | /* One of Asus's motherboards has a bug which causes it to | 244 | /* One of Asus's motherboards has a bug which causes it to |
216 | * wake up immediately from suspend-to-RAM if any of the ports | 245 | * wake up immediately from suspend-to-RAM if any of the ports |
217 | * are connected. In such cases we will not set EGSM. | 246 | * are connected. In such cases we will not set EGSM. |
218 | */ | 247 | */ |
219 | if (dmi_check_system(broken_wakeup_table)) { | 248 | sys_info = dmi_get_system_info(DMI_BOARD_NAME); |
249 | if (sys_info && !strcmp(sys_info, bad_Asus_board)) { | ||
220 | for (port = 0; port < uhci->rh_numports; ++port) { | 250 | for (port = 0; port < uhci->rh_numports; ++port) { |
221 | if (inw(uhci->io_addr + USBPORTSC1 + port * 2) & | 251 | if (inw(uhci->io_addr + USBPORTSC1 + port * 2) & |
222 | USBPORTSC_CCS) | 252 | USBPORTSC_CCS) |
@@ -255,7 +285,9 @@ __acquires(uhci->lock) | |||
255 | int_enable = USBINTR_RESUME; | 285 | int_enable = USBINTR_RESUME; |
256 | if (remote_wakeup_is_broken(uhci)) | 286 | if (remote_wakeup_is_broken(uhci)) |
257 | egsm_enable = 0; | 287 | egsm_enable = 0; |
258 | if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable) | 288 | if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable || |
289 | !device_may_wakeup( | ||
290 | &uhci_to_hcd(uhci)->self.root_hub->dev)) | ||
259 | uhci->working_RD = int_enable = 0; | 291 | uhci->working_RD = int_enable = 0; |
260 | 292 | ||
261 | outw(int_enable, uhci->io_addr + USBINTR); | 293 | outw(int_enable, uhci->io_addr + USBINTR); |
@@ -627,32 +659,11 @@ static int uhci_start(struct usb_hcd *hcd) | |||
627 | /* | 659 | /* |
628 | * Fill the frame list: make all entries point to the proper | 660 | * Fill the frame list: make all entries point to the proper |
629 | * interrupt queue. | 661 | * interrupt queue. |
630 | * | ||
631 | * The interrupt queues will be interleaved as evenly as possible. | ||
632 | * There's not much to be done about period-1 interrupts; they have | ||
633 | * to occur in every frame. But we can schedule period-2 interrupts | ||
634 | * in odd-numbered frames, period-4 interrupts in frames congruent | ||
635 | * to 2 (mod 4), and so on. This way each frame only has two | ||
636 | * interrupt QHs, which will help spread out bandwidth utilization. | ||
637 | */ | 662 | */ |
638 | for (i = 0; i < UHCI_NUMFRAMES; i++) { | 663 | for (i = 0; i < UHCI_NUMFRAMES; i++) { |
639 | int irq; | ||
640 | |||
641 | /* | ||
642 | * ffs (Find First bit Set) does exactly what we need: | ||
643 | * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[8], | ||
644 | * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc. | ||
645 | * ffs >= 7 => not on any high-period queue, so use | ||
646 | * skel_int1_qh = skelqh[9]. | ||
647 | * Add UHCI_NUMFRAMES to insure at least one bit is set. | ||
648 | */ | ||
649 | irq = 8 - (int) __ffs(i + UHCI_NUMFRAMES); | ||
650 | if (irq <= 1) | ||
651 | irq = 9; | ||
652 | 664 | ||
653 | /* Only place we don't use the frame list routines */ | 665 | /* Only place we don't use the frame list routines */ |
654 | uhci->frame[i] = UHCI_PTR_QH | | 666 | uhci->frame[i] = uhci_frame_skel_link(uhci, i); |
655 | cpu_to_le32(uhci->skelqh[irq]->dma_handle); | ||
656 | } | 667 | } |
657 | 668 | ||
658 | /* | 669 | /* |
@@ -921,7 +932,8 @@ static int __init uhci_hcd_init(void) | |||
921 | { | 932 | { |
922 | int retval = -ENOMEM; | 933 | int retval = -ENOMEM; |
923 | 934 | ||
924 | printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "\n"); | 935 | printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n", |
936 | ignore_oc ? ", overcurrent ignored" : ""); | ||
925 | 937 | ||
926 | if (usb_disabled()) | 938 | if (usb_disabled()) |
927 | return -ENODEV; | 939 | return -ENODEV; |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 108e3de2dc26..74469b5bcb61 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
@@ -83,6 +83,7 @@ | |||
83 | #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ | 83 | #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ |
84 | #define CAN_SCHEDULE_FRAMES 1000 /* how far in the future frames | 84 | #define CAN_SCHEDULE_FRAMES 1000 /* how far in the future frames |
85 | * can be scheduled */ | 85 | * can be scheduled */ |
86 | #define MAX_PHASE 32 /* Periodic scheduling length */ | ||
86 | 87 | ||
87 | /* When no queues need Full-Speed Bandwidth Reclamation, | 88 | /* When no queues need Full-Speed Bandwidth Reclamation, |
88 | * delay this long before turning FSBR off */ | 89 | * delay this long before turning FSBR off */ |
@@ -141,6 +142,8 @@ struct uhci_qh { | |||
141 | unsigned long advance_jiffies; /* Time of last queue advance */ | 142 | unsigned long advance_jiffies; /* Time of last queue advance */ |
142 | unsigned int unlink_frame; /* When the QH was unlinked */ | 143 | unsigned int unlink_frame; /* When the QH was unlinked */ |
143 | unsigned int period; /* For Interrupt and Isochronous QHs */ | 144 | unsigned int period; /* For Interrupt and Isochronous QHs */ |
145 | short phase; /* Between 0 and period-1 */ | ||
146 | short load; /* Periodic time requirement, in us */ | ||
144 | unsigned int iso_frame; /* Frame # for iso_packet_desc */ | 147 | unsigned int iso_frame; /* Frame # for iso_packet_desc */ |
145 | int iso_status; /* Status for Isochronous URBs */ | 148 | int iso_status; /* Status for Isochronous URBs */ |
146 | 149 | ||
@@ -153,6 +156,8 @@ struct uhci_qh { | |||
153 | unsigned int needs_fixup:1; /* Must fix the TD toggle values */ | 156 | unsigned int needs_fixup:1; /* Must fix the TD toggle values */ |
154 | unsigned int is_stopped:1; /* Queue was stopped by error/unlink */ | 157 | unsigned int is_stopped:1; /* Queue was stopped by error/unlink */ |
155 | unsigned int wait_expired:1; /* QH_WAIT_TIMEOUT has expired */ | 158 | unsigned int wait_expired:1; /* QH_WAIT_TIMEOUT has expired */ |
159 | unsigned int bandwidth_reserved:1; /* Periodic bandwidth has | ||
160 | * been allocated */ | ||
156 | } __attribute__((aligned(16))); | 161 | } __attribute__((aligned(16))); |
157 | 162 | ||
158 | /* | 163 | /* |
@@ -414,6 +419,9 @@ struct uhci_hcd { | |||
414 | 419 | ||
415 | wait_queue_head_t waitqh; /* endpoint_disable waiters */ | 420 | wait_queue_head_t waitqh; /* endpoint_disable waiters */ |
416 | int num_waiting; /* Number of waiters */ | 421 | int num_waiting; /* Number of waiters */ |
422 | |||
423 | int total_load; /* Sum of array values */ | ||
424 | short load[MAX_PHASE]; /* Periodic allocations */ | ||
417 | }; | 425 | }; |
418 | 426 | ||
419 | /* Convert between a usb_hcd pointer and the corresponding uhci_hcd */ | 427 | /* Convert between a usb_hcd pointer and the corresponding uhci_hcd */ |
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index f8347f1a10b6..bacc25c53ba3 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c | |||
@@ -52,10 +52,20 @@ static int any_ports_active(struct uhci_hcd *uhci) | |||
52 | static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf) | 52 | static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf) |
53 | { | 53 | { |
54 | int port; | 54 | int port; |
55 | int mask = RWC_BITS; | ||
56 | |||
57 | /* Some boards (both VIA and Intel apparently) report bogus | ||
58 | * overcurrent indications, causing massive log spam unless | ||
59 | * we completely ignore them. This doesn't seem to be a problem | ||
60 | * with the chipset so much as with the way it is connected on | ||
61 | * the motherboard; if the overcurrent input is left to float | ||
62 | * then it may constantly register false positives. */ | ||
63 | if (ignore_oc) | ||
64 | mask &= ~USBPORTSC_OCC; | ||
55 | 65 | ||
56 | *buf = 0; | 66 | *buf = 0; |
57 | for (port = 0; port < uhci->rh_numports; ++port) { | 67 | for (port = 0; port < uhci->rh_numports; ++port) { |
58 | if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) || | 68 | if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & mask) || |
59 | test_bit(port, &uhci->port_c_suspend)) | 69 | test_bit(port, &uhci->port_c_suspend)) |
60 | *buf |= (1 << (port + 1)); | 70 | *buf |= (1 << (port + 1)); |
61 | } | 71 | } |
@@ -263,7 +273,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
263 | wPortChange |= USB_PORT_STAT_C_CONNECTION; | 273 | wPortChange |= USB_PORT_STAT_C_CONNECTION; |
264 | if (status & USBPORTSC_PEC) | 274 | if (status & USBPORTSC_PEC) |
265 | wPortChange |= USB_PORT_STAT_C_ENABLE; | 275 | wPortChange |= USB_PORT_STAT_C_ENABLE; |
266 | if (status & USBPORTSC_OCC) | 276 | if ((status & USBPORTSC_OCC) && !ignore_oc) |
267 | wPortChange |= USB_PORT_STAT_C_OVERCURRENT; | 277 | wPortChange |= USB_PORT_STAT_C_OVERCURRENT; |
268 | 278 | ||
269 | if (test_bit(port, &uhci->port_c_suspend)) { | 279 | if (test_bit(port, &uhci->port_c_suspend)) { |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 30b88459ac7d..2cbb239e63f8 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -248,16 +248,26 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, | |||
248 | INIT_LIST_HEAD(&qh->node); | 248 | INIT_LIST_HEAD(&qh->node); |
249 | 249 | ||
250 | if (udev) { /* Normal QH */ | 250 | if (udev) { /* Normal QH */ |
251 | qh->dummy_td = uhci_alloc_td(uhci); | 251 | qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; |
252 | if (!qh->dummy_td) { | 252 | if (qh->type != USB_ENDPOINT_XFER_ISOC) { |
253 | dma_pool_free(uhci->qh_pool, qh, dma_handle); | 253 | qh->dummy_td = uhci_alloc_td(uhci); |
254 | return NULL; | 254 | if (!qh->dummy_td) { |
255 | dma_pool_free(uhci->qh_pool, qh, dma_handle); | ||
256 | return NULL; | ||
257 | } | ||
255 | } | 258 | } |
256 | qh->state = QH_STATE_IDLE; | 259 | qh->state = QH_STATE_IDLE; |
257 | qh->hep = hep; | 260 | qh->hep = hep; |
258 | qh->udev = udev; | 261 | qh->udev = udev; |
259 | hep->hcpriv = qh; | 262 | hep->hcpriv = qh; |
260 | qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; | 263 | |
264 | if (qh->type == USB_ENDPOINT_XFER_INT || | ||
265 | qh->type == USB_ENDPOINT_XFER_ISOC) | ||
266 | qh->load = usb_calc_bus_time(udev->speed, | ||
267 | usb_endpoint_dir_in(&hep->desc), | ||
268 | qh->type == USB_ENDPOINT_XFER_ISOC, | ||
269 | le16_to_cpu(hep->desc.wMaxPacketSize)) | ||
270 | / 1000 + 1; | ||
261 | 271 | ||
262 | } else { /* Skeleton QH */ | 272 | } else { /* Skeleton QH */ |
263 | qh->state = QH_STATE_ACTIVE; | 273 | qh->state = QH_STATE_ACTIVE; |
@@ -275,7 +285,8 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
275 | list_del(&qh->node); | 285 | list_del(&qh->node); |
276 | if (qh->udev) { | 286 | if (qh->udev) { |
277 | qh->hep->hcpriv = NULL; | 287 | qh->hep->hcpriv = NULL; |
278 | uhci_free_td(uhci, qh->dummy_td); | 288 | if (qh->dummy_td) |
289 | uhci_free_td(uhci, qh->dummy_td); | ||
279 | } | 290 | } |
280 | dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); | 291 | dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); |
281 | } | 292 | } |
@@ -327,7 +338,7 @@ static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh, | |||
327 | goto done; | 338 | goto done; |
328 | qh->element = UHCI_PTR_TERM; | 339 | qh->element = UHCI_PTR_TERM; |
329 | 340 | ||
330 | /* Control pipes have to worry about toggles */ | 341 | /* Control pipes don't have to worry about toggles */ |
331 | if (qh->type == USB_ENDPOINT_XFER_CONTROL) | 342 | if (qh->type == USB_ENDPOINT_XFER_CONTROL) |
332 | goto done; | 343 | goto done; |
333 | 344 | ||
@@ -493,6 +504,121 @@ static void uhci_make_qh_idle(struct uhci_hcd *uhci, struct uhci_qh *qh) | |||
493 | wake_up_all(&uhci->waitqh); | 504 | wake_up_all(&uhci->waitqh); |
494 | } | 505 | } |
495 | 506 | ||
507 | /* | ||
508 | * Find the highest existing bandwidth load for a given phase and period. | ||
509 | */ | ||
510 | static int uhci_highest_load(struct uhci_hcd *uhci, int phase, int period) | ||
511 | { | ||
512 | int highest_load = uhci->load[phase]; | ||
513 | |||
514 | for (phase += period; phase < MAX_PHASE; phase += period) | ||
515 | highest_load = max_t(int, highest_load, uhci->load[phase]); | ||
516 | return highest_load; | ||
517 | } | ||
518 | |||
519 | /* | ||
520 | * Set qh->phase to the optimal phase for a periodic transfer and | ||
521 | * check whether the bandwidth requirement is acceptable. | ||
522 | */ | ||
523 | static int uhci_check_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh) | ||
524 | { | ||
525 | int minimax_load; | ||
526 | |||
527 | /* Find the optimal phase (unless it is already set) and get | ||
528 | * its load value. */ | ||
529 | if (qh->phase >= 0) | ||
530 | minimax_load = uhci_highest_load(uhci, qh->phase, qh->period); | ||
531 | else { | ||
532 | int phase, load; | ||
533 | int max_phase = min_t(int, MAX_PHASE, qh->period); | ||
534 | |||
535 | qh->phase = 0; | ||
536 | minimax_load = uhci_highest_load(uhci, qh->phase, qh->period); | ||
537 | for (phase = 1; phase < max_phase; ++phase) { | ||
538 | load = uhci_highest_load(uhci, phase, qh->period); | ||
539 | if (load < minimax_load) { | ||
540 | minimax_load = load; | ||
541 | qh->phase = phase; | ||
542 | } | ||
543 | } | ||
544 | } | ||
545 | |||
546 | /* Maximum allowable periodic bandwidth is 90%, or 900 us per frame */ | ||
547 | if (minimax_load + qh->load > 900) { | ||
548 | dev_dbg(uhci_dev(uhci), "bandwidth allocation failed: " | ||
549 | "period %d, phase %d, %d + %d us\n", | ||
550 | qh->period, qh->phase, minimax_load, qh->load); | ||
551 | return -ENOSPC; | ||
552 | } | ||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | /* | ||
557 | * Reserve a periodic QH's bandwidth in the schedule | ||
558 | */ | ||
559 | static void uhci_reserve_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh) | ||
560 | { | ||
561 | int i; | ||
562 | int load = qh->load; | ||
563 | char *p = "??"; | ||
564 | |||
565 | for (i = qh->phase; i < MAX_PHASE; i += qh->period) { | ||
566 | uhci->load[i] += load; | ||
567 | uhci->total_load += load; | ||
568 | } | ||
569 | uhci_to_hcd(uhci)->self.bandwidth_allocated = | ||
570 | uhci->total_load / MAX_PHASE; | ||
571 | switch (qh->type) { | ||
572 | case USB_ENDPOINT_XFER_INT: | ||
573 | ++uhci_to_hcd(uhci)->self.bandwidth_int_reqs; | ||
574 | p = "INT"; | ||
575 | break; | ||
576 | case USB_ENDPOINT_XFER_ISOC: | ||
577 | ++uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs; | ||
578 | p = "ISO"; | ||
579 | break; | ||
580 | } | ||
581 | qh->bandwidth_reserved = 1; | ||
582 | dev_dbg(uhci_dev(uhci), | ||
583 | "%s dev %d ep%02x-%s, period %d, phase %d, %d us\n", | ||
584 | "reserve", qh->udev->devnum, | ||
585 | qh->hep->desc.bEndpointAddress, p, | ||
586 | qh->period, qh->phase, load); | ||
587 | } | ||
588 | |||
589 | /* | ||
590 | * Release a periodic QH's bandwidth reservation | ||
591 | */ | ||
592 | static void uhci_release_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh) | ||
593 | { | ||
594 | int i; | ||
595 | int load = qh->load; | ||
596 | char *p = "??"; | ||
597 | |||
598 | for (i = qh->phase; i < MAX_PHASE; i += qh->period) { | ||
599 | uhci->load[i] -= load; | ||
600 | uhci->total_load -= load; | ||
601 | } | ||
602 | uhci_to_hcd(uhci)->self.bandwidth_allocated = | ||
603 | uhci->total_load / MAX_PHASE; | ||
604 | switch (qh->type) { | ||
605 | case USB_ENDPOINT_XFER_INT: | ||
606 | --uhci_to_hcd(uhci)->self.bandwidth_int_reqs; | ||
607 | p = "INT"; | ||
608 | break; | ||
609 | case USB_ENDPOINT_XFER_ISOC: | ||
610 | --uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs; | ||
611 | p = "ISO"; | ||
612 | break; | ||
613 | } | ||
614 | qh->bandwidth_reserved = 0; | ||
615 | dev_dbg(uhci_dev(uhci), | ||
616 | "%s dev %d ep%02x-%s, period %d, phase %d, %d us\n", | ||
617 | "release", qh->udev->devnum, | ||
618 | qh->hep->desc.bEndpointAddress, p, | ||
619 | qh->period, qh->phase, load); | ||
620 | } | ||
621 | |||
496 | static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, | 622 | static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, |
497 | struct urb *urb) | 623 | struct urb *urb) |
498 | { | 624 | { |
@@ -796,7 +922,6 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, | |||
796 | wmb(); | 922 | wmb(); |
797 | qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); | 923 | qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); |
798 | qh->dummy_td = td; | 924 | qh->dummy_td = td; |
799 | qh->period = urb->interval; | ||
800 | 925 | ||
801 | usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), | 926 | usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), |
802 | usb_pipeout(urb->pipe), toggle); | 927 | usb_pipeout(urb->pipe), toggle); |
@@ -827,28 +952,42 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, | |||
827 | static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, | 952 | static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, |
828 | struct uhci_qh *qh) | 953 | struct uhci_qh *qh) |
829 | { | 954 | { |
830 | int exponent; | 955 | int ret; |
831 | 956 | ||
832 | /* USB 1.1 interrupt transfers only involve one packet per interval. | 957 | /* USB 1.1 interrupt transfers only involve one packet per interval. |
833 | * Drivers can submit URBs of any length, but longer ones will need | 958 | * Drivers can submit URBs of any length, but longer ones will need |
834 | * multiple intervals to complete. | 959 | * multiple intervals to complete. |
835 | */ | 960 | */ |
836 | 961 | ||
837 | /* Figure out which power-of-two queue to use */ | 962 | if (!qh->bandwidth_reserved) { |
838 | for (exponent = 7; exponent >= 0; --exponent) { | 963 | int exponent; |
839 | if ((1 << exponent) <= urb->interval) | ||
840 | break; | ||
841 | } | ||
842 | if (exponent < 0) | ||
843 | return -EINVAL; | ||
844 | urb->interval = 1 << exponent; | ||
845 | 964 | ||
846 | if (qh->period == 0) | 965 | /* Figure out which power-of-two queue to use */ |
966 | for (exponent = 7; exponent >= 0; --exponent) { | ||
967 | if ((1 << exponent) <= urb->interval) | ||
968 | break; | ||
969 | } | ||
970 | if (exponent < 0) | ||
971 | return -EINVAL; | ||
972 | qh->period = 1 << exponent; | ||
847 | qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)]; | 973 | qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)]; |
848 | else if (qh->period != urb->interval) | ||
849 | return -EINVAL; /* Can't change the period */ | ||
850 | 974 | ||
851 | return uhci_submit_common(uhci, urb, qh); | 975 | /* For now, interrupt phase is fixed by the layout |
976 | * of the QH lists. */ | ||
977 | qh->phase = (qh->period / 2) & (MAX_PHASE - 1); | ||
978 | ret = uhci_check_bandwidth(uhci, qh); | ||
979 | if (ret) | ||
980 | return ret; | ||
981 | } else if (qh->period > urb->interval) | ||
982 | return -EINVAL; /* Can't decrease the period */ | ||
983 | |||
984 | ret = uhci_submit_common(uhci, urb, qh); | ||
985 | if (ret == 0) { | ||
986 | urb->interval = qh->period; | ||
987 | if (!qh->bandwidth_reserved) | ||
988 | uhci_reserve_bandwidth(uhci, qh); | ||
989 | } | ||
990 | return ret; | ||
852 | } | 991 | } |
853 | 992 | ||
854 | /* | 993 | /* |
@@ -995,15 +1134,32 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, | |||
995 | return -EFBIG; | 1134 | return -EFBIG; |
996 | 1135 | ||
997 | /* Check the period and figure out the starting frame number */ | 1136 | /* Check the period and figure out the starting frame number */ |
998 | if (qh->period == 0) { | 1137 | if (!qh->bandwidth_reserved) { |
1138 | qh->period = urb->interval; | ||
999 | if (urb->transfer_flags & URB_ISO_ASAP) { | 1139 | if (urb->transfer_flags & URB_ISO_ASAP) { |
1140 | qh->phase = -1; /* Find the best phase */ | ||
1141 | i = uhci_check_bandwidth(uhci, qh); | ||
1142 | if (i) | ||
1143 | return i; | ||
1144 | |||
1145 | /* Allow a little time to allocate the TDs */ | ||
1000 | uhci_get_current_frame_number(uhci); | 1146 | uhci_get_current_frame_number(uhci); |
1001 | urb->start_frame = uhci->frame_number + 10; | 1147 | frame = uhci->frame_number + 10; |
1148 | |||
1149 | /* Move forward to the first frame having the | ||
1150 | * correct phase */ | ||
1151 | urb->start_frame = frame + ((qh->phase - frame) & | ||
1152 | (qh->period - 1)); | ||
1002 | } else { | 1153 | } else { |
1003 | i = urb->start_frame - uhci->last_iso_frame; | 1154 | i = urb->start_frame - uhci->last_iso_frame; |
1004 | if (i <= 0 || i >= UHCI_NUMFRAMES) | 1155 | if (i <= 0 || i >= UHCI_NUMFRAMES) |
1005 | return -EINVAL; | 1156 | return -EINVAL; |
1157 | qh->phase = urb->start_frame & (qh->period - 1); | ||
1158 | i = uhci_check_bandwidth(uhci, qh); | ||
1159 | if (i) | ||
1160 | return i; | ||
1006 | } | 1161 | } |
1162 | |||
1007 | } else if (qh->period != urb->interval) { | 1163 | } else if (qh->period != urb->interval) { |
1008 | return -EINVAL; /* Can't change the period */ | 1164 | return -EINVAL; /* Can't change the period */ |
1009 | 1165 | ||
@@ -1049,9 +1205,6 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, | |||
1049 | /* Set the interrupt-on-completion flag on the last packet. */ | 1205 | /* Set the interrupt-on-completion flag on the last packet. */ |
1050 | td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); | 1206 | td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); |
1051 | 1207 | ||
1052 | qh->skel = uhci->skel_iso_qh; | ||
1053 | qh->period = urb->interval; | ||
1054 | |||
1055 | /* Add the TDs to the frame list */ | 1208 | /* Add the TDs to the frame list */ |
1056 | frame = urb->start_frame; | 1209 | frame = urb->start_frame; |
1057 | list_for_each_entry(td, &urbp->td_list, list) { | 1210 | list_for_each_entry(td, &urbp->td_list, list) { |
@@ -1065,6 +1218,9 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, | |||
1065 | qh->iso_status = 0; | 1218 | qh->iso_status = 0; |
1066 | } | 1219 | } |
1067 | 1220 | ||
1221 | qh->skel = uhci->skel_iso_qh; | ||
1222 | if (!qh->bandwidth_reserved) | ||
1223 | uhci_reserve_bandwidth(uhci, qh); | ||
1068 | return 0; | 1224 | return 0; |
1069 | } | 1225 | } |
1070 | 1226 | ||
@@ -1119,7 +1275,6 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, | |||
1119 | unsigned long flags; | 1275 | unsigned long flags; |
1120 | struct urb_priv *urbp; | 1276 | struct urb_priv *urbp; |
1121 | struct uhci_qh *qh; | 1277 | struct uhci_qh *qh; |
1122 | int bustime; | ||
1123 | 1278 | ||
1124 | spin_lock_irqsave(&uhci->lock, flags); | 1279 | spin_lock_irqsave(&uhci->lock, flags); |
1125 | 1280 | ||
@@ -1149,35 +1304,11 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, | |||
1149 | ret = uhci_submit_bulk(uhci, urb, qh); | 1304 | ret = uhci_submit_bulk(uhci, urb, qh); |
1150 | break; | 1305 | break; |
1151 | case USB_ENDPOINT_XFER_INT: | 1306 | case USB_ENDPOINT_XFER_INT: |
1152 | if (list_empty(&qh->queue)) { | 1307 | ret = uhci_submit_interrupt(uhci, urb, qh); |
1153 | bustime = usb_check_bandwidth(urb->dev, urb); | ||
1154 | if (bustime < 0) | ||
1155 | ret = bustime; | ||
1156 | else { | ||
1157 | ret = uhci_submit_interrupt(uhci, urb, qh); | ||
1158 | if (ret == 0) | ||
1159 | usb_claim_bandwidth(urb->dev, urb, bustime, 0); | ||
1160 | } | ||
1161 | } else { /* inherit from parent */ | ||
1162 | struct urb_priv *eurbp; | ||
1163 | |||
1164 | eurbp = list_entry(qh->queue.prev, struct urb_priv, | ||
1165 | node); | ||
1166 | urb->bandwidth = eurbp->urb->bandwidth; | ||
1167 | ret = uhci_submit_interrupt(uhci, urb, qh); | ||
1168 | } | ||
1169 | break; | 1308 | break; |
1170 | case USB_ENDPOINT_XFER_ISOC: | 1309 | case USB_ENDPOINT_XFER_ISOC: |
1171 | urb->error_count = 0; | 1310 | urb->error_count = 0; |
1172 | bustime = usb_check_bandwidth(urb->dev, urb); | ||
1173 | if (bustime < 0) { | ||
1174 | ret = bustime; | ||
1175 | break; | ||
1176 | } | ||
1177 | |||
1178 | ret = uhci_submit_isochronous(uhci, urb, qh); | 1311 | ret = uhci_submit_isochronous(uhci, urb, qh); |
1179 | if (ret == 0) | ||
1180 | usb_claim_bandwidth(urb->dev, urb, bustime, 1); | ||
1181 | break; | 1312 | break; |
1182 | } | 1313 | } |
1183 | if (ret != 0) | 1314 | if (ret != 0) |
@@ -1274,24 +1405,6 @@ __acquires(uhci->lock) | |||
1274 | 1405 | ||
1275 | uhci_free_urb_priv(uhci, urbp); | 1406 | uhci_free_urb_priv(uhci, urbp); |
1276 | 1407 | ||
1277 | switch (qh->type) { | ||
1278 | case USB_ENDPOINT_XFER_ISOC: | ||
1279 | /* Release bandwidth for Interrupt or Isoc. transfers */ | ||
1280 | if (urb->bandwidth) | ||
1281 | usb_release_bandwidth(urb->dev, urb, 1); | ||
1282 | break; | ||
1283 | case USB_ENDPOINT_XFER_INT: | ||
1284 | /* Release bandwidth for Interrupt or Isoc. transfers */ | ||
1285 | /* Make sure we don't release if we have a queued URB */ | ||
1286 | if (list_empty(&qh->queue) && urb->bandwidth) | ||
1287 | usb_release_bandwidth(urb->dev, urb, 0); | ||
1288 | else | ||
1289 | /* bandwidth was passed on to queued URB, */ | ||
1290 | /* so don't let usb_unlink_urb() release it */ | ||
1291 | urb->bandwidth = 0; | ||
1292 | break; | ||
1293 | } | ||
1294 | |||
1295 | spin_unlock(&uhci->lock); | 1408 | spin_unlock(&uhci->lock); |
1296 | usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb); | 1409 | usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb); |
1297 | spin_lock(&uhci->lock); | 1410 | spin_lock(&uhci->lock); |
@@ -1300,9 +1413,8 @@ __acquires(uhci->lock) | |||
1300 | * reserved bandwidth. */ | 1413 | * reserved bandwidth. */ |
1301 | if (list_empty(&qh->queue)) { | 1414 | if (list_empty(&qh->queue)) { |
1302 | uhci_unlink_qh(uhci, qh); | 1415 | uhci_unlink_qh(uhci, qh); |
1303 | 1416 | if (qh->bandwidth_reserved) | |
1304 | /* Bandwidth stuff not yet implemented */ | 1417 | uhci_release_bandwidth(uhci, qh); |
1305 | qh->period = 0; | ||
1306 | } | 1418 | } |
1307 | } | 1419 | } |
1308 | 1420 | ||