diff options
46 files changed, 4105 insertions, 232 deletions
diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c index c6fb32c36c52..867ead2559ad 100644 --- a/arch/arm/mach-davinci/usb.c +++ b/arch/arm/mach-davinci/usb.c | |||
| @@ -77,29 +77,6 @@ static struct platform_device usb_dev = { | |||
| 77 | .num_resources = ARRAY_SIZE(usb_resources), | 77 | .num_resources = ARRAY_SIZE(usb_resources), |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | #ifdef CONFIG_USB_MUSB_OTG | ||
| 81 | |||
| 82 | static struct otg_transceiver *xceiv; | ||
| 83 | |||
| 84 | struct otg_transceiver *otg_get_transceiver(void) | ||
| 85 | { | ||
| 86 | if (xceiv) | ||
| 87 | get_device(xceiv->dev); | ||
| 88 | return xceiv; | ||
| 89 | } | ||
| 90 | EXPORT_SYMBOL(otg_get_transceiver); | ||
| 91 | |||
| 92 | int otg_set_transceiver(struct otg_transceiver *x) | ||
| 93 | { | ||
| 94 | if (xceiv && x) | ||
| 95 | return -EBUSY; | ||
| 96 | xceiv = x; | ||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | EXPORT_SYMBOL(otg_set_transceiver); | ||
| 100 | |||
| 101 | #endif | ||
| 102 | |||
| 103 | void __init setup_usb(unsigned mA, unsigned potpgt_msec) | 80 | void __init setup_usb(unsigned mA, unsigned potpgt_msec) |
| 104 | { | 81 | { |
| 105 | usb_data.power = mA / 2; | 82 | usb_data.power = mA / 2; |
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 8b7c419b876e..8bcde8cde554 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
| @@ -13,6 +13,7 @@ obj-$(CONFIG_USB_EHCI_HCD) += host/ | |||
| 13 | obj-$(CONFIG_USB_ISP116X_HCD) += host/ | 13 | obj-$(CONFIG_USB_ISP116X_HCD) += host/ |
| 14 | obj-$(CONFIG_USB_OHCI_HCD) += host/ | 14 | obj-$(CONFIG_USB_OHCI_HCD) += host/ |
| 15 | obj-$(CONFIG_USB_UHCI_HCD) += host/ | 15 | obj-$(CONFIG_USB_UHCI_HCD) += host/ |
| 16 | obj-$(CONFIG_USB_FHCI_HCD) += host/ | ||
| 16 | obj-$(CONFIG_USB_SL811_HCD) += host/ | 17 | obj-$(CONFIG_USB_SL811_HCD) += host/ |
| 17 | obj-$(CONFIG_USB_U132_HCD) += host/ | 18 | obj-$(CONFIG_USB_U132_HCD) += host/ |
| 18 | obj-$(CONFIG_USB_R8A66597_HCD) += host/ | 19 | obj-$(CONFIG_USB_R8A66597_HCD) += host/ |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 00b47ea24f86..97ba4a985edc 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
| @@ -1349,6 +1349,12 @@ static struct usb_device_id acm_ids[] = { | |||
| 1349 | { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */ | 1349 | { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */ |
| 1350 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1350 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
| 1351 | }, | 1351 | }, |
| 1352 | { USB_DEVICE(0x0e8d, 0x3329), /* i-blue 747, Qstarz BT-Q1000, Holux M-241 */ | ||
| 1353 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | ||
| 1354 | }, | ||
| 1355 | { USB_DEVICE(0x0e8d, 0x3329), /* MediaTek Inc GPS */ | ||
| 1356 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | ||
| 1357 | }, | ||
| 1352 | { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ | 1358 | { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ |
| 1353 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1359 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
| 1354 | }, | 1360 | }, |
| @@ -1370,6 +1376,9 @@ static struct usb_device_id acm_ids[] = { | |||
| 1370 | { USB_DEVICE(0x0572, 0x1321), /* Conexant USB MODEM CX93010 */ | 1376 | { USB_DEVICE(0x0572, 0x1321), /* Conexant USB MODEM CX93010 */ |
| 1371 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1377 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
| 1372 | }, | 1378 | }, |
| 1379 | { USB_DEVICE(0x0572, 0x1324), /* Conexant USB MODEM RD02-D400 */ | ||
| 1380 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | ||
| 1381 | }, | ||
| 1373 | 1382 | ||
| 1374 | /* control interfaces with various AT-command sets */ | 1383 | /* control interfaces with various AT-command sets */ |
| 1375 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1384 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index b5775af3ba26..3f3ee1351930 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c | |||
| @@ -226,6 +226,7 @@ static const struct quirk_printer_struct quirk_printers[] = { | |||
| 226 | { 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */ | 226 | { 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */ |
| 227 | { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */ | 227 | { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */ |
| 228 | { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */ | 228 | { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */ |
| 229 | { 0x04f9, 0x000d, USBLP_QUIRK_BIDIR }, /* Brother Industries, Ltd HL-1440 Laser Printer */ | ||
| 229 | { 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt Printer M129C */ | 230 | { 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt Printer M129C */ |
| 230 | { 0, 0 } | 231 | { 0, 0 } |
| 231 | }; | 232 | }; |
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 26fece124e0e..7513bb083c15 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
| @@ -1700,7 +1700,7 @@ const struct file_operations usbdev_file_operations = { | |||
| 1700 | .release = usbdev_release, | 1700 | .release = usbdev_release, |
| 1701 | }; | 1701 | }; |
| 1702 | 1702 | ||
| 1703 | void usb_fs_classdev_common_remove(struct usb_device *udev) | 1703 | static void usbdev_remove(struct usb_device *udev) |
| 1704 | { | 1704 | { |
| 1705 | struct dev_state *ps; | 1705 | struct dev_state *ps; |
| 1706 | struct siginfo sinfo; | 1706 | struct siginfo sinfo; |
| @@ -1742,10 +1742,15 @@ static void usb_classdev_remove(struct usb_device *dev) | |||
| 1742 | { | 1742 | { |
| 1743 | if (dev->usb_classdev) | 1743 | if (dev->usb_classdev) |
| 1744 | device_unregister(dev->usb_classdev); | 1744 | device_unregister(dev->usb_classdev); |
| 1745 | usb_fs_classdev_common_remove(dev); | ||
| 1746 | } | 1745 | } |
| 1747 | 1746 | ||
| 1748 | static int usb_classdev_notify(struct notifier_block *self, | 1747 | #else |
| 1748 | #define usb_classdev_add(dev) 0 | ||
| 1749 | #define usb_classdev_remove(dev) do {} while (0) | ||
| 1750 | |||
| 1751 | #endif | ||
| 1752 | |||
| 1753 | static int usbdev_notify(struct notifier_block *self, | ||
| 1749 | unsigned long action, void *dev) | 1754 | unsigned long action, void *dev) |
| 1750 | { | 1755 | { |
| 1751 | switch (action) { | 1756 | switch (action) { |
| @@ -1755,15 +1760,15 @@ static int usb_classdev_notify(struct notifier_block *self, | |||
| 1755 | break; | 1760 | break; |
| 1756 | case USB_DEVICE_REMOVE: | 1761 | case USB_DEVICE_REMOVE: |
| 1757 | usb_classdev_remove(dev); | 1762 | usb_classdev_remove(dev); |
| 1763 | usbdev_remove(dev); | ||
| 1758 | break; | 1764 | break; |
| 1759 | } | 1765 | } |
| 1760 | return NOTIFY_OK; | 1766 | return NOTIFY_OK; |
| 1761 | } | 1767 | } |
| 1762 | 1768 | ||
| 1763 | static struct notifier_block usbdev_nb = { | 1769 | static struct notifier_block usbdev_nb = { |
| 1764 | .notifier_call = usb_classdev_notify, | 1770 | .notifier_call = usbdev_notify, |
| 1765 | }; | 1771 | }; |
| 1766 | #endif | ||
| 1767 | 1772 | ||
| 1768 | static struct cdev usb_device_cdev; | 1773 | static struct cdev usb_device_cdev; |
| 1769 | 1774 | ||
| @@ -1798,9 +1803,8 @@ int __init usb_devio_init(void) | |||
| 1798 | * to /sys/dev | 1803 | * to /sys/dev |
| 1799 | */ | 1804 | */ |
| 1800 | usb_classdev_class->dev_kobj = NULL; | 1805 | usb_classdev_class->dev_kobj = NULL; |
| 1801 | |||
| 1802 | usb_register_notify(&usbdev_nb); | ||
| 1803 | #endif | 1806 | #endif |
| 1807 | usb_register_notify(&usbdev_nb); | ||
| 1804 | out: | 1808 | out: |
| 1805 | return retval; | 1809 | return retval; |
| 1806 | 1810 | ||
| @@ -1811,8 +1815,8 @@ error_cdev: | |||
| 1811 | 1815 | ||
| 1812 | void usb_devio_cleanup(void) | 1816 | void usb_devio_cleanup(void) |
| 1813 | { | 1817 | { |
| 1814 | #ifdef CONFIG_USB_DEVICE_CLASS | ||
| 1815 | usb_unregister_notify(&usbdev_nb); | 1818 | usb_unregister_notify(&usbdev_nb); |
| 1819 | #ifdef CONFIG_USB_DEVICE_CLASS | ||
| 1816 | class_destroy(usb_classdev_class); | 1820 | class_destroy(usb_classdev_class); |
| 1817 | #endif | 1821 | #endif |
| 1818 | cdev_del(&usb_device_cdev); | 1822 | cdev_del(&usb_device_cdev); |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 98760553bc95..d0a21a5f8201 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
| @@ -284,7 +284,7 @@ static int usb_unbind_interface(struct device *dev) | |||
| 284 | * supports "soft" unbinding. | 284 | * supports "soft" unbinding. |
| 285 | */ | 285 | */ |
| 286 | if (!driver->soft_unbind) | 286 | if (!driver->soft_unbind) |
| 287 | usb_disable_interface(udev, intf); | 287 | usb_disable_interface(udev, intf, false); |
| 288 | 288 | ||
| 289 | driver->disconnect(intf); | 289 | driver->disconnect(intf); |
| 290 | usb_cancel_queued_reset(intf); | 290 | usb_cancel_queued_reset(intf); |
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 507741ed4482..c54fc40458b1 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
| @@ -128,7 +128,6 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | pci_set_master(dev); | 130 | pci_set_master(dev); |
| 131 | device_set_wakeup_enable(&dev->dev, 1); | ||
| 132 | 131 | ||
| 133 | retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); | 132 | retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); |
| 134 | if (retval != 0) | 133 | if (retval != 0) |
| @@ -201,6 +200,7 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) | |||
| 201 | struct usb_hcd *hcd = pci_get_drvdata(dev); | 200 | struct usb_hcd *hcd = pci_get_drvdata(dev); |
| 202 | int retval = 0; | 201 | int retval = 0; |
| 203 | int wake, w; | 202 | int wake, w; |
| 203 | int has_pci_pm; | ||
| 204 | 204 | ||
| 205 | /* Root hub suspend should have stopped all downstream traffic, | 205 | /* Root hub suspend should have stopped all downstream traffic, |
| 206 | * and all bus master traffic. And done so for both the interface | 206 | * and all bus master traffic. And done so for both the interface |
| @@ -230,6 +230,15 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) | |||
| 230 | 230 | ||
| 231 | synchronize_irq(dev->irq); | 231 | synchronize_irq(dev->irq); |
| 232 | 232 | ||
| 233 | /* Downstream ports from this root hub should already be quiesced, so | ||
| 234 | * there will be no DMA activity. Now we can shut down the upstream | ||
| 235 | * link (except maybe for PME# resume signaling) and enter some PCI | ||
| 236 | * low power state, if the hardware allows. | ||
| 237 | */ | ||
| 238 | pci_disable_device(dev); | ||
| 239 | |||
| 240 | pci_save_state(dev); | ||
| 241 | |||
| 233 | /* Don't fail on error to enable wakeup. We rely on pci code | 242 | /* Don't fail on error to enable wakeup. We rely on pci code |
| 234 | * to reject requests the hardware can't implement, rather | 243 | * to reject requests the hardware can't implement, rather |
| 235 | * than coding the same thing. | 244 | * than coding the same thing. |
| @@ -241,35 +250,6 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) | |||
| 241 | wake = w; | 250 | wake = w; |
| 242 | dev_dbg(&dev->dev, "wakeup: %d\n", wake); | 251 | dev_dbg(&dev->dev, "wakeup: %d\n", wake); |
| 243 | 252 | ||
| 244 | /* Downstream ports from this root hub should already be quiesced, so | ||
| 245 | * there will be no DMA activity. Now we can shut down the upstream | ||
| 246 | * link (except maybe for PME# resume signaling) and enter some PCI | ||
| 247 | * low power state, if the hardware allows. | ||
| 248 | */ | ||
| 249 | pci_disable_device(dev); | ||
| 250 | done: | ||
| 251 | return retval; | ||
| 252 | } | ||
| 253 | EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend); | ||
| 254 | |||
| 255 | /** | ||
| 256 | * usb_hcd_pci_suspend_late - suspend a PCI-based HCD after IRQs are disabled | ||
| 257 | * @dev: USB Host Controller being suspended | ||
| 258 | * @message: Power Management message describing this state transition | ||
| 259 | * | ||
| 260 | * Store this function in the HCD's struct pci_driver as .suspend_late. | ||
| 261 | */ | ||
| 262 | int usb_hcd_pci_suspend_late(struct pci_dev *dev, pm_message_t message) | ||
| 263 | { | ||
| 264 | int retval = 0; | ||
| 265 | int has_pci_pm; | ||
| 266 | |||
| 267 | /* We might already be suspended (runtime PM -- not yet written) */ | ||
| 268 | if (dev->current_state != PCI_D0) | ||
| 269 | goto done; | ||
| 270 | |||
| 271 | pci_save_state(dev); | ||
| 272 | |||
| 273 | /* Don't change state if we don't need to */ | 253 | /* Don't change state if we don't need to */ |
| 274 | if (message.event == PM_EVENT_FREEZE || | 254 | if (message.event == PM_EVENT_FREEZE || |
| 275 | message.event == PM_EVENT_PRETHAW) { | 255 | message.event == PM_EVENT_PRETHAW) { |
| @@ -315,7 +295,7 @@ int usb_hcd_pci_suspend_late(struct pci_dev *dev, pm_message_t message) | |||
| 315 | done: | 295 | done: |
| 316 | return retval; | 296 | return retval; |
| 317 | } | 297 | } |
| 318 | EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend_late); | 298 | EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend); |
| 319 | 299 | ||
| 320 | /** | 300 | /** |
| 321 | * usb_hcd_pci_resume_early - resume a PCI-based HCD before IRQs are enabled | 301 | * usb_hcd_pci_resume_early - resume a PCI-based HCD before IRQs are enabled |
| @@ -325,65 +305,8 @@ EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend_late); | |||
| 325 | */ | 305 | */ |
| 326 | int usb_hcd_pci_resume_early(struct pci_dev *dev) | 306 | int usb_hcd_pci_resume_early(struct pci_dev *dev) |
| 327 | { | 307 | { |
| 328 | int retval = 0; | 308 | pci_restore_state(dev); |
| 329 | pci_power_t state = dev->current_state; | 309 | return 0; |
| 330 | |||
| 331 | #ifdef CONFIG_PPC_PMAC | ||
| 332 | /* Reenable ASIC clocks for USB */ | ||
| 333 | if (machine_is(powermac)) { | ||
| 334 | struct device_node *of_node; | ||
| 335 | |||
| 336 | of_node = pci_device_to_OF_node(dev); | ||
| 337 | if (of_node) | ||
| 338 | pmac_call_feature(PMAC_FTR_USB_ENABLE, | ||
| 339 | of_node, 0, 1); | ||
| 340 | } | ||
| 341 | #endif | ||
| 342 | |||
| 343 | /* NOTE: chip docs cover clean "real suspend" cases (what Linux | ||
| 344 | * calls "standby", "suspend to RAM", and so on). There are also | ||
| 345 | * dirty cases when swsusp fakes a suspend in "shutdown" mode. | ||
| 346 | */ | ||
| 347 | if (state != PCI_D0) { | ||
| 348 | #ifdef DEBUG | ||
| 349 | int pci_pm; | ||
| 350 | u16 pmcr; | ||
| 351 | |||
| 352 | pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM); | ||
| 353 | pci_read_config_word(dev, pci_pm + PCI_PM_CTRL, &pmcr); | ||
| 354 | pmcr &= PCI_PM_CTRL_STATE_MASK; | ||
| 355 | if (pmcr) { | ||
| 356 | /* Clean case: power to USB and to HC registers was | ||
| 357 | * maintained; remote wakeup is easy. | ||
| 358 | */ | ||
| 359 | dev_dbg(&dev->dev, "resume from PCI D%d\n", pmcr); | ||
| 360 | } else { | ||
| 361 | /* Clean: HC lost Vcc power, D0 uninitialized | ||
| 362 | * + Vaux may have preserved port and transceiver | ||
| 363 | * state ... for remote wakeup from D3cold | ||
| 364 | * + or not; HCD must reinit + re-enumerate | ||
| 365 | * | ||
| 366 | * Dirty: D0 semi-initialized cases with swsusp | ||
| 367 | * + after BIOS init | ||
| 368 | * + after Linux init (HCD statically linked) | ||
| 369 | */ | ||
| 370 | dev_dbg(&dev->dev, "resume from previous PCI D%d\n", | ||
| 371 | state); | ||
| 372 | } | ||
| 373 | #endif | ||
| 374 | |||
| 375 | retval = pci_set_power_state(dev, PCI_D0); | ||
| 376 | } else { | ||
| 377 | /* Same basic cases: clean (powered/not), dirty */ | ||
| 378 | dev_dbg(&dev->dev, "PCI legacy resume\n"); | ||
| 379 | } | ||
| 380 | |||
| 381 | if (retval < 0) | ||
| 382 | dev_err(&dev->dev, "can't resume: %d\n", retval); | ||
| 383 | else | ||
| 384 | pci_restore_state(dev); | ||
| 385 | |||
| 386 | return retval; | ||
| 387 | } | 310 | } |
| 388 | EXPORT_SYMBOL_GPL(usb_hcd_pci_resume_early); | 311 | EXPORT_SYMBOL_GPL(usb_hcd_pci_resume_early); |
| 389 | 312 | ||
| @@ -398,6 +321,18 @@ int usb_hcd_pci_resume(struct pci_dev *dev) | |||
| 398 | struct usb_hcd *hcd; | 321 | struct usb_hcd *hcd; |
| 399 | int retval; | 322 | int retval; |
| 400 | 323 | ||
| 324 | #ifdef CONFIG_PPC_PMAC | ||
| 325 | /* Reenable ASIC clocks for USB */ | ||
| 326 | if (machine_is(powermac)) { | ||
| 327 | struct device_node *of_node; | ||
| 328 | |||
| 329 | of_node = pci_device_to_OF_node(dev); | ||
| 330 | if (of_node) | ||
| 331 | pmac_call_feature(PMAC_FTR_USB_ENABLE, | ||
| 332 | of_node, 0, 1); | ||
| 333 | } | ||
| 334 | #endif | ||
| 335 | |||
| 401 | hcd = pci_get_drvdata(dev); | 336 | hcd = pci_get_drvdata(dev); |
| 402 | if (hcd->state != HC_STATE_SUSPENDED) { | 337 | if (hcd->state != HC_STATE_SUSPENDED) { |
| 403 | dev_dbg(hcd->self.controller, | 338 | dev_dbg(hcd->self.controller, |
| @@ -405,6 +340,8 @@ int usb_hcd_pci_resume(struct pci_dev *dev) | |||
| 405 | return 0; | 340 | return 0; |
| 406 | } | 341 | } |
| 407 | 342 | ||
| 343 | pci_enable_wake(dev, PCI_D0, false); | ||
| 344 | |||
| 408 | retval = pci_enable_device(dev); | 345 | retval = pci_enable_device(dev); |
| 409 | if (retval < 0) { | 346 | if (retval < 0) { |
| 410 | dev_err(&dev->dev, "can't re-enable after resume, %d!\n", | 347 | dev_err(&dev->dev, "can't re-enable after resume, %d!\n", |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 572d2cf46e8d..5b94a56bec23 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
| @@ -257,7 +257,6 @@ extern void usb_hcd_pci_remove(struct pci_dev *dev); | |||
| 257 | 257 | ||
| 258 | #ifdef CONFIG_PM | 258 | #ifdef CONFIG_PM |
| 259 | extern int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t msg); | 259 | extern int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t msg); |
| 260 | extern int usb_hcd_pci_suspend_late(struct pci_dev *dev, pm_message_t msg); | ||
| 261 | extern int usb_hcd_pci_resume_early(struct pci_dev *dev); | 260 | extern int usb_hcd_pci_resume_early(struct pci_dev *dev); |
| 262 | extern int usb_hcd_pci_resume(struct pci_dev *dev); | 261 | extern int usb_hcd_pci_resume(struct pci_dev *dev); |
| 263 | #endif /* CONFIG_PM */ | 262 | #endif /* CONFIG_PM */ |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 94d5ee263c20..cd50d86029e7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -2382,8 +2382,8 @@ static int hub_port_debounce(struct usb_hub *hub, int port1) | |||
| 2382 | 2382 | ||
| 2383 | void usb_ep0_reinit(struct usb_device *udev) | 2383 | void usb_ep0_reinit(struct usb_device *udev) |
| 2384 | { | 2384 | { |
| 2385 | usb_disable_endpoint(udev, 0 + USB_DIR_IN); | 2385 | usb_disable_endpoint(udev, 0 + USB_DIR_IN, true); |
| 2386 | usb_disable_endpoint(udev, 0 + USB_DIR_OUT); | 2386 | usb_disable_endpoint(udev, 0 + USB_DIR_OUT, true); |
| 2387 | usb_enable_endpoint(udev, &udev->ep0, true); | 2387 | usb_enable_endpoint(udev, &udev->ep0, true); |
| 2388 | } | 2388 | } |
| 2389 | EXPORT_SYMBOL_GPL(usb_ep0_reinit); | 2389 | EXPORT_SYMBOL_GPL(usb_ep0_reinit); |
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 2a129cb7bb56..dff5760a37f6 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
| @@ -717,7 +717,6 @@ static void usbfs_remove_device(struct usb_device *dev) | |||
| 717 | fs_remove_file (dev->usbfs_dentry); | 717 | fs_remove_file (dev->usbfs_dentry); |
| 718 | dev->usbfs_dentry = NULL; | 718 | dev->usbfs_dentry = NULL; |
| 719 | } | 719 | } |
| 720 | usb_fs_classdev_common_remove(dev); | ||
| 721 | } | 720 | } |
| 722 | 721 | ||
| 723 | static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev) | 722 | static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev) |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index de51667dd64d..31fb204f44c6 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
| @@ -1039,14 +1039,15 @@ static void remove_intf_ep_devs(struct usb_interface *intf) | |||
| 1039 | * @dev: the device whose endpoint is being disabled | 1039 | * @dev: the device whose endpoint is being disabled |
| 1040 | * @epaddr: the endpoint's address. Endpoint number for output, | 1040 | * @epaddr: the endpoint's address. Endpoint number for output, |
| 1041 | * endpoint number + USB_DIR_IN for input | 1041 | * endpoint number + USB_DIR_IN for input |
| 1042 | * @reset_hardware: flag to erase any endpoint state stored in the | ||
| 1043 | * controller hardware | ||
| 1042 | * | 1044 | * |
| 1043 | * Deallocates hcd/hardware state for this endpoint ... and nukes all | 1045 | * Disables the endpoint for URB submission and nukes all pending URBs. |
| 1044 | * pending urbs. | 1046 | * If @reset_hardware is set then also deallocates hcd/hardware state |
| 1045 | * | 1047 | * for the endpoint. |
| 1046 | * If the HCD hasn't registered a disable() function, this sets the | ||
| 1047 | * endpoint's maxpacket size to 0 to prevent further submissions. | ||
| 1048 | */ | 1048 | */ |
| 1049 | void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) | 1049 | void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr, |
| 1050 | bool reset_hardware) | ||
| 1050 | { | 1051 | { |
| 1051 | unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK; | 1052 | unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK; |
| 1052 | struct usb_host_endpoint *ep; | 1053 | struct usb_host_endpoint *ep; |
| @@ -1056,15 +1057,18 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) | |||
| 1056 | 1057 | ||
| 1057 | if (usb_endpoint_out(epaddr)) { | 1058 | if (usb_endpoint_out(epaddr)) { |
| 1058 | ep = dev->ep_out[epnum]; | 1059 | ep = dev->ep_out[epnum]; |
| 1059 | dev->ep_out[epnum] = NULL; | 1060 | if (reset_hardware) |
| 1061 | dev->ep_out[epnum] = NULL; | ||
| 1060 | } else { | 1062 | } else { |
| 1061 | ep = dev->ep_in[epnum]; | 1063 | ep = dev->ep_in[epnum]; |
| 1062 | dev->ep_in[epnum] = NULL; | 1064 | if (reset_hardware) |
| 1065 | dev->ep_in[epnum] = NULL; | ||
| 1063 | } | 1066 | } |
| 1064 | if (ep) { | 1067 | if (ep) { |
| 1065 | ep->enabled = 0; | 1068 | ep->enabled = 0; |
| 1066 | usb_hcd_flush_endpoint(dev, ep); | 1069 | usb_hcd_flush_endpoint(dev, ep); |
| 1067 | usb_hcd_disable_endpoint(dev, ep); | 1070 | if (reset_hardware) |
| 1071 | usb_hcd_disable_endpoint(dev, ep); | ||
| 1068 | } | 1072 | } |
| 1069 | } | 1073 | } |
| 1070 | 1074 | ||
| @@ -1072,17 +1076,21 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) | |||
| 1072 | * usb_disable_interface -- Disable all endpoints for an interface | 1076 | * usb_disable_interface -- Disable all endpoints for an interface |
| 1073 | * @dev: the device whose interface is being disabled | 1077 | * @dev: the device whose interface is being disabled |
| 1074 | * @intf: pointer to the interface descriptor | 1078 | * @intf: pointer to the interface descriptor |
| 1079 | * @reset_hardware: flag to erase any endpoint state stored in the | ||
| 1080 | * controller hardware | ||
| 1075 | * | 1081 | * |
| 1076 | * Disables all the endpoints for the interface's current altsetting. | 1082 | * Disables all the endpoints for the interface's current altsetting. |
| 1077 | */ | 1083 | */ |
| 1078 | void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf) | 1084 | void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf, |
| 1085 | bool reset_hardware) | ||
| 1079 | { | 1086 | { |
| 1080 | struct usb_host_interface *alt = intf->cur_altsetting; | 1087 | struct usb_host_interface *alt = intf->cur_altsetting; |
| 1081 | int i; | 1088 | int i; |
| 1082 | 1089 | ||
| 1083 | for (i = 0; i < alt->desc.bNumEndpoints; ++i) { | 1090 | for (i = 0; i < alt->desc.bNumEndpoints; ++i) { |
| 1084 | usb_disable_endpoint(dev, | 1091 | usb_disable_endpoint(dev, |
| 1085 | alt->endpoint[i].desc.bEndpointAddress); | 1092 | alt->endpoint[i].desc.bEndpointAddress, |
| 1093 | reset_hardware); | ||
| 1086 | } | 1094 | } |
| 1087 | } | 1095 | } |
| 1088 | 1096 | ||
| @@ -1103,8 +1111,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) | |||
| 1103 | dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, | 1111 | dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__, |
| 1104 | skip_ep0 ? "non-ep0" : "all"); | 1112 | skip_ep0 ? "non-ep0" : "all"); |
| 1105 | for (i = skip_ep0; i < 16; ++i) { | 1113 | for (i = skip_ep0; i < 16; ++i) { |
| 1106 | usb_disable_endpoint(dev, i); | 1114 | usb_disable_endpoint(dev, i, true); |
| 1107 | usb_disable_endpoint(dev, i + USB_DIR_IN); | 1115 | usb_disable_endpoint(dev, i + USB_DIR_IN, true); |
| 1108 | } | 1116 | } |
| 1109 | dev->toggle[0] = dev->toggle[1] = 0; | 1117 | dev->toggle[0] = dev->toggle[1] = 0; |
| 1110 | 1118 | ||
| @@ -1274,7 +1282,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) | |||
| 1274 | remove_intf_ep_devs(iface); | 1282 | remove_intf_ep_devs(iface); |
| 1275 | usb_remove_sysfs_intf_files(iface); | 1283 | usb_remove_sysfs_intf_files(iface); |
| 1276 | } | 1284 | } |
| 1277 | usb_disable_interface(dev, iface); | 1285 | usb_disable_interface(dev, iface, true); |
| 1278 | 1286 | ||
| 1279 | iface->cur_altsetting = alt; | 1287 | iface->cur_altsetting = alt; |
| 1280 | 1288 | ||
| @@ -1353,8 +1361,8 @@ int usb_reset_configuration(struct usb_device *dev) | |||
| 1353 | */ | 1361 | */ |
| 1354 | 1362 | ||
| 1355 | for (i = 1; i < 16; ++i) { | 1363 | for (i = 1; i < 16; ++i) { |
| 1356 | usb_disable_endpoint(dev, i); | 1364 | usb_disable_endpoint(dev, i, true); |
| 1357 | usb_disable_endpoint(dev, i + USB_DIR_IN); | 1365 | usb_disable_endpoint(dev, i + USB_DIR_IN, true); |
| 1358 | } | 1366 | } |
| 1359 | 1367 | ||
| 1360 | config = dev->actconfig; | 1368 | config = dev->actconfig; |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 386177867a8a..79d8a9ea559b 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
| @@ -15,9 +15,10 @@ extern void usb_enable_endpoint(struct usb_device *dev, | |||
| 15 | struct usb_host_endpoint *ep, bool reset_toggle); | 15 | struct usb_host_endpoint *ep, bool reset_toggle); |
| 16 | extern void usb_enable_interface(struct usb_device *dev, | 16 | extern void usb_enable_interface(struct usb_device *dev, |
| 17 | struct usb_interface *intf, bool reset_toggles); | 17 | struct usb_interface *intf, bool reset_toggles); |
| 18 | extern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr); | 18 | extern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr, |
| 19 | bool reset_hardware); | ||
| 19 | extern void usb_disable_interface(struct usb_device *dev, | 20 | extern void usb_disable_interface(struct usb_device *dev, |
| 20 | struct usb_interface *intf); | 21 | struct usb_interface *intf, bool reset_hardware); |
| 21 | extern void usb_release_interface_cache(struct kref *ref); | 22 | extern void usb_release_interface_cache(struct kref *ref); |
| 22 | extern void usb_disable_device(struct usb_device *dev, int skip_ep0); | 23 | extern void usb_disable_device(struct usb_device *dev, int skip_ep0); |
| 23 | extern int usb_deauthorize_device(struct usb_device *); | 24 | extern int usb_deauthorize_device(struct usb_device *); |
| @@ -151,7 +152,6 @@ extern struct usb_driver usbfs_driver; | |||
| 151 | extern const struct file_operations usbfs_devices_fops; | 152 | extern const struct file_operations usbfs_devices_fops; |
| 152 | extern const struct file_operations usbdev_file_operations; | 153 | extern const struct file_operations usbdev_file_operations; |
| 153 | extern void usbfs_conn_disc_event(void); | 154 | extern void usbfs_conn_disc_event(void); |
| 154 | extern void usb_fs_classdev_common_remove(struct usb_device *udev); | ||
| 155 | 155 | ||
| 156 | extern int usb_devio_init(void); | 156 | extern int usb_devio_init(void); |
| 157 | extern void usb_devio_cleanup(void); | 157 | extern void usb_devio_cleanup(void); |
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index f2da0269e1b1..5d11c291f1ad 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c | |||
| @@ -683,6 +683,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
| 683 | struct usb_request *req = cdev->req; | 683 | struct usb_request *req = cdev->req; |
| 684 | int value = -EOPNOTSUPP; | 684 | int value = -EOPNOTSUPP; |
| 685 | u16 w_index = le16_to_cpu(ctrl->wIndex); | 685 | u16 w_index = le16_to_cpu(ctrl->wIndex); |
| 686 | u8 intf = w_index & 0xFF; | ||
| 686 | u16 w_value = le16_to_cpu(ctrl->wValue); | 687 | u16 w_value = le16_to_cpu(ctrl->wValue); |
| 687 | u16 w_length = le16_to_cpu(ctrl->wLength); | 688 | u16 w_length = le16_to_cpu(ctrl->wLength); |
| 688 | struct usb_function *f = NULL; | 689 | struct usb_function *f = NULL; |
| @@ -769,10 +770,10 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
| 769 | goto unknown; | 770 | goto unknown; |
| 770 | if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) | 771 | if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) |
| 771 | break; | 772 | break; |
| 772 | f = cdev->config->interface[w_index]; | 773 | f = cdev->config->interface[intf]; |
| 773 | if (!f) | 774 | if (!f) |
| 774 | break; | 775 | break; |
| 775 | if (w_value && !f->get_alt) | 776 | if (w_value && !f->set_alt) |
| 776 | break; | 777 | break; |
| 777 | value = f->set_alt(f, w_index, w_value); | 778 | value = f->set_alt(f, w_index, w_value); |
| 778 | break; | 779 | break; |
| @@ -781,7 +782,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
| 781 | goto unknown; | 782 | goto unknown; |
| 782 | if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) | 783 | if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) |
| 783 | break; | 784 | break; |
| 784 | f = cdev->config->interface[w_index]; | 785 | f = cdev->config->interface[intf]; |
| 785 | if (!f) | 786 | if (!f) |
| 786 | break; | 787 | break; |
| 787 | /* lots of interfaces only need altsetting zero... */ | 788 | /* lots of interfaces only need altsetting zero... */ |
| @@ -808,7 +809,7 @@ unknown: | |||
| 808 | */ | 809 | */ |
| 809 | if ((ctrl->bRequestType & USB_RECIP_MASK) | 810 | if ((ctrl->bRequestType & USB_RECIP_MASK) |
| 810 | == USB_RECIP_INTERFACE) { | 811 | == USB_RECIP_INTERFACE) { |
| 811 | f = cdev->config->interface[w_index]; | 812 | f = cdev->config->interface[intf]; |
| 812 | if (f && f->setup) | 813 | if (f && f->setup) |
| 813 | value = f->setup(f, ctrl); | 814 | value = f->setup(f, ctrl); |
| 814 | else | 815 | else |
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index cde8fdf15d5b..77c5d0a8a06e 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c | |||
| @@ -297,7 +297,7 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) | |||
| 297 | 297 | ||
| 298 | for (i = 0; i < 100; i ++) { | 298 | for (i = 0; i < 100; i ++) { |
| 299 | temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); | 299 | temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); |
| 300 | if (!temp & EPSTAT_STALL) | 300 | if (!(temp & EPSTAT_STALL)) |
| 301 | break; | 301 | break; |
| 302 | udelay(20); | 302 | udelay(20); |
| 303 | } | 303 | } |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 2b476b6b3d4d..2c63bfb1f8d9 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
| @@ -140,6 +140,7 @@ config USB_OHCI_HCD | |||
| 140 | tristate "OHCI HCD support" | 140 | tristate "OHCI HCD support" |
| 141 | depends on USB && USB_ARCH_HAS_OHCI | 141 | depends on USB && USB_ARCH_HAS_OHCI |
| 142 | select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 | 142 | select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 |
| 143 | select USB_OTG_UTILS if ARCH_OMAP | ||
| 143 | ---help--- | 144 | ---help--- |
| 144 | The Open Host Controller Interface (OHCI) is a standard for accessing | 145 | The Open Host Controller Interface (OHCI) is a standard for accessing |
| 145 | USB 1.1 host controller hardware. It does more in hardware than Intel's | 146 | USB 1.1 host controller hardware. It does more in hardware than Intel's |
| @@ -238,6 +239,23 @@ config USB_UHCI_HCD | |||
| 238 | To compile this driver as a module, choose M here: the | 239 | To compile this driver as a module, choose M here: the |
| 239 | module will be called uhci-hcd. | 240 | module will be called uhci-hcd. |
| 240 | 241 | ||
| 242 | config USB_FHCI_HCD | ||
| 243 | tristate "Freescale QE USB Host Controller support" | ||
| 244 | depends on USB && OF_GPIO && QE_GPIO && QUICC_ENGINE | ||
| 245 | select FSL_GTM | ||
| 246 | select QE_USB | ||
| 247 | help | ||
| 248 | This driver enables support for Freescale QE USB Host Controller | ||
| 249 | (as found on MPC8360 and MPC8323 processors), the driver supports | ||
| 250 | Full and Low Speed USB. | ||
| 251 | |||
| 252 | config FHCI_DEBUG | ||
| 253 | bool "Freescale QE USB Host Controller debug support" | ||
| 254 | depends on USB_FHCI_HCD && DEBUG_FS | ||
| 255 | help | ||
| 256 | Say "y" to see some FHCI debug information and statistics | ||
| 257 | throught debugfs. | ||
| 258 | |||
| 241 | config USB_U132_HCD | 259 | config USB_U132_HCD |
| 242 | tristate "Elan U132 Adapter Host Controller" | 260 | tristate "Elan U132 Adapter Host Controller" |
| 243 | depends on USB && USB_FTDI_ELAN | 261 | depends on USB && USB_FTDI_ELAN |
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index e5f3f20787e4..f163571e33d8 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
| @@ -7,6 +7,11 @@ ifeq ($(CONFIG_USB_DEBUG),y) | |||
| 7 | endif | 7 | endif |
| 8 | 8 | ||
| 9 | isp1760-objs := isp1760-hcd.o isp1760-if.o | 9 | isp1760-objs := isp1760-hcd.o isp1760-if.o |
| 10 | fhci-objs := fhci-hcd.o fhci-hub.o fhci-q.o fhci-mem.o \ | ||
| 11 | fhci-tds.o fhci-sched.o | ||
| 12 | ifeq ($(CONFIG_FHCI_DEBUG),y) | ||
| 13 | fhci-objs += fhci-dbg.o | ||
| 14 | endif | ||
| 10 | 15 | ||
| 11 | obj-$(CONFIG_USB_WHCI_HCD) += whci/ | 16 | obj-$(CONFIG_USB_WHCI_HCD) += whci/ |
| 12 | 17 | ||
| @@ -17,6 +22,7 @@ obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o | |||
| 17 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o | 22 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o |
| 18 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o | 23 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o |
| 19 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o | 24 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o |
| 25 | obj-$(CONFIG_USB_FHCI_HCD) += fhci.o | ||
| 20 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o | 26 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o |
| 21 | obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o | 27 | obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o |
| 22 | obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o | 28 | obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index bdc6e86e1f8b..bb21fb0a4969 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
| @@ -230,7 +230,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
| 230 | pci_read_config_word(pdev, 0x62, &port_wake); | 230 | pci_read_config_word(pdev, 0x62, &port_wake); |
| 231 | if (port_wake & 0x0001) { | 231 | if (port_wake & 0x0001) { |
| 232 | dev_warn(&pdev->dev, "Enabling legacy PCI PM\n"); | 232 | dev_warn(&pdev->dev, "Enabling legacy PCI PM\n"); |
| 233 | device_init_wakeup(&pdev->dev, 1); | 233 | device_set_wakeup_capable(&pdev->dev, 1); |
| 234 | } | 234 | } |
| 235 | } | 235 | } |
| 236 | 236 | ||
| @@ -432,7 +432,6 @@ static struct pci_driver ehci_pci_driver = { | |||
| 432 | 432 | ||
| 433 | #ifdef CONFIG_PM | 433 | #ifdef CONFIG_PM |
| 434 | .suspend = usb_hcd_pci_suspend, | 434 | .suspend = usb_hcd_pci_suspend, |
| 435 | .suspend_late = usb_hcd_pci_suspend_late, | ||
| 436 | .resume_early = usb_hcd_pci_resume_early, | 435 | .resume_early = usb_hcd_pci_resume_early, |
| 437 | .resume = usb_hcd_pci_resume, | 436 | .resume = usb_hcd_pci_resume, |
| 438 | #endif | 437 | #endif |
diff --git a/drivers/usb/host/fhci-dbg.c b/drivers/usb/host/fhci-dbg.c new file mode 100644 index 000000000000..34e14edf390b --- /dev/null +++ b/drivers/usb/host/fhci-dbg.c | |||
| @@ -0,0 +1,139 @@ | |||
| 1 | /* | ||
| 2 | * Freescale QUICC Engine USB Host Controller Driver | ||
| 3 | * | ||
| 4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
| 5 | * Shlomi Gridish <gridish@freescale.com> | ||
| 6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
| 7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
| 8 | * Peter Barada <peterb@logicpd.com> | ||
| 9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
| 10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License as published by the | ||
| 14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 15 | * option) any later version. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/errno.h> | ||
| 20 | #include <linux/debugfs.h> | ||
| 21 | #include <linux/seq_file.h> | ||
| 22 | #include <linux/usb.h> | ||
| 23 | #include "../core/hcd.h" | ||
| 24 | #include "fhci.h" | ||
| 25 | |||
| 26 | void fhci_dbg_isr(struct fhci_hcd *fhci, int usb_er) | ||
| 27 | { | ||
| 28 | int i; | ||
| 29 | |||
| 30 | if (usb_er == -1) { | ||
| 31 | fhci->usb_irq_stat[12]++; | ||
| 32 | return; | ||
| 33 | } | ||
| 34 | |||
| 35 | for (i = 0; i < 12; ++i) { | ||
| 36 | if (usb_er & (1 << i)) | ||
| 37 | fhci->usb_irq_stat[i]++; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | static int fhci_dfs_regs_show(struct seq_file *s, void *v) | ||
| 42 | { | ||
| 43 | struct fhci_hcd *fhci = s->private; | ||
| 44 | struct fhci_regs __iomem *regs = fhci->regs; | ||
| 45 | |||
| 46 | seq_printf(s, | ||
| 47 | "mode: 0x%x\n" "addr: 0x%x\n" | ||
| 48 | "command: 0x%x\n" "ep0: 0x%x\n" | ||
| 49 | "event: 0x%x\n" "mask: 0x%x\n" | ||
| 50 | "status: 0x%x\n" "SOF timer: %d\n" | ||
| 51 | "frame number: %d\n" | ||
| 52 | "lines status: 0x%x\n", | ||
| 53 | in_8(®s->usb_mod), in_8(®s->usb_addr), | ||
| 54 | in_8(®s->usb_comm), in_be16(®s->usb_ep[0]), | ||
| 55 | in_be16(®s->usb_event), in_be16(®s->usb_mask), | ||
| 56 | in_8(®s->usb_status), in_be16(®s->usb_sof_tmr), | ||
| 57 | in_be16(®s->usb_frame_num), | ||
| 58 | fhci_ioports_check_bus_state(fhci)); | ||
| 59 | |||
| 60 | return 0; | ||
| 61 | } | ||
| 62 | |||
| 63 | static int fhci_dfs_irq_stat_show(struct seq_file *s, void *v) | ||
| 64 | { | ||
| 65 | struct fhci_hcd *fhci = s->private; | ||
| 66 | int *usb_irq_stat = fhci->usb_irq_stat; | ||
| 67 | |||
| 68 | seq_printf(s, | ||
| 69 | "RXB: %d\n" "TXB: %d\n" "BSY: %d\n" | ||
| 70 | "SOF: %d\n" "TXE0: %d\n" "TXE1: %d\n" | ||
| 71 | "TXE2: %d\n" "TXE3: %d\n" "IDLE: %d\n" | ||
| 72 | "RESET: %d\n" "SFT: %d\n" "MSF: %d\n" | ||
| 73 | "IDLE_ONLY: %d\n", | ||
| 74 | usb_irq_stat[0], usb_irq_stat[1], usb_irq_stat[2], | ||
| 75 | usb_irq_stat[3], usb_irq_stat[4], usb_irq_stat[5], | ||
| 76 | usb_irq_stat[6], usb_irq_stat[7], usb_irq_stat[8], | ||
| 77 | usb_irq_stat[9], usb_irq_stat[10], usb_irq_stat[11], | ||
| 78 | usb_irq_stat[12]); | ||
| 79 | |||
| 80 | return 0; | ||
| 81 | } | ||
| 82 | |||
| 83 | static int fhci_dfs_regs_open(struct inode *inode, struct file *file) | ||
| 84 | { | ||
| 85 | return single_open(file, fhci_dfs_regs_show, inode->i_private); | ||
| 86 | } | ||
| 87 | |||
| 88 | static int fhci_dfs_irq_stat_open(struct inode *inode, struct file *file) | ||
| 89 | { | ||
| 90 | return single_open(file, fhci_dfs_irq_stat_show, inode->i_private); | ||
| 91 | } | ||
| 92 | |||
| 93 | static const struct file_operations fhci_dfs_regs_fops = { | ||
| 94 | .open = fhci_dfs_regs_open, | ||
| 95 | .read = seq_read, | ||
| 96 | .llseek = seq_lseek, | ||
| 97 | .release = single_release, | ||
| 98 | }; | ||
| 99 | |||
| 100 | static const struct file_operations fhci_dfs_irq_stat_fops = { | ||
| 101 | .open = fhci_dfs_irq_stat_open, | ||
| 102 | .read = seq_read, | ||
| 103 | .llseek = seq_lseek, | ||
| 104 | .release = single_release, | ||
| 105 | }; | ||
| 106 | |||
| 107 | void fhci_dfs_create(struct fhci_hcd *fhci) | ||
| 108 | { | ||
| 109 | struct device *dev = fhci_to_hcd(fhci)->self.controller; | ||
| 110 | |||
| 111 | fhci->dfs_root = debugfs_create_dir(dev->bus_id, NULL); | ||
| 112 | if (!fhci->dfs_root) { | ||
| 113 | WARN_ON(1); | ||
| 114 | return; | ||
| 115 | } | ||
| 116 | |||
| 117 | fhci->dfs_regs = debugfs_create_file("regs", S_IFREG | S_IRUGO, | ||
| 118 | fhci->dfs_root, fhci, &fhci_dfs_regs_fops); | ||
| 119 | |||
| 120 | fhci->dfs_irq_stat = debugfs_create_file("irq_stat", | ||
| 121 | S_IFREG | S_IRUGO, fhci->dfs_root, fhci, | ||
| 122 | &fhci_dfs_irq_stat_fops); | ||
| 123 | |||
| 124 | WARN_ON(!fhci->dfs_regs || !fhci->dfs_irq_stat); | ||
| 125 | } | ||
| 126 | |||
| 127 | void fhci_dfs_destroy(struct fhci_hcd *fhci) | ||
| 128 | { | ||
| 129 | if (!fhci->dfs_root) | ||
| 130 | return; | ||
| 131 | |||
| 132 | if (fhci->dfs_irq_stat) | ||
| 133 | debugfs_remove(fhci->dfs_irq_stat); | ||
| 134 | |||
| 135 | if (fhci->dfs_regs) | ||
| 136 | debugfs_remove(fhci->dfs_regs); | ||
| 137 | |||
| 138 | debugfs_remove(fhci->dfs_root); | ||
| 139 | } | ||
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c new file mode 100644 index 000000000000..ba622cc8a9ba --- /dev/null +++ b/drivers/usb/host/fhci-hcd.c | |||
| @@ -0,0 +1,836 @@ | |||
| 1 | /* | ||
| 2 | * Freescale QUICC Engine USB Host Controller Driver | ||
| 3 | * | ||
| 4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
| 5 | * Shlomi Gridish <gridish@freescale.com> | ||
| 6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
| 7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
| 8 | * Peter Barada <peterb@logicpd.com> | ||
| 9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
| 10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License as published by the | ||
| 14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 15 | * option) any later version. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/types.h> | ||
| 20 | #include <linux/spinlock.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/delay.h> | ||
| 23 | #include <linux/errno.h> | ||
| 24 | #include <linux/list.h> | ||
| 25 | #include <linux/interrupt.h> | ||
| 26 | #include <linux/io.h> | ||
| 27 | #include <linux/usb.h> | ||
| 28 | #include <linux/of_platform.h> | ||
| 29 | #include <linux/of_gpio.h> | ||
| 30 | #include <asm/qe.h> | ||
| 31 | #include <asm/fsl_gtm.h> | ||
| 32 | #include "../core/hcd.h" | ||
| 33 | #include "fhci.h" | ||
| 34 | |||
| 35 | void fhci_start_sof_timer(struct fhci_hcd *fhci) | ||
| 36 | { | ||
| 37 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
| 38 | |||
| 39 | /* clear frame_n */ | ||
| 40 | out_be16(&fhci->pram->frame_num, 0); | ||
| 41 | |||
| 42 | out_be16(&fhci->regs->usb_sof_tmr, 0); | ||
| 43 | setbits8(&fhci->regs->usb_mod, USB_MODE_SFTE); | ||
| 44 | |||
| 45 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
| 46 | } | ||
| 47 | |||
| 48 | void fhci_stop_sof_timer(struct fhci_hcd *fhci) | ||
| 49 | { | ||
| 50 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
| 51 | |||
| 52 | clrbits8(&fhci->regs->usb_mod, USB_MODE_SFTE); | ||
| 53 | gtm_stop_timer16(fhci->timer); | ||
| 54 | |||
| 55 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
| 56 | } | ||
| 57 | |||
| 58 | u16 fhci_get_sof_timer_count(struct fhci_usb *usb) | ||
| 59 | { | ||
| 60 | return be16_to_cpu(in_be16(&usb->fhci->regs->usb_sof_tmr) / 12); | ||
| 61 | } | ||
| 62 | |||
| 63 | /* initialize the endpoint zero */ | ||
| 64 | static u32 endpoint_zero_init(struct fhci_usb *usb, | ||
| 65 | enum fhci_mem_alloc data_mem, | ||
| 66 | u32 ring_len) | ||
| 67 | { | ||
| 68 | u32 rc; | ||
| 69 | |||
| 70 | rc = fhci_create_ep(usb, data_mem, ring_len); | ||
| 71 | if (rc) | ||
| 72 | return rc; | ||
| 73 | |||
| 74 | /* inilialize endpoint registers */ | ||
| 75 | fhci_init_ep_registers(usb, usb->ep0, data_mem); | ||
| 76 | |||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | /* enable the USB interrupts */ | ||
| 81 | void fhci_usb_enable_interrupt(struct fhci_usb *usb) | ||
| 82 | { | ||
| 83 | struct fhci_hcd *fhci = usb->fhci; | ||
| 84 | |||
| 85 | if (usb->intr_nesting_cnt == 1) { | ||
| 86 | /* initialize the USB interrupt */ | ||
| 87 | enable_irq(fhci_to_hcd(fhci)->irq); | ||
| 88 | |||
| 89 | /* initialize the event register and mask register */ | ||
| 90 | out_be16(&usb->fhci->regs->usb_event, 0xffff); | ||
| 91 | out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | ||
| 92 | |||
| 93 | /* enable the timer interrupts */ | ||
| 94 | enable_irq(fhci->timer->irq); | ||
| 95 | } else if (usb->intr_nesting_cnt > 1) | ||
| 96 | fhci_info(fhci, "unbalanced USB interrupts nesting\n"); | ||
| 97 | usb->intr_nesting_cnt--; | ||
| 98 | } | ||
| 99 | |||
| 100 | /* diable the usb interrupt */ | ||
| 101 | void fhci_usb_disable_interrupt(struct fhci_usb *usb) | ||
| 102 | { | ||
| 103 | struct fhci_hcd *fhci = usb->fhci; | ||
| 104 | |||
| 105 | if (usb->intr_nesting_cnt == 0) { | ||
| 106 | /* diable the timer interrupt */ | ||
| 107 | disable_irq_nosync(fhci->timer->irq); | ||
| 108 | |||
| 109 | /* disable the usb interrupt */ | ||
| 110 | disable_irq_nosync(fhci_to_hcd(fhci)->irq); | ||
| 111 | out_be16(&usb->fhci->regs->usb_mask, 0); | ||
| 112 | } | ||
| 113 | usb->intr_nesting_cnt++; | ||
| 114 | } | ||
| 115 | |||
| 116 | /* enable the USB controller */ | ||
| 117 | static u32 fhci_usb_enable(struct fhci_hcd *fhci) | ||
| 118 | { | ||
| 119 | struct fhci_usb *usb = fhci->usb_lld; | ||
| 120 | |||
| 121 | out_be16(&usb->fhci->regs->usb_event, 0xffff); | ||
| 122 | out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | ||
| 123 | setbits8(&usb->fhci->regs->usb_mod, USB_MODE_EN); | ||
| 124 | |||
| 125 | mdelay(100); | ||
| 126 | |||
| 127 | return 0; | ||
| 128 | } | ||
| 129 | |||
| 130 | /* disable the USB controller */ | ||
| 131 | static u32 fhci_usb_disable(struct fhci_hcd *fhci) | ||
| 132 | { | ||
| 133 | struct fhci_usb *usb = fhci->usb_lld; | ||
| 134 | |||
| 135 | fhci_usb_disable_interrupt(usb); | ||
| 136 | fhci_port_disable(fhci); | ||
| 137 | |||
| 138 | /* disable the usb controller */ | ||
| 139 | if (usb->port_status == FHCI_PORT_FULL || | ||
| 140 | usb->port_status == FHCI_PORT_LOW) | ||
| 141 | fhci_device_disconnected_interrupt(fhci); | ||
| 142 | |||
| 143 | clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_EN); | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | /* check the bus state by polling the QE bit on the IO ports */ | ||
| 149 | int fhci_ioports_check_bus_state(struct fhci_hcd *fhci) | ||
| 150 | { | ||
| 151 | u8 bits = 0; | ||
| 152 | |||
| 153 | /* check USBOE,if transmitting,exit */ | ||
| 154 | if (!gpio_get_value(fhci->gpios[GPIO_USBOE])) | ||
| 155 | return -1; | ||
| 156 | |||
| 157 | /* check USBRP */ | ||
| 158 | if (gpio_get_value(fhci->gpios[GPIO_USBRP])) | ||
| 159 | bits |= 0x2; | ||
| 160 | |||
| 161 | /* check USBRN */ | ||
| 162 | if (gpio_get_value(fhci->gpios[GPIO_USBRN])) | ||
| 163 | bits |= 0x1; | ||
| 164 | |||
| 165 | return bits; | ||
| 166 | } | ||
| 167 | |||
| 168 | static void fhci_mem_free(struct fhci_hcd *fhci) | ||
| 169 | { | ||
| 170 | struct ed *ed; | ||
| 171 | struct ed *next_ed; | ||
| 172 | struct td *td; | ||
| 173 | struct td *next_td; | ||
| 174 | |||
| 175 | list_for_each_entry_safe(ed, next_ed, &fhci->empty_eds, node) { | ||
| 176 | list_del(&ed->node); | ||
| 177 | kfree(ed); | ||
| 178 | } | ||
| 179 | |||
| 180 | list_for_each_entry_safe(td, next_td, &fhci->empty_tds, node) { | ||
| 181 | list_del(&td->node); | ||
| 182 | kfree(td); | ||
| 183 | } | ||
| 184 | |||
| 185 | kfree(fhci->vroot_hub); | ||
| 186 | fhci->vroot_hub = NULL; | ||
| 187 | |||
| 188 | kfree(fhci->hc_list); | ||
| 189 | fhci->hc_list = NULL; | ||
| 190 | } | ||
| 191 | |||
| 192 | static int fhci_mem_init(struct fhci_hcd *fhci) | ||
| 193 | { | ||
| 194 | int i; | ||
| 195 | |||
| 196 | fhci->hc_list = kzalloc(sizeof(*fhci->hc_list), GFP_KERNEL); | ||
| 197 | if (!fhci->hc_list) | ||
| 198 | goto err; | ||
| 199 | |||
| 200 | INIT_LIST_HEAD(&fhci->hc_list->ctrl_list); | ||
| 201 | INIT_LIST_HEAD(&fhci->hc_list->bulk_list); | ||
| 202 | INIT_LIST_HEAD(&fhci->hc_list->iso_list); | ||
| 203 | INIT_LIST_HEAD(&fhci->hc_list->intr_list); | ||
| 204 | INIT_LIST_HEAD(&fhci->hc_list->done_list); | ||
| 205 | |||
| 206 | fhci->vroot_hub = kzalloc(sizeof(*fhci->vroot_hub), GFP_KERNEL); | ||
| 207 | if (!fhci->vroot_hub) | ||
| 208 | goto err; | ||
| 209 | |||
| 210 | INIT_LIST_HEAD(&fhci->empty_eds); | ||
| 211 | INIT_LIST_HEAD(&fhci->empty_tds); | ||
| 212 | |||
| 213 | /* initialize work queue to handle done list */ | ||
| 214 | fhci_tasklet.data = (unsigned long)fhci; | ||
| 215 | fhci->process_done_task = &fhci_tasklet; | ||
| 216 | |||
| 217 | for (i = 0; i < MAX_TDS; i++) { | ||
| 218 | struct td *td; | ||
| 219 | |||
| 220 | td = kmalloc(sizeof(*td), GFP_KERNEL); | ||
| 221 | if (!td) | ||
| 222 | goto err; | ||
| 223 | fhci_recycle_empty_td(fhci, td); | ||
| 224 | } | ||
| 225 | for (i = 0; i < MAX_EDS; i++) { | ||
| 226 | struct ed *ed; | ||
| 227 | |||
| 228 | ed = kmalloc(sizeof(*ed), GFP_KERNEL); | ||
| 229 | if (!ed) | ||
| 230 | goto err; | ||
| 231 | fhci_recycle_empty_ed(fhci, ed); | ||
| 232 | } | ||
| 233 | |||
| 234 | fhci->active_urbs = 0; | ||
| 235 | return 0; | ||
| 236 | err: | ||
| 237 | fhci_mem_free(fhci); | ||
| 238 | return -ENOMEM; | ||
| 239 | } | ||
| 240 | |||
| 241 | /* destroy the fhci_usb structure */ | ||
| 242 | static void fhci_usb_free(void *lld) | ||
| 243 | { | ||
| 244 | struct fhci_usb *usb = lld; | ||
| 245 | struct fhci_hcd *fhci = usb->fhci; | ||
| 246 | |||
| 247 | if (usb) { | ||
| 248 | fhci_config_transceiver(fhci, FHCI_PORT_POWER_OFF); | ||
| 249 | fhci_ep0_free(usb); | ||
| 250 | kfree(usb->actual_frame); | ||
| 251 | kfree(usb); | ||
| 252 | } | ||
| 253 | } | ||
| 254 | |||
| 255 | /* initialize the USB */ | ||
| 256 | static int fhci_usb_init(struct fhci_hcd *fhci) | ||
| 257 | { | ||
| 258 | struct fhci_usb *usb = fhci->usb_lld; | ||
| 259 | |||
| 260 | memset_io(usb->fhci->pram, 0, FHCI_PRAM_SIZE); | ||
| 261 | |||
| 262 | usb->port_status = FHCI_PORT_DISABLED; | ||
| 263 | usb->max_frame_usage = FRAME_TIME_USAGE; | ||
| 264 | usb->sw_transaction_time = SW_FIX_TIME_BETWEEN_TRANSACTION; | ||
| 265 | |||
| 266 | usb->actual_frame = kzalloc(sizeof(*usb->actual_frame), GFP_KERNEL); | ||
| 267 | if (!usb->actual_frame) { | ||
| 268 | fhci_usb_free(usb); | ||
| 269 | return -ENOMEM; | ||
| 270 | } | ||
| 271 | |||
| 272 | INIT_LIST_HEAD(&usb->actual_frame->tds_list); | ||
| 273 | |||
| 274 | /* initializing registers on chip, clear frame number */ | ||
| 275 | out_be16(&fhci->pram->frame_num, 0); | ||
| 276 | |||
| 277 | /* clear rx state */ | ||
| 278 | out_be32(&fhci->pram->rx_state, 0); | ||
| 279 | |||
| 280 | /* set mask register */ | ||
| 281 | usb->saved_msk = (USB_E_TXB_MASK | | ||
| 282 | USB_E_TXE1_MASK | | ||
| 283 | USB_E_IDLE_MASK | | ||
| 284 | USB_E_RESET_MASK | USB_E_SFT_MASK | USB_E_MSF_MASK); | ||
| 285 | |||
| 286 | out_8(&usb->fhci->regs->usb_mod, USB_MODE_HOST | USB_MODE_EN); | ||
| 287 | |||
| 288 | /* clearing the mask register */ | ||
| 289 | out_be16(&usb->fhci->regs->usb_mask, 0); | ||
| 290 | |||
| 291 | /* initialing the event register */ | ||
| 292 | out_be16(&usb->fhci->regs->usb_event, 0xffff); | ||
| 293 | |||
| 294 | if (endpoint_zero_init(usb, DEFAULT_DATA_MEM, DEFAULT_RING_LEN) != 0) { | ||
| 295 | fhci_usb_free(usb); | ||
| 296 | return -EINVAL; | ||
| 297 | } | ||
| 298 | |||
| 299 | return 0; | ||
| 300 | } | ||
| 301 | |||
| 302 | /* initialize the fhci_usb struct and the corresponding data staruct */ | ||
| 303 | static struct fhci_usb *fhci_create_lld(struct fhci_hcd *fhci) | ||
| 304 | { | ||
| 305 | struct fhci_usb *usb; | ||
| 306 | |||
| 307 | /* allocate memory for SCC data structure */ | ||
| 308 | usb = kzalloc(sizeof(*usb), GFP_KERNEL); | ||
| 309 | if (!usb) { | ||
| 310 | fhci_err(fhci, "no memory for SCC data struct\n"); | ||
| 311 | return NULL; | ||
| 312 | } | ||
| 313 | |||
| 314 | usb->fhci = fhci; | ||
| 315 | usb->hc_list = fhci->hc_list; | ||
| 316 | usb->vroot_hub = fhci->vroot_hub; | ||
| 317 | |||
| 318 | usb->transfer_confirm = fhci_transfer_confirm_callback; | ||
| 319 | |||
| 320 | return usb; | ||
| 321 | } | ||
| 322 | |||
| 323 | static int fhci_start(struct usb_hcd *hcd) | ||
| 324 | { | ||
| 325 | int ret; | ||
| 326 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
| 327 | |||
| 328 | ret = fhci_mem_init(fhci); | ||
| 329 | if (ret) { | ||
| 330 | fhci_err(fhci, "failed to allocate memory\n"); | ||
| 331 | goto err; | ||
| 332 | } | ||
| 333 | |||
| 334 | fhci->usb_lld = fhci_create_lld(fhci); | ||
| 335 | if (!fhci->usb_lld) { | ||
| 336 | fhci_err(fhci, "low level driver config failed\n"); | ||
| 337 | ret = -ENOMEM; | ||
| 338 | goto err; | ||
| 339 | } | ||
| 340 | |||
| 341 | ret = fhci_usb_init(fhci); | ||
| 342 | if (ret) { | ||
| 343 | fhci_err(fhci, "low level driver initialize failed\n"); | ||
| 344 | goto err; | ||
| 345 | } | ||
| 346 | |||
| 347 | spin_lock_init(&fhci->lock); | ||
| 348 | |||
| 349 | /* connect the virtual root hub */ | ||
| 350 | fhci->vroot_hub->dev_num = 1; /* this field may be needed to fix */ | ||
| 351 | fhci->vroot_hub->hub.wHubStatus = 0; | ||
| 352 | fhci->vroot_hub->hub.wHubChange = 0; | ||
| 353 | fhci->vroot_hub->port.wPortStatus = 0; | ||
| 354 | fhci->vroot_hub->port.wPortChange = 0; | ||
| 355 | |||
| 356 | hcd->state = HC_STATE_RUNNING; | ||
| 357 | |||
| 358 | /* | ||
| 359 | * From here on, khubd concurrently accesses the root | ||
| 360 | * hub; drivers will be talking to enumerated devices. | ||
| 361 | * (On restart paths, khubd already knows about the root | ||
| 362 | * hub and could find work as soon as we wrote FLAG_CF.) | ||
| 363 | * | ||
| 364 | * Before this point the HC was idle/ready. After, khubd | ||
| 365 | * and device drivers may start it running. | ||
| 366 | */ | ||
| 367 | fhci_usb_enable(fhci); | ||
| 368 | return 0; | ||
| 369 | err: | ||
| 370 | fhci_mem_free(fhci); | ||
| 371 | return ret; | ||
| 372 | } | ||
| 373 | |||
| 374 | static void fhci_stop(struct usb_hcd *hcd) | ||
| 375 | { | ||
| 376 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
| 377 | |||
| 378 | fhci_usb_disable_interrupt(fhci->usb_lld); | ||
| 379 | fhci_usb_disable(fhci); | ||
| 380 | |||
| 381 | fhci_usb_free(fhci->usb_lld); | ||
| 382 | fhci->usb_lld = NULL; | ||
| 383 | fhci_mem_free(fhci); | ||
| 384 | } | ||
| 385 | |||
| 386 | static int fhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, | ||
| 387 | gfp_t mem_flags) | ||
| 388 | { | ||
| 389 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
| 390 | u32 pipe = urb->pipe; | ||
| 391 | int ret; | ||
| 392 | int i; | ||
| 393 | int size = 0; | ||
| 394 | struct urb_priv *urb_priv; | ||
| 395 | unsigned long flags; | ||
| 396 | |||
| 397 | switch (usb_pipetype(pipe)) { | ||
| 398 | case PIPE_CONTROL: | ||
| 399 | /* 1 td fro setup,1 for ack */ | ||
| 400 | size = 2; | ||
| 401 | case PIPE_BULK: | ||
| 402 | /* one td for every 4096 bytes(can be upto 8k) */ | ||
| 403 | size += urb->transfer_buffer_length / 4096; | ||
| 404 | /* ...add for any remaining bytes... */ | ||
| 405 | if ((urb->transfer_buffer_length % 4096) != 0) | ||
| 406 | size++; | ||
| 407 | /* ..and maybe a zero length packet to wrap it up */ | ||
| 408 | if (size == 0) | ||
| 409 | size++; | ||
| 410 | else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0 | ||
| 411 | && (urb->transfer_buffer_length | ||
| 412 | % usb_maxpacket(urb->dev, pipe, | ||
| 413 | usb_pipeout(pipe))) != 0) | ||
| 414 | size++; | ||
| 415 | break; | ||
| 416 | case PIPE_ISOCHRONOUS: | ||
| 417 | size = urb->number_of_packets; | ||
| 418 | if (size <= 0) | ||
| 419 | return -EINVAL; | ||
| 420 | for (i = 0; i < urb->number_of_packets; i++) { | ||
| 421 | urb->iso_frame_desc[i].actual_length = 0; | ||
| 422 | urb->iso_frame_desc[i].status = (u32) (-EXDEV); | ||
| 423 | } | ||
| 424 | break; | ||
| 425 | case PIPE_INTERRUPT: | ||
| 426 | size = 1; | ||
| 427 | } | ||
| 428 | |||
| 429 | /* allocate the private part of the URB */ | ||
| 430 | urb_priv = kzalloc(sizeof(*urb_priv), mem_flags); | ||
| 431 | if (!urb_priv) | ||
| 432 | return -ENOMEM; | ||
| 433 | |||
| 434 | /* allocate the private part of the URB */ | ||
| 435 | urb_priv->tds = kzalloc(size * sizeof(struct td), mem_flags); | ||
| 436 | if (!urb_priv->tds) { | ||
| 437 | kfree(urb_priv); | ||
| 438 | return -ENOMEM; | ||
| 439 | } | ||
| 440 | |||
| 441 | spin_lock_irqsave(&fhci->lock, flags); | ||
| 442 | |||
| 443 | ret = usb_hcd_link_urb_to_ep(hcd, urb); | ||
| 444 | if (ret) | ||
| 445 | goto err; | ||
| 446 | |||
| 447 | /* fill the private part of the URB */ | ||
| 448 | urb_priv->num_of_tds = size; | ||
| 449 | |||
| 450 | urb->status = -EINPROGRESS; | ||
| 451 | urb->actual_length = 0; | ||
| 452 | urb->error_count = 0; | ||
| 453 | urb->hcpriv = urb_priv; | ||
| 454 | |||
| 455 | fhci_queue_urb(fhci, urb); | ||
| 456 | err: | ||
| 457 | if (ret) { | ||
| 458 | kfree(urb_priv->tds); | ||
| 459 | kfree(urb_priv); | ||
| 460 | } | ||
| 461 | spin_unlock_irqrestore(&fhci->lock, flags); | ||
| 462 | return ret; | ||
| 463 | } | ||
| 464 | |||
| 465 | /* dequeue FHCI URB */ | ||
| 466 | static int fhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | ||
| 467 | { | ||
| 468 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
| 469 | struct fhci_usb *usb = fhci->usb_lld; | ||
| 470 | int ret = -EINVAL; | ||
| 471 | unsigned long flags; | ||
| 472 | |||
| 473 | if (!urb || !urb->dev || !urb->dev->bus) | ||
| 474 | goto out; | ||
| 475 | |||
| 476 | spin_lock_irqsave(&fhci->lock, flags); | ||
| 477 | |||
| 478 | ret = usb_hcd_check_unlink_urb(hcd, urb, status); | ||
| 479 | if (ret) | ||
| 480 | goto out2; | ||
| 481 | |||
| 482 | if (usb->port_status != FHCI_PORT_DISABLED) { | ||
| 483 | struct urb_priv *urb_priv; | ||
| 484 | |||
| 485 | /* | ||
| 486 | * flag the urb's data for deletion in some upcoming | ||
| 487 | * SF interrupt's delete list processing | ||
| 488 | */ | ||
| 489 | urb_priv = urb->hcpriv; | ||
| 490 | |||
| 491 | if (!urb_priv || (urb_priv->state == URB_DEL)) | ||
| 492 | goto out2; | ||
| 493 | |||
| 494 | urb_priv->state = URB_DEL; | ||
| 495 | |||
| 496 | /* already pending? */ | ||
| 497 | urb_priv->ed->state = FHCI_ED_URB_DEL; | ||
| 498 | } else { | ||
| 499 | fhci_urb_complete_free(fhci, urb); | ||
| 500 | } | ||
| 501 | |||
| 502 | out2: | ||
| 503 | spin_unlock_irqrestore(&fhci->lock, flags); | ||
| 504 | out: | ||
| 505 | return ret; | ||
| 506 | } | ||
| 507 | |||
| 508 | static void fhci_endpoint_disable(struct usb_hcd *hcd, | ||
| 509 | struct usb_host_endpoint *ep) | ||
| 510 | { | ||
| 511 | struct fhci_hcd *fhci; | ||
| 512 | struct ed *ed; | ||
| 513 | unsigned long flags; | ||
| 514 | |||
| 515 | fhci = hcd_to_fhci(hcd); | ||
| 516 | spin_lock_irqsave(&fhci->lock, flags); | ||
| 517 | ed = ep->hcpriv; | ||
| 518 | if (ed) { | ||
| 519 | while (ed->td_head != NULL) { | ||
| 520 | struct td *td = fhci_remove_td_from_ed(ed); | ||
| 521 | fhci_urb_complete_free(fhci, td->urb); | ||
| 522 | } | ||
| 523 | fhci_recycle_empty_ed(fhci, ed); | ||
| 524 | ep->hcpriv = NULL; | ||
| 525 | } | ||
| 526 | spin_unlock_irqrestore(&fhci->lock, flags); | ||
| 527 | } | ||
| 528 | |||
| 529 | static int fhci_get_frame_number(struct usb_hcd *hcd) | ||
| 530 | { | ||
| 531 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
| 532 | |||
| 533 | return get_frame_num(fhci); | ||
| 534 | } | ||
| 535 | |||
| 536 | static const struct hc_driver fhci_driver = { | ||
| 537 | .description = "fsl,usb-fhci", | ||
| 538 | .product_desc = "FHCI HOST Controller", | ||
| 539 | .hcd_priv_size = sizeof(struct fhci_hcd), | ||
| 540 | |||
| 541 | /* generic hardware linkage */ | ||
| 542 | .irq = fhci_irq, | ||
| 543 | .flags = HCD_USB11 | HCD_MEMORY, | ||
| 544 | |||
| 545 | /* basic lifecycle operation */ | ||
| 546 | .start = fhci_start, | ||
| 547 | .stop = fhci_stop, | ||
| 548 | |||
| 549 | /* managing i/o requests and associated device resources */ | ||
| 550 | .urb_enqueue = fhci_urb_enqueue, | ||
| 551 | .urb_dequeue = fhci_urb_dequeue, | ||
| 552 | .endpoint_disable = fhci_endpoint_disable, | ||
| 553 | |||
| 554 | /* scheduling support */ | ||
| 555 | .get_frame_number = fhci_get_frame_number, | ||
| 556 | |||
| 557 | /* root hub support */ | ||
| 558 | .hub_status_data = fhci_hub_status_data, | ||
| 559 | .hub_control = fhci_hub_control, | ||
| 560 | }; | ||
| 561 | |||
| 562 | static int __devinit of_fhci_probe(struct of_device *ofdev, | ||
| 563 | const struct of_device_id *ofid) | ||
| 564 | { | ||
| 565 | struct device *dev = &ofdev->dev; | ||
| 566 | struct device_node *node = ofdev->node; | ||
| 567 | struct usb_hcd *hcd; | ||
| 568 | struct fhci_hcd *fhci; | ||
| 569 | struct resource usb_regs; | ||
| 570 | unsigned long pram_addr; | ||
| 571 | unsigned int usb_irq; | ||
| 572 | const char *sprop; | ||
| 573 | const u32 *iprop; | ||
| 574 | int size; | ||
| 575 | int ret; | ||
| 576 | int i; | ||
| 577 | int j; | ||
| 578 | |||
| 579 | if (usb_disabled()) | ||
| 580 | return -ENODEV; | ||
| 581 | |||
| 582 | sprop = of_get_property(node, "mode", NULL); | ||
| 583 | if (sprop && strcmp(sprop, "host")) | ||
| 584 | return -ENODEV; | ||
| 585 | |||
| 586 | hcd = usb_create_hcd(&fhci_driver, dev, dev->bus_id); | ||
| 587 | if (!hcd) { | ||
| 588 | dev_err(dev, "could not create hcd\n"); | ||
| 589 | return -ENOMEM; | ||
| 590 | } | ||
| 591 | |||
| 592 | fhci = hcd_to_fhci(hcd); | ||
| 593 | hcd->self.controller = dev; | ||
| 594 | dev_set_drvdata(dev, hcd); | ||
| 595 | |||
| 596 | iprop = of_get_property(node, "hub-power-budget", &size); | ||
| 597 | if (iprop && size == sizeof(*iprop)) | ||
| 598 | hcd->power_budget = *iprop; | ||
| 599 | |||
| 600 | /* FHCI registers. */ | ||
| 601 | ret = of_address_to_resource(node, 0, &usb_regs); | ||
| 602 | if (ret) { | ||
| 603 | dev_err(dev, "could not get regs\n"); | ||
| 604 | goto err_regs; | ||
| 605 | } | ||
| 606 | |||
| 607 | hcd->regs = ioremap(usb_regs.start, usb_regs.end - usb_regs.start + 1); | ||
| 608 | if (!hcd->regs) { | ||
| 609 | dev_err(dev, "could not ioremap regs\n"); | ||
| 610 | ret = -ENOMEM; | ||
| 611 | goto err_regs; | ||
| 612 | } | ||
| 613 | fhci->regs = hcd->regs; | ||
| 614 | |||
| 615 | /* Parameter RAM. */ | ||
| 616 | iprop = of_get_property(node, "reg", &size); | ||
| 617 | if (!iprop || size < sizeof(*iprop) * 4) { | ||
| 618 | dev_err(dev, "can't get pram offset\n"); | ||
| 619 | ret = -EINVAL; | ||
| 620 | goto err_pram; | ||
| 621 | } | ||
| 622 | |||
| 623 | pram_addr = cpm_muram_alloc_fixed(iprop[2], FHCI_PRAM_SIZE); | ||
| 624 | if (IS_ERR_VALUE(pram_addr)) { | ||
| 625 | dev_err(dev, "failed to allocate usb pram\n"); | ||
| 626 | ret = -ENOMEM; | ||
| 627 | goto err_pram; | ||
| 628 | } | ||
| 629 | fhci->pram = cpm_muram_addr(pram_addr); | ||
| 630 | |||
| 631 | /* GPIOs and pins */ | ||
| 632 | for (i = 0; i < NUM_GPIOS; i++) { | ||
| 633 | int gpio; | ||
| 634 | enum of_gpio_flags flags; | ||
| 635 | |||
| 636 | gpio = of_get_gpio_flags(node, i, &flags); | ||
| 637 | fhci->gpios[i] = gpio; | ||
| 638 | fhci->alow_gpios[i] = flags & OF_GPIO_ACTIVE_LOW; | ||
| 639 | |||
| 640 | if (!gpio_is_valid(gpio)) { | ||
| 641 | if (i < GPIO_SPEED) { | ||
| 642 | dev_err(dev, "incorrect GPIO%d: %d\n", | ||
| 643 | i, gpio); | ||
| 644 | goto err_gpios; | ||
| 645 | } else { | ||
| 646 | dev_info(dev, "assuming board doesn't have " | ||
| 647 | "%s gpio\n", i == GPIO_SPEED ? | ||
| 648 | "speed" : "power"); | ||
| 649 | continue; | ||
| 650 | } | ||
| 651 | } | ||
| 652 | |||
| 653 | ret = gpio_request(gpio, dev->bus_id); | ||
| 654 | if (ret) { | ||
| 655 | dev_err(dev, "failed to request gpio %d", i); | ||
| 656 | goto err_gpios; | ||
| 657 | } | ||
| 658 | |||
| 659 | if (i >= GPIO_SPEED) { | ||
| 660 | ret = gpio_direction_output(gpio, 0); | ||
| 661 | if (ret) { | ||
| 662 | dev_err(dev, "failed to set gpio %d as " | ||
| 663 | "an output\n", i); | ||
| 664 | i++; | ||
| 665 | goto err_gpios; | ||
| 666 | } | ||
| 667 | } | ||
| 668 | } | ||
| 669 | |||
| 670 | for (j = 0; j < NUM_PINS; j++) { | ||
| 671 | fhci->pins[j] = qe_pin_request(ofdev->node, j); | ||
| 672 | if (IS_ERR(fhci->pins[j])) { | ||
| 673 | ret = PTR_ERR(fhci->pins[j]); | ||
| 674 | dev_err(dev, "can't get pin %d: %d\n", j, ret); | ||
| 675 | goto err_pins; | ||
| 676 | } | ||
| 677 | } | ||
| 678 | |||
| 679 | /* Frame limit timer and its interrupt. */ | ||
| 680 | fhci->timer = gtm_get_timer16(); | ||
| 681 | if (IS_ERR(fhci->timer)) { | ||
| 682 | ret = PTR_ERR(fhci->timer); | ||
| 683 | dev_err(dev, "failed to request qe timer: %i", ret); | ||
| 684 | goto err_get_timer; | ||
| 685 | } | ||
| 686 | |||
| 687 | ret = request_irq(fhci->timer->irq, fhci_frame_limit_timer_irq, | ||
| 688 | IRQF_DISABLED, "qe timer (usb)", hcd); | ||
| 689 | if (ret) { | ||
| 690 | dev_err(dev, "failed to request timer irq"); | ||
| 691 | goto err_timer_irq; | ||
| 692 | } | ||
| 693 | |||
| 694 | /* USB Host interrupt. */ | ||
| 695 | usb_irq = irq_of_parse_and_map(node, 0); | ||
| 696 | if (usb_irq == NO_IRQ) { | ||
| 697 | dev_err(dev, "could not get usb irq\n"); | ||
| 698 | ret = -EINVAL; | ||
| 699 | goto err_usb_irq; | ||
| 700 | } | ||
| 701 | |||
| 702 | /* Clocks. */ | ||
| 703 | sprop = of_get_property(node, "fsl,fullspeed-clock", NULL); | ||
| 704 | if (sprop) { | ||
| 705 | fhci->fullspeed_clk = qe_clock_source(sprop); | ||
| 706 | if (fhci->fullspeed_clk == QE_CLK_DUMMY) { | ||
| 707 | dev_err(dev, "wrong fullspeed-clock\n"); | ||
| 708 | ret = -EINVAL; | ||
| 709 | goto err_clocks; | ||
| 710 | } | ||
| 711 | } | ||
| 712 | |||
| 713 | sprop = of_get_property(node, "fsl,lowspeed-clock", NULL); | ||
| 714 | if (sprop) { | ||
| 715 | fhci->lowspeed_clk = qe_clock_source(sprop); | ||
| 716 | if (fhci->lowspeed_clk == QE_CLK_DUMMY) { | ||
| 717 | dev_err(dev, "wrong lowspeed-clock\n"); | ||
| 718 | ret = -EINVAL; | ||
| 719 | goto err_clocks; | ||
| 720 | } | ||
| 721 | } | ||
| 722 | |||
| 723 | if (fhci->fullspeed_clk == QE_CLK_NONE && | ||
| 724 | fhci->lowspeed_clk == QE_CLK_NONE) { | ||
| 725 | dev_err(dev, "no clocks specified\n"); | ||
| 726 | ret = -EINVAL; | ||
| 727 | goto err_clocks; | ||
| 728 | } | ||
| 729 | |||
| 730 | dev_info(dev, "at 0x%p, irq %d\n", hcd->regs, usb_irq); | ||
| 731 | |||
| 732 | fhci_config_transceiver(fhci, FHCI_PORT_POWER_OFF); | ||
| 733 | |||
| 734 | /* Start with full-speed, if possible. */ | ||
| 735 | if (fhci->fullspeed_clk != QE_CLK_NONE) { | ||
| 736 | fhci_config_transceiver(fhci, FHCI_PORT_FULL); | ||
| 737 | qe_usb_clock_set(fhci->fullspeed_clk, USB_CLOCK); | ||
| 738 | } else { | ||
| 739 | fhci_config_transceiver(fhci, FHCI_PORT_LOW); | ||
| 740 | qe_usb_clock_set(fhci->lowspeed_clk, USB_CLOCK >> 3); | ||
| 741 | } | ||
| 742 | |||
| 743 | /* Clear and disable any pending interrupts. */ | ||
| 744 | out_be16(&fhci->regs->usb_event, 0xffff); | ||
| 745 | out_be16(&fhci->regs->usb_mask, 0); | ||
| 746 | |||
| 747 | ret = usb_add_hcd(hcd, usb_irq, IRQF_DISABLED); | ||
| 748 | if (ret < 0) | ||
| 749 | goto err_add_hcd; | ||
| 750 | |||
| 751 | fhci_dfs_create(fhci); | ||
| 752 | |||
| 753 | return 0; | ||
| 754 | |||
| 755 | err_add_hcd: | ||
| 756 | err_clocks: | ||
| 757 | irq_dispose_mapping(usb_irq); | ||
| 758 | err_usb_irq: | ||
| 759 | free_irq(fhci->timer->irq, hcd); | ||
| 760 | err_timer_irq: | ||
| 761 | gtm_put_timer16(fhci->timer); | ||
| 762 | err_get_timer: | ||
| 763 | err_pins: | ||
| 764 | while (--j >= 0) | ||
| 765 | qe_pin_free(fhci->pins[j]); | ||
| 766 | err_gpios: | ||
| 767 | while (--i >= 0) { | ||
| 768 | if (gpio_is_valid(fhci->gpios[i])) | ||
| 769 | gpio_free(fhci->gpios[i]); | ||
| 770 | } | ||
| 771 | cpm_muram_free(pram_addr); | ||
| 772 | err_pram: | ||
| 773 | iounmap(hcd->regs); | ||
| 774 | err_regs: | ||
| 775 | usb_put_hcd(hcd); | ||
| 776 | return ret; | ||
| 777 | } | ||
| 778 | |||
| 779 | static int __devexit fhci_remove(struct device *dev) | ||
| 780 | { | ||
| 781 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
| 782 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
| 783 | int i; | ||
| 784 | int j; | ||
| 785 | |||
| 786 | usb_remove_hcd(hcd); | ||
| 787 | free_irq(fhci->timer->irq, hcd); | ||
| 788 | gtm_put_timer16(fhci->timer); | ||
| 789 | cpm_muram_free(cpm_muram_offset(fhci->pram)); | ||
| 790 | for (i = 0; i < NUM_GPIOS; i++) { | ||
| 791 | if (!gpio_is_valid(fhci->gpios[i])) | ||
| 792 | continue; | ||
| 793 | gpio_free(fhci->gpios[i]); | ||
| 794 | } | ||
| 795 | for (j = 0; j < NUM_PINS; j++) | ||
| 796 | qe_pin_free(fhci->pins[j]); | ||
| 797 | fhci_dfs_destroy(fhci); | ||
| 798 | usb_put_hcd(hcd); | ||
| 799 | return 0; | ||
| 800 | } | ||
| 801 | |||
| 802 | static int __devexit of_fhci_remove(struct of_device *ofdev) | ||
| 803 | { | ||
| 804 | return fhci_remove(&ofdev->dev); | ||
| 805 | } | ||
| 806 | |||
| 807 | static struct of_device_id of_fhci_match[] = { | ||
| 808 | { .compatible = "fsl,mpc8323-qe-usb", }, | ||
| 809 | {}, | ||
| 810 | }; | ||
| 811 | MODULE_DEVICE_TABLE(of, of_fhci_match); | ||
| 812 | |||
| 813 | static struct of_platform_driver of_fhci_driver = { | ||
| 814 | .name = "fsl,usb-fhci", | ||
| 815 | .match_table = of_fhci_match, | ||
| 816 | .probe = of_fhci_probe, | ||
| 817 | .remove = __devexit_p(of_fhci_remove), | ||
| 818 | }; | ||
| 819 | |||
| 820 | static int __init fhci_module_init(void) | ||
| 821 | { | ||
| 822 | return of_register_platform_driver(&of_fhci_driver); | ||
| 823 | } | ||
| 824 | module_init(fhci_module_init); | ||
| 825 | |||
| 826 | static void __exit fhci_module_exit(void) | ||
| 827 | { | ||
| 828 | of_unregister_platform_driver(&of_fhci_driver); | ||
| 829 | } | ||
| 830 | module_exit(fhci_module_exit); | ||
| 831 | |||
| 832 | MODULE_DESCRIPTION("USB Freescale Host Controller Interface Driver"); | ||
| 833 | MODULE_AUTHOR("Shlomi Gridish <gridish@freescale.com>, " | ||
| 834 | "Jerry Huang <Chang-Ming.Huang@freescale.com>, " | ||
| 835 | "Anton Vorontsov <avorontsov@ru.mvista.com>"); | ||
| 836 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/host/fhci-hub.c b/drivers/usb/host/fhci-hub.c new file mode 100644 index 000000000000..0cfaedc3e124 --- /dev/null +++ b/drivers/usb/host/fhci-hub.c | |||
| @@ -0,0 +1,345 @@ | |||
| 1 | /* | ||
| 2 | * Freescale QUICC Engine USB Host Controller Driver | ||
| 3 | * | ||
| 4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
| 5 | * Shlomi Gridish <gridish@freescale.com> | ||
| 6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
| 7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
| 8 | * Peter Barada <peterb@logicpd.com> | ||
| 9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
| 10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License as published by the | ||
| 14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 15 | * option) any later version. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/types.h> | ||
| 20 | #include <linux/spinlock.h> | ||
| 21 | #include <linux/delay.h> | ||
| 22 | #include <linux/errno.h> | ||
| 23 | #include <linux/io.h> | ||
| 24 | #include <linux/usb.h> | ||
| 25 | #include <linux/gpio.h> | ||
| 26 | #include <asm/qe.h> | ||
| 27 | #include "../core/hcd.h" | ||
| 28 | #include "fhci.h" | ||
| 29 | |||
| 30 | /* virtual root hub specific descriptor */ | ||
| 31 | static u8 root_hub_des[] = { | ||
| 32 | 0x09, /* blength */ | ||
| 33 | 0x29, /* bDescriptorType;hub-descriptor */ | ||
| 34 | 0x01, /* bNbrPorts */ | ||
| 35 | 0x00, /* wHubCharacteristics */ | ||
| 36 | 0x00, | ||
| 37 | 0x01, /* bPwrOn2pwrGood;2ms */ | ||
| 38 | 0x00, /* bHubContrCurrent;0mA */ | ||
| 39 | 0x00, /* DeviceRemoveable */ | ||
| 40 | 0xff, /* PortPwrCtrlMask */ | ||
| 41 | }; | ||
| 42 | |||
| 43 | static void fhci_gpio_set_value(struct fhci_hcd *fhci, int gpio_nr, bool on) | ||
| 44 | { | ||
| 45 | int gpio = fhci->gpios[gpio_nr]; | ||
| 46 | bool alow = fhci->alow_gpios[gpio_nr]; | ||
| 47 | |||
| 48 | if (!gpio_is_valid(gpio)) | ||
| 49 | return; | ||
| 50 | |||
| 51 | gpio_set_value(gpio, on ^ alow); | ||
| 52 | mdelay(5); | ||
| 53 | } | ||
| 54 | |||
| 55 | void fhci_config_transceiver(struct fhci_hcd *fhci, | ||
| 56 | enum fhci_port_status status) | ||
| 57 | { | ||
| 58 | fhci_dbg(fhci, "-> %s: %d\n", __func__, status); | ||
| 59 | |||
| 60 | switch (status) { | ||
| 61 | case FHCI_PORT_POWER_OFF: | ||
| 62 | fhci_gpio_set_value(fhci, GPIO_POWER, false); | ||
| 63 | break; | ||
| 64 | case FHCI_PORT_DISABLED: | ||
| 65 | case FHCI_PORT_WAITING: | ||
| 66 | fhci_gpio_set_value(fhci, GPIO_POWER, true); | ||
| 67 | break; | ||
| 68 | case FHCI_PORT_LOW: | ||
| 69 | fhci_gpio_set_value(fhci, GPIO_SPEED, false); | ||
| 70 | break; | ||
| 71 | case FHCI_PORT_FULL: | ||
| 72 | fhci_gpio_set_value(fhci, GPIO_SPEED, true); | ||
| 73 | break; | ||
| 74 | default: | ||
| 75 | WARN_ON(1); | ||
| 76 | break; | ||
| 77 | } | ||
| 78 | |||
| 79 | fhci_dbg(fhci, "<- %s: %d\n", __func__, status); | ||
| 80 | } | ||
| 81 | |||
| 82 | /* disable the USB port by clearing the EN bit in the USBMOD register */ | ||
| 83 | void fhci_port_disable(struct fhci_hcd *fhci) | ||
| 84 | { | ||
| 85 | struct fhci_usb *usb = (struct fhci_usb *)fhci->usb_lld; | ||
| 86 | enum fhci_port_status port_status; | ||
| 87 | |||
| 88 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
| 89 | |||
| 90 | fhci_stop_sof_timer(fhci); | ||
| 91 | |||
| 92 | fhci_flush_all_transmissions(usb); | ||
| 93 | |||
| 94 | fhci_usb_disable_interrupt((struct fhci_usb *)fhci->usb_lld); | ||
| 95 | port_status = usb->port_status; | ||
| 96 | usb->port_status = FHCI_PORT_DISABLED; | ||
| 97 | |||
| 98 | /* Enable IDLE since we want to know if something comes along */ | ||
| 99 | usb->saved_msk |= USB_E_IDLE_MASK; | ||
| 100 | out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | ||
| 101 | |||
| 102 | /* check if during the disconnection process attached new device */ | ||
| 103 | if (port_status == FHCI_PORT_WAITING) | ||
| 104 | fhci_device_connected_interrupt(fhci); | ||
| 105 | usb->vroot_hub->port.wPortStatus &= ~USB_PORT_STAT_ENABLE; | ||
| 106 | usb->vroot_hub->port.wPortChange |= USB_PORT_STAT_C_ENABLE; | ||
| 107 | fhci_usb_enable_interrupt((struct fhci_usb *)fhci->usb_lld); | ||
| 108 | |||
| 109 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
| 110 | } | ||
| 111 | |||
| 112 | /* enable the USB port by setting the EN bit in the USBMOD register */ | ||
| 113 | void fhci_port_enable(void *lld) | ||
| 114 | { | ||
| 115 | struct fhci_usb *usb = (struct fhci_usb *)lld; | ||
| 116 | struct fhci_hcd *fhci = usb->fhci; | ||
| 117 | |||
| 118 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
| 119 | |||
| 120 | fhci_config_transceiver(fhci, usb->port_status); | ||
| 121 | |||
| 122 | if ((usb->port_status != FHCI_PORT_FULL) && | ||
| 123 | (usb->port_status != FHCI_PORT_LOW)) | ||
| 124 | fhci_start_sof_timer(fhci); | ||
| 125 | |||
| 126 | usb->vroot_hub->port.wPortStatus |= USB_PORT_STAT_ENABLE; | ||
| 127 | usb->vroot_hub->port.wPortChange |= USB_PORT_STAT_C_ENABLE; | ||
| 128 | |||
| 129 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
| 130 | } | ||
| 131 | |||
| 132 | void fhci_io_port_generate_reset(struct fhci_hcd *fhci) | ||
| 133 | { | ||
| 134 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
| 135 | |||
| 136 | gpio_direction_output(fhci->gpios[GPIO_USBOE], 0); | ||
| 137 | gpio_direction_output(fhci->gpios[GPIO_USBTP], 0); | ||
| 138 | gpio_direction_output(fhci->gpios[GPIO_USBTN], 0); | ||
| 139 | |||
| 140 | mdelay(5); | ||
| 141 | |||
| 142 | qe_pin_set_dedicated(fhci->pins[PIN_USBOE]); | ||
| 143 | qe_pin_set_dedicated(fhci->pins[PIN_USBTP]); | ||
| 144 | qe_pin_set_dedicated(fhci->pins[PIN_USBTN]); | ||
| 145 | |||
| 146 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
| 147 | } | ||
| 148 | |||
| 149 | /* generate the RESET condition on the bus */ | ||
| 150 | void fhci_port_reset(void *lld) | ||
| 151 | { | ||
| 152 | struct fhci_usb *usb = (struct fhci_usb *)lld; | ||
| 153 | struct fhci_hcd *fhci = usb->fhci; | ||
| 154 | u8 mode; | ||
| 155 | u16 mask; | ||
| 156 | |||
| 157 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
| 158 | |||
| 159 | fhci_stop_sof_timer(fhci); | ||
| 160 | /* disable the USB controller */ | ||
| 161 | mode = in_8(&fhci->regs->usb_mod); | ||
| 162 | out_8(&fhci->regs->usb_mod, mode & (~USB_MODE_EN)); | ||
| 163 | |||
| 164 | /* disable idle interrupts */ | ||
| 165 | mask = in_be16(&fhci->regs->usb_mask); | ||
| 166 | out_be16(&fhci->regs->usb_mask, mask & (~USB_E_IDLE_MASK)); | ||
| 167 | |||
| 168 | fhci_io_port_generate_reset(fhci); | ||
| 169 | |||
| 170 | /* enable interrupt on this endpoint */ | ||
| 171 | out_be16(&fhci->regs->usb_mask, mask); | ||
| 172 | |||
| 173 | /* enable the USB controller */ | ||
| 174 | mode = in_8(&fhci->regs->usb_mod); | ||
| 175 | out_8(&fhci->regs->usb_mod, mode | USB_MODE_EN); | ||
| 176 | fhci_start_sof_timer(fhci); | ||
| 177 | |||
| 178 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
| 179 | } | ||
| 180 | |||
| 181 | int fhci_hub_status_data(struct usb_hcd *hcd, char *buf) | ||
| 182 | { | ||
| 183 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
| 184 | int ret = 0; | ||
| 185 | unsigned long flags; | ||
| 186 | |||
| 187 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
| 188 | |||
| 189 | spin_lock_irqsave(&fhci->lock, flags); | ||
| 190 | |||
| 191 | if (fhci->vroot_hub->port.wPortChange & (USB_PORT_STAT_C_CONNECTION | | ||
| 192 | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_SUSPEND | | ||
| 193 | USB_PORT_STAT_C_RESET | USB_PORT_STAT_C_OVERCURRENT)) { | ||
| 194 | *buf = 1 << 1; | ||
| 195 | ret = 1; | ||
| 196 | fhci_dbg(fhci, "-- %s\n", __func__); | ||
| 197 | } | ||
| 198 | |||
| 199 | spin_unlock_irqrestore(&fhci->lock, flags); | ||
| 200 | |||
| 201 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
| 202 | |||
| 203 | return ret; | ||
| 204 | } | ||
| 205 | |||
| 206 | int fhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | ||
| 207 | u16 wIndex, char *buf, u16 wLength) | ||
| 208 | { | ||
| 209 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
| 210 | int retval = 0; | ||
| 211 | int len = 0; | ||
| 212 | struct usb_hub_status *hub_status; | ||
| 213 | struct usb_port_status *port_status; | ||
| 214 | unsigned long flags; | ||
| 215 | |||
| 216 | spin_lock_irqsave(&fhci->lock, flags); | ||
| 217 | |||
| 218 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
| 219 | |||
| 220 | switch (typeReq) { | ||
| 221 | case ClearHubFeature: | ||
| 222 | switch (wValue) { | ||
| 223 | case C_HUB_LOCAL_POWER: | ||
| 224 | case C_HUB_OVER_CURRENT: | ||
| 225 | break; | ||
| 226 | default: | ||
| 227 | goto error; | ||
| 228 | } | ||
| 229 | break; | ||
| 230 | case ClearPortFeature: | ||
| 231 | fhci->vroot_hub->feature &= (1 << wValue); | ||
| 232 | |||
| 233 | switch (wValue) { | ||
| 234 | case USB_PORT_FEAT_ENABLE: | ||
| 235 | fhci->vroot_hub->port.wPortStatus &= | ||
| 236 | ~USB_PORT_STAT_ENABLE; | ||
| 237 | fhci_port_disable(fhci); | ||
| 238 | break; | ||
| 239 | case USB_PORT_FEAT_C_ENABLE: | ||
| 240 | fhci->vroot_hub->port.wPortChange &= | ||
| 241 | ~USB_PORT_STAT_C_ENABLE; | ||
| 242 | break; | ||
| 243 | case USB_PORT_FEAT_SUSPEND: | ||
| 244 | fhci->vroot_hub->port.wPortStatus &= | ||
| 245 | ~USB_PORT_STAT_SUSPEND; | ||
| 246 | fhci_stop_sof_timer(fhci); | ||
| 247 | break; | ||
| 248 | case USB_PORT_FEAT_C_SUSPEND: | ||
| 249 | fhci->vroot_hub->port.wPortChange &= | ||
| 250 | ~USB_PORT_STAT_C_SUSPEND; | ||
| 251 | break; | ||
| 252 | case USB_PORT_FEAT_POWER: | ||
| 253 | fhci->vroot_hub->port.wPortStatus &= | ||
| 254 | ~USB_PORT_STAT_POWER; | ||
| 255 | fhci_config_transceiver(fhci, FHCI_PORT_POWER_OFF); | ||
| 256 | break; | ||
| 257 | case USB_PORT_FEAT_C_CONNECTION: | ||
| 258 | fhci->vroot_hub->port.wPortChange &= | ||
| 259 | ~USB_PORT_STAT_C_CONNECTION; | ||
| 260 | break; | ||
| 261 | case USB_PORT_FEAT_C_OVER_CURRENT: | ||
| 262 | fhci->vroot_hub->port.wPortChange &= | ||
| 263 | ~USB_PORT_STAT_C_OVERCURRENT; | ||
| 264 | break; | ||
| 265 | case USB_PORT_FEAT_C_RESET: | ||
| 266 | fhci->vroot_hub->port.wPortChange &= | ||
| 267 | ~USB_PORT_STAT_C_RESET; | ||
| 268 | break; | ||
| 269 | default: | ||
| 270 | goto error; | ||
| 271 | } | ||
| 272 | break; | ||
| 273 | case GetHubDescriptor: | ||
| 274 | memcpy(buf, root_hub_des, sizeof(root_hub_des)); | ||
| 275 | buf[3] = 0x11; /* per-port power, no ovrcrnt */ | ||
| 276 | len = (buf[0] < wLength) ? buf[0] : wLength; | ||
| 277 | break; | ||
| 278 | case GetHubStatus: | ||
| 279 | hub_status = (struct usb_hub_status *)buf; | ||
| 280 | hub_status->wHubStatus = | ||
| 281 | cpu_to_le16(fhci->vroot_hub->hub.wHubStatus); | ||
| 282 | hub_status->wHubChange = | ||
| 283 | cpu_to_le16(fhci->vroot_hub->hub.wHubChange); | ||
| 284 | len = 4; | ||
| 285 | break; | ||
| 286 | case GetPortStatus: | ||
| 287 | port_status = (struct usb_port_status *)buf; | ||
| 288 | port_status->wPortStatus = | ||
| 289 | cpu_to_le16(fhci->vroot_hub->port.wPortStatus); | ||
| 290 | port_status->wPortChange = | ||
| 291 | cpu_to_le16(fhci->vroot_hub->port.wPortChange); | ||
| 292 | len = 4; | ||
| 293 | break; | ||
| 294 | case SetHubFeature: | ||
| 295 | switch (wValue) { | ||
| 296 | case C_HUB_OVER_CURRENT: | ||
| 297 | case C_HUB_LOCAL_POWER: | ||
| 298 | break; | ||
| 299 | default: | ||
| 300 | goto error; | ||
| 301 | } | ||
| 302 | break; | ||
| 303 | case SetPortFeature: | ||
| 304 | fhci->vroot_hub->feature |= (1 << wValue); | ||
| 305 | |||
| 306 | switch (wValue) { | ||
| 307 | case USB_PORT_FEAT_ENABLE: | ||
| 308 | fhci->vroot_hub->port.wPortStatus |= | ||
| 309 | USB_PORT_STAT_ENABLE; | ||
| 310 | fhci_port_enable(fhci->usb_lld); | ||
| 311 | break; | ||
| 312 | case USB_PORT_FEAT_SUSPEND: | ||
| 313 | fhci->vroot_hub->port.wPortStatus |= | ||
| 314 | USB_PORT_STAT_SUSPEND; | ||
| 315 | fhci_stop_sof_timer(fhci); | ||
| 316 | break; | ||
| 317 | case USB_PORT_FEAT_RESET: | ||
| 318 | fhci->vroot_hub->port.wPortStatus |= | ||
| 319 | USB_PORT_STAT_RESET; | ||
| 320 | fhci_port_reset(fhci->usb_lld); | ||
| 321 | fhci->vroot_hub->port.wPortStatus |= | ||
| 322 | USB_PORT_STAT_ENABLE; | ||
| 323 | fhci->vroot_hub->port.wPortStatus &= | ||
| 324 | ~USB_PORT_STAT_RESET; | ||
| 325 | break; | ||
| 326 | case USB_PORT_FEAT_POWER: | ||
| 327 | fhci->vroot_hub->port.wPortStatus |= | ||
| 328 | USB_PORT_STAT_POWER; | ||
| 329 | fhci_config_transceiver(fhci, FHCI_PORT_WAITING); | ||
| 330 | break; | ||
| 331 | default: | ||
| 332 | goto error; | ||
| 333 | } | ||
| 334 | break; | ||
| 335 | default: | ||
| 336 | error: | ||
| 337 | retval = -EPIPE; | ||
| 338 | } | ||
| 339 | |||
| 340 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
| 341 | |||
| 342 | spin_unlock_irqrestore(&fhci->lock, flags); | ||
| 343 | |||
| 344 | return retval; | ||
| 345 | } | ||
diff --git a/drivers/usb/host/fhci-mem.c b/drivers/usb/host/fhci-mem.c new file mode 100644 index 000000000000..2c0736c99712 --- /dev/null +++ b/drivers/usb/host/fhci-mem.c | |||
| @@ -0,0 +1,113 @@ | |||
| 1 | /* | ||
| 2 | * Freescale QUICC Engine USB Host Controller Driver | ||
| 3 | * | ||
| 4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
| 5 | * Shlomi Gridish <gridish@freescale.com> | ||
| 6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
| 7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
| 8 | * Peter Barada <peterb@logicpd.com> | ||
| 9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
| 10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License as published by the | ||
| 14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 15 | * option) any later version. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/types.h> | ||
| 20 | #include <linux/delay.h> | ||
| 21 | #include <linux/list.h> | ||
| 22 | #include <linux/usb.h> | ||
| 23 | #include "../core/hcd.h" | ||
| 24 | #include "fhci.h" | ||
| 25 | |||
| 26 | static void init_td(struct td *td) | ||
| 27 | { | ||
| 28 | memset(td, 0, sizeof(*td)); | ||
| 29 | INIT_LIST_HEAD(&td->node); | ||
| 30 | INIT_LIST_HEAD(&td->frame_lh); | ||
| 31 | } | ||
| 32 | |||
| 33 | static void init_ed(struct ed *ed) | ||
| 34 | { | ||
| 35 | memset(ed, 0, sizeof(*ed)); | ||
| 36 | INIT_LIST_HEAD(&ed->td_list); | ||
| 37 | INIT_LIST_HEAD(&ed->node); | ||
| 38 | } | ||
| 39 | |||
| 40 | static struct td *get_empty_td(struct fhci_hcd *fhci) | ||
| 41 | { | ||
| 42 | struct td *td; | ||
| 43 | |||
| 44 | if (!list_empty(&fhci->empty_tds)) { | ||
| 45 | td = list_entry(fhci->empty_tds.next, struct td, node); | ||
| 46 | list_del(fhci->empty_tds.next); | ||
| 47 | } else { | ||
| 48 | td = kmalloc(sizeof(*td), GFP_ATOMIC); | ||
| 49 | if (!td) | ||
| 50 | fhci_err(fhci, "No memory to allocate to TD\n"); | ||
| 51 | else | ||
| 52 | init_td(td); | ||
| 53 | } | ||
| 54 | |||
| 55 | return td; | ||
| 56 | } | ||
| 57 | |||
| 58 | void fhci_recycle_empty_td(struct fhci_hcd *fhci, struct td *td) | ||
| 59 | { | ||
| 60 | init_td(td); | ||
| 61 | list_add(&td->node, &fhci->empty_tds); | ||
| 62 | } | ||
| 63 | |||
| 64 | struct ed *fhci_get_empty_ed(struct fhci_hcd *fhci) | ||
| 65 | { | ||
| 66 | struct ed *ed; | ||
| 67 | |||
| 68 | if (!list_empty(&fhci->empty_eds)) { | ||
| 69 | ed = list_entry(fhci->empty_eds.next, struct ed, node); | ||
| 70 | list_del(fhci->empty_eds.next); | ||
| 71 | } else { | ||
| 72 | ed = kmalloc(sizeof(*ed), GFP_ATOMIC); | ||
| 73 | if (!ed) | ||
| 74 | fhci_err(fhci, "No memory to allocate to ED\n"); | ||
| 75 | else | ||
| 76 | init_ed(ed); | ||
| 77 | } | ||
| 78 | |||
| 79 | return ed; | ||
| 80 | } | ||
| 81 | |||
| 82 | void fhci_recycle_empty_ed(struct fhci_hcd *fhci, struct ed *ed) | ||
| 83 | { | ||
| 84 | init_ed(ed); | ||
| 85 | list_add(&ed->node, &fhci->empty_eds); | ||
| 86 | } | ||
| 87 | |||
| 88 | struct td *fhci_td_fill(struct fhci_hcd *fhci, struct urb *urb, | ||
| 89 | struct urb_priv *urb_priv, struct ed *ed, u16 index, | ||
| 90 | enum fhci_ta_type type, int toggle, u8 *data, u32 len, | ||
| 91 | u16 interval, u16 start_frame, bool ioc) | ||
| 92 | { | ||
| 93 | struct td *td = get_empty_td(fhci); | ||
| 94 | |||
| 95 | if (!td) | ||
| 96 | return NULL; | ||
| 97 | |||
| 98 | td->urb = urb; | ||
| 99 | td->ed = ed; | ||
| 100 | td->type = type; | ||
| 101 | td->toggle = toggle; | ||
| 102 | td->data = data; | ||
| 103 | td->len = len; | ||
| 104 | td->iso_index = index; | ||
| 105 | td->interval = interval; | ||
| 106 | td->start_frame = start_frame; | ||
| 107 | td->ioc = ioc; | ||
| 108 | td->status = USB_TD_OK; | ||
| 109 | |||
| 110 | urb_priv->tds[index] = td; | ||
| 111 | |||
| 112 | return td; | ||
| 113 | } | ||
diff --git a/drivers/usb/host/fhci-q.c b/drivers/usb/host/fhci-q.c new file mode 100644 index 000000000000..b0a1446ba292 --- /dev/null +++ b/drivers/usb/host/fhci-q.c | |||
| @@ -0,0 +1,284 @@ | |||
| 1 | /* | ||
| 2 | * Freescale QUICC Engine USB Host Controller Driver | ||
| 3 | * | ||
| 4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
| 5 | * Shlomi Gridish <gridish@freescale.com> | ||
| 6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
| 7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
| 8 | * Peter Barada <peterb@logicpd.com> | ||
| 9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
| 10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License as published by the | ||
| 14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 15 | * option) any later version. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/types.h> | ||
| 20 | #include <linux/spinlock.h> | ||
| 21 | #include <linux/errno.h> | ||
| 22 | #include <linux/list.h> | ||
| 23 | #include <linux/usb.h> | ||
| 24 | #include "../core/hcd.h" | ||
| 25 | #include "fhci.h" | ||
| 26 | |||
| 27 | /* maps the hardware error code to the USB error code */ | ||
| 28 | static int status_to_error(u32 status) | ||
| 29 | { | ||
| 30 | if (status == USB_TD_OK) | ||
| 31 | return 0; | ||
| 32 | else if (status & USB_TD_RX_ER_CRC) | ||
| 33 | return -EILSEQ; | ||
| 34 | else if (status & USB_TD_RX_ER_NONOCT) | ||
| 35 | return -EPROTO; | ||
| 36 | else if (status & USB_TD_RX_ER_OVERUN) | ||
| 37 | return -ECOMM; | ||
| 38 | else if (status & USB_TD_RX_ER_BITSTUFF) | ||
| 39 | return -EPROTO; | ||
| 40 | else if (status & USB_TD_RX_ER_PID) | ||
| 41 | return -EILSEQ; | ||
| 42 | else if (status & (USB_TD_TX_ER_NAK | USB_TD_TX_ER_TIMEOUT)) | ||
| 43 | return -ETIMEDOUT; | ||
| 44 | else if (status & USB_TD_TX_ER_STALL) | ||
| 45 | return -EPIPE; | ||
| 46 | else if (status & USB_TD_TX_ER_UNDERUN) | ||
| 47 | return -ENOSR; | ||
| 48 | else if (status & USB_TD_RX_DATA_UNDERUN) | ||
| 49 | return -EREMOTEIO; | ||
| 50 | else if (status & USB_TD_RX_DATA_OVERUN) | ||
| 51 | return -EOVERFLOW; | ||
| 52 | else | ||
| 53 | return -EINVAL; | ||
| 54 | } | ||
| 55 | |||
| 56 | void fhci_add_td_to_frame(struct fhci_time_frame *frame, struct td *td) | ||
| 57 | { | ||
| 58 | list_add_tail(&td->frame_lh, &frame->tds_list); | ||
| 59 | } | ||
| 60 | |||
| 61 | void fhci_add_tds_to_ed(struct ed *ed, struct td **td_list, int number) | ||
| 62 | { | ||
| 63 | int i; | ||
| 64 | |||
| 65 | for (i = 0; i < number; i++) { | ||
| 66 | struct td *td = td_list[i]; | ||
| 67 | list_add_tail(&td->node, &ed->td_list); | ||
| 68 | } | ||
| 69 | if (ed->td_head == NULL) | ||
| 70 | ed->td_head = td_list[0]; | ||
| 71 | } | ||
| 72 | |||
| 73 | static struct td *peek_td_from_ed(struct ed *ed) | ||
| 74 | { | ||
| 75 | struct td *td; | ||
| 76 | |||
| 77 | if (!list_empty(&ed->td_list)) | ||
| 78 | td = list_entry(ed->td_list.next, struct td, node); | ||
| 79 | else | ||
| 80 | td = NULL; | ||
| 81 | |||
| 82 | return td; | ||
| 83 | } | ||
| 84 | |||
| 85 | struct td *fhci_remove_td_from_frame(struct fhci_time_frame *frame) | ||
| 86 | { | ||
| 87 | struct td *td; | ||
| 88 | |||
| 89 | if (!list_empty(&frame->tds_list)) { | ||
| 90 | td = list_entry(frame->tds_list.next, struct td, frame_lh); | ||
| 91 | list_del_init(frame->tds_list.next); | ||
| 92 | } else | ||
| 93 | td = NULL; | ||
| 94 | |||
| 95 | return td; | ||
| 96 | } | ||
| 97 | |||
| 98 | struct td *fhci_peek_td_from_frame(struct fhci_time_frame *frame) | ||
| 99 | { | ||
| 100 | struct td *td; | ||
| 101 | |||
| 102 | if (!list_empty(&frame->tds_list)) | ||
| 103 | td = list_entry(frame->tds_list.next, struct td, frame_lh); | ||
| 104 | else | ||
| 105 | td = NULL; | ||
| 106 | |||
| 107 | return td; | ||
| 108 | } | ||
| 109 | |||
| 110 | struct td *fhci_remove_td_from_ed(struct ed *ed) | ||
| 111 | { | ||
| 112 | struct td *td; | ||
| 113 | |||
| 114 | if (!list_empty(&ed->td_list)) { | ||
| 115 | td = list_entry(ed->td_list.next, struct td, node); | ||
| 116 | list_del_init(ed->td_list.next); | ||
| 117 | |||
| 118 | /* if this TD was the ED's head, find next TD */ | ||
| 119 | if (!list_empty(&ed->td_list)) | ||
| 120 | ed->td_head = list_entry(ed->td_list.next, struct td, | ||
| 121 | node); | ||
| 122 | else | ||
| 123 | ed->td_head = NULL; | ||
| 124 | } else | ||
| 125 | td = NULL; | ||
| 126 | |||
| 127 | return td; | ||
| 128 | } | ||
| 129 | |||
| 130 | struct td *fhci_remove_td_from_done_list(struct fhci_controller_list *p_list) | ||
| 131 | { | ||
| 132 | struct td *td; | ||
| 133 | |||
| 134 | if (!list_empty(&p_list->done_list)) { | ||
| 135 | td = list_entry(p_list->done_list.next, struct td, node); | ||
| 136 | list_del_init(p_list->done_list.next); | ||
| 137 | } else | ||
| 138 | td = NULL; | ||
| 139 | |||
| 140 | return td; | ||
| 141 | } | ||
| 142 | |||
| 143 | void fhci_move_td_from_ed_to_done_list(struct fhci_usb *usb, struct ed *ed) | ||
| 144 | { | ||
| 145 | struct td *td; | ||
| 146 | |||
| 147 | td = ed->td_head; | ||
| 148 | list_del_init(&td->node); | ||
| 149 | |||
| 150 | /* If this TD was the ED's head,find next TD */ | ||
| 151 | if (!list_empty(&ed->td_list)) | ||
| 152 | ed->td_head = list_entry(ed->td_list.next, struct td, node); | ||
| 153 | else { | ||
| 154 | ed->td_head = NULL; | ||
| 155 | ed->state = FHCI_ED_SKIP; | ||
| 156 | } | ||
| 157 | ed->toggle_carry = td->toggle; | ||
| 158 | list_add_tail(&td->node, &usb->hc_list->done_list); | ||
| 159 | if (td->ioc) | ||
| 160 | usb->transfer_confirm(usb->fhci); | ||
| 161 | } | ||
| 162 | |||
| 163 | /* free done FHCI URB resource such as ED and TD */ | ||
| 164 | static void free_urb_priv(struct fhci_hcd *fhci, struct urb *urb) | ||
| 165 | { | ||
| 166 | int i; | ||
| 167 | struct urb_priv *urb_priv = urb->hcpriv; | ||
| 168 | struct ed *ed = urb_priv->ed; | ||
| 169 | |||
| 170 | for (i = 0; i < urb_priv->num_of_tds; i++) { | ||
| 171 | list_del_init(&urb_priv->tds[i]->node); | ||
| 172 | fhci_recycle_empty_td(fhci, urb_priv->tds[i]); | ||
| 173 | } | ||
| 174 | |||
| 175 | /* if this TD was the ED's head,find the next TD */ | ||
| 176 | if (!list_empty(&ed->td_list)) | ||
| 177 | ed->td_head = list_entry(ed->td_list.next, struct td, node); | ||
| 178 | else | ||
| 179 | ed->td_head = NULL; | ||
| 180 | |||
| 181 | kfree(urb_priv->tds); | ||
| 182 | kfree(urb_priv); | ||
| 183 | urb->hcpriv = NULL; | ||
| 184 | |||
| 185 | /* if this TD was the ED's head,find next TD */ | ||
| 186 | if (ed->td_head == NULL) | ||
| 187 | list_del_init(&ed->node); | ||
| 188 | fhci->active_urbs--; | ||
| 189 | } | ||
| 190 | |||
| 191 | /* this routine called to complete and free done URB */ | ||
| 192 | void fhci_urb_complete_free(struct fhci_hcd *fhci, struct urb *urb) | ||
| 193 | { | ||
| 194 | free_urb_priv(fhci, urb); | ||
| 195 | |||
| 196 | if (urb->status == -EINPROGRESS) { | ||
| 197 | if (urb->actual_length != urb->transfer_buffer_length && | ||
| 198 | urb->transfer_flags & URB_SHORT_NOT_OK) | ||
| 199 | urb->status = -EREMOTEIO; | ||
| 200 | else | ||
| 201 | urb->status = 0; | ||
| 202 | } | ||
| 203 | |||
| 204 | usb_hcd_unlink_urb_from_ep(fhci_to_hcd(fhci), urb); | ||
| 205 | |||
| 206 | spin_unlock(&fhci->lock); | ||
| 207 | |||
| 208 | usb_hcd_giveback_urb(fhci_to_hcd(fhci), urb, urb->status); | ||
| 209 | |||
| 210 | spin_lock(&fhci->lock); | ||
| 211 | } | ||
| 212 | |||
| 213 | /* | ||
| 214 | * caculate transfer length/stats and update the urb | ||
| 215 | * Precondition: irqsafe(only for urb-?status locking) | ||
| 216 | */ | ||
| 217 | void fhci_done_td(struct urb *urb, struct td *td) | ||
| 218 | { | ||
| 219 | struct ed *ed = td->ed; | ||
| 220 | u32 cc = td->status; | ||
| 221 | |||
| 222 | /* ISO...drivers see per-TD length/status */ | ||
| 223 | if (ed->mode == FHCI_TF_ISO) { | ||
| 224 | u32 len; | ||
| 225 | if (!(urb->transfer_flags & URB_SHORT_NOT_OK && | ||
| 226 | cc == USB_TD_RX_DATA_UNDERUN)) | ||
| 227 | cc = USB_TD_OK; | ||
| 228 | |||
| 229 | if (usb_pipeout(urb->pipe)) | ||
| 230 | len = urb->iso_frame_desc[td->iso_index].length; | ||
| 231 | else | ||
| 232 | len = td->actual_len; | ||
| 233 | |||
| 234 | urb->actual_length += len; | ||
| 235 | urb->iso_frame_desc[td->iso_index].actual_length = len; | ||
| 236 | urb->iso_frame_desc[td->iso_index].status = | ||
| 237 | status_to_error(cc); | ||
| 238 | } | ||
| 239 | |||
| 240 | /* BULK,INT,CONTROL... drivers see aggregate length/status, | ||
| 241 | * except that "setup" bytes aren't counted and "short" transfers | ||
| 242 | * might not be reported as errors. | ||
| 243 | */ | ||
| 244 | else { | ||
| 245 | if (td->error_cnt >= 3) | ||
| 246 | urb->error_count = 3; | ||
| 247 | |||
| 248 | /* control endpoint only have soft stalls */ | ||
| 249 | |||
| 250 | /* update packet status if needed(short may be ok) */ | ||
| 251 | if (!(urb->transfer_flags & URB_SHORT_NOT_OK) && | ||
| 252 | cc == USB_TD_RX_DATA_UNDERUN) { | ||
| 253 | ed->state = FHCI_ED_OPER; | ||
| 254 | cc = USB_TD_OK; | ||
| 255 | } | ||
| 256 | if (cc != USB_TD_OK) { | ||
| 257 | if (urb->status == -EINPROGRESS) | ||
| 258 | urb->status = status_to_error(cc); | ||
| 259 | } | ||
| 260 | |||
| 261 | /* count all non-empty packets except control SETUP packet */ | ||
| 262 | if (td->type != FHCI_TA_SETUP || td->iso_index != 0) | ||
| 263 | urb->actual_length += td->actual_len; | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | /* there are some pedning request to unlink */ | ||
| 268 | void fhci_del_ed_list(struct fhci_hcd *fhci, struct ed *ed) | ||
| 269 | { | ||
| 270 | struct td *td = peek_td_from_ed(ed); | ||
| 271 | struct urb *urb = td->urb; | ||
| 272 | struct urb_priv *urb_priv = urb->hcpriv; | ||
| 273 | |||
| 274 | if (urb_priv->state == URB_DEL) { | ||
| 275 | td = fhci_remove_td_from_ed(ed); | ||
| 276 | /* HC may have partly processed this TD */ | ||
| 277 | if (td->status != USB_TD_INPROGRESS) | ||
| 278 | fhci_done_td(urb, td); | ||
| 279 | |||
| 280 | /* URB is done;clean up */ | ||
| 281 | if (++(urb_priv->tds_cnt) == urb_priv->num_of_tds) | ||
| 282 | fhci_urb_complete_free(fhci, urb); | ||
| 283 | } | ||
| 284 | } | ||
diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c new file mode 100644 index 000000000000..bb63b68ddb77 --- /dev/null +++ b/drivers/usb/host/fhci-sched.c | |||
| @@ -0,0 +1,888 @@ | |||
| 1 | /* | ||
| 2 | * Freescale QUICC Engine USB Host Controller Driver | ||
| 3 | * | ||
| 4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
| 5 | * Shlomi Gridish <gridish@freescale.com> | ||
| 6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
| 7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
| 8 | * Peter Barada <peterb@logicpd.com> | ||
| 9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
| 10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License as published by the | ||
| 14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 15 | * option) any later version. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/types.h> | ||
| 20 | #include <linux/spinlock.h> | ||
| 21 | #include <linux/delay.h> | ||
| 22 | #include <linux/errno.h> | ||
| 23 | #include <linux/list.h> | ||
| 24 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/io.h> | ||
| 26 | #include <linux/usb.h> | ||
| 27 | #include <asm/qe.h> | ||
| 28 | #include <asm/fsl_gtm.h> | ||
| 29 | #include "../core/hcd.h" | ||
| 30 | #include "fhci.h" | ||
| 31 | |||
| 32 | static void recycle_frame(struct fhci_usb *usb, struct packet *pkt) | ||
| 33 | { | ||
| 34 | pkt->data = NULL; | ||
| 35 | pkt->len = 0; | ||
| 36 | pkt->status = USB_TD_OK; | ||
| 37 | pkt->info = 0; | ||
| 38 | pkt->priv_data = NULL; | ||
| 39 | |||
| 40 | cq_put(usb->ep0->empty_frame_Q, pkt); | ||
| 41 | } | ||
| 42 | |||
| 43 | /* confirm submitted packet */ | ||
| 44 | void fhci_transaction_confirm(struct fhci_usb *usb, struct packet *pkt) | ||
| 45 | { | ||
| 46 | struct td *td; | ||
| 47 | struct packet *td_pkt; | ||
| 48 | struct ed *ed; | ||
| 49 | u32 trans_len; | ||
| 50 | bool td_done = false; | ||
| 51 | |||
| 52 | td = fhci_remove_td_from_frame(usb->actual_frame); | ||
| 53 | td_pkt = td->pkt; | ||
| 54 | trans_len = pkt->len; | ||
| 55 | td->status = pkt->status; | ||
| 56 | if (td->type == FHCI_TA_IN && td_pkt->info & PKT_DUMMY_PACKET) { | ||
| 57 | if ((td->data + td->actual_len) && trans_len) | ||
| 58 | memcpy(td->data + td->actual_len, pkt->data, | ||
| 59 | trans_len); | ||
| 60 | cq_put(usb->ep0->dummy_packets_Q, pkt->data); | ||
| 61 | } | ||
| 62 | |||
| 63 | recycle_frame(usb, pkt); | ||
| 64 | |||
| 65 | ed = td->ed; | ||
| 66 | if (ed->mode == FHCI_TF_ISO) { | ||
| 67 | if (ed->td_list.next->next != &ed->td_list) { | ||
| 68 | struct td *td_next = | ||
| 69 | list_entry(ed->td_list.next->next, struct td, | ||
| 70 | node); | ||
| 71 | |||
| 72 | td_next->start_frame = usb->actual_frame->frame_num; | ||
| 73 | } | ||
| 74 | td->actual_len = trans_len; | ||
| 75 | td_done = true; | ||
| 76 | } else if ((td->status & USB_TD_ERROR) && | ||
| 77 | !(td->status & USB_TD_TX_ER_NAK)) { | ||
| 78 | /* | ||
| 79 | * There was an error on the transaction (but not NAK). | ||
| 80 | * If it is fatal error (data underrun, stall, bad pid or 3 | ||
| 81 | * errors exceeded), mark this TD as done. | ||
| 82 | */ | ||
| 83 | if ((td->status & USB_TD_RX_DATA_UNDERUN) || | ||
| 84 | (td->status & USB_TD_TX_ER_STALL) || | ||
| 85 | (td->status & USB_TD_RX_ER_PID) || | ||
| 86 | (++td->error_cnt >= 3)) { | ||
| 87 | ed->state = FHCI_ED_HALTED; | ||
| 88 | td_done = true; | ||
| 89 | |||
| 90 | if (td->status & USB_TD_RX_DATA_UNDERUN) { | ||
| 91 | fhci_dbg(usb->fhci, "td err fu\n"); | ||
| 92 | td->toggle = !td->toggle; | ||
| 93 | td->actual_len += trans_len; | ||
| 94 | } else { | ||
| 95 | fhci_dbg(usb->fhci, "td err f!u\n"); | ||
| 96 | } | ||
| 97 | } else { | ||
| 98 | fhci_dbg(usb->fhci, "td err !f\n"); | ||
| 99 | /* it is not a fatal error -retry this transaction */ | ||
| 100 | td->nak_cnt = 0; | ||
| 101 | td->error_cnt++; | ||
| 102 | td->status = USB_TD_OK; | ||
| 103 | } | ||
| 104 | } else if (td->status & USB_TD_TX_ER_NAK) { | ||
| 105 | /* there was a NAK response */ | ||
| 106 | fhci_vdbg(usb->fhci, "td nack\n"); | ||
| 107 | td->nak_cnt++; | ||
| 108 | td->error_cnt = 0; | ||
| 109 | td->status = USB_TD_OK; | ||
| 110 | } else { | ||
| 111 | /* there was no error on transaction */ | ||
| 112 | td->error_cnt = 0; | ||
| 113 | td->nak_cnt = 0; | ||
| 114 | td->toggle = !td->toggle; | ||
| 115 | td->actual_len += trans_len; | ||
| 116 | |||
| 117 | if (td->len == td->actual_len) | ||
| 118 | td_done = true; | ||
| 119 | } | ||
| 120 | |||
| 121 | if (td_done) | ||
| 122 | fhci_move_td_from_ed_to_done_list(usb, ed); | ||
| 123 | } | ||
| 124 | |||
| 125 | /* | ||
| 126 | * Flush all transmitted packets from BDs | ||
| 127 | * This routine is called when disabling the USB port to flush all | ||
| 128 | * transmissions that are allready scheduled in the BDs | ||
| 129 | */ | ||
| 130 | void fhci_flush_all_transmissions(struct fhci_usb *usb) | ||
| 131 | { | ||
| 132 | u8 mode; | ||
| 133 | struct td *td; | ||
| 134 | |||
| 135 | mode = in_8(&usb->fhci->regs->usb_mod); | ||
| 136 | clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_EN); | ||
| 137 | |||
| 138 | fhci_flush_bds(usb); | ||
| 139 | |||
| 140 | while ((td = fhci_peek_td_from_frame(usb->actual_frame)) != NULL) { | ||
| 141 | struct packet *pkt = td->pkt; | ||
| 142 | |||
| 143 | pkt->status = USB_TD_TX_ER_TIMEOUT; | ||
| 144 | fhci_transaction_confirm(usb, pkt); | ||
| 145 | } | ||
| 146 | |||
| 147 | usb->actual_frame->frame_status = FRAME_END_TRANSMISSION; | ||
| 148 | |||
| 149 | /* reset the event register */ | ||
| 150 | out_be16(&usb->fhci->regs->usb_event, 0xffff); | ||
| 151 | /* enable the USB controller */ | ||
| 152 | out_8(&usb->fhci->regs->usb_mod, mode | USB_MODE_EN); | ||
| 153 | } | ||
| 154 | |||
| 155 | /* | ||
| 156 | * This function forms the packet and transmit the packet. This function | ||
| 157 | * will handle all endpoint type:ISO,interrupt,control and bulk | ||
| 158 | */ | ||
| 159 | static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td) | ||
| 160 | { | ||
| 161 | u32 fw_transaction_time, len = 0; | ||
| 162 | struct packet *pkt; | ||
| 163 | u8 *data = NULL; | ||
| 164 | |||
| 165 | /* calcalate data address,len and toggle and then add the transaction */ | ||
| 166 | if (td->toggle == USB_TD_TOGGLE_CARRY) | ||
| 167 | td->toggle = ed->toggle_carry; | ||
| 168 | |||
| 169 | switch (ed->mode) { | ||
| 170 | case FHCI_TF_ISO: | ||
| 171 | len = td->len; | ||
| 172 | if (td->type != FHCI_TA_IN) | ||
| 173 | data = td->data; | ||
| 174 | break; | ||
| 175 | case FHCI_TF_CTRL: | ||
| 176 | case FHCI_TF_BULK: | ||
| 177 | len = min(td->len - td->actual_len, ed->max_pkt_size); | ||
| 178 | if (!((td->type == FHCI_TA_IN) && | ||
| 179 | ((len + td->actual_len) == td->len))) | ||
| 180 | data = td->data + td->actual_len; | ||
| 181 | break; | ||
| 182 | case FHCI_TF_INTR: | ||
| 183 | len = min(td->len, ed->max_pkt_size); | ||
| 184 | if (!((td->type == FHCI_TA_IN) && | ||
| 185 | ((td->len + CRC_SIZE) >= ed->max_pkt_size))) | ||
| 186 | data = td->data; | ||
| 187 | break; | ||
| 188 | default: | ||
| 189 | break; | ||
| 190 | } | ||
| 191 | |||
| 192 | if (usb->port_status == FHCI_PORT_FULL) | ||
| 193 | fw_transaction_time = (((len + PROTOCOL_OVERHEAD) * 11) >> 4); | ||
| 194 | else | ||
| 195 | fw_transaction_time = ((len + PROTOCOL_OVERHEAD) * 6); | ||
| 196 | |||
| 197 | /* check if there's enough space in this frame to submit this TD */ | ||
| 198 | if (usb->actual_frame->total_bytes + len + PROTOCOL_OVERHEAD >= | ||
| 199 | usb->max_bytes_per_frame) { | ||
| 200 | fhci_vdbg(usb->fhci, "not enough space in this frame: " | ||
| 201 | "%d %d %d\n", usb->actual_frame->total_bytes, len, | ||
| 202 | usb->max_bytes_per_frame); | ||
| 203 | return -1; | ||
| 204 | } | ||
| 205 | |||
| 206 | /* check if there's enough time in this frame to submit this TD */ | ||
| 207 | if (usb->actual_frame->frame_status != FRAME_IS_PREPARED && | ||
| 208 | (usb->actual_frame->frame_status & FRAME_END_TRANSMISSION || | ||
| 209 | (fw_transaction_time + usb->sw_transaction_time >= | ||
| 210 | 1000 - fhci_get_sof_timer_count(usb)))) { | ||
| 211 | fhci_dbg(usb->fhci, "not enough time in this frame\n"); | ||
| 212 | return -1; | ||
| 213 | } | ||
| 214 | |||
| 215 | /* update frame object fields before transmitting */ | ||
| 216 | pkt = cq_get(usb->ep0->empty_frame_Q); | ||
| 217 | if (!pkt) { | ||
| 218 | fhci_dbg(usb->fhci, "there is no empty frame\n"); | ||
| 219 | return -1; | ||
| 220 | } | ||
| 221 | td->pkt = pkt; | ||
| 222 | |||
| 223 | pkt->info = 0; | ||
| 224 | if (data == NULL) { | ||
| 225 | data = cq_get(usb->ep0->dummy_packets_Q); | ||
| 226 | BUG_ON(!data); | ||
| 227 | pkt->info = PKT_DUMMY_PACKET; | ||
| 228 | } | ||
| 229 | pkt->data = data; | ||
| 230 | pkt->len = len; | ||
| 231 | pkt->status = USB_TD_OK; | ||
| 232 | /* update TD status field before transmitting */ | ||
| 233 | td->status = USB_TD_INPROGRESS; | ||
| 234 | /* update actual frame time object with the actual transmission */ | ||
| 235 | usb->actual_frame->total_bytes += (len + PROTOCOL_OVERHEAD); | ||
| 236 | fhci_add_td_to_frame(usb->actual_frame, td); | ||
| 237 | |||
| 238 | if (usb->port_status != FHCI_PORT_FULL && | ||
| 239 | usb->port_status != FHCI_PORT_LOW) { | ||
| 240 | pkt->status = USB_TD_TX_ER_TIMEOUT; | ||
| 241 | pkt->len = 0; | ||
| 242 | fhci_transaction_confirm(usb, pkt); | ||
| 243 | } else if (fhci_host_transaction(usb, pkt, td->type, ed->dev_addr, | ||
| 244 | ed->ep_addr, ed->mode, ed->speed, td->toggle)) { | ||
| 245 | /* remove TD from actual frame */ | ||
| 246 | list_del_init(&td->frame_lh); | ||
| 247 | td->status = USB_TD_OK; | ||
| 248 | if (pkt->info & PKT_DUMMY_PACKET) | ||
| 249 | cq_put(usb->ep0->dummy_packets_Q, pkt->data); | ||
| 250 | recycle_frame(usb, pkt); | ||
| 251 | usb->actual_frame->total_bytes -= (len + PROTOCOL_OVERHEAD); | ||
| 252 | fhci_err(usb->fhci, "host transaction failed\n"); | ||
| 253 | return -1; | ||
| 254 | } | ||
| 255 | |||
| 256 | return len; | ||
| 257 | } | ||
| 258 | |||
| 259 | static void move_head_to_tail(struct list_head *list) | ||
| 260 | { | ||
| 261 | struct list_head *node = list->next; | ||
| 262 | |||
| 263 | if (!list_empty(list)) { | ||
| 264 | list_del(node); | ||
| 265 | list_add_tail(node, list); | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | /* | ||
| 270 | * This function goes through the endpoint list and schedules the | ||
| 271 | * transactions within this list | ||
| 272 | */ | ||
| 273 | static int scan_ed_list(struct fhci_usb *usb, | ||
| 274 | struct list_head *list, enum fhci_tf_mode list_type) | ||
| 275 | { | ||
| 276 | static const int frame_part[4] = { | ||
| 277 | [FHCI_TF_CTRL] = MAX_BYTES_PER_FRAME, | ||
| 278 | [FHCI_TF_ISO] = (MAX_BYTES_PER_FRAME * | ||
| 279 | MAX_PERIODIC_FRAME_USAGE) / 100, | ||
| 280 | [FHCI_TF_BULK] = MAX_BYTES_PER_FRAME, | ||
| 281 | [FHCI_TF_INTR] = (MAX_BYTES_PER_FRAME * | ||
| 282 | MAX_PERIODIC_FRAME_USAGE) / 100 | ||
| 283 | }; | ||
| 284 | struct ed *ed; | ||
| 285 | struct td *td; | ||
| 286 | int ans = 1; | ||
| 287 | u32 save_transaction_time = usb->sw_transaction_time; | ||
| 288 | |||
| 289 | list_for_each_entry(ed, list, node) { | ||
| 290 | td = ed->td_head; | ||
| 291 | |||
| 292 | if (!td || (td && td->status == USB_TD_INPROGRESS)) | ||
| 293 | continue; | ||
| 294 | |||
| 295 | if (ed->state != FHCI_ED_OPER) { | ||
| 296 | if (ed->state == FHCI_ED_URB_DEL) { | ||
| 297 | td->status = USB_TD_OK; | ||
| 298 | fhci_move_td_from_ed_to_done_list(usb, ed); | ||
| 299 | ed->state = FHCI_ED_SKIP; | ||
| 300 | } | ||
| 301 | continue; | ||
| 302 | } | ||
| 303 | |||
| 304 | /* | ||
| 305 | * if it isn't interrupt pipe or it is not iso pipe and the | ||
| 306 | * interval time passed | ||
| 307 | */ | ||
| 308 | if ((list_type == FHCI_TF_INTR || list_type == FHCI_TF_ISO) && | ||
| 309 | (((usb->actual_frame->frame_num - | ||
| 310 | td->start_frame) & 0x7ff) < td->interval)) | ||
| 311 | continue; | ||
| 312 | |||
| 313 | if (add_packet(usb, ed, td) < 0) | ||
| 314 | continue; | ||
| 315 | |||
| 316 | /* update time stamps in the TD */ | ||
| 317 | td->start_frame = usb->actual_frame->frame_num; | ||
| 318 | usb->sw_transaction_time += save_transaction_time; | ||
| 319 | |||
| 320 | if (usb->actual_frame->total_bytes >= | ||
| 321 | usb->max_bytes_per_frame) { | ||
| 322 | usb->actual_frame->frame_status = | ||
| 323 | FRAME_DATA_END_TRANSMISSION; | ||
| 324 | fhci_push_dummy_bd(usb->ep0); | ||
| 325 | ans = 0; | ||
| 326 | break; | ||
| 327 | } | ||
| 328 | |||
| 329 | if (usb->actual_frame->total_bytes >= frame_part[list_type]) | ||
| 330 | break; | ||
| 331 | } | ||
| 332 | |||
| 333 | /* be fair to each ED(move list head around) */ | ||
| 334 | move_head_to_tail(list); | ||
| 335 | usb->sw_transaction_time = save_transaction_time; | ||
| 336 | |||
| 337 | return ans; | ||
| 338 | } | ||
| 339 | |||
| 340 | static u32 rotate_frames(struct fhci_usb *usb) | ||
| 341 | { | ||
| 342 | struct fhci_hcd *fhci = usb->fhci; | ||
| 343 | |||
| 344 | if (!list_empty(&usb->actual_frame->tds_list)) { | ||
| 345 | if ((((in_be16(&fhci->pram->frame_num) & 0x07ff) - | ||
| 346 | usb->actual_frame->frame_num) & 0x7ff) > 5) | ||
| 347 | fhci_flush_actual_frame(usb); | ||
| 348 | else | ||
| 349 | return -EINVAL; | ||
| 350 | } | ||
| 351 | |||
| 352 | usb->actual_frame->frame_status = FRAME_IS_PREPARED; | ||
| 353 | usb->actual_frame->frame_num = in_be16(&fhci->pram->frame_num) & 0x7ff; | ||
| 354 | usb->actual_frame->total_bytes = 0; | ||
| 355 | |||
| 356 | return 0; | ||
| 357 | } | ||
| 358 | |||
| 359 | /* | ||
| 360 | * This function schedule the USB transaction and will process the | ||
| 361 | * endpoint in the following order: iso, interrupt, control and bulk. | ||
| 362 | */ | ||
| 363 | void fhci_schedule_transactions(struct fhci_usb *usb) | ||
| 364 | { | ||
| 365 | int left = 1; | ||
| 366 | |||
| 367 | if (usb->actual_frame->frame_status & FRAME_END_TRANSMISSION) | ||
| 368 | if (rotate_frames(usb) != 0) | ||
| 369 | return; | ||
| 370 | |||
| 371 | if (usb->actual_frame->frame_status & FRAME_END_TRANSMISSION) | ||
| 372 | return; | ||
| 373 | |||
| 374 | if (usb->actual_frame->total_bytes == 0) { | ||
| 375 | /* | ||
| 376 | * schedule the next available ISO transfer | ||
| 377 | *or next stage of the ISO transfer | ||
| 378 | */ | ||
| 379 | scan_ed_list(usb, &usb->hc_list->iso_list, FHCI_TF_ISO); | ||
| 380 | |||
| 381 | /* | ||
| 382 | * schedule the next available interrupt transfer or | ||
| 383 | * the next stage of the interrupt transfer | ||
| 384 | */ | ||
| 385 | scan_ed_list(usb, &usb->hc_list->intr_list, FHCI_TF_INTR); | ||
| 386 | |||
| 387 | /* | ||
| 388 | * schedule the next available control transfer | ||
| 389 | * or the next stage of the control transfer | ||
| 390 | */ | ||
| 391 | left = scan_ed_list(usb, &usb->hc_list->ctrl_list, | ||
| 392 | FHCI_TF_CTRL); | ||
| 393 | } | ||
| 394 | |||
| 395 | /* | ||
| 396 | * schedule the next available bulk transfer or the next stage of the | ||
| 397 | * bulk transfer | ||
| 398 | */ | ||
| 399 | if (left > 0) | ||
| 400 | scan_ed_list(usb, &usb->hc_list->bulk_list, FHCI_TF_BULK); | ||
| 401 | } | ||
| 402 | |||
| 403 | /* Handles SOF interrupt */ | ||
| 404 | static void sof_interrupt(struct fhci_hcd *fhci) | ||
| 405 | { | ||
| 406 | struct fhci_usb *usb = fhci->usb_lld; | ||
| 407 | |||
| 408 | if ((usb->port_status == FHCI_PORT_DISABLED) && | ||
| 409 | (usb->vroot_hub->port.wPortStatus & USB_PORT_STAT_CONNECTION) && | ||
| 410 | !(usb->vroot_hub->port.wPortChange & USB_PORT_STAT_C_CONNECTION)) { | ||
| 411 | if (usb->vroot_hub->port.wPortStatus & USB_PORT_STAT_LOW_SPEED) | ||
| 412 | usb->port_status = FHCI_PORT_LOW; | ||
| 413 | else | ||
| 414 | usb->port_status = FHCI_PORT_FULL; | ||
| 415 | /* Disable IDLE */ | ||
| 416 | usb->saved_msk &= ~USB_E_IDLE_MASK; | ||
| 417 | out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | ||
| 418 | } | ||
| 419 | |||
| 420 | gtm_set_exact_timer16(fhci->timer, usb->max_frame_usage, false); | ||
| 421 | |||
| 422 | fhci_host_transmit_actual_frame(usb); | ||
| 423 | usb->actual_frame->frame_status = FRAME_IS_TRANSMITTED; | ||
| 424 | |||
| 425 | fhci_schedule_transactions(usb); | ||
| 426 | } | ||
| 427 | |||
| 428 | /* Handles device disconnected interrupt on port */ | ||
| 429 | void fhci_device_disconnected_interrupt(struct fhci_hcd *fhci) | ||
| 430 | { | ||
| 431 | struct fhci_usb *usb = fhci->usb_lld; | ||
| 432 | |||
| 433 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
| 434 | |||
| 435 | fhci_usb_disable_interrupt(usb); | ||
| 436 | clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_LSS); | ||
| 437 | usb->port_status = FHCI_PORT_DISABLED; | ||
| 438 | |||
| 439 | fhci_stop_sof_timer(fhci); | ||
| 440 | |||
| 441 | /* Enable IDLE since we want to know if something comes along */ | ||
| 442 | usb->saved_msk |= USB_E_IDLE_MASK; | ||
| 443 | out_be16(&usb->fhci->regs->usb_mask, usb->saved_msk); | ||
| 444 | |||
| 445 | usb->vroot_hub->port.wPortStatus &= ~USB_PORT_STAT_CONNECTION; | ||
| 446 | usb->vroot_hub->port.wPortChange |= USB_PORT_STAT_C_CONNECTION; | ||
| 447 | usb->max_bytes_per_frame = 0; | ||
| 448 | fhci_usb_enable_interrupt(usb); | ||
| 449 | |||
| 450 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
| 451 | } | ||
| 452 | |||
| 453 | /* detect a new device connected on the USB port */ | ||
| 454 | void fhci_device_connected_interrupt(struct fhci_hcd *fhci) | ||
| 455 | { | ||
| 456 | |||
| 457 | struct fhci_usb *usb = fhci->usb_lld; | ||
| 458 | int state; | ||
| 459 | int ret; | ||
| 460 | |||
| 461 | fhci_dbg(fhci, "-> %s\n", __func__); | ||
| 462 | |||
| 463 | fhci_usb_disable_interrupt(usb); | ||
| 464 | state = fhci_ioports_check_bus_state(fhci); | ||
| 465 | |||
| 466 | /* low-speed device was connected to the USB port */ | ||
| 467 | if (state == 1) { | ||
| 468 | ret = qe_usb_clock_set(fhci->lowspeed_clk, USB_CLOCK >> 3); | ||
| 469 | if (ret) { | ||
| 470 | fhci_warn(fhci, "Low-Speed device is not supported, " | ||
| 471 | "try use BRGx\n"); | ||
| 472 | goto out; | ||
| 473 | } | ||
| 474 | |||
| 475 | usb->port_status = FHCI_PORT_LOW; | ||
| 476 | setbits8(&usb->fhci->regs->usb_mod, USB_MODE_LSS); | ||
| 477 | usb->vroot_hub->port.wPortStatus |= | ||
| 478 | (USB_PORT_STAT_LOW_SPEED | | ||
| 479 | USB_PORT_STAT_CONNECTION); | ||
| 480 | usb->vroot_hub->port.wPortChange |= | ||
| 481 | USB_PORT_STAT_C_CONNECTION; | ||
| 482 | usb->max_bytes_per_frame = | ||
| 483 | (MAX_BYTES_PER_FRAME >> 3) - 7; | ||
| 484 | fhci_port_enable(usb); | ||
| 485 | } else if (state == 2) { | ||
| 486 | ret = qe_usb_clock_set(fhci->fullspeed_clk, USB_CLOCK); | ||
| 487 | if (ret) { | ||
| 488 | fhci_warn(fhci, "Full-Speed device is not supported, " | ||
| 489 | "try use CLKx\n"); | ||
| 490 | goto out; | ||
| 491 | } | ||
| 492 | |||
| 493 | usb->port_status = FHCI_PORT_FULL; | ||
| 494 | clrbits8(&usb->fhci->regs->usb_mod, USB_MODE_LSS); | ||
| 495 | usb->vroot_hub->port.wPortStatus &= | ||
| 496 | ~USB_PORT_STAT_LOW_SPEED; | ||
| 497 | usb->vroot_hub->port.wPortStatus |= | ||
| 498 | USB_PORT_STAT_CONNECTION; | ||
| 499 | usb->vroot_hub->port.wPortChange |= | ||
| 500 | USB_PORT_STAT_C_CONNECTION; | ||
| 501 | usb->max_bytes_per_frame = (MAX_BYTES_PER_FRAME - 15); | ||
| 502 | fhci_port_enable(usb); | ||
| 503 | } | ||
| 504 | out: | ||
| 505 | fhci_usb_enable_interrupt(usb); | ||
| 506 | fhci_dbg(fhci, "<- %s\n", __func__); | ||
| 507 | } | ||
| 508 | |||
| 509 | irqreturn_t fhci_frame_limit_timer_irq(int irq, void *_hcd) | ||
| 510 | { | ||
| 511 | struct usb_hcd *hcd = _hcd; | ||
| 512 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
| 513 | struct fhci_usb *usb = fhci->usb_lld; | ||
| 514 | |||
| 515 | spin_lock(&fhci->lock); | ||
| 516 | |||
| 517 | gtm_set_exact_timer16(fhci->timer, 1000, false); | ||
| 518 | |||
| 519 | if (usb->actual_frame->frame_status == FRAME_IS_TRANSMITTED) { | ||
| 520 | usb->actual_frame->frame_status = FRAME_TIMER_END_TRANSMISSION; | ||
| 521 | fhci_push_dummy_bd(usb->ep0); | ||
| 522 | } | ||
| 523 | |||
| 524 | fhci_schedule_transactions(usb); | ||
| 525 | |||
| 526 | spin_unlock(&fhci->lock); | ||
| 527 | |||
| 528 | return IRQ_HANDLED; | ||
| 529 | } | ||
| 530 | |||
| 531 | /* Cancel transmission on the USB endpoint */ | ||
| 532 | static void abort_transmission(struct fhci_usb *usb) | ||
| 533 | { | ||
| 534 | fhci_dbg(usb->fhci, "-> %s\n", __func__); | ||
| 535 | /* issue stop Tx command */ | ||
| 536 | qe_issue_cmd(QE_USB_STOP_TX, QE_CR_SUBBLOCK_USB, EP_ZERO, 0); | ||
| 537 | /* flush Tx FIFOs */ | ||
| 538 | out_8(&usb->fhci->regs->usb_comm, USB_CMD_FLUSH_FIFO | EP_ZERO); | ||
| 539 | udelay(1000); | ||
| 540 | /* reset Tx BDs */ | ||
| 541 | fhci_flush_bds(usb); | ||
| 542 | /* issue restart Tx command */ | ||
| 543 | qe_issue_cmd(QE_USB_RESTART_TX, QE_CR_SUBBLOCK_USB, EP_ZERO, 0); | ||
| 544 | fhci_dbg(usb->fhci, "<- %s\n", __func__); | ||
| 545 | } | ||
| 546 | |||
| 547 | irqreturn_t fhci_irq(struct usb_hcd *hcd) | ||
| 548 | { | ||
| 549 | struct fhci_hcd *fhci = hcd_to_fhci(hcd); | ||
| 550 | struct fhci_usb *usb; | ||
| 551 | u16 usb_er = 0; | ||
| 552 | unsigned long flags; | ||
| 553 | |||
| 554 | spin_lock_irqsave(&fhci->lock, flags); | ||
| 555 | |||
| 556 | usb = fhci->usb_lld; | ||
| 557 | |||
| 558 | usb_er |= in_be16(&usb->fhci->regs->usb_event) & | ||
| 559 | in_be16(&usb->fhci->regs->usb_mask); | ||
| 560 | |||
| 561 | /* clear event bits for next time */ | ||
| 562 | out_be16(&usb->fhci->regs->usb_event, usb_er); | ||
| 563 | |||
| 564 | fhci_dbg_isr(fhci, usb_er); | ||
| 565 | |||
| 566 | if (usb_er & USB_E_RESET_MASK) { | ||
| 567 | if ((usb->port_status == FHCI_PORT_FULL) || | ||
| 568 | (usb->port_status == FHCI_PORT_LOW)) { | ||
| 569 | fhci_device_disconnected_interrupt(fhci); | ||
| 570 | usb_er &= ~USB_E_IDLE_MASK; | ||
| 571 | } else if (usb->port_status == FHCI_PORT_WAITING) { | ||
| 572 | usb->port_status = FHCI_PORT_DISCONNECTING; | ||
| 573 | |||
| 574 | /* Turn on IDLE since we want to disconnect */ | ||
| 575 | usb->saved_msk |= USB_E_IDLE_MASK; | ||
| 576 | out_be16(&usb->fhci->regs->usb_event, | ||
| 577 | usb->saved_msk); | ||
| 578 | } else if (usb->port_status == FHCI_PORT_DISABLED) { | ||
| 579 | if (fhci_ioports_check_bus_state(fhci) == 1 && | ||
| 580 | usb->port_status != FHCI_PORT_LOW && | ||
| 581 | usb->port_status != FHCI_PORT_FULL) | ||
| 582 | fhci_device_connected_interrupt(fhci); | ||
| 583 | } | ||
| 584 | usb_er &= ~USB_E_RESET_MASK; | ||
| 585 | } | ||
| 586 | |||
| 587 | if (usb_er & USB_E_MSF_MASK) { | ||
| 588 | abort_transmission(fhci->usb_lld); | ||
| 589 | usb_er &= ~USB_E_MSF_MASK; | ||
| 590 | } | ||
| 591 | |||
| 592 | if (usb_er & (USB_E_SOF_MASK | USB_E_SFT_MASK)) { | ||
| 593 | sof_interrupt(fhci); | ||
| 594 | usb_er &= ~(USB_E_SOF_MASK | USB_E_SFT_MASK); | ||
| 595 | } | ||
| 596 | |||
| 597 | if (usb_er & USB_E_TXB_MASK) { | ||
| 598 | fhci_tx_conf_interrupt(fhci->usb_lld); | ||
| 599 | usb_er &= ~USB_E_TXB_MASK; | ||
| 600 | } | ||
| 601 | |||
| 602 | if (usb_er & USB_E_TXE1_MASK) { | ||
| 603 | fhci_tx_conf_interrupt(fhci->usb_lld); | ||
| 604 | usb_er &= ~USB_E_TXE1_MASK; | ||
| 605 | } | ||
| 606 | |||
| 607 | if (usb_er & USB_E_IDLE_MASK) { | ||
| 608 | if (usb->port_status == FHCI_PORT_DISABLED && | ||
| 609 | usb->port_status != FHCI_PORT_LOW && | ||
| 610 | usb->port_status != FHCI_PORT_FULL) { | ||
| 611 | usb_er &= ~USB_E_RESET_MASK; | ||
| 612 | fhci_device_connected_interrupt(fhci); | ||
| 613 | } else if (usb->port_status == | ||
| 614 | FHCI_PORT_DISCONNECTING) { | ||
| 615 | /* XXX usb->port_status = FHCI_PORT_WAITING; */ | ||
| 616 | /* Disable IDLE */ | ||
| 617 | usb->saved_msk &= ~USB_E_IDLE_MASK; | ||
| 618 | out_be16(&usb->fhci->regs->usb_mask, | ||
| 619 | usb->saved_msk); | ||
| 620 | } else { | ||
| 621 | fhci_dbg_isr(fhci, -1); | ||
| 622 | } | ||
| 623 | |||
| 624 | usb_er &= ~USB_E_IDLE_MASK; | ||
| 625 | } | ||
| 626 | |||
| 627 | spin_unlock_irqrestore(&fhci->lock, flags); | ||
| 628 | |||
| 629 | return IRQ_HANDLED; | ||
| 630 | } | ||
| 631 | |||
| 632 | |||
| 633 | /* | ||
| 634 | * Process normal completions(error or sucess) and clean the schedule. | ||
| 635 | * | ||
| 636 | * This is the main path for handing urbs back to drivers. The only other patth | ||
| 637 | * is process_del_list(),which unlinks URBs by scanning EDs,instead of scanning | ||
| 638 | * the (re-reversed) done list as this does. | ||
| 639 | */ | ||
| 640 | static void process_done_list(unsigned long data) | ||
| 641 | { | ||
| 642 | struct urb *urb; | ||
| 643 | struct ed *ed; | ||
| 644 | struct td *td; | ||
| 645 | struct urb_priv *urb_priv; | ||
| 646 | struct fhci_hcd *fhci = (struct fhci_hcd *)data; | ||
| 647 | |||
| 648 | disable_irq(fhci->timer->irq); | ||
| 649 | disable_irq(fhci_to_hcd(fhci)->irq); | ||
| 650 | spin_lock(&fhci->lock); | ||
| 651 | |||
| 652 | td = fhci_remove_td_from_done_list(fhci->hc_list); | ||
| 653 | while (td != NULL) { | ||
| 654 | urb = td->urb; | ||
| 655 | urb_priv = urb->hcpriv; | ||
| 656 | ed = td->ed; | ||
| 657 | |||
| 658 | /* update URB's length and status from TD */ | ||
| 659 | fhci_done_td(urb, td); | ||
| 660 | urb_priv->tds_cnt++; | ||
| 661 | |||
| 662 | /* | ||
| 663 | * if all this urb's TDs are done, call complete() | ||
| 664 | * Interrupt transfers are the onley special case: | ||
| 665 | * they are reissued,until "deleted" by usb_unlink_urb | ||
| 666 | * (real work done in a SOF intr, by process_del_list) | ||
| 667 | */ | ||
| 668 | if (urb_priv->tds_cnt == urb_priv->num_of_tds) { | ||
| 669 | fhci_urb_complete_free(fhci, urb); | ||
| 670 | } else if (urb_priv->state == URB_DEL && | ||
| 671 | ed->state == FHCI_ED_SKIP) { | ||
| 672 | fhci_del_ed_list(fhci, ed); | ||
| 673 | ed->state = FHCI_ED_OPER; | ||
| 674 | } else if (ed->state == FHCI_ED_HALTED) { | ||
| 675 | urb_priv->state = URB_DEL; | ||
| 676 | ed->state = FHCI_ED_URB_DEL; | ||
| 677 | fhci_del_ed_list(fhci, ed); | ||
| 678 | ed->state = FHCI_ED_OPER; | ||
| 679 | } | ||
| 680 | |||
| 681 | td = fhci_remove_td_from_done_list(fhci->hc_list); | ||
| 682 | } | ||
| 683 | |||
| 684 | spin_unlock(&fhci->lock); | ||
| 685 | enable_irq(fhci->timer->irq); | ||
| 686 | enable_irq(fhci_to_hcd(fhci)->irq); | ||
| 687 | } | ||
| 688 | |||
| 689 | DECLARE_TASKLET(fhci_tasklet, process_done_list, 0); | ||
| 690 | |||
| 691 | /* transfer complted callback */ | ||
| 692 | u32 fhci_transfer_confirm_callback(struct fhci_hcd *fhci) | ||
| 693 | { | ||
| 694 | if (!fhci->process_done_task->state) | ||
| 695 | tasklet_schedule(fhci->process_done_task); | ||
| 696 | return 0; | ||
| 697 | } | ||
| 698 | |||
| 699 | /* | ||
| 700 | * adds urb to the endpoint descriptor list | ||
| 701 | * arguments: | ||
| 702 | * fhci data structure for the Low level host controller | ||
| 703 | * ep USB Host endpoint data structure | ||
| 704 | * urb USB request block data structure | ||
| 705 | */ | ||
| 706 | void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb) | ||
| 707 | { | ||
| 708 | struct ed *ed = urb->ep->hcpriv; | ||
| 709 | struct urb_priv *urb_priv = urb->hcpriv; | ||
| 710 | u32 data_len = urb->transfer_buffer_length; | ||
| 711 | int urb_state = 0; | ||
| 712 | int toggle = 0; | ||
| 713 | struct td *td; | ||
| 714 | u8 *data; | ||
| 715 | u16 cnt = 0; | ||
| 716 | |||
| 717 | if (ed == NULL) { | ||
| 718 | ed = fhci_get_empty_ed(fhci); | ||
| 719 | ed->dev_addr = usb_pipedevice(urb->pipe); | ||
| 720 | ed->ep_addr = usb_pipeendpoint(urb->pipe); | ||
| 721 | switch (usb_pipetype(urb->pipe)) { | ||
| 722 | case PIPE_CONTROL: | ||
| 723 | ed->mode = FHCI_TF_CTRL; | ||
| 724 | break; | ||
| 725 | case PIPE_BULK: | ||
| 726 | ed->mode = FHCI_TF_BULK; | ||
| 727 | break; | ||
| 728 | case PIPE_INTERRUPT: | ||
| 729 | ed->mode = FHCI_TF_INTR; | ||
| 730 | break; | ||
| 731 | case PIPE_ISOCHRONOUS: | ||
| 732 | ed->mode = FHCI_TF_ISO; | ||
| 733 | break; | ||
| 734 | default: | ||
| 735 | break; | ||
| 736 | } | ||
| 737 | ed->speed = (urb->dev->speed == USB_SPEED_LOW) ? | ||
| 738 | FHCI_LOW_SPEED : FHCI_FULL_SPEED; | ||
| 739 | ed->max_pkt_size = usb_maxpacket(urb->dev, | ||
| 740 | urb->pipe, usb_pipeout(urb->pipe)); | ||
| 741 | urb->ep->hcpriv = ed; | ||
| 742 | fhci_dbg(fhci, "new ep speed=%d max_pkt_size=%d\n", | ||
| 743 | ed->speed, ed->max_pkt_size); | ||
| 744 | } | ||
| 745 | |||
| 746 | /* for ISO transfer calculate start frame index */ | ||
| 747 | if (ed->mode == FHCI_TF_ISO && urb->transfer_flags & URB_ISO_ASAP) | ||
| 748 | urb->start_frame = ed->td_head ? ed->last_iso + 1 : | ||
| 749 | get_frame_num(fhci); | ||
| 750 | |||
| 751 | /* | ||
| 752 | * OHCI handles the DATA toggle itself,we just use the USB | ||
| 753 | * toggle bits | ||
| 754 | */ | ||
| 755 | if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), | ||
| 756 | usb_pipeout(urb->pipe))) | ||
| 757 | toggle = USB_TD_TOGGLE_CARRY; | ||
| 758 | else { | ||
| 759 | toggle = USB_TD_TOGGLE_DATA0; | ||
| 760 | usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), | ||
| 761 | usb_pipeout(urb->pipe), 1); | ||
| 762 | } | ||
| 763 | |||
| 764 | urb_priv->tds_cnt = 0; | ||
| 765 | urb_priv->ed = ed; | ||
| 766 | if (data_len > 0) | ||
| 767 | data = urb->transfer_buffer; | ||
| 768 | else | ||
| 769 | data = NULL; | ||
| 770 | |||
| 771 | switch (ed->mode) { | ||
| 772 | case FHCI_TF_BULK: | ||
| 773 | if (urb->transfer_flags & URB_ZERO_PACKET && | ||
| 774 | urb->transfer_buffer_length > 0 && | ||
| 775 | ((urb->transfer_buffer_length % | ||
| 776 | usb_maxpacket(urb->dev, urb->pipe, | ||
| 777 | usb_pipeout(urb->pipe))) == 0)) | ||
| 778 | urb_state = US_BULK0; | ||
| 779 | while (data_len > 4096) { | ||
| 780 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt, | ||
| 781 | usb_pipeout(urb->pipe) ? FHCI_TA_OUT : | ||
| 782 | FHCI_TA_IN, | ||
| 783 | cnt ? USB_TD_TOGGLE_CARRY : | ||
| 784 | toggle, | ||
| 785 | data, 4096, 0, 0, true); | ||
| 786 | data += 4096; | ||
| 787 | data_len -= 4096; | ||
| 788 | cnt++; | ||
| 789 | } | ||
| 790 | |||
| 791 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt, | ||
| 792 | usb_pipeout(urb->pipe) ? FHCI_TA_OUT : FHCI_TA_IN, | ||
| 793 | cnt ? USB_TD_TOGGLE_CARRY : toggle, | ||
| 794 | data, data_len, 0, 0, true); | ||
| 795 | cnt++; | ||
| 796 | |||
| 797 | if (urb->transfer_flags & URB_ZERO_PACKET && | ||
| 798 | cnt < urb_priv->num_of_tds) { | ||
| 799 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt, | ||
| 800 | usb_pipeout(urb->pipe) ? FHCI_TA_OUT : | ||
| 801 | FHCI_TA_IN, | ||
| 802 | USB_TD_TOGGLE_CARRY, NULL, 0, 0, 0, true); | ||
| 803 | cnt++; | ||
| 804 | } | ||
| 805 | break; | ||
| 806 | case FHCI_TF_INTR: | ||
| 807 | urb->start_frame = get_frame_num(fhci) + 1; | ||
| 808 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, | ||
| 809 | usb_pipeout(urb->pipe) ? FHCI_TA_OUT : FHCI_TA_IN, | ||
| 810 | USB_TD_TOGGLE_DATA0, data, data_len, | ||
| 811 | urb->interval, urb->start_frame, true); | ||
| 812 | break; | ||
| 813 | case FHCI_TF_CTRL: | ||
| 814 | ed->dev_addr = usb_pipedevice(urb->pipe); | ||
| 815 | ed->max_pkt_size = usb_maxpacket(urb->dev, urb->pipe, | ||
| 816 | usb_pipeout(urb->pipe)); | ||
| 817 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, FHCI_TA_SETUP, | ||
| 818 | USB_TD_TOGGLE_DATA0, urb->setup_packet, 8, 0, 0, true); | ||
| 819 | |||
| 820 | if (data_len > 0) { | ||
| 821 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, | ||
| 822 | usb_pipeout(urb->pipe) ? FHCI_TA_OUT : | ||
| 823 | FHCI_TA_IN, | ||
| 824 | USB_TD_TOGGLE_DATA1, data, data_len, 0, 0, | ||
| 825 | true); | ||
| 826 | } | ||
| 827 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt++, | ||
| 828 | usb_pipeout(urb->pipe) ? FHCI_TA_IN : FHCI_TA_OUT, | ||
| 829 | USB_TD_TOGGLE_DATA1, data, 0, 0, 0, true); | ||
| 830 | urb_state = US_CTRL_SETUP; | ||
| 831 | break; | ||
| 832 | case FHCI_TF_ISO: | ||
| 833 | for (cnt = 0; cnt < urb->number_of_packets; cnt++) { | ||
| 834 | u16 frame = urb->start_frame; | ||
| 835 | |||
| 836 | /* | ||
| 837 | * FIXME scheduling should handle frame counter | ||
| 838 | * roll-around ... exotic case (and OHCI has | ||
| 839 | * a 2^16 iso range, vs other HCs max of 2^10) | ||
| 840 | */ | ||
| 841 | frame += cnt * urb->interval; | ||
| 842 | frame &= 0x07ff; | ||
| 843 | td = fhci_td_fill(fhci, urb, urb_priv, ed, cnt, | ||
| 844 | usb_pipeout(urb->pipe) ? FHCI_TA_OUT : | ||
| 845 | FHCI_TA_IN, | ||
| 846 | USB_TD_TOGGLE_DATA0, | ||
| 847 | data + urb->iso_frame_desc[cnt].offset, | ||
| 848 | urb->iso_frame_desc[cnt].length, | ||
| 849 | urb->interval, frame, true); | ||
| 850 | } | ||
| 851 | break; | ||
| 852 | default: | ||
| 853 | break; | ||
| 854 | } | ||
| 855 | |||
| 856 | /* | ||
| 857 | * set the state of URB | ||
| 858 | * control pipe:3 states -- setup,data,status | ||
| 859 | * interrupt and bulk pipe:1 state -- data | ||
| 860 | */ | ||
| 861 | urb->pipe &= ~0x1f; | ||
| 862 | urb->pipe |= urb_state & 0x1f; | ||
| 863 | |||
| 864 | urb_priv->state = URB_INPROGRESS; | ||
| 865 | |||
| 866 | if (!ed->td_head) { | ||
| 867 | ed->state = FHCI_ED_OPER; | ||
| 868 | switch (ed->mode) { | ||
| 869 | case FHCI_TF_CTRL: | ||
| 870 | list_add(&ed->node, &fhci->hc_list->ctrl_list); | ||
| 871 | break; | ||
| 872 | case FHCI_TF_BULK: | ||
| 873 | list_add(&ed->node, &fhci->hc_list->bulk_list); | ||
| 874 | break; | ||
| 875 | case FHCI_TF_INTR: | ||
| 876 | list_add(&ed->node, &fhci->hc_list->intr_list); | ||
| 877 | break; | ||
| 878 | case FHCI_TF_ISO: | ||
| 879 | list_add(&ed->node, &fhci->hc_list->iso_list); | ||
| 880 | break; | ||
| 881 | default: | ||
| 882 | break; | ||
| 883 | } | ||
| 884 | } | ||
| 885 | |||
| 886 | fhci_add_tds_to_ed(ed, urb_priv->tds, urb_priv->num_of_tds); | ||
| 887 | fhci->active_urbs++; | ||
| 888 | } | ||
diff --git a/drivers/usb/host/fhci-tds.c b/drivers/usb/host/fhci-tds.c new file mode 100644 index 000000000000..b40332290319 --- /dev/null +++ b/drivers/usb/host/fhci-tds.c | |||
| @@ -0,0 +1,626 @@ | |||
| 1 | /* | ||
| 2 | * Freescale QUICC Engine USB Host Controller Driver | ||
| 3 | * | ||
| 4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
| 5 | * Shlomi Gridish <gridish@freescale.com> | ||
| 6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
| 7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
| 8 | * Peter Barada <peterb@logicpd.com> | ||
| 9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
| 10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License as published by the | ||
| 14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 15 | * option) any later version. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/types.h> | ||
| 20 | #include <linux/errno.h> | ||
| 21 | #include <linux/list.h> | ||
| 22 | #include <linux/io.h> | ||
| 23 | #include <linux/usb.h> | ||
| 24 | #include "../core/hcd.h" | ||
| 25 | #include "fhci.h" | ||
| 26 | |||
| 27 | #define DUMMY_BD_BUFFER 0xdeadbeef | ||
| 28 | #define DUMMY2_BD_BUFFER 0xbaadf00d | ||
| 29 | |||
| 30 | /* Transaction Descriptors bits */ | ||
| 31 | #define TD_R 0x8000 /* ready bit */ | ||
| 32 | #define TD_W 0x2000 /* wrap bit */ | ||
| 33 | #define TD_I 0x1000 /* interrupt on completion */ | ||
| 34 | #define TD_L 0x0800 /* last */ | ||
| 35 | #define TD_TC 0x0400 /* transmit CRC */ | ||
| 36 | #define TD_CNF 0x0200 /* CNF - Must be always 1 */ | ||
| 37 | #define TD_LSP 0x0100 /* Low-speed transaction */ | ||
| 38 | #define TD_PID 0x00c0 /* packet id */ | ||
| 39 | #define TD_RXER 0x0020 /* Rx error or not */ | ||
| 40 | |||
| 41 | #define TD_NAK 0x0010 /* No ack. */ | ||
| 42 | #define TD_STAL 0x0008 /* Stall recieved */ | ||
| 43 | #define TD_TO 0x0004 /* time out */ | ||
| 44 | #define TD_UN 0x0002 /* underrun */ | ||
| 45 | #define TD_NO 0x0010 /* Rx Non Octet Aligned Packet */ | ||
| 46 | #define TD_AB 0x0008 /* Frame Aborted */ | ||
| 47 | #define TD_CR 0x0004 /* CRC Error */ | ||
| 48 | #define TD_OV 0x0002 /* Overrun */ | ||
| 49 | #define TD_BOV 0x0001 /* Buffer Overrun */ | ||
| 50 | |||
| 51 | #define TD_ERRORS (TD_NAK | TD_STAL | TD_TO | TD_UN | \ | ||
| 52 | TD_NO | TD_AB | TD_CR | TD_OV | TD_BOV) | ||
| 53 | |||
| 54 | #define TD_PID_DATA0 0x0080 /* Data 0 toggle */ | ||
| 55 | #define TD_PID_DATA1 0x00c0 /* Data 1 toggle */ | ||
| 56 | #define TD_PID_TOGGLE 0x00c0 /* Data 0/1 toggle mask */ | ||
| 57 | |||
| 58 | #define TD_TOK_SETUP 0x0000 | ||
| 59 | #define TD_TOK_OUT 0x4000 | ||
| 60 | #define TD_TOK_IN 0x8000 | ||
| 61 | #define TD_ISO 0x1000 | ||
| 62 | #define TD_ENDP 0x0780 | ||
| 63 | #define TD_ADDR 0x007f | ||
| 64 | |||
| 65 | #define TD_ENDP_SHIFT 7 | ||
| 66 | |||
| 67 | struct usb_td { | ||
| 68 | __be16 status; | ||
| 69 | __be16 length; | ||
| 70 | __be32 buf_ptr; | ||
| 71 | __be16 extra; | ||
| 72 | __be16 reserved; | ||
| 73 | }; | ||
| 74 | |||
| 75 | static struct usb_td __iomem *next_bd(struct usb_td __iomem *base, | ||
| 76 | struct usb_td __iomem *td, | ||
| 77 | u16 status) | ||
| 78 | { | ||
| 79 | if (status & TD_W) | ||
| 80 | return base; | ||
| 81 | else | ||
| 82 | return ++td; | ||
| 83 | } | ||
| 84 | |||
| 85 | void fhci_push_dummy_bd(struct endpoint *ep) | ||
| 86 | { | ||
| 87 | if (ep->already_pushed_dummy_bd == false) { | ||
| 88 | u16 td_status = in_be16(&ep->empty_td->status); | ||
| 89 | |||
| 90 | out_be32(&ep->empty_td->buf_ptr, DUMMY_BD_BUFFER); | ||
| 91 | /* get the next TD in the ring */ | ||
| 92 | ep->empty_td = next_bd(ep->td_base, ep->empty_td, td_status); | ||
| 93 | ep->already_pushed_dummy_bd = true; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | /* destroy an USB endpoint */ | ||
| 98 | void fhci_ep0_free(struct fhci_usb *usb) | ||
| 99 | { | ||
| 100 | struct endpoint *ep; | ||
| 101 | int size; | ||
| 102 | |||
| 103 | ep = usb->ep0; | ||
| 104 | if (ep) { | ||
| 105 | if (ep->td_base) | ||
| 106 | cpm_muram_free(cpm_muram_offset(ep->td_base)); | ||
| 107 | |||
| 108 | if (ep->conf_frame_Q) { | ||
| 109 | size = cq_howmany(ep->conf_frame_Q); | ||
| 110 | for (; size; size--) { | ||
| 111 | struct packet *pkt = cq_get(ep->conf_frame_Q); | ||
| 112 | |||
| 113 | kfree(pkt); | ||
| 114 | } | ||
| 115 | cq_delete(ep->conf_frame_Q); | ||
| 116 | } | ||
| 117 | |||
| 118 | if (ep->empty_frame_Q) { | ||
| 119 | size = cq_howmany(ep->empty_frame_Q); | ||
| 120 | for (; size; size--) { | ||
| 121 | struct packet *pkt = cq_get(ep->empty_frame_Q); | ||
| 122 | |||
| 123 | kfree(pkt); | ||
| 124 | } | ||
| 125 | cq_delete(ep->empty_frame_Q); | ||
| 126 | } | ||
| 127 | |||
| 128 | if (ep->dummy_packets_Q) { | ||
| 129 | size = cq_howmany(ep->dummy_packets_Q); | ||
| 130 | for (; size; size--) { | ||
| 131 | u8 *buff = cq_get(ep->dummy_packets_Q); | ||
| 132 | |||
| 133 | kfree(buff); | ||
| 134 | } | ||
| 135 | cq_delete(ep->dummy_packets_Q); | ||
| 136 | } | ||
| 137 | |||
| 138 | kfree(ep); | ||
| 139 | usb->ep0 = NULL; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | /* | ||
| 144 | * create the endpoint structure | ||
| 145 | * | ||
| 146 | * arguments: | ||
| 147 | * usb A pointer to the data structure of the USB | ||
| 148 | * data_mem The data memory partition(BUS) | ||
| 149 | * ring_len TD ring length | ||
| 150 | */ | ||
| 151 | u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem, | ||
| 152 | u32 ring_len) | ||
| 153 | { | ||
| 154 | struct endpoint *ep; | ||
| 155 | struct usb_td __iomem *td; | ||
| 156 | unsigned long ep_offset; | ||
| 157 | char *err_for = "enpoint PRAM"; | ||
| 158 | int ep_mem_size; | ||
| 159 | u32 i; | ||
| 160 | |||
| 161 | /* we need at least 3 TDs in the ring */ | ||
| 162 | if (!(ring_len > 2)) { | ||
| 163 | fhci_err(usb->fhci, "illegal TD ring length parameters\n"); | ||
| 164 | return -EINVAL; | ||
| 165 | } | ||
| 166 | |||
| 167 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); | ||
| 168 | if (!ep) | ||
| 169 | return -ENOMEM; | ||
| 170 | |||
| 171 | ep_mem_size = ring_len * sizeof(*td) + sizeof(struct fhci_ep_pram); | ||
| 172 | ep_offset = cpm_muram_alloc(ep_mem_size, 32); | ||
| 173 | if (IS_ERR_VALUE(ep_offset)) | ||
| 174 | goto err; | ||
| 175 | ep->td_base = cpm_muram_addr(ep_offset); | ||
| 176 | |||
| 177 | /* zero all queue pointers */ | ||
| 178 | ep->conf_frame_Q = cq_new(ring_len + 2); | ||
| 179 | ep->empty_frame_Q = cq_new(ring_len + 2); | ||
| 180 | ep->dummy_packets_Q = cq_new(ring_len + 2); | ||
| 181 | if (!ep->conf_frame_Q || !ep->empty_frame_Q || !ep->dummy_packets_Q) { | ||
| 182 | err_for = "frame_queues"; | ||
| 183 | goto err; | ||
| 184 | } | ||
| 185 | |||
| 186 | for (i = 0; i < (ring_len + 1); i++) { | ||
| 187 | struct packet *pkt; | ||
| 188 | u8 *buff; | ||
| 189 | |||
| 190 | pkt = kmalloc(sizeof(*pkt), GFP_KERNEL); | ||
| 191 | if (!pkt) { | ||
| 192 | err_for = "frame"; | ||
| 193 | goto err; | ||
| 194 | } | ||
| 195 | |||
| 196 | buff = kmalloc(1028 * sizeof(*buff), GFP_KERNEL); | ||
| 197 | if (!buff) { | ||
| 198 | kfree(pkt); | ||
| 199 | err_for = "buffer"; | ||
| 200 | goto err; | ||
| 201 | } | ||
| 202 | cq_put(ep->empty_frame_Q, pkt); | ||
| 203 | cq_put(ep->dummy_packets_Q, buff); | ||
| 204 | } | ||
| 205 | |||
| 206 | /* we put the endpoint parameter RAM right behind the TD ring */ | ||
| 207 | ep->ep_pram_ptr = (void __iomem *)ep->td_base + sizeof(*td) * ring_len; | ||
| 208 | |||
| 209 | ep->conf_td = ep->td_base; | ||
| 210 | ep->empty_td = ep->td_base; | ||
| 211 | |||
| 212 | ep->already_pushed_dummy_bd = false; | ||
| 213 | |||
| 214 | /* initialize tds */ | ||
| 215 | td = ep->td_base; | ||
| 216 | for (i = 0; i < ring_len; i++) { | ||
| 217 | out_be32(&td->buf_ptr, 0); | ||
| 218 | out_be16(&td->status, 0); | ||
| 219 | out_be16(&td->length, 0); | ||
| 220 | out_be16(&td->extra, 0); | ||
| 221 | td++; | ||
| 222 | } | ||
| 223 | td--; | ||
| 224 | out_be16(&td->status, TD_W); /* for last TD set Wrap bit */ | ||
| 225 | out_be16(&td->length, 0); | ||
| 226 | |||
| 227 | /* endpoint structure has been created */ | ||
| 228 | usb->ep0 = ep; | ||
| 229 | |||
| 230 | return 0; | ||
| 231 | err: | ||
| 232 | fhci_ep0_free(usb); | ||
| 233 | kfree(ep); | ||
| 234 | fhci_err(usb->fhci, "no memory for the %s\n", err_for); | ||
| 235 | return -ENOMEM; | ||
| 236 | } | ||
| 237 | |||
| 238 | /* | ||
| 239 | * initialize the endpoint register according to the given parameters | ||
| 240 | * | ||
| 241 | * artuments: | ||
| 242 | * usb A pointer to the data strucutre of the USB | ||
| 243 | * ep A pointer to the endpoint structre | ||
| 244 | * data_mem The data memory partition(BUS) | ||
| 245 | */ | ||
| 246 | void fhci_init_ep_registers(struct fhci_usb *usb, struct endpoint *ep, | ||
| 247 | enum fhci_mem_alloc data_mem) | ||
| 248 | { | ||
| 249 | u8 rt; | ||
| 250 | |||
| 251 | /* set the endpoint registers according to the endpoint */ | ||
| 252 | out_be16(&usb->fhci->regs->usb_ep[0], | ||
| 253 | USB_TRANS_CTR | USB_EP_MF | USB_EP_RTE); | ||
| 254 | out_be16(&usb->fhci->pram->ep_ptr[0], | ||
| 255 | cpm_muram_offset(ep->ep_pram_ptr)); | ||
| 256 | |||
| 257 | rt = (BUS_MODE_BO_BE | BUS_MODE_GBL); | ||
| 258 | #ifdef MULTI_DATA_BUS | ||
| 259 | if (data_mem == MEM_SECONDARY) | ||
| 260 | rt |= BUS_MODE_DTB; | ||
| 261 | #endif | ||
| 262 | out_8(&ep->ep_pram_ptr->rx_func_code, rt); | ||
| 263 | out_8(&ep->ep_pram_ptr->tx_func_code, rt); | ||
| 264 | out_be16(&ep->ep_pram_ptr->rx_buff_len, 1028); | ||
| 265 | out_be16(&ep->ep_pram_ptr->rx_base, 0); | ||
| 266 | out_be16(&ep->ep_pram_ptr->tx_base, cpm_muram_offset(ep->td_base)); | ||
| 267 | out_be16(&ep->ep_pram_ptr->rx_bd_ptr, 0); | ||
| 268 | out_be16(&ep->ep_pram_ptr->tx_bd_ptr, cpm_muram_offset(ep->td_base)); | ||
| 269 | out_be32(&ep->ep_pram_ptr->tx_state, 0); | ||
| 270 | } | ||
| 271 | |||
| 272 | /* | ||
| 273 | * Collect the submitted frames and inform the application about them | ||
| 274 | * It is also prepearing the TDs for new frames. If the Tx interrupts | ||
| 275 | * are diabled, the application should call that routine to get | ||
| 276 | * confirmation about the submitted frames. Otherwise, the routine is | ||
| 277 | * called frome the interrupt service routine during the Tx interrupt. | ||
| 278 | * In that case the application is informed by calling the application | ||
| 279 | * specific 'fhci_transaction_confirm' routine | ||
| 280 | */ | ||
| 281 | static void fhci_td_transaction_confirm(struct fhci_usb *usb) | ||
| 282 | { | ||
| 283 | struct endpoint *ep = usb->ep0; | ||
| 284 | struct packet *pkt; | ||
| 285 | struct usb_td __iomem *td; | ||
| 286 | u16 extra_data; | ||
| 287 | u16 td_status; | ||
| 288 | u16 td_length; | ||
| 289 | u32 buf; | ||
| 290 | |||
| 291 | /* | ||
| 292 | * collect transmitted BDs from the chip. The routine clears all BDs | ||
| 293 | * with R bit = 0 and the pointer to data buffer is not NULL, that is | ||
| 294 | * BDs which point to the transmitted data buffer | ||
| 295 | */ | ||
| 296 | while (1) { | ||
| 297 | td = ep->conf_td; | ||
| 298 | td_status = in_be16(&td->status); | ||
| 299 | td_length = in_be16(&td->length); | ||
| 300 | buf = in_be32(&td->buf_ptr); | ||
| 301 | extra_data = in_be16(&td->extra); | ||
| 302 | |||
| 303 | /* check if the TD is empty */ | ||
| 304 | if (!(!(td_status & TD_R) && ((td_status & ~TD_W) || buf))) | ||
| 305 | break; | ||
| 306 | /* check if it is a dummy buffer */ | ||
| 307 | else if ((buf == DUMMY_BD_BUFFER) && !(td_status & ~TD_W)) | ||
| 308 | break; | ||
| 309 | |||
| 310 | /* mark TD as empty */ | ||
| 311 | clrbits16(&td->status, ~TD_W); | ||
| 312 | out_be16(&td->length, 0); | ||
| 313 | out_be32(&td->buf_ptr, 0); | ||
| 314 | out_be16(&td->extra, 0); | ||
| 315 | /* advance the TD pointer */ | ||
| 316 | ep->conf_td = next_bd(ep->td_base, ep->conf_td, td_status); | ||
| 317 | |||
| 318 | /* check if it is a dummy buffer(type2) */ | ||
| 319 | if ((buf == DUMMY2_BD_BUFFER) && !(td_status & ~TD_W)) | ||
| 320 | continue; | ||
| 321 | |||
| 322 | pkt = cq_get(ep->conf_frame_Q); | ||
| 323 | if (!pkt) | ||
| 324 | fhci_err(usb->fhci, "no frame to confirm\n"); | ||
| 325 | |||
| 326 | if (td_status & TD_ERRORS) { | ||
| 327 | if (td_status & TD_RXER) { | ||
| 328 | if (td_status & TD_CR) | ||
| 329 | pkt->status = USB_TD_RX_ER_CRC; | ||
| 330 | else if (td_status & TD_AB) | ||
| 331 | pkt->status = USB_TD_RX_ER_BITSTUFF; | ||
| 332 | else if (td_status & TD_OV) | ||
| 333 | pkt->status = USB_TD_RX_ER_OVERUN; | ||
| 334 | else if (td_status & TD_BOV) | ||
| 335 | pkt->status = USB_TD_RX_DATA_OVERUN; | ||
| 336 | else if (td_status & TD_NO) | ||
| 337 | pkt->status = USB_TD_RX_ER_NONOCT; | ||
| 338 | else | ||
| 339 | fhci_err(usb->fhci, "illegal error " | ||
| 340 | "occured\n"); | ||
| 341 | } else if (td_status & TD_NAK) | ||
| 342 | pkt->status = USB_TD_TX_ER_NAK; | ||
| 343 | else if (td_status & TD_TO) | ||
| 344 | pkt->status = USB_TD_TX_ER_TIMEOUT; | ||
| 345 | else if (td_status & TD_UN) | ||
| 346 | pkt->status = USB_TD_TX_ER_UNDERUN; | ||
| 347 | else if (td_status & TD_STAL) | ||
| 348 | pkt->status = USB_TD_TX_ER_STALL; | ||
| 349 | else | ||
| 350 | fhci_err(usb->fhci, "illegal error occured\n"); | ||
| 351 | } else if ((extra_data & TD_TOK_IN) && | ||
| 352 | pkt->len > td_length - CRC_SIZE) { | ||
| 353 | pkt->status = USB_TD_RX_DATA_UNDERUN; | ||
| 354 | } | ||
| 355 | |||
| 356 | if (extra_data & TD_TOK_IN) | ||
| 357 | pkt->len = td_length - CRC_SIZE; | ||
| 358 | else if (pkt->info & PKT_ZLP) | ||
| 359 | pkt->len = 0; | ||
| 360 | else | ||
| 361 | pkt->len = td_length; | ||
| 362 | |||
| 363 | fhci_transaction_confirm(usb, pkt); | ||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 367 | /* | ||
| 368 | * Submitting a data frame to a specified endpoint of a USB device | ||
| 369 | * The frame is put in the driver's transmit queue for this endpoint | ||
| 370 | * | ||
| 371 | * Arguments: | ||
| 372 | * usb A pointer to the USB structure | ||
| 373 | * pkt A pointer to the user frame structure | ||
| 374 | * trans_type Transaction tyep - IN,OUT or SETUP | ||
| 375 | * dest_addr Device address - 0~127 | ||
| 376 | * dest_ep Endpoint number of the device - 0~16 | ||
| 377 | * trans_mode Pipe type - ISO,Interrupt,bulk or control | ||
| 378 | * dest_speed USB speed - Low speed or FULL speed | ||
| 379 | * data_toggle Data sequence toggle - 0 or 1 | ||
| 380 | */ | ||
| 381 | u32 fhci_host_transaction(struct fhci_usb *usb, | ||
| 382 | struct packet *pkt, | ||
| 383 | enum fhci_ta_type trans_type, | ||
| 384 | u8 dest_addr, | ||
| 385 | u8 dest_ep, | ||
| 386 | enum fhci_tf_mode trans_mode, | ||
| 387 | enum fhci_speed dest_speed, u8 data_toggle) | ||
| 388 | { | ||
| 389 | struct endpoint *ep = usb->ep0; | ||
| 390 | struct usb_td __iomem *td; | ||
| 391 | u16 extra_data; | ||
| 392 | u16 td_status; | ||
| 393 | |||
| 394 | fhci_usb_disable_interrupt(usb); | ||
| 395 | /* start from the next BD that should be filled */ | ||
| 396 | td = ep->empty_td; | ||
| 397 | td_status = in_be16(&td->status); | ||
| 398 | |||
| 399 | if (td_status & TD_R && in_be16(&td->length)) { | ||
| 400 | /* if the TD is not free */ | ||
| 401 | fhci_usb_enable_interrupt(usb); | ||
| 402 | return -1; | ||
| 403 | } | ||
| 404 | |||
| 405 | /* get the next TD in the ring */ | ||
| 406 | ep->empty_td = next_bd(ep->td_base, ep->empty_td, td_status); | ||
| 407 | fhci_usb_enable_interrupt(usb); | ||
| 408 | pkt->priv_data = td; | ||
| 409 | out_be32(&td->buf_ptr, virt_to_phys(pkt->data)); | ||
| 410 | /* sets up transaction parameters - addr,endp,dir,and type */ | ||
| 411 | extra_data = (dest_ep << TD_ENDP_SHIFT) | dest_addr; | ||
| 412 | switch (trans_type) { | ||
| 413 | case FHCI_TA_IN: | ||
| 414 | extra_data |= TD_TOK_IN; | ||
| 415 | break; | ||
| 416 | case FHCI_TA_OUT: | ||
| 417 | extra_data |= TD_TOK_OUT; | ||
| 418 | break; | ||
| 419 | case FHCI_TA_SETUP: | ||
| 420 | extra_data |= TD_TOK_SETUP; | ||
| 421 | break; | ||
| 422 | } | ||
| 423 | if (trans_mode == FHCI_TF_ISO) | ||
| 424 | extra_data |= TD_ISO; | ||
| 425 | out_be16(&td->extra, extra_data); | ||
| 426 | |||
| 427 | /* sets up the buffer descriptor */ | ||
| 428 | td_status = ((td_status & TD_W) | TD_R | TD_L | TD_I | TD_CNF); | ||
| 429 | if (!(pkt->info & PKT_NO_CRC)) | ||
| 430 | td_status |= TD_TC; | ||
| 431 | |||
| 432 | switch (trans_type) { | ||
| 433 | case FHCI_TA_IN: | ||
| 434 | if (data_toggle) | ||
| 435 | pkt->info |= PKT_PID_DATA1; | ||
| 436 | else | ||
| 437 | pkt->info |= PKT_PID_DATA0; | ||
| 438 | break; | ||
| 439 | default: | ||
| 440 | if (data_toggle) { | ||
| 441 | td_status |= TD_PID_DATA1; | ||
| 442 | pkt->info |= PKT_PID_DATA1; | ||
| 443 | } else { | ||
| 444 | td_status |= TD_PID_DATA0; | ||
| 445 | pkt->info |= PKT_PID_DATA0; | ||
| 446 | } | ||
| 447 | break; | ||
| 448 | } | ||
| 449 | |||
| 450 | if ((dest_speed == FHCI_LOW_SPEED) && | ||
| 451 | (usb->port_status == FHCI_PORT_FULL)) | ||
| 452 | td_status |= TD_LSP; | ||
| 453 | |||
| 454 | out_be16(&td->status, td_status); | ||
| 455 | |||
| 456 | /* set up buffer length */ | ||
| 457 | if (trans_type == FHCI_TA_IN) | ||
| 458 | out_be16(&td->length, pkt->len + CRC_SIZE); | ||
| 459 | else | ||
| 460 | out_be16(&td->length, pkt->len); | ||
| 461 | |||
| 462 | /* put the frame to the confirmation queue */ | ||
| 463 | cq_put(ep->conf_frame_Q, pkt); | ||
| 464 | |||
| 465 | if (cq_howmany(ep->conf_frame_Q) == 1) | ||
| 466 | out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO); | ||
| 467 | |||
| 468 | return 0; | ||
| 469 | } | ||
| 470 | |||
| 471 | /* Reset the Tx BD ring */ | ||
| 472 | void fhci_flush_bds(struct fhci_usb *usb) | ||
| 473 | { | ||
| 474 | u16 extra_data; | ||
| 475 | u16 td_status; | ||
| 476 | u32 buf; | ||
| 477 | struct usb_td __iomem *td; | ||
| 478 | struct endpoint *ep = usb->ep0; | ||
| 479 | |||
| 480 | td = ep->td_base; | ||
| 481 | while (1) { | ||
| 482 | td_status = in_be16(&td->status); | ||
| 483 | buf = in_be32(&td->buf_ptr); | ||
| 484 | extra_data = in_be16(&td->extra); | ||
| 485 | |||
| 486 | /* if the TD is not empty - we'll confirm it as Timeout */ | ||
| 487 | if (td_status & TD_R) | ||
| 488 | out_be16(&td->status, (td_status & ~TD_R) | TD_TO); | ||
| 489 | /* if this TD is dummy - let's skip this TD */ | ||
| 490 | else if (in_be32(&td->buf_ptr) == DUMMY_BD_BUFFER) | ||
| 491 | out_be32(&td->buf_ptr, DUMMY2_BD_BUFFER); | ||
| 492 | /* if this is the last TD - break */ | ||
| 493 | if (td_status & TD_W) | ||
| 494 | break; | ||
| 495 | |||
| 496 | td++; | ||
| 497 | } | ||
| 498 | |||
| 499 | fhci_td_transaction_confirm(usb); | ||
| 500 | |||
| 501 | td = ep->td_base; | ||
| 502 | do { | ||
| 503 | out_be16(&td->status, 0); | ||
| 504 | out_be16(&td->length, 0); | ||
| 505 | out_be32(&td->buf_ptr, 0); | ||
| 506 | out_be16(&td->extra, 0); | ||
| 507 | td++; | ||
| 508 | } while (!(in_be16(&td->status) & TD_W)); | ||
| 509 | out_be16(&td->status, TD_W); /* for last TD set Wrap bit */ | ||
| 510 | out_be16(&td->length, 0); | ||
| 511 | out_be32(&td->buf_ptr, 0); | ||
| 512 | out_be16(&td->extra, 0); | ||
| 513 | |||
| 514 | out_be16(&ep->ep_pram_ptr->tx_bd_ptr, | ||
| 515 | in_be16(&ep->ep_pram_ptr->tx_base)); | ||
| 516 | out_be32(&ep->ep_pram_ptr->tx_state, 0); | ||
| 517 | out_be16(&ep->ep_pram_ptr->tx_cnt, 0); | ||
| 518 | ep->empty_td = ep->td_base; | ||
| 519 | ep->conf_td = ep->td_base; | ||
| 520 | } | ||
| 521 | |||
| 522 | /* | ||
| 523 | * Flush all transmitted packets from TDs in the actual frame. | ||
| 524 | * This routine is called when something wrong with the controller and | ||
| 525 | * we want to get rid of the actual frame and start again next frame | ||
| 526 | */ | ||
| 527 | void fhci_flush_actual_frame(struct fhci_usb *usb) | ||
| 528 | { | ||
| 529 | u8 mode; | ||
| 530 | u16 tb_ptr; | ||
| 531 | u16 extra_data; | ||
| 532 | u16 td_status; | ||
| 533 | u32 buf_ptr; | ||
| 534 | struct usb_td __iomem *td; | ||
| 535 | struct endpoint *ep = usb->ep0; | ||
| 536 | |||
| 537 | /* disable the USB controller */ | ||
| 538 | mode = in_8(&usb->fhci->regs->usb_mod); | ||
| 539 | out_8(&usb->fhci->regs->usb_mod, mode & ~USB_MODE_EN); | ||
| 540 | |||
| 541 | tb_ptr = in_be16(&ep->ep_pram_ptr->tx_bd_ptr); | ||
| 542 | td = cpm_muram_addr(tb_ptr); | ||
| 543 | td_status = in_be16(&td->status); | ||
| 544 | buf_ptr = in_be32(&td->buf_ptr); | ||
| 545 | extra_data = in_be16(&td->extra); | ||
| 546 | do { | ||
| 547 | if (td_status & TD_R) { | ||
| 548 | out_be16(&td->status, (td_status & ~TD_R) | TD_TO); | ||
| 549 | } else { | ||
| 550 | out_be32(&td->buf_ptr, 0); | ||
| 551 | ep->already_pushed_dummy_bd = false; | ||
| 552 | break; | ||
| 553 | } | ||
| 554 | |||
| 555 | /* advance the TD pointer */ | ||
| 556 | td = next_bd(ep->td_base, td, td_status); | ||
| 557 | td_status = in_be16(&td->status); | ||
| 558 | buf_ptr = in_be32(&td->buf_ptr); | ||
| 559 | extra_data = in_be16(&td->extra); | ||
| 560 | } while ((td_status & TD_R) || buf_ptr); | ||
| 561 | |||
| 562 | fhci_td_transaction_confirm(usb); | ||
| 563 | |||
| 564 | out_be16(&ep->ep_pram_ptr->tx_bd_ptr, | ||
| 565 | in_be16(&ep->ep_pram_ptr->tx_base)); | ||
| 566 | out_be32(&ep->ep_pram_ptr->tx_state, 0); | ||
| 567 | out_be16(&ep->ep_pram_ptr->tx_cnt, 0); | ||
| 568 | ep->empty_td = ep->td_base; | ||
| 569 | ep->conf_td = ep->td_base; | ||
| 570 | |||
| 571 | usb->actual_frame->frame_status = FRAME_TIMER_END_TRANSMISSION; | ||
| 572 | |||
| 573 | /* reset the event register */ | ||
| 574 | out_be16(&usb->fhci->regs->usb_event, 0xffff); | ||
| 575 | /* enable the USB controller */ | ||
| 576 | out_8(&usb->fhci->regs->usb_mod, mode | USB_MODE_EN); | ||
| 577 | } | ||
| 578 | |||
| 579 | /* handles Tx confirm and Tx error interrupt */ | ||
| 580 | void fhci_tx_conf_interrupt(struct fhci_usb *usb) | ||
| 581 | { | ||
| 582 | fhci_td_transaction_confirm(usb); | ||
| 583 | |||
| 584 | /* | ||
| 585 | * Schedule another transaction to this frame only if we have | ||
| 586 | * already confirmed all transaction in the frame. | ||
| 587 | */ | ||
| 588 | if (((fhci_get_sof_timer_count(usb) < usb->max_frame_usage) || | ||
| 589 | (usb->actual_frame->frame_status & FRAME_END_TRANSMISSION)) && | ||
| 590 | (list_empty(&usb->actual_frame->tds_list))) | ||
| 591 | fhci_schedule_transactions(usb); | ||
| 592 | } | ||
| 593 | |||
| 594 | void fhci_host_transmit_actual_frame(struct fhci_usb *usb) | ||
| 595 | { | ||
| 596 | u16 tb_ptr; | ||
| 597 | u16 td_status; | ||
| 598 | struct usb_td __iomem *td; | ||
| 599 | struct endpoint *ep = usb->ep0; | ||
| 600 | |||
| 601 | tb_ptr = in_be16(&ep->ep_pram_ptr->tx_bd_ptr); | ||
| 602 | td = cpm_muram_addr(tb_ptr); | ||
| 603 | |||
| 604 | if (in_be32(&td->buf_ptr) == DUMMY_BD_BUFFER) { | ||
| 605 | struct usb_td __iomem *old_td = td; | ||
| 606 | |||
| 607 | ep->already_pushed_dummy_bd = false; | ||
| 608 | td_status = in_be16(&td->status); | ||
| 609 | /* gets the next TD in the ring */ | ||
| 610 | td = next_bd(ep->td_base, td, td_status); | ||
| 611 | tb_ptr = cpm_muram_offset(td); | ||
| 612 | out_be16(&ep->ep_pram_ptr->tx_bd_ptr, tb_ptr); | ||
| 613 | |||
| 614 | /* start transmit only if we have something in the TDs */ | ||
| 615 | if (in_be16(&td->status) & TD_R) | ||
| 616 | out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO); | ||
| 617 | |||
| 618 | if (in_be32(&ep->conf_td->buf_ptr) == DUMMY_BD_BUFFER) { | ||
| 619 | out_be32(&old_td->buf_ptr, 0); | ||
| 620 | ep->conf_td = next_bd(ep->td_base, ep->conf_td, | ||
| 621 | td_status); | ||
| 622 | } else { | ||
| 623 | out_be32(&old_td->buf_ptr, DUMMY2_BD_BUFFER); | ||
| 624 | } | ||
| 625 | } | ||
| 626 | } | ||
diff --git a/drivers/usb/host/fhci.h b/drivers/usb/host/fhci.h new file mode 100644 index 000000000000..7116284ed21a --- /dev/null +++ b/drivers/usb/host/fhci.h | |||
| @@ -0,0 +1,607 @@ | |||
| 1 | /* | ||
| 2 | * Freescale QUICC Engine USB Host Controller Driver | ||
| 3 | * | ||
| 4 | * Copyright (c) Freescale Semicondutor, Inc. 2006. | ||
| 5 | * Shlomi Gridish <gridish@freescale.com> | ||
| 6 | * Jerry Huang <Chang-Ming.Huang@freescale.com> | ||
| 7 | * Copyright (c) Logic Product Development, Inc. 2007 | ||
| 8 | * Peter Barada <peterb@logicpd.com> | ||
| 9 | * Copyright (c) MontaVista Software, Inc. 2008. | ||
| 10 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License as published by the | ||
| 14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 15 | * option) any later version. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef __FHCI_H | ||
| 19 | #define __FHCI_H | ||
| 20 | |||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/types.h> | ||
| 23 | #include <linux/spinlock.h> | ||
| 24 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/kfifo.h> | ||
| 26 | #include <linux/io.h> | ||
| 27 | #include <linux/usb.h> | ||
| 28 | #include <asm/qe.h> | ||
| 29 | #include "../core/hcd.h" | ||
| 30 | |||
| 31 | #define USB_CLOCK 48000000 | ||
| 32 | |||
| 33 | #define FHCI_PRAM_SIZE 0x100 | ||
| 34 | |||
| 35 | #define MAX_EDS 32 | ||
| 36 | #define MAX_TDS 32 | ||
| 37 | |||
| 38 | |||
| 39 | /* CRC16 field size */ | ||
| 40 | #define CRC_SIZE 2 | ||
| 41 | |||
| 42 | /* USB protocol overhead for each frame transmitted from the host */ | ||
| 43 | #define PROTOCOL_OVERHEAD 7 | ||
| 44 | |||
| 45 | /* Packet structure, info field */ | ||
| 46 | #define PKT_PID_DATA0 0x80000000 /* PID - Data toggle zero */ | ||
| 47 | #define PKT_PID_DATA1 0x40000000 /* PID - Data toggle one */ | ||
| 48 | #define PKT_PID_SETUP 0x20000000 /* PID - Setup bit */ | ||
| 49 | #define PKT_SETUP_STATUS 0x10000000 /* Setup status bit */ | ||
| 50 | #define PKT_SETADDR_STATUS 0x08000000 /* Set address status bit */ | ||
| 51 | #define PKT_SET_HOST_LAST 0x04000000 /* Last data packet */ | ||
| 52 | #define PKT_HOST_DATA 0x02000000 /* Data packet */ | ||
| 53 | #define PKT_FIRST_IN_FRAME 0x01000000 /* First packet in the frame */ | ||
| 54 | #define PKT_TOKEN_FRAME 0x00800000 /* Token packet */ | ||
| 55 | #define PKT_ZLP 0x00400000 /* Zero length packet */ | ||
| 56 | #define PKT_IN_TOKEN_FRAME 0x00200000 /* IN token packet */ | ||
| 57 | #define PKT_OUT_TOKEN_FRAME 0x00100000 /* OUT token packet */ | ||
| 58 | #define PKT_SETUP_TOKEN_FRAME 0x00080000 /* SETUP token packet */ | ||
| 59 | #define PKT_STALL_FRAME 0x00040000 /* STALL packet */ | ||
| 60 | #define PKT_NACK_FRAME 0x00020000 /* NACK packet */ | ||
| 61 | #define PKT_NO_PID 0x00010000 /* No PID */ | ||
| 62 | #define PKT_NO_CRC 0x00008000 /* don't append CRC */ | ||
| 63 | #define PKT_HOST_COMMAND 0x00004000 /* Host command packet */ | ||
| 64 | #define PKT_DUMMY_PACKET 0x00002000 /* Dummy packet, used for mmm */ | ||
| 65 | #define PKT_LOW_SPEED_PACKET 0x00001000 /* Low-Speed packet */ | ||
| 66 | |||
| 67 | #define TRANS_OK (0) | ||
| 68 | #define TRANS_INPROGRESS (-1) | ||
| 69 | #define TRANS_DISCARD (-2) | ||
| 70 | #define TRANS_FAIL (-3) | ||
| 71 | |||
| 72 | #define PS_INT 0 | ||
| 73 | #define PS_DISCONNECTED 1 | ||
| 74 | #define PS_CONNECTED 2 | ||
| 75 | #define PS_READY 3 | ||
| 76 | #define PS_MISSING 4 | ||
| 77 | |||
| 78 | /* Transfer Descriptor status field */ | ||
| 79 | #define USB_TD_OK 0x00000000 /* TD transmited or received ok */ | ||
| 80 | #define USB_TD_INPROGRESS 0x80000000 /* TD is being transmitted */ | ||
| 81 | #define USB_TD_RX_ER_NONOCT 0x40000000 /* Tx Non Octet Aligned Packet */ | ||
| 82 | #define USB_TD_RX_ER_BITSTUFF 0x20000000 /* Frame Aborted-Received pkt */ | ||
| 83 | #define USB_TD_RX_ER_CRC 0x10000000 /* CRC error */ | ||
| 84 | #define USB_TD_RX_ER_OVERUN 0x08000000 /* Over - run occured */ | ||
| 85 | #define USB_TD_RX_ER_PID 0x04000000 /* wrong PID received */ | ||
| 86 | #define USB_TD_RX_DATA_UNDERUN 0x02000000 /* shorter than expected */ | ||
| 87 | #define USB_TD_RX_DATA_OVERUN 0x01000000 /* longer than expected */ | ||
| 88 | #define USB_TD_TX_ER_NAK 0x00800000 /* NAK handshake */ | ||
| 89 | #define USB_TD_TX_ER_STALL 0x00400000 /* STALL handshake */ | ||
| 90 | #define USB_TD_TX_ER_TIMEOUT 0x00200000 /* transmit time out */ | ||
| 91 | #define USB_TD_TX_ER_UNDERUN 0x00100000 /* transmit underrun */ | ||
| 92 | |||
| 93 | #define USB_TD_ERROR (USB_TD_RX_ER_NONOCT | USB_TD_RX_ER_BITSTUFF | \ | ||
| 94 | USB_TD_RX_ER_CRC | USB_TD_RX_ER_OVERUN | USB_TD_RX_ER_PID | \ | ||
| 95 | USB_TD_RX_DATA_UNDERUN | USB_TD_RX_DATA_OVERUN | \ | ||
| 96 | USB_TD_TX_ER_NAK | USB_TD_TX_ER_STALL | \ | ||
| 97 | USB_TD_TX_ER_TIMEOUT | USB_TD_TX_ER_UNDERUN) | ||
| 98 | |||
| 99 | /* Transfer Descriptor toggle field */ | ||
| 100 | #define USB_TD_TOGGLE_DATA0 0 | ||
| 101 | #define USB_TD_TOGGLE_DATA1 1 | ||
| 102 | #define USB_TD_TOGGLE_CARRY 2 | ||
| 103 | |||
| 104 | /* #define MULTI_DATA_BUS */ | ||
| 105 | |||
| 106 | /* Bus mode register RBMR/TBMR */ | ||
| 107 | #define BUS_MODE_GBL 0x20 /* Global snooping */ | ||
| 108 | #define BUS_MODE_BO 0x18 /* Byte ordering */ | ||
| 109 | #define BUS_MODE_BO_BE 0x10 /* Byte ordering - Big-endian */ | ||
| 110 | #define BUS_MODE_DTB 0x02 /* Data bus */ | ||
| 111 | |||
| 112 | /* FHCI QE USB Register Description */ | ||
| 113 | |||
| 114 | /* USB Mode Register bit define */ | ||
| 115 | #define USB_MODE_EN 0x01 | ||
| 116 | #define USB_MODE_HOST 0x02 | ||
| 117 | #define USB_MODE_TEST 0x04 | ||
| 118 | #define USB_MODE_SFTE 0x08 | ||
| 119 | #define USB_MODE_RESUME 0x40 | ||
| 120 | #define USB_MODE_LSS 0x80 | ||
| 121 | |||
| 122 | /* USB Slave Address Register Mask */ | ||
| 123 | #define USB_SLVADDR_MASK 0x7F | ||
| 124 | |||
| 125 | /* USB Endpoint register define */ | ||
| 126 | #define USB_EPNUM_MASK 0xF000 | ||
| 127 | #define USB_EPNUM_SHIFT 12 | ||
| 128 | |||
| 129 | #define USB_TRANS_MODE_SHIFT 8 | ||
| 130 | #define USB_TRANS_CTR 0x0000 | ||
| 131 | #define USB_TRANS_INT 0x0100 | ||
| 132 | #define USB_TRANS_BULK 0x0200 | ||
| 133 | #define USB_TRANS_ISO 0x0300 | ||
| 134 | |||
| 135 | #define USB_EP_MF 0x0020 | ||
| 136 | #define USB_EP_RTE 0x0010 | ||
| 137 | |||
| 138 | #define USB_THS_SHIFT 2 | ||
| 139 | #define USB_THS_MASK 0x000c | ||
| 140 | #define USB_THS_NORMAL 0x0 | ||
| 141 | #define USB_THS_IGNORE_IN 0x0004 | ||
| 142 | #define USB_THS_NACK 0x0008 | ||
| 143 | #define USB_THS_STALL 0x000c | ||
| 144 | |||
| 145 | #define USB_RHS_SHIFT 0 | ||
| 146 | #define USB_RHS_MASK 0x0003 | ||
| 147 | #define USB_RHS_NORMAL 0x0 | ||
| 148 | #define USB_RHS_IGNORE_OUT 0x0001 | ||
| 149 | #define USB_RHS_NACK 0x0002 | ||
| 150 | #define USB_RHS_STALL 0x0003 | ||
| 151 | |||
| 152 | #define USB_RTHS_MASK 0x000f | ||
| 153 | |||
| 154 | /* USB Command Register define */ | ||
| 155 | #define USB_CMD_STR_FIFO 0x80 | ||
| 156 | #define USB_CMD_FLUSH_FIFO 0x40 | ||
| 157 | #define USB_CMD_ISFT 0x20 | ||
| 158 | #define USB_CMD_DSFT 0x10 | ||
| 159 | #define USB_CMD_EP_MASK 0x03 | ||
| 160 | |||
| 161 | /* USB Event and Mask Register define */ | ||
| 162 | #define USB_E_MSF_MASK 0x0800 | ||
| 163 | #define USB_E_SFT_MASK 0x0400 | ||
| 164 | #define USB_E_RESET_MASK 0x0200 | ||
| 165 | #define USB_E_IDLE_MASK 0x0100 | ||
| 166 | #define USB_E_TXE4_MASK 0x0080 | ||
| 167 | #define USB_E_TXE3_MASK 0x0040 | ||
| 168 | #define USB_E_TXE2_MASK 0x0020 | ||
| 169 | #define USB_E_TXE1_MASK 0x0010 | ||
| 170 | #define USB_E_SOF_MASK 0x0008 | ||
| 171 | #define USB_E_BSY_MASK 0x0004 | ||
| 172 | #define USB_E_TXB_MASK 0x0002 | ||
| 173 | #define USB_E_RXB_MASK 0x0001 | ||
| 174 | |||
| 175 | /* Freescale USB Host controller registers */ | ||
| 176 | struct fhci_regs { | ||
| 177 | u8 usb_mod; /* mode register */ | ||
| 178 | u8 usb_addr; /* address register */ | ||
| 179 | u8 usb_comm; /* command register */ | ||
| 180 | u8 reserved1[1]; | ||
| 181 | __be16 usb_ep[4]; /* endpoint register */ | ||
| 182 | u8 reserved2[4]; | ||
| 183 | __be16 usb_event; /* event register */ | ||
| 184 | u8 reserved3[2]; | ||
| 185 | __be16 usb_mask; /* mask register */ | ||
| 186 | u8 reserved4[1]; | ||
| 187 | u8 usb_status; /* status register */ | ||
| 188 | __be16 usb_sof_tmr; /* Start Of Frame timer */ | ||
| 189 | u8 reserved5[2]; | ||
| 190 | __be16 usb_frame_num; /* frame number register */ | ||
| 191 | u8 reserved6[1]; | ||
| 192 | }; | ||
| 193 | |||
| 194 | /* Freescale USB HOST */ | ||
| 195 | struct fhci_pram { | ||
| 196 | __be16 ep_ptr[4]; /* Endpoint porter reg */ | ||
| 197 | __be32 rx_state; /* Rx internal state */ | ||
| 198 | __be32 rx_ptr; /* Rx internal data pointer */ | ||
| 199 | __be16 frame_num; /* Frame number */ | ||
| 200 | __be16 rx_cnt; /* Rx byte count */ | ||
| 201 | __be32 rx_temp; /* Rx temp */ | ||
| 202 | __be32 rx_data_temp; /* Rx data temp */ | ||
| 203 | __be16 rx_u_ptr; /* Rx microcode return address temp */ | ||
| 204 | u8 reserved1[2]; /* reserved area */ | ||
| 205 | __be32 sof_tbl; /* SOF lookup table pointer */ | ||
| 206 | u8 sof_u_crc_temp; /* SOF micorcode CRC5 temp reg */ | ||
| 207 | u8 reserved2[0xdb]; | ||
| 208 | }; | ||
| 209 | |||
| 210 | /* Freescale USB Endpoint*/ | ||
| 211 | struct fhci_ep_pram { | ||
| 212 | __be16 rx_base; /* Rx BD base address */ | ||
| 213 | __be16 tx_base; /* Tx BD base address */ | ||
| 214 | u8 rx_func_code; /* Rx function code */ | ||
| 215 | u8 tx_func_code; /* Tx function code */ | ||
| 216 | __be16 rx_buff_len; /* Rx buffer length */ | ||
| 217 | __be16 rx_bd_ptr; /* Rx BD pointer */ | ||
| 218 | __be16 tx_bd_ptr; /* Tx BD pointer */ | ||
| 219 | __be32 tx_state; /* Tx internal state */ | ||
| 220 | __be32 tx_ptr; /* Tx internal data pointer */ | ||
| 221 | __be16 tx_crc; /* temp transmit CRC */ | ||
| 222 | __be16 tx_cnt; /* Tx byte count */ | ||
| 223 | __be32 tx_temp; /* Tx temp */ | ||
| 224 | __be16 tx_u_ptr; /* Tx microcode return address temp */ | ||
| 225 | __be16 reserved; | ||
| 226 | }; | ||
| 227 | |||
| 228 | struct fhci_controller_list { | ||
| 229 | struct list_head ctrl_list; /* control endpoints */ | ||
| 230 | struct list_head bulk_list; /* bulk endpoints */ | ||
| 231 | struct list_head iso_list; /* isochronous endpoints */ | ||
| 232 | struct list_head intr_list; /* interruput endpoints */ | ||
| 233 | struct list_head done_list; /* done transfers */ | ||
| 234 | }; | ||
| 235 | |||
| 236 | struct virtual_root_hub { | ||
| 237 | int dev_num; /* USB address of the root hub */ | ||
| 238 | u32 feature; /* indicates what feature has been set */ | ||
| 239 | struct usb_hub_status hub; | ||
| 240 | struct usb_port_status port; | ||
| 241 | }; | ||
| 242 | |||
| 243 | enum fhci_gpios { | ||
| 244 | GPIO_USBOE = 0, | ||
| 245 | GPIO_USBTP, | ||
| 246 | GPIO_USBTN, | ||
| 247 | GPIO_USBRP, | ||
| 248 | GPIO_USBRN, | ||
| 249 | /* these are optional */ | ||
| 250 | GPIO_SPEED, | ||
| 251 | GPIO_POWER, | ||
| 252 | NUM_GPIOS, | ||
| 253 | }; | ||
| 254 | |||
| 255 | enum fhci_pins { | ||
| 256 | PIN_USBOE = 0, | ||
| 257 | PIN_USBTP, | ||
| 258 | PIN_USBTN, | ||
| 259 | NUM_PINS, | ||
| 260 | }; | ||
| 261 | |||
| 262 | struct fhci_hcd { | ||
| 263 | enum qe_clock fullspeed_clk; | ||
| 264 | enum qe_clock lowspeed_clk; | ||
| 265 | struct qe_pin *pins[NUM_PINS]; | ||
| 266 | int gpios[NUM_GPIOS]; | ||
| 267 | bool alow_gpios[NUM_GPIOS]; | ||
| 268 | |||
| 269 | struct fhci_regs __iomem *regs; /* I/O memory used to communicate */ | ||
| 270 | struct fhci_pram __iomem *pram; /* Parameter RAM */ | ||
| 271 | struct gtm_timer *timer; | ||
| 272 | |||
| 273 | spinlock_t lock; | ||
| 274 | struct fhci_usb *usb_lld; /* Low-level driver */ | ||
| 275 | struct virtual_root_hub *vroot_hub; /* the virtual root hub */ | ||
| 276 | int active_urbs; | ||
| 277 | struct fhci_controller_list *hc_list; | ||
| 278 | struct tasklet_struct *process_done_task; /* tasklet for done list */ | ||
| 279 | |||
| 280 | struct list_head empty_eds; | ||
| 281 | struct list_head empty_tds; | ||
| 282 | |||
| 283 | #ifdef CONFIG_FHCI_DEBUG | ||
| 284 | int usb_irq_stat[13]; | ||
| 285 | struct dentry *dfs_root; | ||
| 286 | struct dentry *dfs_regs; | ||
| 287 | struct dentry *dfs_irq_stat; | ||
| 288 | #endif | ||
| 289 | }; | ||
| 290 | |||
| 291 | #define USB_FRAME_USAGE 90 | ||
| 292 | #define FRAME_TIME_USAGE (USB_FRAME_USAGE*10) /* frame time usage */ | ||
| 293 | #define SW_FIX_TIME_BETWEEN_TRANSACTION 150 /* SW */ | ||
| 294 | #define MAX_BYTES_PER_FRAME (USB_FRAME_USAGE*15) | ||
| 295 | #define MAX_PERIODIC_FRAME_USAGE 90 | ||
| 296 | |||
| 297 | /* transaction type */ | ||
| 298 | enum fhci_ta_type { | ||
| 299 | FHCI_TA_IN = 0, /* input transaction */ | ||
| 300 | FHCI_TA_OUT, /* output transaction */ | ||
| 301 | FHCI_TA_SETUP, /* setup transaction */ | ||
| 302 | }; | ||
| 303 | |||
| 304 | /* transfer mode */ | ||
| 305 | enum fhci_tf_mode { | ||
| 306 | FHCI_TF_CTRL = 0, | ||
| 307 | FHCI_TF_ISO, | ||
| 308 | FHCI_TF_BULK, | ||
| 309 | FHCI_TF_INTR, | ||
| 310 | }; | ||
| 311 | |||
| 312 | enum fhci_speed { | ||
| 313 | FHCI_FULL_SPEED, | ||
| 314 | FHCI_LOW_SPEED, | ||
| 315 | }; | ||
| 316 | |||
| 317 | /* endpoint state */ | ||
| 318 | enum fhci_ed_state { | ||
| 319 | FHCI_ED_NEW = 0, /* pipe is new */ | ||
| 320 | FHCI_ED_OPER, /* pipe is operating */ | ||
| 321 | FHCI_ED_URB_DEL, /* pipe is in hold because urb is being deleted */ | ||
| 322 | FHCI_ED_SKIP, /* skip this pipe */ | ||
| 323 | FHCI_ED_HALTED, /* pipe is halted */ | ||
| 324 | }; | ||
| 325 | |||
| 326 | enum fhci_port_status { | ||
| 327 | FHCI_PORT_POWER_OFF = 0, | ||
| 328 | FHCI_PORT_DISABLED, | ||
| 329 | FHCI_PORT_DISCONNECTING, | ||
| 330 | FHCI_PORT_WAITING, /* waiting for connection */ | ||
| 331 | FHCI_PORT_FULL, /* full speed connected */ | ||
| 332 | FHCI_PORT_LOW, /* low speed connected */ | ||
| 333 | }; | ||
| 334 | |||
| 335 | enum fhci_mem_alloc { | ||
| 336 | MEM_CACHABLE_SYS = 0x00000001, /* primary DDR,cachable */ | ||
| 337 | MEM_NOCACHE_SYS = 0x00000004, /* primary DDR,non-cachable */ | ||
| 338 | MEM_SECONDARY = 0x00000002, /* either secondary DDR or SDRAM */ | ||
| 339 | MEM_PRAM = 0x00000008, /* multi-user RAM identifier */ | ||
| 340 | }; | ||
| 341 | |||
| 342 | /* USB default parameters*/ | ||
| 343 | #define DEFAULT_RING_LEN 8 | ||
| 344 | #define DEFAULT_DATA_MEM MEM_CACHABLE_SYS | ||
| 345 | |||
| 346 | struct ed { | ||
| 347 | u8 dev_addr; /* device address */ | ||
| 348 | u8 ep_addr; /* endpoint address */ | ||
| 349 | enum fhci_tf_mode mode; /* USB transfer mode */ | ||
| 350 | enum fhci_speed speed; | ||
| 351 | unsigned int max_pkt_size; | ||
| 352 | enum fhci_ed_state state; | ||
| 353 | struct list_head td_list; /* a list of all queued TD to this pipe */ | ||
| 354 | struct list_head node; | ||
| 355 | |||
| 356 | /* read only parameters, should be cleared upon initialization */ | ||
| 357 | u8 toggle_carry; /* toggle carry from the last TD submitted */ | ||
| 358 | u32 last_iso; /* time stamp of last queued ISO transfer */ | ||
| 359 | struct td *td_head; /* a pointer to the current TD handled */ | ||
| 360 | }; | ||
| 361 | |||
| 362 | struct td { | ||
| 363 | void *data; /* a pointer to the data buffer */ | ||
| 364 | unsigned int len; /* length of the data to be submitted */ | ||
| 365 | unsigned int actual_len; /* actual bytes transfered on this td */ | ||
| 366 | enum fhci_ta_type type; /* transaction type */ | ||
| 367 | u8 toggle; /* toggle for next trans. within this TD */ | ||
| 368 | u16 iso_index; /* ISO transaction index */ | ||
| 369 | u16 start_frame; /* start frame time stamp */ | ||
| 370 | u16 interval; /* interval between trans. (for ISO/Intr) */ | ||
| 371 | u32 status; /* status of the TD */ | ||
| 372 | struct ed *ed; /* a handle to the corresponding ED */ | ||
| 373 | struct urb *urb; /* a handle to the corresponding URB */ | ||
| 374 | bool ioc; /* Inform On Completion */ | ||
| 375 | struct list_head node; | ||
| 376 | |||
| 377 | /* read only parameters should be cleared upon initialization */ | ||
| 378 | struct packet *pkt; | ||
| 379 | int nak_cnt; | ||
| 380 | int error_cnt; | ||
| 381 | struct list_head frame_lh; | ||
| 382 | }; | ||
| 383 | |||
| 384 | struct packet { | ||
| 385 | u8 *data; /* packet data */ | ||
| 386 | u32 len; /* packet length */ | ||
| 387 | u32 status; /* status of the packet - equivalent to the status | ||
| 388 | * field for the corresponding structure td */ | ||
| 389 | u32 info; /* packet information */ | ||
| 390 | void __iomem *priv_data; /* private data of the driver (TDs or BDs) */ | ||
| 391 | }; | ||
| 392 | |||
| 393 | /* struct for each URB */ | ||
| 394 | #define URB_INPROGRESS 0 | ||
| 395 | #define URB_DEL 1 | ||
| 396 | |||
| 397 | /* URB states (state field) */ | ||
| 398 | #define US_BULK 0 | ||
| 399 | #define US_BULK0 1 | ||
| 400 | |||
| 401 | /* three setup states */ | ||
| 402 | #define US_CTRL_SETUP 2 | ||
| 403 | #define US_CTRL_DATA 1 | ||
| 404 | #define US_CTRL_ACK 0 | ||
| 405 | |||
| 406 | #define EP_ZERO 0 | ||
| 407 | |||
| 408 | struct urb_priv { | ||
| 409 | int num_of_tds; | ||
| 410 | int tds_cnt; | ||
| 411 | int state; | ||
| 412 | |||
| 413 | struct td **tds; | ||
| 414 | struct ed *ed; | ||
| 415 | struct timer_list time_out; | ||
| 416 | }; | ||
| 417 | |||
| 418 | struct endpoint { | ||
| 419 | /* Pointer to ep parameter RAM */ | ||
| 420 | struct fhci_ep_pram __iomem *ep_pram_ptr; | ||
| 421 | |||
| 422 | /* Host transactions */ | ||
| 423 | struct usb_td __iomem *td_base; /* first TD in the ring */ | ||
| 424 | struct usb_td __iomem *conf_td; /* next TD for confirm after transac */ | ||
| 425 | struct usb_td __iomem *empty_td;/* next TD for new transaction req. */ | ||
| 426 | struct kfifo *empty_frame_Q; /* Empty frames list to use */ | ||
| 427 | struct kfifo *conf_frame_Q; /* frames passed to TDs,waiting for tx */ | ||
| 428 | struct kfifo *dummy_packets_Q;/* dummy packets for the CRC overun */ | ||
| 429 | |||
| 430 | bool already_pushed_dummy_bd; | ||
| 431 | }; | ||
| 432 | |||
| 433 | /* struct for each 1mSec frame time */ | ||
| 434 | #define FRAME_IS_TRANSMITTED 0x00 | ||
| 435 | #define FRAME_TIMER_END_TRANSMISSION 0x01 | ||
| 436 | #define FRAME_DATA_END_TRANSMISSION 0x02 | ||
| 437 | #define FRAME_END_TRANSMISSION 0x03 | ||
| 438 | #define FRAME_IS_PREPARED 0x04 | ||
| 439 | |||
| 440 | struct fhci_time_frame { | ||
| 441 | u16 frame_num; /* frame number */ | ||
| 442 | u16 total_bytes; /* total bytes submitted within this frame */ | ||
| 443 | u8 frame_status; /* flag that indicates to stop fill this frame */ | ||
| 444 | struct list_head tds_list; /* all tds of this frame */ | ||
| 445 | }; | ||
| 446 | |||
| 447 | /* internal driver structure*/ | ||
| 448 | struct fhci_usb { | ||
| 449 | u16 saved_msk; /* saving of the USB mask register */ | ||
| 450 | struct endpoint *ep0; /* pointer for endpoint0 structure */ | ||
| 451 | int intr_nesting_cnt; /* interrupt nesting counter */ | ||
| 452 | u16 max_frame_usage; /* max frame time usage,in micro-sec */ | ||
| 453 | u16 max_bytes_per_frame; /* max byte can be tx in one time frame */ | ||
| 454 | u32 sw_transaction_time; /* sw complete trans time,in micro-sec */ | ||
| 455 | struct fhci_time_frame *actual_frame; | ||
| 456 | struct fhci_controller_list *hc_list; /* main structure for hc */ | ||
| 457 | struct virtual_root_hub *vroot_hub; | ||
| 458 | enum fhci_port_status port_status; /* v_rh port status */ | ||
| 459 | |||
| 460 | u32 (*transfer_confirm)(struct fhci_hcd *fhci); | ||
| 461 | |||
| 462 | struct fhci_hcd *fhci; | ||
| 463 | }; | ||
| 464 | |||
| 465 | /* | ||
| 466 | * Various helpers and prototypes below. | ||
| 467 | */ | ||
| 468 | |||
| 469 | static inline u16 get_frame_num(struct fhci_hcd *fhci) | ||
| 470 | { | ||
| 471 | return in_be16(&fhci->pram->frame_num) & 0x07ff; | ||
| 472 | } | ||
| 473 | |||
| 474 | #define fhci_dbg(fhci, fmt, args...) \ | ||
| 475 | dev_dbg(fhci_to_hcd(fhci)->self.controller, fmt, ##args) | ||
| 476 | #define fhci_vdbg(fhci, fmt, args...) \ | ||
| 477 | dev_vdbg(fhci_to_hcd(fhci)->self.controller, fmt, ##args) | ||
| 478 | #define fhci_err(fhci, fmt, args...) \ | ||
| 479 | dev_err(fhci_to_hcd(fhci)->self.controller, fmt, ##args) | ||
| 480 | #define fhci_info(fhci, fmt, args...) \ | ||
| 481 | dev_info(fhci_to_hcd(fhci)->self.controller, fmt, ##args) | ||
| 482 | #define fhci_warn(fhci, fmt, args...) \ | ||
| 483 | dev_warn(fhci_to_hcd(fhci)->self.controller, fmt, ##args) | ||
| 484 | |||
| 485 | static inline struct fhci_hcd *hcd_to_fhci(struct usb_hcd *hcd) | ||
| 486 | { | ||
| 487 | return (struct fhci_hcd *)hcd->hcd_priv; | ||
| 488 | } | ||
| 489 | |||
| 490 | static inline struct usb_hcd *fhci_to_hcd(struct fhci_hcd *fhci) | ||
| 491 | { | ||
| 492 | return container_of((void *)fhci, struct usb_hcd, hcd_priv); | ||
| 493 | } | ||
| 494 | |||
| 495 | /* fifo of pointers */ | ||
| 496 | static inline struct kfifo *cq_new(int size) | ||
| 497 | { | ||
| 498 | return kfifo_alloc(size * sizeof(void *), GFP_KERNEL, NULL); | ||
| 499 | } | ||
| 500 | |||
| 501 | static inline void cq_delete(struct kfifo *kfifo) | ||
| 502 | { | ||
| 503 | kfifo_free(kfifo); | ||
| 504 | } | ||
| 505 | |||
| 506 | static inline unsigned int cq_howmany(struct kfifo *kfifo) | ||
| 507 | { | ||
| 508 | return __kfifo_len(kfifo) / sizeof(void *); | ||
| 509 | } | ||
| 510 | |||
| 511 | static inline int cq_put(struct kfifo *kfifo, void *p) | ||
| 512 | { | ||
| 513 | return __kfifo_put(kfifo, (void *)&p, sizeof(p)); | ||
| 514 | } | ||
| 515 | |||
| 516 | static inline void *cq_get(struct kfifo *kfifo) | ||
| 517 | { | ||
| 518 | void *p = NULL; | ||
| 519 | |||
| 520 | __kfifo_get(kfifo, (void *)&p, sizeof(p)); | ||
| 521 | return p; | ||
| 522 | } | ||
| 523 | |||
| 524 | /* fhci-hcd.c */ | ||
| 525 | void fhci_start_sof_timer(struct fhci_hcd *fhci); | ||
| 526 | void fhci_stop_sof_timer(struct fhci_hcd *fhci); | ||
| 527 | u16 fhci_get_sof_timer_count(struct fhci_usb *usb); | ||
| 528 | void fhci_usb_enable_interrupt(struct fhci_usb *usb); | ||
| 529 | void fhci_usb_disable_interrupt(struct fhci_usb *usb); | ||
| 530 | int fhci_ioports_check_bus_state(struct fhci_hcd *fhci); | ||
| 531 | |||
| 532 | /* fhci-mem.c */ | ||
| 533 | void fhci_recycle_empty_td(struct fhci_hcd *fhci, struct td *td); | ||
| 534 | void fhci_recycle_empty_ed(struct fhci_hcd *fhci, struct ed *ed); | ||
| 535 | struct ed *fhci_get_empty_ed(struct fhci_hcd *fhci); | ||
| 536 | struct td *fhci_td_fill(struct fhci_hcd *fhci, struct urb *urb, | ||
| 537 | struct urb_priv *urb_priv, struct ed *ed, u16 index, | ||
| 538 | enum fhci_ta_type type, int toggle, u8 *data, u32 len, | ||
| 539 | u16 interval, u16 start_frame, bool ioc); | ||
| 540 | void fhci_add_tds_to_ed(struct ed *ed, struct td **td_list, int number); | ||
| 541 | |||
| 542 | /* fhci-hub.c */ | ||
| 543 | void fhci_config_transceiver(struct fhci_hcd *fhci, | ||
| 544 | enum fhci_port_status status); | ||
| 545 | void fhci_port_disable(struct fhci_hcd *fhci); | ||
| 546 | void fhci_port_enable(void *lld); | ||
| 547 | void fhci_io_port_generate_reset(struct fhci_hcd *fhci); | ||
| 548 | void fhci_port_reset(void *lld); | ||
| 549 | int fhci_hub_status_data(struct usb_hcd *hcd, char *buf); | ||
| 550 | int fhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | ||
| 551 | u16 wIndex, char *buf, u16 wLength); | ||
| 552 | |||
| 553 | /* fhci-tds.c */ | ||
| 554 | void fhci_flush_bds(struct fhci_usb *usb); | ||
| 555 | void fhci_flush_actual_frame(struct fhci_usb *usb); | ||
| 556 | u32 fhci_host_transaction(struct fhci_usb *usb, struct packet *pkt, | ||
| 557 | enum fhci_ta_type trans_type, u8 dest_addr, | ||
| 558 | u8 dest_ep, enum fhci_tf_mode trans_mode, | ||
| 559 | enum fhci_speed dest_speed, u8 data_toggle); | ||
| 560 | void fhci_host_transmit_actual_frame(struct fhci_usb *usb); | ||
| 561 | void fhci_tx_conf_interrupt(struct fhci_usb *usb); | ||
| 562 | void fhci_push_dummy_bd(struct endpoint *ep); | ||
| 563 | u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem, | ||
| 564 | u32 ring_len); | ||
| 565 | void fhci_init_ep_registers(struct fhci_usb *usb, | ||
| 566 | struct endpoint *ep, | ||
| 567 | enum fhci_mem_alloc data_mem); | ||
| 568 | void fhci_ep0_free(struct fhci_usb *usb); | ||
| 569 | |||
| 570 | /* fhci-sched.c */ | ||
| 571 | extern struct tasklet_struct fhci_tasklet; | ||
| 572 | void fhci_transaction_confirm(struct fhci_usb *usb, struct packet *pkt); | ||
| 573 | void fhci_flush_all_transmissions(struct fhci_usb *usb); | ||
| 574 | void fhci_schedule_transactions(struct fhci_usb *usb); | ||
| 575 | void fhci_device_connected_interrupt(struct fhci_hcd *fhci); | ||
| 576 | void fhci_device_disconnected_interrupt(struct fhci_hcd *fhci); | ||
| 577 | void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb); | ||
| 578 | u32 fhci_transfer_confirm_callback(struct fhci_hcd *fhci); | ||
| 579 | irqreturn_t fhci_irq(struct usb_hcd *hcd); | ||
| 580 | irqreturn_t fhci_frame_limit_timer_irq(int irq, void *_hcd); | ||
| 581 | |||
| 582 | /* fhci-q.h */ | ||
| 583 | void fhci_urb_complete_free(struct fhci_hcd *fhci, struct urb *urb); | ||
| 584 | struct td *fhci_remove_td_from_ed(struct ed *ed); | ||
| 585 | struct td *fhci_remove_td_from_frame(struct fhci_time_frame *frame); | ||
| 586 | void fhci_move_td_from_ed_to_done_list(struct fhci_usb *usb, struct ed *ed); | ||
| 587 | struct td *fhci_peek_td_from_frame(struct fhci_time_frame *frame); | ||
| 588 | void fhci_add_td_to_frame(struct fhci_time_frame *frame, struct td *td); | ||
| 589 | struct td *fhci_remove_td_from_done_list(struct fhci_controller_list *p_list); | ||
| 590 | void fhci_done_td(struct urb *urb, struct td *td); | ||
| 591 | void fhci_del_ed_list(struct fhci_hcd *fhci, struct ed *ed); | ||
| 592 | |||
| 593 | #ifdef CONFIG_FHCI_DEBUG | ||
| 594 | |||
| 595 | void fhci_dbg_isr(struct fhci_hcd *fhci, int usb_er); | ||
| 596 | void fhci_dfs_destroy(struct fhci_hcd *fhci); | ||
| 597 | void fhci_dfs_create(struct fhci_hcd *fhci); | ||
| 598 | |||
| 599 | #else | ||
| 600 | |||
| 601 | static inline void fhci_dbg_isr(struct fhci_hcd *fhci, int usb_er) {} | ||
| 602 | static inline void fhci_dfs_destroy(struct fhci_hcd *fhci) {} | ||
| 603 | static inline void fhci_dfs_create(struct fhci_hcd *fhci) {} | ||
| 604 | |||
| 605 | #endif /* CONFIG_FHCI_DEBUG */ | ||
| 606 | |||
| 607 | #endif /* __FHCI_H */ | ||
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 65a9609f4ad6..5cf5f1eca4f4 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
| @@ -593,12 +593,10 @@ static int ohci_run (struct ohci_hcd *ohci) | |||
| 593 | * to be checked in case boot firmware (BIOS/SMM/...) has set up | 593 | * to be checked in case boot firmware (BIOS/SMM/...) has set up |
| 594 | * wakeup in a way the bus isn't aware of (e.g., legacy PCI PM). | 594 | * wakeup in a way the bus isn't aware of (e.g., legacy PCI PM). |
| 595 | * If the bus glue detected wakeup capability then it should | 595 | * If the bus glue detected wakeup capability then it should |
| 596 | * already be enabled. Either way, if wakeup should be enabled | 596 | * already be enabled; if so we'll just enable it again. |
| 597 | * but isn't, we'll enable it now. | ||
| 598 | */ | 597 | */ |
| 599 | if ((ohci->hc_control & OHCI_CTRL_RWC) != 0 | 598 | if ((ohci->hc_control & OHCI_CTRL_RWC) != 0) |
| 600 | && !device_can_wakeup(hcd->self.controller)) | 599 | device_set_wakeup_capable(hcd->self.controller, 1); |
| 601 | device_init_wakeup(hcd->self.controller, 1); | ||
| 602 | 600 | ||
| 603 | switch (ohci->hc_control & OHCI_CTRL_HCFS) { | 601 | switch (ohci->hc_control & OHCI_CTRL_HCFS) { |
| 604 | case OHCI_USB_OPER: | 602 | case OHCI_USB_OPER: |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 8b28ae7865ba..5d625c3fd423 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
| @@ -487,7 +487,6 @@ static struct pci_driver ohci_pci_driver = { | |||
| 487 | 487 | ||
| 488 | #ifdef CONFIG_PM | 488 | #ifdef CONFIG_PM |
| 489 | .suspend = usb_hcd_pci_suspend, | 489 | .suspend = usb_hcd_pci_suspend, |
| 490 | .suspend_late = usb_hcd_pci_suspend_late, | ||
| 491 | .resume_early = usb_hcd_pci_resume_early, | 490 | .resume_early = usb_hcd_pci_resume_early, |
| 492 | .resume = usb_hcd_pci_resume, | 491 | .resume = usb_hcd_pci_resume, |
| 493 | #endif | 492 | #endif |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 4e221060f58c..944f7e0ca4df 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
| @@ -942,7 +942,6 @@ static struct pci_driver uhci_pci_driver = { | |||
| 942 | 942 | ||
| 943 | #ifdef CONFIG_PM | 943 | #ifdef CONFIG_PM |
| 944 | .suspend = usb_hcd_pci_suspend, | 944 | .suspend = usb_hcd_pci_suspend, |
| 945 | .suspend_late = usb_hcd_pci_suspend_late, | ||
| 946 | .resume_early = usb_hcd_pci_resume_early, | 945 | .resume_early = usb_hcd_pci_resume_early, |
| 947 | .resume = usb_hcd_pci_resume, | 946 | .resume = usb_hcd_pci_resume, |
| 948 | #endif /* PM */ | 947 | #endif /* PM */ |
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 189a9db03509..ad4fb15b5dcb 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c | |||
| @@ -57,7 +57,6 @@ | |||
| 57 | #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 /* USB Product ID of Machine Test System */ | 57 | #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 /* USB Product ID of Machine Test System */ |
| 58 | 58 | ||
| 59 | #define USB_VENDOR_ID_VERNIER 0x08f7 | 59 | #define USB_VENDOR_ID_VERNIER 0x08f7 |
| 60 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 | ||
| 61 | #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 | 60 | #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 |
| 62 | #define USB_DEVICE_ID_VERNIER_SKIP 0x0003 | 61 | #define USB_DEVICE_ID_VERNIER_SKIP 0x0003 |
| 63 | #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 | 62 | #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 |
| @@ -85,7 +84,6 @@ static struct usb_device_id ld_usb_table [] = { | |||
| 85 | { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) }, | 84 | { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) }, |
| 86 | { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) }, | 85 | { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) }, |
| 87 | { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) }, | 86 | { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) }, |
| 88 | { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) }, | ||
| 89 | { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) }, | 87 | { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) }, |
| 90 | { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, | 88 | { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, |
| 91 | { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) }, | 89 | { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) }, |
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index e06810aef2df..4cf27c72423e 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get) | 37 | #define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get) |
| 38 | #define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch) | 38 | #define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch) |
| 39 | #define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8) | 39 | #define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8) |
| 40 | |||
| 40 | #ifdef CONFIG_COMPAT | 41 | #ifdef CONFIG_COMPAT |
| 41 | #define MON_IOCX_GET32 _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get32) | 42 | #define MON_IOCX_GET32 _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get32) |
| 42 | #define MON_IOCX_MFETCH32 _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch32) | 43 | #define MON_IOCX_MFETCH32 _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch32) |
| @@ -921,21 +922,6 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file, | |||
| 921 | } | 922 | } |
| 922 | break; | 923 | break; |
| 923 | 924 | ||
| 924 | #ifdef CONFIG_COMPAT | ||
| 925 | case MON_IOCX_GET32: { | ||
| 926 | struct mon_bin_get32 getb; | ||
| 927 | |||
| 928 | if (copy_from_user(&getb, (void __user *)arg, | ||
| 929 | sizeof(struct mon_bin_get32))) | ||
| 930 | return -EFAULT; | ||
| 931 | |||
| 932 | ret = mon_bin_get_event(file, rp, | ||
| 933 | compat_ptr(getb.hdr32), compat_ptr(getb.data32), | ||
| 934 | getb.alloc32); | ||
| 935 | } | ||
| 936 | break; | ||
| 937 | #endif | ||
| 938 | |||
| 939 | case MON_IOCX_MFETCH: | 925 | case MON_IOCX_MFETCH: |
| 940 | { | 926 | { |
| 941 | struct mon_bin_mfetch mfetch; | 927 | struct mon_bin_mfetch mfetch; |
| @@ -962,7 +948,57 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file, | |||
| 962 | } | 948 | } |
| 963 | break; | 949 | break; |
| 964 | 950 | ||
| 951 | case MON_IOCG_STATS: { | ||
| 952 | struct mon_bin_stats __user *sp; | ||
| 953 | unsigned int nevents; | ||
| 954 | unsigned int ndropped; | ||
| 955 | |||
| 956 | spin_lock_irqsave(&rp->b_lock, flags); | ||
| 957 | ndropped = rp->cnt_lost; | ||
| 958 | rp->cnt_lost = 0; | ||
| 959 | spin_unlock_irqrestore(&rp->b_lock, flags); | ||
| 960 | nevents = mon_bin_queued(rp); | ||
| 961 | |||
| 962 | sp = (struct mon_bin_stats __user *)arg; | ||
| 963 | if (put_user(rp->cnt_lost, &sp->dropped)) | ||
| 964 | return -EFAULT; | ||
| 965 | if (put_user(nevents, &sp->queued)) | ||
| 966 | return -EFAULT; | ||
| 967 | |||
| 968 | } | ||
| 969 | break; | ||
| 970 | |||
| 971 | default: | ||
| 972 | return -ENOTTY; | ||
| 973 | } | ||
| 974 | |||
| 975 | return ret; | ||
| 976 | } | ||
| 977 | |||
| 965 | #ifdef CONFIG_COMPAT | 978 | #ifdef CONFIG_COMPAT |
| 979 | static long mon_bin_compat_ioctl(struct file *file, | ||
| 980 | unsigned int cmd, unsigned long arg) | ||
| 981 | { | ||
| 982 | struct mon_reader_bin *rp = file->private_data; | ||
| 983 | int ret; | ||
| 984 | |||
| 985 | switch (cmd) { | ||
| 986 | |||
| 987 | case MON_IOCX_GET32: { | ||
| 988 | struct mon_bin_get32 getb; | ||
| 989 | |||
| 990 | if (copy_from_user(&getb, (void __user *)arg, | ||
| 991 | sizeof(struct mon_bin_get32))) | ||
| 992 | return -EFAULT; | ||
| 993 | |||
| 994 | ret = mon_bin_get_event(file, rp, | ||
| 995 | compat_ptr(getb.hdr32), compat_ptr(getb.data32), | ||
| 996 | getb.alloc32); | ||
| 997 | if (ret < 0) | ||
| 998 | return ret; | ||
| 999 | } | ||
| 1000 | return 0; | ||
| 1001 | |||
| 966 | case MON_IOCX_MFETCH32: | 1002 | case MON_IOCX_MFETCH32: |
| 967 | { | 1003 | { |
| 968 | struct mon_bin_mfetch32 mfetch; | 1004 | struct mon_bin_mfetch32 mfetch; |
| @@ -986,37 +1022,25 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file, | |||
| 986 | return ret; | 1022 | return ret; |
| 987 | if (put_user(ret, &uptr->nfetch32)) | 1023 | if (put_user(ret, &uptr->nfetch32)) |
| 988 | return -EFAULT; | 1024 | return -EFAULT; |
| 989 | ret = 0; | ||
| 990 | } | 1025 | } |
| 991 | break; | 1026 | return 0; |
| 992 | #endif | ||
| 993 | |||
| 994 | case MON_IOCG_STATS: { | ||
| 995 | struct mon_bin_stats __user *sp; | ||
| 996 | unsigned int nevents; | ||
| 997 | unsigned int ndropped; | ||
| 998 | |||
| 999 | spin_lock_irqsave(&rp->b_lock, flags); | ||
| 1000 | ndropped = rp->cnt_lost; | ||
| 1001 | rp->cnt_lost = 0; | ||
| 1002 | spin_unlock_irqrestore(&rp->b_lock, flags); | ||
| 1003 | nevents = mon_bin_queued(rp); | ||
| 1004 | 1027 | ||
| 1005 | sp = (struct mon_bin_stats __user *)arg; | 1028 | case MON_IOCG_STATS: |
| 1006 | if (put_user(rp->cnt_lost, &sp->dropped)) | 1029 | return mon_bin_ioctl(NULL, file, cmd, |
| 1007 | return -EFAULT; | 1030 | (unsigned long) compat_ptr(arg)); |
| 1008 | if (put_user(nevents, &sp->queued)) | ||
| 1009 | return -EFAULT; | ||
| 1010 | 1031 | ||
| 1011 | } | 1032 | case MON_IOCQ_URB_LEN: |
| 1012 | break; | 1033 | case MON_IOCQ_RING_SIZE: |
| 1034 | case MON_IOCT_RING_SIZE: | ||
| 1035 | case MON_IOCH_MFLUSH: | ||
| 1036 | return mon_bin_ioctl(NULL, file, cmd, arg); | ||
| 1013 | 1037 | ||
| 1014 | default: | 1038 | default: |
| 1015 | return -ENOTTY; | 1039 | ; |
| 1016 | } | 1040 | } |
| 1017 | 1041 | return -ENOTTY; | |
| 1018 | return ret; | ||
| 1019 | } | 1042 | } |
| 1043 | #endif /* CONFIG_COMPAT */ | ||
| 1020 | 1044 | ||
| 1021 | static unsigned int | 1045 | static unsigned int |
| 1022 | mon_bin_poll(struct file *file, struct poll_table_struct *wait) | 1046 | mon_bin_poll(struct file *file, struct poll_table_struct *wait) |
| @@ -1094,6 +1118,9 @@ static const struct file_operations mon_fops_binary = { | |||
| 1094 | /* .write = mon_text_write, */ | 1118 | /* .write = mon_text_write, */ |
| 1095 | .poll = mon_bin_poll, | 1119 | .poll = mon_bin_poll, |
| 1096 | .ioctl = mon_bin_ioctl, | 1120 | .ioctl = mon_bin_ioctl, |
| 1121 | #ifdef CONFIG_COMPAT | ||
| 1122 | .compat_ioctl = mon_bin_compat_ioctl, | ||
| 1123 | #endif | ||
| 1097 | .release = mon_bin_release, | 1124 | .release = mon_bin_release, |
| 1098 | .mmap = mon_bin_mmap, | 1125 | .mmap = mon_bin_mmap, |
| 1099 | }; | 1126 | }; |
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 5af7379cd9a3..9985db08e7db 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig | |||
| @@ -11,6 +11,7 @@ config USB_MUSB_HDRC | |||
| 11 | depends on (USB || USB_GADGET) && HAVE_CLK | 11 | depends on (USB || USB_GADGET) && HAVE_CLK |
| 12 | depends on !SUPERH | 12 | depends on !SUPERH |
| 13 | select TWL4030_USB if MACH_OMAP_3430SDP | 13 | select TWL4030_USB if MACH_OMAP_3430SDP |
| 14 | select USB_OTG_UTILS | ||
| 14 | tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' | 15 | tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' |
| 15 | help | 16 | help |
| 16 | Say Y here if your system has a dual role high speed USB | 17 | Say Y here if your system has a dual role high speed USB |
| @@ -49,7 +50,7 @@ comment "OMAP 343x high speed USB support" | |||
| 49 | depends on USB_MUSB_HDRC && ARCH_OMAP34XX | 50 | depends on USB_MUSB_HDRC && ARCH_OMAP34XX |
| 50 | 51 | ||
| 51 | comment "Blackfin high speed USB Support" | 52 | comment "Blackfin high speed USB Support" |
| 52 | depends on USB_MUSB_HDRC && (BF54x && !BF544) || (BF52x && !BF522 && !BF523) | 53 | depends on USB_MUSB_HDRC && ((BF54x && !BF544) || (BF52x && !BF522 && !BF523)) |
| 53 | 54 | ||
| 54 | config USB_TUSB6010 | 55 | config USB_TUSB6010 |
| 55 | boolean "TUSB 6010 support" | 56 | boolean "TUSB 6010 support" |
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 5ad6d0893cbe..569ef0fed0f6 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <linux/usb.h> | 9 | #include <linux/usb.h> |
| 10 | 10 | ||
| 11 | #include "musb_core.h" | 11 | #include "musb_core.h" |
| 12 | #include "musb_debug.h" | ||
| 12 | #include "cppi_dma.h" | 13 | #include "cppi_dma.h" |
| 13 | 14 | ||
| 14 | 15 | ||
| @@ -423,6 +424,7 @@ cppi_rndis_update(struct cppi_channel *c, int is_rx, | |||
| 423 | } | 424 | } |
| 424 | } | 425 | } |
| 425 | 426 | ||
| 427 | #ifdef CONFIG_USB_MUSB_DEBUG | ||
| 426 | static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd) | 428 | static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd) |
| 427 | { | 429 | { |
| 428 | pr_debug("RXBD/%s %08x: " | 430 | pr_debug("RXBD/%s %08x: " |
| @@ -431,10 +433,11 @@ static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd) | |||
| 431 | bd->hw_next, bd->hw_bufp, bd->hw_off_len, | 433 | bd->hw_next, bd->hw_bufp, bd->hw_off_len, |
| 432 | bd->hw_options); | 434 | bd->hw_options); |
| 433 | } | 435 | } |
| 436 | #endif | ||
| 434 | 437 | ||
| 435 | static void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx) | 438 | static void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx) |
| 436 | { | 439 | { |
| 437 | #if MUSB_DEBUG > 0 | 440 | #ifdef CONFIG_USB_MUSB_DEBUG |
| 438 | struct cppi_descriptor *bd; | 441 | struct cppi_descriptor *bd; |
| 439 | 442 | ||
| 440 | if (!_dbg_level(level)) | 443 | if (!_dbg_level(level)) |
| @@ -881,12 +884,14 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket) | |||
| 881 | bd->hw_options |= CPPI_SOP_SET; | 884 | bd->hw_options |= CPPI_SOP_SET; |
| 882 | tail->hw_options |= CPPI_EOP_SET; | 885 | tail->hw_options |= CPPI_EOP_SET; |
| 883 | 886 | ||
| 884 | if (debug >= 5) { | 887 | #ifdef CONFIG_USB_MUSB_DEBUG |
| 888 | if (_dbg_level(5)) { | ||
| 885 | struct cppi_descriptor *d; | 889 | struct cppi_descriptor *d; |
| 886 | 890 | ||
| 887 | for (d = rx->head; d; d = d->next) | 891 | for (d = rx->head; d; d = d->next) |
| 888 | cppi_dump_rxbd("S", d); | 892 | cppi_dump_rxbd("S", d); |
| 889 | } | 893 | } |
| 894 | #endif | ||
| 890 | 895 | ||
| 891 | /* in case the preceding transfer left some state... */ | 896 | /* in case the preceding transfer left some state... */ |
| 892 | tail = rx->last_processed; | 897 | tail = rx->last_processed; |
| @@ -990,6 +995,7 @@ static int cppi_channel_program(struct dma_channel *ch, | |||
| 990 | cppi_ch->offset = 0; | 995 | cppi_ch->offset = 0; |
| 991 | cppi_ch->maxpacket = maxpacket; | 996 | cppi_ch->maxpacket = maxpacket; |
| 992 | cppi_ch->buf_len = len; | 997 | cppi_ch->buf_len = len; |
| 998 | cppi_ch->channel.actual_len = 0; | ||
| 993 | 999 | ||
| 994 | /* TX channel? or RX? */ | 1000 | /* TX channel? or RX? */ |
| 995 | if (cppi_ch->transmit) | 1001 | if (cppi_ch->transmit) |
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 0d566dc5ce06..5a8fd5d57a11 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c | |||
| @@ -32,9 +32,10 @@ | |||
| 32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
| 33 | #include <linux/gpio.h> | 33 | #include <linux/gpio.h> |
| 34 | 34 | ||
| 35 | #include <mach/arch/hardware.h> | 35 | #include <mach/hardware.h> |
| 36 | #include <mach/arch/memory.h> | 36 | #include <mach/memory.h> |
| 37 | #include <mach/arch/gpio.h> | 37 | #include <mach/gpio.h> |
| 38 | |||
| 38 | #include <asm/mach-types.h> | 39 | #include <asm/mach-types.h> |
| 39 | 40 | ||
| 40 | #include "musb_core.h" | 41 | #include "musb_core.h" |
| @@ -370,12 +371,6 @@ int musb_platform_set_mode(struct musb *musb, u8 mode) | |||
| 370 | return -EIO; | 371 | return -EIO; |
| 371 | } | 372 | } |
| 372 | 373 | ||
| 373 | int musb_platform_set_mode(struct musb *musb, u8 mode) | ||
| 374 | { | ||
| 375 | /* EVM can't do this (right?) */ | ||
| 376 | return -EIO; | ||
| 377 | } | ||
| 378 | |||
| 379 | int __init musb_platform_init(struct musb *musb) | 374 | int __init musb_platform_init(struct musb *musb) |
| 380 | { | 375 | { |
| 381 | void __iomem *tibase = musb->ctrl_base; | 376 | void __iomem *tibase = musb->ctrl_base; |
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 6c7faacfb535..2cc34fa05b73 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
| @@ -1824,8 +1824,9 @@ static void musb_free(struct musb *musb) | |||
| 1824 | musb_gadget_cleanup(musb); | 1824 | musb_gadget_cleanup(musb); |
| 1825 | #endif | 1825 | #endif |
| 1826 | 1826 | ||
| 1827 | if (musb->nIrq >= 0 && musb->irq_wake) { | 1827 | if (musb->nIrq >= 0) { |
| 1828 | disable_irq_wake(musb->nIrq); | 1828 | if (musb->irq_wake) |
| 1829 | disable_irq_wake(musb->nIrq); | ||
| 1829 | free_irq(musb->nIrq, musb); | 1830 | free_irq(musb->nIrq, musb); |
| 1830 | } | 1831 | } |
| 1831 | if (is_dma_capable() && musb->dma_controller) { | 1832 | if (is_dma_capable() && musb->dma_controller) { |
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 6197daeab8f9..4ea305387981 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c | |||
| @@ -874,10 +874,10 @@ static int musb_gadget_enable(struct usb_ep *ep, | |||
| 874 | status = -EBUSY; | 874 | status = -EBUSY; |
| 875 | goto fail; | 875 | goto fail; |
| 876 | } | 876 | } |
| 877 | musb_ep->type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; | 877 | musb_ep->type = usb_endpoint_type(desc); |
| 878 | 878 | ||
| 879 | /* check direction and (later) maxpacket size against endpoint */ | 879 | /* check direction and (later) maxpacket size against endpoint */ |
| 880 | if ((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) != epnum) | 880 | if (usb_endpoint_num(desc) != epnum) |
| 881 | goto fail; | 881 | goto fail; |
| 882 | 882 | ||
| 883 | /* REVISIT this rules out high bandwidth periodic transfers */ | 883 | /* REVISIT this rules out high bandwidth periodic transfers */ |
| @@ -890,7 +890,7 @@ static int musb_gadget_enable(struct usb_ep *ep, | |||
| 890 | * packet size (or fail), set the mode, clear the fifo | 890 | * packet size (or fail), set the mode, clear the fifo |
| 891 | */ | 891 | */ |
| 892 | musb_ep_select(mbase, epnum); | 892 | musb_ep_select(mbase, epnum); |
| 893 | if (desc->bEndpointAddress & USB_DIR_IN) { | 893 | if (usb_endpoint_dir_in(desc)) { |
| 894 | u16 int_txe = musb_readw(mbase, MUSB_INTRTXE); | 894 | u16 int_txe = musb_readw(mbase, MUSB_INTRTXE); |
| 895 | 895 | ||
| 896 | if (hw_ep->is_shared_fifo) | 896 | if (hw_ep->is_shared_fifo) |
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 99fa61234876..a035ceccf950 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c | |||
| @@ -1847,8 +1847,8 @@ static int musb_urb_enqueue( | |||
| 1847 | goto done; | 1847 | goto done; |
| 1848 | } | 1848 | } |
| 1849 | 1849 | ||
| 1850 | qh->epnum = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | 1850 | qh->epnum = usb_endpoint_num(epd); |
| 1851 | qh->type = epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; | 1851 | qh->type = usb_endpoint_type(epd); |
| 1852 | 1852 | ||
| 1853 | /* NOTE: urb->dev->devnum is wrong during SET_ADDRESS */ | 1853 | /* NOTE: urb->dev->devnum is wrong during SET_ADDRESS */ |
| 1854 | qh->addr_reg = (u8) usb_pipedevice(urb->pipe); | 1854 | qh->addr_reg = (u8) usb_pipedevice(urb->pipe); |
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c index 52f7f29cebda..7e073a0d7ac9 100644 --- a/drivers/usb/musb/tusb6010_omap.c +++ b/drivers/usb/musb/tusb6010_omap.c | |||
| @@ -15,8 +15,8 @@ | |||
| 15 | #include <linux/usb.h> | 15 | #include <linux/usb.h> |
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/dma-mapping.h> | 17 | #include <linux/dma-mapping.h> |
| 18 | #include <asm/arch/dma.h> | 18 | #include <mach/dma.h> |
| 19 | #include <asm/arch/mux.h> | 19 | #include <mach/mux.h> |
| 20 | 20 | ||
| 21 | #include "musb_core.h" | 21 | #include "musb_core.h" |
| 22 | 22 | ||
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 8e8dbdb9b39b..ee55b449ffde 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig | |||
| @@ -6,14 +6,14 @@ | |||
| 6 | 6 | ||
| 7 | comment "OTG and related infrastructure" | 7 | comment "OTG and related infrastructure" |
| 8 | 8 | ||
| 9 | if USB || USB_GADGET | ||
| 10 | |||
| 11 | config USB_OTG_UTILS | 9 | config USB_OTG_UTILS |
| 12 | bool | 10 | bool |
| 13 | help | 11 | help |
| 14 | Select this to make sure the build includes objects from | 12 | Select this to make sure the build includes objects from |
| 15 | the OTG infrastructure directory. | 13 | the OTG infrastructure directory. |
| 16 | 14 | ||
| 15 | if USB || USB_GADGET | ||
| 16 | |||
| 17 | # | 17 | # |
| 18 | # USB Transceiver Drivers | 18 | # USB Transceiver Drivers |
| 19 | # | 19 | # |
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index cfaf1f085535..027f4b7dde86 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c | |||
| @@ -85,6 +85,8 @@ static struct usb_device_id id_table [] = { | |||
| 85 | { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ | 85 | { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ |
| 86 | { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ | 86 | { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ |
| 87 | { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ | 87 | { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ |
| 88 | { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ | ||
| 89 | { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demostration module */ | ||
| 88 | { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ | 90 | { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ |
| 89 | { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ | 91 | { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ |
| 90 | { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ | 92 | { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c70a8f667d85..75597337583e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
| @@ -660,6 +660,8 @@ static struct usb_device_id id_table_combined [] = { | |||
| 660 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, | 660 | { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) }, |
| 661 | { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) }, | 661 | { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DGQG_PID) }, |
| 662 | { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, | 662 | { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) }, |
| 663 | { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, | ||
| 664 | { USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) }, | ||
| 663 | { }, /* Optional parameter entry */ | 665 | { }, /* Optional parameter entry */ |
| 664 | { } /* Terminating entry */ | 666 | { } /* Terminating entry */ |
| 665 | }; | 667 | }; |
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 373ee09975bb..1b62eff475d2 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h | |||
| @@ -854,6 +854,10 @@ | |||
| 854 | #define FTDI_DOMINTELL_DGQG_PID 0xEF50 /* Master */ | 854 | #define FTDI_DOMINTELL_DGQG_PID 0xEF50 /* Master */ |
| 855 | #define FTDI_DOMINTELL_DUSB_PID 0xEF51 /* DUSB01 module */ | 855 | #define FTDI_DOMINTELL_DUSB_PID 0xEF51 /* DUSB01 module */ |
| 856 | 856 | ||
| 857 | /* Alti-2 products http://www.alti-2.com */ | ||
| 858 | #define ALTI2_VID 0x1BC9 | ||
| 859 | #define ALTI2_N3_PID 0x6001 /* Neptune 3 */ | ||
| 860 | |||
| 857 | /* Commands */ | 861 | /* Commands */ |
| 858 | #define FTDI_SIO_RESET 0 /* Reset the port */ | 862 | #define FTDI_SIO_RESET 0 /* Reset the port */ |
| 859 | #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ | 863 | #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ |
| @@ -881,6 +885,11 @@ | |||
| 881 | #define RATOC_PRODUCT_ID_USB60F 0xb020 | 885 | #define RATOC_PRODUCT_ID_USB60F 0xb020 |
| 882 | 886 | ||
| 883 | /* | 887 | /* |
| 888 | * DIEBOLD BCS SE923 | ||
| 889 | */ | ||
| 890 | #define DIEBOLD_BCS_SE923_PID 0xfb99 | ||
| 891 | |||
| 892 | /* | ||
| 884 | * BmRequestType: 1100 0000b | 893 | * BmRequestType: 1100 0000b |
| 885 | * bRequest: FTDI_E2_READ | 894 | * bRequest: FTDI_E2_READ |
| 886 | * wValue: 0 | 895 | * wValue: 0 |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5ed183477aaf..6c89da9c6fea 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
| @@ -158,6 +158,13 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po | |||
| 158 | #define HUAWEI_PRODUCT_E143E 0x143E | 158 | #define HUAWEI_PRODUCT_E143E 0x143E |
| 159 | #define HUAWEI_PRODUCT_E143F 0x143F | 159 | #define HUAWEI_PRODUCT_E143F 0x143F |
| 160 | 160 | ||
| 161 | #define QUANTA_VENDOR_ID 0x0408 | ||
| 162 | #define QUANTA_PRODUCT_Q101 0xEA02 | ||
| 163 | #define QUANTA_PRODUCT_Q111 0xEA03 | ||
| 164 | #define QUANTA_PRODUCT_GLX 0xEA04 | ||
| 165 | #define QUANTA_PRODUCT_GKE 0xEA05 | ||
| 166 | #define QUANTA_PRODUCT_GLE 0xEA06 | ||
| 167 | |||
| 161 | #define NOVATELWIRELESS_VENDOR_ID 0x1410 | 168 | #define NOVATELWIRELESS_VENDOR_ID 0x1410 |
| 162 | 169 | ||
| 163 | /* YISO PRODUCTS */ | 170 | /* YISO PRODUCTS */ |
| @@ -224,7 +231,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po | |||
| 224 | #define ONDA_VENDOR_ID 0x19d2 | 231 | #define ONDA_VENDOR_ID 0x19d2 |
| 225 | #define ONDA_PRODUCT_MSA501HS 0x0001 | 232 | #define ONDA_PRODUCT_MSA501HS 0x0001 |
| 226 | #define ONDA_PRODUCT_ET502HS 0x0002 | 233 | #define ONDA_PRODUCT_ET502HS 0x0002 |
| 227 | #define ONDA_PRODUCT_MT503HS 0x0200 | 234 | #define ONDA_PRODUCT_MT503HS 0x2000 |
| 228 | 235 | ||
| 229 | #define BANDRICH_VENDOR_ID 0x1A8D | 236 | #define BANDRICH_VENDOR_ID 0x1A8D |
| 230 | #define BANDRICH_PRODUCT_C100_1 0x1002 | 237 | #define BANDRICH_PRODUCT_C100_1 0x1002 |
| @@ -298,6 +305,11 @@ static struct usb_device_id option_ids[] = { | |||
| 298 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) }, | 305 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) }, |
| 299 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) }, | 306 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) }, |
| 300 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) }, | 307 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) }, |
| 308 | { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q101) }, | ||
| 309 | { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q111) }, | ||
| 310 | { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, | ||
| 311 | { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) }, | ||
| 312 | { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, | ||
| 301 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) }, | 313 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) }, |
| 302 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, | 314 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, |
| 303 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, | 315 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, |
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 3cf41df302d7..baf591137b80 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c | |||
| @@ -184,6 +184,7 @@ static struct usb_device_id ti_id_table_3410[7+TI_EXTRA_VID_PID_COUNT+1] = { | |||
| 184 | { USB_DEVICE(MTS_VENDOR_ID, MTS_CDMA_PRODUCT_ID) }, | 184 | { USB_DEVICE(MTS_VENDOR_ID, MTS_CDMA_PRODUCT_ID) }, |
| 185 | { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_PRODUCT_ID) }, | 185 | { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_PRODUCT_ID) }, |
| 186 | { USB_DEVICE(MTS_VENDOR_ID, MTS_EDGE_PRODUCT_ID) }, | 186 | { USB_DEVICE(MTS_VENDOR_ID, MTS_EDGE_PRODUCT_ID) }, |
| 187 | { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, | ||
| 187 | }; | 188 | }; |
| 188 | 189 | ||
| 189 | static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = { | 190 | static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = { |
| @@ -191,6 +192,7 @@ static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = { | |||
| 191 | { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) }, | 192 | { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) }, |
| 192 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) }, | 193 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) }, |
| 193 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, | 194 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, |
| 195 | { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, | ||
| 194 | }; | 196 | }; |
| 195 | 197 | ||
| 196 | static struct usb_device_id ti_id_table_combined[6+2*TI_EXTRA_VID_PID_COUNT+1] = { | 198 | static struct usb_device_id ti_id_table_combined[6+2*TI_EXTRA_VID_PID_COUNT+1] = { |
| @@ -205,6 +207,7 @@ static struct usb_device_id ti_id_table_combined[6+2*TI_EXTRA_VID_PID_COUNT+1] = | |||
| 205 | { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) }, | 207 | { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) }, |
| 206 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) }, | 208 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) }, |
| 207 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, | 209 | { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, |
| 210 | { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, | ||
| 208 | { } | 211 | { } |
| 209 | }; | 212 | }; |
| 210 | 213 | ||
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h index 7e4752fbf232..b7ea5dbadee5 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.h +++ b/drivers/usb/serial/ti_usb_3410_5052.h | |||
| @@ -27,7 +27,9 @@ | |||
| 27 | 27 | ||
| 28 | /* Vendor and product ids */ | 28 | /* Vendor and product ids */ |
| 29 | #define TI_VENDOR_ID 0x0451 | 29 | #define TI_VENDOR_ID 0x0451 |
| 30 | #define IBM_VENDOR_ID 0x04b3 | ||
| 30 | #define TI_3410_PRODUCT_ID 0x3410 | 31 | #define TI_3410_PRODUCT_ID 0x3410 |
| 32 | #define IBM_4543_PRODUCT_ID 0x4543 | ||
| 31 | #define TI_3410_EZ430_ID 0xF430 /* TI ez430 development tool */ | 33 | #define TI_3410_EZ430_ID 0xF430 /* TI ez430 development tool */ |
| 32 | #define TI_5052_BOOT_PRODUCT_ID 0x5052 /* no EEPROM, no firmware */ | 34 | #define TI_5052_BOOT_PRODUCT_ID 0x5052 /* no EEPROM, no firmware */ |
| 33 | #define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */ | 35 | #define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */ |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index a7f9513fa19d..69269f739563 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
| @@ -995,6 +995,16 @@ UNUSUAL_DEV( 0x071b, 0x3203, 0x0000, 0x0000, | |||
| 995 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 995 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 996 | US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64), | 996 | US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64), |
| 997 | 997 | ||
| 998 | /* Reported by Jean-Baptiste Onofre <jb@nanthrax.net> | ||
| 999 | * Support the following product : | ||
| 1000 | * "Dane-Elec MediaTouch" | ||
| 1001 | */ | ||
| 1002 | UNUSUAL_DEV( 0x071b, 0x32bb, 0x0000, 0x0000, | ||
| 1003 | "RockChip", | ||
| 1004 | "MTP", | ||
| 1005 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
| 1006 | US_FL_NO_WP_DETECT | US_FL_MAX_SECTORS_64), | ||
| 1007 | |||
| 998 | /* Reported by Massimiliano Ghilardi <massimiliano.ghilardi@gmail.com> | 1008 | /* Reported by Massimiliano Ghilardi <massimiliano.ghilardi@gmail.com> |
| 999 | * This USB MP3/AVI player device fails and disconnects if more than 128 | 1009 | * This USB MP3/AVI player device fails and disconnects if more than 128 |
| 1000 | * sectors (64kB) are read/written in a single command, and may be present | 1010 | * sectors (64kB) are read/written in a single command, and may be present |
| @@ -1251,6 +1261,13 @@ UNUSUAL_DEV( 0x0840, 0x0084, 0x0001, 0x0001, | |||
| 1251 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1261 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 1252 | US_FL_FIX_CAPACITY), | 1262 | US_FL_FIX_CAPACITY), |
| 1253 | 1263 | ||
| 1264 | /* Reported by Martijn Hijdra <martijn.hijdra@gmail.com> */ | ||
| 1265 | UNUSUAL_DEV( 0x0840, 0x0085, 0x0001, 0x0001, | ||
| 1266 | "Argosy", | ||
| 1267 | "Storage", | ||
| 1268 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
| 1269 | US_FL_FIX_CAPACITY), | ||
| 1270 | |||
| 1254 | /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>. | 1271 | /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>. |
| 1255 | * Flag will support Bulk devices which use a standards-violating 32-byte | 1272 | * Flag will support Bulk devices which use a standards-violating 32-byte |
| 1256 | * Command Block Wrapper. Here, the "DC2MEGA" cameras (several brands) with | 1273 | * Command Block Wrapper. Here, the "DC2MEGA" cameras (several brands) with |
| @@ -1589,6 +1606,13 @@ UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, | |||
| 1589 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1606 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 1590 | US_FL_NO_WP_DETECT ), | 1607 | US_FL_NO_WP_DETECT ), |
| 1591 | 1608 | ||
| 1609 | /* Reported by The Solutor <thesolutor@gmail.com> */ | ||
| 1610 | UNUSUAL_DEV( 0x0fce, 0xd0e1, 0x0000, 0x0000, | ||
| 1611 | "Sony Ericsson", | ||
| 1612 | "MD400", | ||
| 1613 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
| 1614 | US_FL_IGNORE_DEVICE), | ||
| 1615 | |||
| 1592 | /* Reported by Jan Mate <mate@fiit.stuba.sk> | 1616 | /* Reported by Jan Mate <mate@fiit.stuba.sk> |
| 1593 | * and by Soeren Sonnenburg <kernel@nn7.de> */ | 1617 | * and by Soeren Sonnenburg <kernel@nn7.de> */ |
| 1594 | UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, | 1618 | UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, |
| @@ -2031,15 +2055,11 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, | |||
| 2031 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 2055 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 2032 | US_FL_IGNORE_RESIDUE ), | 2056 | US_FL_IGNORE_RESIDUE ), |
| 2033 | 2057 | ||
| 2034 | /* Reported by Mauro Andreolini <andreoli@weblab.ing.unimo.it> | 2058 | UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001, |
| 2035 | * This entry is needed to bypass the ZeroCD mechanism | 2059 | "ST", |
| 2036 | * and to properly load as a modem device. | 2060 | "2A", |
| 2037 | */ | ||
| 2038 | UNUSUAL_DEV( 0x19d2, 0x2000, 0x0000, 0x0000, | ||
| 2039 | "Onda ET502HS", | ||
| 2040 | "USB MMC Storage", | ||
| 2041 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 2061 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
| 2042 | US_FL_IGNORE_DEVICE), | 2062 | US_FL_FIX_CAPACITY), |
| 2043 | 2063 | ||
| 2044 | /* patch submitted by Davide Perini <perini.davide@dpsoftware.org> | 2064 | /* patch submitted by Davide Perini <perini.davide@dpsoftware.org> |
| 2045 | * and Renato Perini <rperini@email.it> | 2065 | * and Renato Perini <rperini@email.it> |
diff --git a/include/linux/usb.h b/include/linux/usb.h index 85ee9be9361e..88079fd60235 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
| @@ -418,6 +418,8 @@ struct usb_tt; | |||
| 418 | * @autosuspend_disabled: autosuspend disabled by the user | 418 | * @autosuspend_disabled: autosuspend disabled by the user |
| 419 | * @autoresume_disabled: autoresume disabled by the user | 419 | * @autoresume_disabled: autoresume disabled by the user |
| 420 | * @skip_sys_resume: skip the next system resume | 420 | * @skip_sys_resume: skip the next system resume |
| 421 | * @wusb_dev: if this is a Wireless USB device, link to the WUSB | ||
| 422 | * specific data for the device. | ||
| 421 | * | 423 | * |
| 422 | * Notes: | 424 | * Notes: |
| 423 | * Usbcore drivers should not set usbdev->state directly. Instead use | 425 | * Usbcore drivers should not set usbdev->state directly. Instead use |
