diff options
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 118 |
1 files changed, 95 insertions, 23 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 099aff64f536..c4e15ed1405a 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -41,10 +41,6 @@ | |||
41 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
42 | #include <asm/system.h> | 42 | #include <asm/system.h> |
43 | #include <asm/unaligned.h> | 43 | #include <asm/unaligned.h> |
44 | #ifdef CONFIG_PPC_PS3 | ||
45 | #include <asm/firmware.h> | ||
46 | #endif | ||
47 | |||
48 | 44 | ||
49 | /*-------------------------------------------------------------------------*/ | 45 | /*-------------------------------------------------------------------------*/ |
50 | 46 | ||
@@ -201,9 +197,15 @@ static void tdi_reset (struct ehci_hcd *ehci) | |||
201 | u32 __iomem *reg_ptr; | 197 | u32 __iomem *reg_ptr; |
202 | u32 tmp; | 198 | u32 tmp; |
203 | 199 | ||
204 | reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x68); | 200 | reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE); |
205 | tmp = ehci_readl(ehci, reg_ptr); | 201 | tmp = ehci_readl(ehci, reg_ptr); |
206 | tmp |= 0x3; | 202 | tmp |= USBMODE_CM_HC; |
203 | /* The default byte access to MMR space is LE after | ||
204 | * controller reset. Set the required endian mode | ||
205 | * for transfer buffers to match the host microprocessor | ||
206 | */ | ||
207 | if (ehci_big_endian_mmio(ehci)) | ||
208 | tmp |= USBMODE_BE; | ||
207 | ehci_writel(ehci, tmp, reg_ptr); | 209 | ehci_writel(ehci, tmp, reg_ptr); |
208 | } | 210 | } |
209 | 211 | ||
@@ -273,6 +275,58 @@ static void ehci_work(struct ehci_hcd *ehci); | |||
273 | 275 | ||
274 | /*-------------------------------------------------------------------------*/ | 276 | /*-------------------------------------------------------------------------*/ |
275 | 277 | ||
278 | #ifdef CONFIG_CPU_FREQ | ||
279 | |||
280 | #include <linux/cpufreq.h> | ||
281 | |||
282 | static void ehci_cpufreq_pause (struct ehci_hcd *ehci) | ||
283 | { | ||
284 | unsigned long flags; | ||
285 | |||
286 | spin_lock_irqsave(&ehci->lock, flags); | ||
287 | if (!ehci->cpufreq_changing++) | ||
288 | qh_inactivate_split_intr_qhs(ehci); | ||
289 | spin_unlock_irqrestore(&ehci->lock, flags); | ||
290 | } | ||
291 | |||
292 | static void ehci_cpufreq_unpause (struct ehci_hcd *ehci) | ||
293 | { | ||
294 | unsigned long flags; | ||
295 | |||
296 | spin_lock_irqsave(&ehci->lock, flags); | ||
297 | if (!--ehci->cpufreq_changing) | ||
298 | qh_reactivate_split_intr_qhs(ehci); | ||
299 | spin_unlock_irqrestore(&ehci->lock, flags); | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * ehci_cpufreq_notifier is needed to avoid MMF errors that occur when | ||
304 | * EHCI controllers that don't cache many uframes get delayed trying to | ||
305 | * read main memory during CPU frequency transitions. This can cause | ||
306 | * split interrupt transactions to not be completed in the required uframe. | ||
307 | * This has been observed on the Broadcom/ServerWorks HT1000 controller. | ||
308 | */ | ||
309 | static int ehci_cpufreq_notifier(struct notifier_block *nb, unsigned long val, | ||
310 | void *data) | ||
311 | { | ||
312 | struct ehci_hcd *ehci = container_of(nb, struct ehci_hcd, | ||
313 | cpufreq_transition); | ||
314 | |||
315 | switch (val) { | ||
316 | case CPUFREQ_PRECHANGE: | ||
317 | ehci_cpufreq_pause(ehci); | ||
318 | break; | ||
319 | case CPUFREQ_POSTCHANGE: | ||
320 | ehci_cpufreq_unpause(ehci); | ||
321 | break; | ||
322 | } | ||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | #endif | ||
327 | |||
328 | /*-------------------------------------------------------------------------*/ | ||
329 | |||
276 | static void ehci_watchdog (unsigned long param) | 330 | static void ehci_watchdog (unsigned long param) |
277 | { | 331 | { |
278 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; | 332 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; |
@@ -347,6 +401,8 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on) | |||
347 | is_on ? SetPortFeature : ClearPortFeature, | 401 | is_on ? SetPortFeature : ClearPortFeature, |
348 | USB_PORT_FEAT_POWER, | 402 | USB_PORT_FEAT_POWER, |
349 | port--, NULL, 0); | 403 | port--, NULL, 0); |
404 | /* Flush those writes */ | ||
405 | ehci_readl(ehci, &ehci->regs->command); | ||
350 | msleep(20); | 406 | msleep(20); |
351 | } | 407 | } |
352 | 408 | ||
@@ -404,6 +460,10 @@ static void ehci_stop (struct usb_hcd *hcd) | |||
404 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); | 460 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
405 | spin_unlock_irq(&ehci->lock); | 461 | spin_unlock_irq(&ehci->lock); |
406 | 462 | ||
463 | #ifdef CONFIG_CPU_FREQ | ||
464 | cpufreq_unregister_notifier(&ehci->cpufreq_transition, | ||
465 | CPUFREQ_TRANSITION_NOTIFIER); | ||
466 | #endif | ||
407 | /* let companion controllers work when we aren't */ | 467 | /* let companion controllers work when we aren't */ |
408 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); | 468 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); |
409 | 469 | ||
@@ -470,12 +530,12 @@ static int ehci_init(struct usb_hcd *hcd) | |||
470 | * from automatically advancing to the next td after short reads. | 530 | * from automatically advancing to the next td after short reads. |
471 | */ | 531 | */ |
472 | ehci->async->qh_next.qh = NULL; | 532 | ehci->async->qh_next.qh = NULL; |
473 | ehci->async->hw_next = QH_NEXT(ehci->async->qh_dma); | 533 | ehci->async->hw_next = QH_NEXT(ehci, ehci->async->qh_dma); |
474 | ehci->async->hw_info1 = cpu_to_le32(QH_HEAD); | 534 | ehci->async->hw_info1 = cpu_to_hc32(ehci, QH_HEAD); |
475 | ehci->async->hw_token = cpu_to_le32(QTD_STS_HALT); | 535 | ehci->async->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); |
476 | ehci->async->hw_qtd_next = EHCI_LIST_END; | 536 | ehci->async->hw_qtd_next = EHCI_LIST_END(ehci); |
477 | ehci->async->qh_state = QH_STATE_LINKED; | 537 | ehci->async->qh_state = QH_STATE_LINKED; |
478 | ehci->async->hw_alt_next = QTD_NEXT(ehci->async->dummy->qtd_dma); | 538 | ehci->async->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma); |
479 | 539 | ||
480 | /* clear interrupt enables, set irq latency */ | 540 | /* clear interrupt enables, set irq latency */ |
481 | if (log2_irq_thresh < 0 || log2_irq_thresh > 6) | 541 | if (log2_irq_thresh < 0 || log2_irq_thresh > 6) |
@@ -509,6 +569,17 @@ static int ehci_init(struct usb_hcd *hcd) | |||
509 | } | 569 | } |
510 | ehci->command = temp; | 570 | ehci->command = temp; |
511 | 571 | ||
572 | #ifdef CONFIG_CPU_FREQ | ||
573 | INIT_LIST_HEAD(&ehci->split_intr_qhs); | ||
574 | /* | ||
575 | * If the EHCI controller caches enough uframes, this probably | ||
576 | * isn't needed unless there are so many low/full speed devices | ||
577 | * that the controller's can't cache it all. | ||
578 | */ | ||
579 | ehci->cpufreq_transition.notifier_call = ehci_cpufreq_notifier; | ||
580 | cpufreq_register_notifier(&ehci->cpufreq_transition, | ||
581 | CPUFREQ_TRANSITION_NOTIFIER); | ||
582 | #endif | ||
512 | return 0; | 583 | return 0; |
513 | } | 584 | } |
514 | 585 | ||
@@ -925,7 +996,7 @@ MODULE_LICENSE ("GPL"); | |||
925 | #define PCI_DRIVER ehci_pci_driver | 996 | #define PCI_DRIVER ehci_pci_driver |
926 | #endif | 997 | #endif |
927 | 998 | ||
928 | #ifdef CONFIG_MPC834x | 999 | #ifdef CONFIG_USB_EHCI_FSL |
929 | #include "ehci-fsl.c" | 1000 | #include "ehci-fsl.c" |
930 | #define PLATFORM_DRIVER ehci_fsl_driver | 1001 | #define PLATFORM_DRIVER ehci_fsl_driver |
931 | #endif | 1002 | #endif |
@@ -937,7 +1008,12 @@ MODULE_LICENSE ("GPL"); | |||
937 | 1008 | ||
938 | #ifdef CONFIG_PPC_PS3 | 1009 | #ifdef CONFIG_PPC_PS3 |
939 | #include "ehci-ps3.c" | 1010 | #include "ehci-ps3.c" |
940 | #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_sb_driver | 1011 | #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver |
1012 | #endif | ||
1013 | |||
1014 | #ifdef CONFIG_440EPX | ||
1015 | #include "ehci-ppc-soc.c" | ||
1016 | #define PLATFORM_DRIVER ehci_ppc_soc_driver | ||
941 | #endif | 1017 | #endif |
942 | 1018 | ||
943 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ | 1019 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ |
@@ -971,18 +1047,15 @@ static int __init ehci_hcd_init(void) | |||
971 | #endif | 1047 | #endif |
972 | 1048 | ||
973 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1049 | #ifdef PS3_SYSTEM_BUS_DRIVER |
974 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) { | 1050 | retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER); |
975 | retval = ps3_system_bus_driver_register( | 1051 | if (retval < 0) { |
976 | &PS3_SYSTEM_BUS_DRIVER); | ||
977 | if (retval < 0) { | ||
978 | #ifdef PLATFORM_DRIVER | 1052 | #ifdef PLATFORM_DRIVER |
979 | platform_driver_unregister(&PLATFORM_DRIVER); | 1053 | platform_driver_unregister(&PLATFORM_DRIVER); |
980 | #endif | 1054 | #endif |
981 | #ifdef PCI_DRIVER | 1055 | #ifdef PCI_DRIVER |
982 | pci_unregister_driver(&PCI_DRIVER); | 1056 | pci_unregister_driver(&PCI_DRIVER); |
983 | #endif | 1057 | #endif |
984 | return retval; | 1058 | return retval; |
985 | } | ||
986 | } | 1059 | } |
987 | #endif | 1060 | #endif |
988 | 1061 | ||
@@ -999,8 +1072,7 @@ static void __exit ehci_hcd_cleanup(void) | |||
999 | pci_unregister_driver(&PCI_DRIVER); | 1072 | pci_unregister_driver(&PCI_DRIVER); |
1000 | #endif | 1073 | #endif |
1001 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1074 | #ifdef PS3_SYSTEM_BUS_DRIVER |
1002 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) | 1075 | ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); |
1003 | ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | ||
1004 | #endif | 1076 | #endif |
1005 | } | 1077 | } |
1006 | module_exit(ehci_hcd_cleanup); | 1078 | module_exit(ehci_hcd_cleanup); |