diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/usb/host/ehci-hcd.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 135 |
1 files changed, 112 insertions, 23 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 34a928d3b7d2..f8030ee928e8 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -1,4 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Enhanced Host Controller Interface (EHCI) driver for USB. | ||
3 | * | ||
4 | * Maintainer: Alan Stern <stern@rowland.harvard.edu> | ||
5 | * | ||
2 | * Copyright (c) 2000-2004 by David Brownell | 6 | * Copyright (c) 2000-2004 by David Brownell |
3 | * | 7 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
@@ -118,6 +122,7 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us\n"); | |||
118 | 122 | ||
119 | #include "ehci.h" | 123 | #include "ehci.h" |
120 | #include "ehci-dbg.c" | 124 | #include "ehci-dbg.c" |
125 | #include "pci-quirks.h" | ||
121 | 126 | ||
122 | /*-------------------------------------------------------------------------*/ | 127 | /*-------------------------------------------------------------------------*/ |
123 | 128 | ||
@@ -194,6 +199,17 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, | |||
194 | return -ETIMEDOUT; | 199 | return -ETIMEDOUT; |
195 | } | 200 | } |
196 | 201 | ||
202 | /* check TDI/ARC silicon is in host mode */ | ||
203 | static int tdi_in_host_mode (struct ehci_hcd *ehci) | ||
204 | { | ||
205 | u32 __iomem *reg_ptr; | ||
206 | u32 tmp; | ||
207 | |||
208 | reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE); | ||
209 | tmp = ehci_readl(ehci, reg_ptr); | ||
210 | return (tmp & 3) == USBMODE_CM_HC; | ||
211 | } | ||
212 | |||
197 | /* force HC to halt state from unknown (EHCI spec section 2.3) */ | 213 | /* force HC to halt state from unknown (EHCI spec section 2.3) */ |
198 | static int ehci_halt (struct ehci_hcd *ehci) | 214 | static int ehci_halt (struct ehci_hcd *ehci) |
199 | { | 215 | { |
@@ -202,6 +218,10 @@ static int ehci_halt (struct ehci_hcd *ehci) | |||
202 | /* disable any irqs left enabled by previous code */ | 218 | /* disable any irqs left enabled by previous code */ |
203 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); | 219 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
204 | 220 | ||
221 | if (ehci_is_TDI(ehci) && tdi_in_host_mode(ehci) == 0) { | ||
222 | return 0; | ||
223 | } | ||
224 | |||
205 | if ((temp & STS_HALT) != 0) | 225 | if ((temp & STS_HALT) != 0) |
206 | return 0; | 226 | return 0; |
207 | 227 | ||
@@ -514,6 +534,9 @@ static void ehci_stop (struct usb_hcd *hcd) | |||
514 | spin_unlock_irq (&ehci->lock); | 534 | spin_unlock_irq (&ehci->lock); |
515 | ehci_mem_cleanup (ehci); | 535 | ehci_mem_cleanup (ehci); |
516 | 536 | ||
537 | if (ehci->amd_pll_fix == 1) | ||
538 | usb_amd_dev_put(); | ||
539 | |||
517 | #ifdef EHCI_STATS | 540 | #ifdef EHCI_STATS |
518 | ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", | 541 | ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", |
519 | ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, | 542 | ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, |
@@ -549,6 +572,8 @@ static int ehci_init(struct usb_hcd *hcd) | |||
549 | ehci->iaa_watchdog.function = ehci_iaa_watchdog; | 572 | ehci->iaa_watchdog.function = ehci_iaa_watchdog; |
550 | ehci->iaa_watchdog.data = (unsigned long) ehci; | 573 | ehci->iaa_watchdog.data = (unsigned long) ehci; |
551 | 574 | ||
575 | hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); | ||
576 | |||
552 | /* | 577 | /* |
553 | * hw default: 1K periodic list heads, one per frame. | 578 | * hw default: 1K periodic list heads, one per frame. |
554 | * periodic_size can shrink by USBCMD update if hcc_params allows. | 579 | * periodic_size can shrink by USBCMD update if hcc_params allows. |
@@ -556,11 +581,20 @@ static int ehci_init(struct usb_hcd *hcd) | |||
556 | ehci->periodic_size = DEFAULT_I_TDPS; | 581 | ehci->periodic_size = DEFAULT_I_TDPS; |
557 | INIT_LIST_HEAD(&ehci->cached_itd_list); | 582 | INIT_LIST_HEAD(&ehci->cached_itd_list); |
558 | INIT_LIST_HEAD(&ehci->cached_sitd_list); | 583 | INIT_LIST_HEAD(&ehci->cached_sitd_list); |
584 | |||
585 | if (HCC_PGM_FRAMELISTLEN(hcc_params)) { | ||
586 | /* periodic schedule size can be smaller than default */ | ||
587 | switch (EHCI_TUNE_FLS) { | ||
588 | case 0: ehci->periodic_size = 1024; break; | ||
589 | case 1: ehci->periodic_size = 512; break; | ||
590 | case 2: ehci->periodic_size = 256; break; | ||
591 | default: BUG(); | ||
592 | } | ||
593 | } | ||
559 | if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) | 594 | if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) |
560 | return retval; | 595 | return retval; |
561 | 596 | ||
562 | /* controllers may cache some of the periodic schedule ... */ | 597 | /* controllers may cache some of the periodic schedule ... */ |
563 | hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); | ||
564 | if (HCC_ISOC_CACHE(hcc_params)) // full frame cache | 598 | if (HCC_ISOC_CACHE(hcc_params)) // full frame cache |
565 | ehci->i_thresh = 2 + 8; | 599 | ehci->i_thresh = 2 + 8; |
566 | else // N microframes cached | 600 | else // N microframes cached |
@@ -614,12 +648,6 @@ static int ehci_init(struct usb_hcd *hcd) | |||
614 | /* periodic schedule size can be smaller than default */ | 648 | /* periodic schedule size can be smaller than default */ |
615 | temp &= ~(3 << 2); | 649 | temp &= ~(3 << 2); |
616 | temp |= (EHCI_TUNE_FLS << 2); | 650 | temp |= (EHCI_TUNE_FLS << 2); |
617 | switch (EHCI_TUNE_FLS) { | ||
618 | case 0: ehci->periodic_size = 1024; break; | ||
619 | case 1: ehci->periodic_size = 512; break; | ||
620 | case 2: ehci->periodic_size = 256; break; | ||
621 | default: BUG(); | ||
622 | } | ||
623 | } | 651 | } |
624 | if (HCC_LPM(hcc_params)) { | 652 | if (HCC_LPM(hcc_params)) { |
625 | /* support link power management EHCI 1.1 addendum */ | 653 | /* support link power management EHCI 1.1 addendum */ |
@@ -651,7 +679,12 @@ static int ehci_run (struct usb_hcd *hcd) | |||
651 | hcd->uses_new_polling = 1; | 679 | hcd->uses_new_polling = 1; |
652 | 680 | ||
653 | /* EHCI spec section 4.1 */ | 681 | /* EHCI spec section 4.1 */ |
654 | if ((retval = ehci_reset(ehci)) != 0) { | 682 | /* |
683 | * TDI driver does the ehci_reset in their reset callback. | ||
684 | * Don't reset here, because configuration settings will | ||
685 | * vanish. | ||
686 | */ | ||
687 | if (!ehci_is_TDI(ehci) && (retval = ehci_reset(ehci)) != 0) { | ||
655 | ehci_mem_cleanup(ehci); | 688 | ehci_mem_cleanup(ehci); |
656 | return retval; | 689 | return retval; |
657 | } | 690 | } |
@@ -710,7 +743,7 @@ static int ehci_run (struct usb_hcd *hcd) | |||
710 | up_write(&ehci_cf_port_reset_rwsem); | 743 | up_write(&ehci_cf_port_reset_rwsem); |
711 | ehci->last_periodic_enable = ktime_get_real(); | 744 | ehci->last_periodic_enable = ktime_get_real(); |
712 | 745 | ||
713 | temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); | 746 | temp = HC_VERSION(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); |
714 | ehci_info (ehci, | 747 | ehci_info (ehci, |
715 | "USB %x.%x started, EHCI %x.%02x%s\n", | 748 | "USB %x.%x started, EHCI %x.%02x%s\n", |
716 | ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), | 749 | ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), |
@@ -748,8 +781,9 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
748 | goto dead; | 781 | goto dead; |
749 | } | 782 | } |
750 | 783 | ||
784 | /* Shared IRQ? */ | ||
751 | masked_status = status & INTR_MASK; | 785 | masked_status = status & INTR_MASK; |
752 | if (!masked_status) { /* irq sharing? */ | 786 | if (!masked_status || unlikely(hcd->state == HC_STATE_HALT)) { |
753 | spin_unlock(&ehci->lock); | 787 | spin_unlock(&ehci->lock); |
754 | return IRQ_NONE; | 788 | return IRQ_NONE; |
755 | } | 789 | } |
@@ -844,6 +878,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
844 | dead: | 878 | dead: |
845 | ehci_reset(ehci); | 879 | ehci_reset(ehci); |
846 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); | 880 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); |
881 | usb_hc_died(hcd); | ||
847 | /* generic layer kills/unlinks all urbs, then | 882 | /* generic layer kills/unlinks all urbs, then |
848 | * uses ehci_stop to clean up the rest | 883 | * uses ehci_stop to clean up the rest |
849 | */ | 884 | */ |
@@ -1048,10 +1083,11 @@ rescan: | |||
1048 | tmp && tmp != qh; | 1083 | tmp && tmp != qh; |
1049 | tmp = tmp->qh_next.qh) | 1084 | tmp = tmp->qh_next.qh) |
1050 | continue; | 1085 | continue; |
1051 | /* periodic qh self-unlinks on empty */ | 1086 | /* periodic qh self-unlinks on empty, and a COMPLETING qh |
1052 | if (!tmp) | 1087 | * may already be unlinked. |
1053 | goto nogood; | 1088 | */ |
1054 | unlink_async (ehci, qh); | 1089 | if (tmp) |
1090 | unlink_async(ehci, qh); | ||
1055 | /* FALL THROUGH */ | 1091 | /* FALL THROUGH */ |
1056 | case QH_STATE_UNLINK: /* wait for hw to finish? */ | 1092 | case QH_STATE_UNLINK: /* wait for hw to finish? */ |
1057 | case QH_STATE_UNLINK_WAIT: | 1093 | case QH_STATE_UNLINK_WAIT: |
@@ -1068,7 +1104,6 @@ idle_timeout: | |||
1068 | } | 1104 | } |
1069 | /* else FALL THROUGH */ | 1105 | /* else FALL THROUGH */ |
1070 | default: | 1106 | default: |
1071 | nogood: | ||
1072 | /* caller was supposed to have unlinked any requests; | 1107 | /* caller was supposed to have unlinked any requests; |
1073 | * that's not our job. just leak this memory. | 1108 | * that's not our job. just leak this memory. |
1074 | */ | 1109 | */ |
@@ -1080,7 +1115,6 @@ nogood: | |||
1080 | ep->hcpriv = NULL; | 1115 | ep->hcpriv = NULL; |
1081 | done: | 1116 | done: |
1082 | spin_unlock_irqrestore (&ehci->lock, flags); | 1117 | spin_unlock_irqrestore (&ehci->lock, flags); |
1083 | return; | ||
1084 | } | 1118 | } |
1085 | 1119 | ||
1086 | static void | 1120 | static void |
@@ -1152,12 +1186,17 @@ MODULE_LICENSE ("GPL"); | |||
1152 | #define PLATFORM_DRIVER ehci_mxc_driver | 1186 | #define PLATFORM_DRIVER ehci_mxc_driver |
1153 | #endif | 1187 | #endif |
1154 | 1188 | ||
1189 | #ifdef CONFIG_USB_EHCI_SH | ||
1190 | #include "ehci-sh.c" | ||
1191 | #define PLATFORM_DRIVER ehci_hcd_sh_driver | ||
1192 | #endif | ||
1193 | |||
1155 | #ifdef CONFIG_SOC_AU1200 | 1194 | #ifdef CONFIG_SOC_AU1200 |
1156 | #include "ehci-au1xxx.c" | 1195 | #include "ehci-au1xxx.c" |
1157 | #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver | 1196 | #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver |
1158 | #endif | 1197 | #endif |
1159 | 1198 | ||
1160 | #ifdef CONFIG_ARCH_OMAP3 | 1199 | #ifdef CONFIG_USB_EHCI_HCD_OMAP |
1161 | #include "ehci-omap.c" | 1200 | #include "ehci-omap.c" |
1162 | #define PLATFORM_DRIVER ehci_hcd_omap_driver | 1201 | #define PLATFORM_DRIVER ehci_hcd_omap_driver |
1163 | #endif | 1202 | #endif |
@@ -1197,6 +1236,56 @@ MODULE_LICENSE ("GPL"); | |||
1197 | #define PLATFORM_DRIVER ehci_atmel_driver | 1236 | #define PLATFORM_DRIVER ehci_atmel_driver |
1198 | #endif | 1237 | #endif |
1199 | 1238 | ||
1239 | #ifdef CONFIG_USB_OCTEON_EHCI | ||
1240 | #include "ehci-octeon.c" | ||
1241 | #define PLATFORM_DRIVER ehci_octeon_driver | ||
1242 | #endif | ||
1243 | |||
1244 | #ifdef CONFIG_USB_CNS3XXX_EHCI | ||
1245 | #include "ehci-cns3xxx.c" | ||
1246 | #define PLATFORM_DRIVER cns3xxx_ehci_driver | ||
1247 | #endif | ||
1248 | |||
1249 | #ifdef CONFIG_ARCH_VT8500 | ||
1250 | #include "ehci-vt8500.c" | ||
1251 | #define PLATFORM_DRIVER vt8500_ehci_driver | ||
1252 | #endif | ||
1253 | |||
1254 | #ifdef CONFIG_PLAT_SPEAR | ||
1255 | #include "ehci-spear.c" | ||
1256 | #define PLATFORM_DRIVER spear_ehci_hcd_driver | ||
1257 | #endif | ||
1258 | |||
1259 | #ifdef CONFIG_USB_EHCI_MSM | ||
1260 | #include "ehci-msm.c" | ||
1261 | #define PLATFORM_DRIVER ehci_msm_driver | ||
1262 | #endif | ||
1263 | |||
1264 | #ifdef CONFIG_USB_EHCI_HCD_PMC_MSP | ||
1265 | #include "ehci-pmcmsp.c" | ||
1266 | #define PLATFORM_DRIVER ehci_hcd_msp_driver | ||
1267 | #endif | ||
1268 | |||
1269 | #ifdef CONFIG_USB_EHCI_TEGRA | ||
1270 | #include "ehci-tegra.c" | ||
1271 | #define PLATFORM_DRIVER tegra_ehci_driver | ||
1272 | #endif | ||
1273 | |||
1274 | #ifdef CONFIG_USB_EHCI_S5P | ||
1275 | #include "ehci-s5p.c" | ||
1276 | #define PLATFORM_DRIVER s5p_ehci_driver | ||
1277 | #endif | ||
1278 | |||
1279 | #ifdef CONFIG_USB_EHCI_ATH79 | ||
1280 | #include "ehci-ath79.c" | ||
1281 | #define PLATFORM_DRIVER ehci_ath79_driver | ||
1282 | #endif | ||
1283 | |||
1284 | #ifdef CONFIG_SPARC_LEON | ||
1285 | #include "ehci-grlib.c" | ||
1286 | #define PLATFORM_DRIVER ehci_grlib_driver | ||
1287 | #endif | ||
1288 | |||
1200 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ | 1289 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ |
1201 | !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ | 1290 | !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ |
1202 | !defined(XILINX_OF_PLATFORM_DRIVER) | 1291 | !defined(XILINX_OF_PLATFORM_DRIVER) |
@@ -1249,24 +1338,24 @@ static int __init ehci_hcd_init(void) | |||
1249 | #endif | 1338 | #endif |
1250 | 1339 | ||
1251 | #ifdef OF_PLATFORM_DRIVER | 1340 | #ifdef OF_PLATFORM_DRIVER |
1252 | retval = of_register_platform_driver(&OF_PLATFORM_DRIVER); | 1341 | retval = platform_driver_register(&OF_PLATFORM_DRIVER); |
1253 | if (retval < 0) | 1342 | if (retval < 0) |
1254 | goto clean3; | 1343 | goto clean3; |
1255 | #endif | 1344 | #endif |
1256 | 1345 | ||
1257 | #ifdef XILINX_OF_PLATFORM_DRIVER | 1346 | #ifdef XILINX_OF_PLATFORM_DRIVER |
1258 | retval = of_register_platform_driver(&XILINX_OF_PLATFORM_DRIVER); | 1347 | retval = platform_driver_register(&XILINX_OF_PLATFORM_DRIVER); |
1259 | if (retval < 0) | 1348 | if (retval < 0) |
1260 | goto clean4; | 1349 | goto clean4; |
1261 | #endif | 1350 | #endif |
1262 | return retval; | 1351 | return retval; |
1263 | 1352 | ||
1264 | #ifdef XILINX_OF_PLATFORM_DRIVER | 1353 | #ifdef XILINX_OF_PLATFORM_DRIVER |
1265 | /* of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); */ | 1354 | /* platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); */ |
1266 | clean4: | 1355 | clean4: |
1267 | #endif | 1356 | #endif |
1268 | #ifdef OF_PLATFORM_DRIVER | 1357 | #ifdef OF_PLATFORM_DRIVER |
1269 | of_unregister_platform_driver(&OF_PLATFORM_DRIVER); | 1358 | platform_driver_unregister(&OF_PLATFORM_DRIVER); |
1270 | clean3: | 1359 | clean3: |
1271 | #endif | 1360 | #endif |
1272 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1361 | #ifdef PS3_SYSTEM_BUS_DRIVER |
@@ -1294,10 +1383,10 @@ module_init(ehci_hcd_init); | |||
1294 | static void __exit ehci_hcd_cleanup(void) | 1383 | static void __exit ehci_hcd_cleanup(void) |
1295 | { | 1384 | { |
1296 | #ifdef XILINX_OF_PLATFORM_DRIVER | 1385 | #ifdef XILINX_OF_PLATFORM_DRIVER |
1297 | of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); | 1386 | platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); |
1298 | #endif | 1387 | #endif |
1299 | #ifdef OF_PLATFORM_DRIVER | 1388 | #ifdef OF_PLATFORM_DRIVER |
1300 | of_unregister_platform_driver(&OF_PLATFORM_DRIVER); | 1389 | platform_driver_unregister(&OF_PLATFORM_DRIVER); |
1301 | #endif | 1390 | #endif |
1302 | #ifdef PLATFORM_DRIVER | 1391 | #ifdef PLATFORM_DRIVER |
1303 | platform_driver_unregister(&PLATFORM_DRIVER); | 1392 | platform_driver_unregister(&PLATFORM_DRIVER); |