Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: EHCI: make ehci-tegra a separate driver

Separate the Tegra on-chip host controller driver from
ehci-hcd host code so that it can be built as a separate driver module.
This work is part of enabling multi-platform kernels on ARM.

Signed-off-by: Manjunath Goudar <manjunath.goudar@linaro.org>
[swarren, reworked Manjunath's patches to split them more logically,
minor re-order of added lines to better match layout of other split-up
HCD drivers and existing code, add MODULE_DEVICE_TABLE, fix
MODULE_LICENSE, adapted to change in earlier patches which removed the
ehci_driver_overrides addition, removed all PM code and solved circular
dependencies.]
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Tested-by: Thierry Reding <thierry.reding@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Manjunath Goudar and committed by
Greg Kroah-Hartman
9fc5f24e 91a687d8

+76 -60
+1 -1
drivers/usb/host/Kconfig
··· 198 198 has an external PHY. 199 199 200 200 config USB_EHCI_TEGRA 201 - boolean "NVIDIA Tegra HCD support" 201 + tristate "NVIDIA Tegra HCD support" 202 202 depends on ARCH_TEGRA 203 203 select USB_EHCI_ROOT_HUB_TT 204 204 select USB_PHY
+1
drivers/usb/host/Makefile
··· 33 33 obj-$(CONFIG_USB_EHCI_S5P) += ehci-s5p.o 34 34 obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o 35 35 obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o 36 + obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o 36 37 37 38 obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o 38 39 obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
-5
drivers/usb/host/ehci-hcd.c
··· 1269 1269 #define PLATFORM_DRIVER ehci_hcd_msp_driver 1270 1270 #endif 1271 1271 1272 - #ifdef CONFIG_USB_EHCI_TEGRA 1273 - #include "ehci-tegra.c" 1274 - #define PLATFORM_DRIVER tegra_ehci_driver 1275 - #endif 1276 - 1277 1272 #ifdef CONFIG_SPARC_LEON 1278 1273 #include "ehci-grlib.c" 1279 1274 #define PLATFORM_DRIVER ehci_grlib_driver
+74 -54
drivers/usb/host/ehci-tegra.c
··· 17 17 */ 18 18 19 19 #include <linux/clk.h> 20 + #include <linux/clk/tegra.h> 21 + #include <linux/dma-mapping.h> 20 22 #include <linux/err.h> 21 - #include <linux/platform_device.h> 22 - #include <linux/platform_data/tegra_usb.h> 23 - #include <linux/irq.h> 24 - #include <linux/usb/otg.h> 25 23 #include <linux/gpio.h> 24 + #include <linux/io.h> 25 + #include <linux/irq.h> 26 + #include <linux/module.h> 26 27 #include <linux/of.h> 27 28 #include <linux/of_gpio.h> 29 + #include <linux/platform_device.h> 30 + #include <linux/platform_data/tegra_usb.h> 28 31 #include <linux/pm_runtime.h> 32 + #include <linux/slab.h> 29 33 #include <linux/usb/ehci_def.h> 30 34 #include <linux/usb/tegra_usb_phy.h> 31 - #include <linux/clk/tegra.h> 35 + #include <linux/usb.h> 36 + #include <linux/usb/hcd.h> 37 + #include <linux/usb/otg.h> 38 + 39 + #include "ehci.h" 32 40 33 41 #define TEGRA_USB_BASE 0xC5000000 34 42 #define TEGRA_USB2_BASE 0xC5004000 35 43 #define TEGRA_USB3_BASE 0xC5008000 36 44 45 + #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) 46 + 37 47 #define TEGRA_USB_DMA_ALIGN 32 48 + 49 + #define DRIVER_DESC "Tegra EHCI driver" 50 + #define DRV_NAME "tegra-ehci" 51 + 52 + static struct hc_driver __read_mostly tegra_ehci_hc_driver; 53 + 54 + static int (*orig_hub_control)(struct usb_hcd *hcd, 55 + u16 typeReq, u16 wValue, u16 wIndex, 56 + char *buf, u16 wLength); 38 57 39 58 struct tegra_ehci_hcd { 40 59 struct ehci_hcd *ehci; ··· 237 218 spin_unlock_irqrestore(&ehci->lock, flags); 238 219 239 220 /* Handle the hub control events here */ 240 - return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); 221 + return orig_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); 222 + 241 223 done: 242 224 spin_unlock_irqrestore(&ehci->lock, flags); 243 225 return retval; 244 - } 245 - 246 - static int tegra_ehci_setup(struct usb_hcd *hcd) 247 - { 248 - struct ehci_hcd *ehci = hcd_to_ehci(hcd); 249 - 250 - /* EHCI registers start at offset 0x100 */ 251 - ehci->caps = hcd->regs + 0x100; 252 - 253 - /* switch to host mode */ 254 - hcd->has_tt = 1; 255 - 256 - return ehci_setup(hcd); 257 226 } 258 227 259 228 struct dma_aligned_buffer { ··· 322 315 usb_hcd_unmap_urb_for_dma(hcd, urb); 323 316 free_dma_aligned_buffer(urb); 324 317 } 325 - 326 - static const struct hc_driver tegra_ehci_hc_driver = { 327 - .description = hcd_name, 328 - .product_desc = "Tegra EHCI Host Controller", 329 - .hcd_priv_size = sizeof(struct ehci_hcd), 330 - .flags = HCD_USB2 | HCD_MEMORY, 331 - 332 - /* standard ehci functions */ 333 - .irq = ehci_irq, 334 - .start = ehci_run, 335 - .stop = ehci_stop, 336 - .urb_enqueue = ehci_urb_enqueue, 337 - .urb_dequeue = ehci_urb_dequeue, 338 - .endpoint_disable = ehci_endpoint_disable, 339 - .endpoint_reset = ehci_endpoint_reset, 340 - .get_frame_number = ehci_get_frame, 341 - .hub_status_data = ehci_hub_status_data, 342 - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 343 - .relinquish_port = ehci_relinquish_port, 344 - .port_handed_over = ehci_port_handed_over, 345 - 346 - /* modified ehci functions for tegra */ 347 - .reset = tegra_ehci_setup, 348 - .shutdown = ehci_shutdown, 349 - .map_urb_for_dma = tegra_ehci_map_urb_for_dma, 350 - .unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma, 351 - .hub_control = tegra_ehci_hub_control, 352 - #ifdef CONFIG_PM 353 - .bus_suspend = ehci_bus_suspend, 354 - .bus_resume = ehci_bus_resume, 355 - #endif 356 - }; 357 318 358 319 static int setup_vbus_gpio(struct platform_device *pdev, 359 320 struct tegra_ehci_platform_data *pdata) ··· 419 444 err = -ENOMEM; 420 445 goto cleanup_clk; 421 446 } 447 + tegra->ehci = hcd_to_ehci(hcd); 448 + 449 + hcd->has_tt = 1; 422 450 hcd->phy = u_phy; 423 451 424 452 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ··· 438 460 err = -ENOMEM; 439 461 goto cleanup_hcd_create; 440 462 } 463 + tegra->ehci->caps = hcd->regs + 0x100; 441 464 442 465 err = usb_phy_init(hcd->phy); 443 466 if (err) { ··· 460 481 dev_err(&pdev->dev, "Failed to power on the phy\n"); 461 482 goto cleanup_phy; 462 483 } 463 - 464 - tegra->ehci = hcd_to_ehci(hcd); 465 484 466 485 irq = platform_get_irq(pdev, 0); 467 486 if (!irq) { ··· 535 558 .remove = tegra_ehci_remove, 536 559 .shutdown = tegra_ehci_hcd_shutdown, 537 560 .driver = { 538 - .name = "tegra-ehci", 561 + .name = DRV_NAME, 539 562 .of_match_table = tegra_ehci_of_match, 540 563 } 541 564 }; 565 + 566 + static const struct ehci_driver_overrides tegra_overrides __initconst = { 567 + .extra_priv_size = sizeof(struct tegra_ehci_hcd), 568 + }; 569 + 570 + static int __init ehci_tegra_init(void) 571 + { 572 + if (usb_disabled()) 573 + return -ENODEV; 574 + 575 + pr_info(DRV_NAME ": " DRIVER_DESC "\n"); 576 + 577 + ehci_init_driver(&tegra_ehci_hc_driver, &tegra_overrides); 578 + 579 + /* 580 + * The Tegra HW has some unusual quirks, which require Tegra-specific 581 + * workarounds. We override certain hc_driver functions here to 582 + * achieve that. We explicitly do not enhance ehci_driver_overrides to 583 + * allow this more easily, since this is an unusual case, and we don't 584 + * want to encourage others to override these functions by making it 585 + * too easy. 586 + */ 587 + 588 + orig_hub_control = tegra_ehci_hc_driver.hub_control; 589 + 590 + tegra_ehci_hc_driver.map_urb_for_dma = tegra_ehci_map_urb_for_dma; 591 + tegra_ehci_hc_driver.unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma; 592 + tegra_ehci_hc_driver.hub_control = tegra_ehci_hub_control; 593 + 594 + return platform_driver_register(&tegra_ehci_driver); 595 + } 596 + module_init(ehci_tegra_init); 597 + 598 + static void __exit ehci_tegra_cleanup(void) 599 + { 600 + platform_driver_unregister(&tegra_ehci_driver); 601 + } 602 + module_exit(ehci_tegra_cleanup); 603 + 604 + MODULE_DESCRIPTION(DRIVER_DESC); 605 + MODULE_LICENSE("GPL"); 606 + MODULE_ALIAS("platform:" DRV_NAME); 607 + MODULE_DEVICE_TABLE(of, tegra_ehci_of_match);