aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnatolij Gustschin <agust@denx.de>2011-04-18 16:02:00 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-02 19:59:38 -0400
commit83722bc9430424de1614ff31696f73a40b3d81a9 (patch)
tree4ff0ffe40e080ee03b9ede04b3e943b79335335f
parent0807c500a1a6d7fa20cbd7bbe7fea14a66112463 (diff)
USB: extend ehci-fsl and fsl_udc_core driver for OTG operation
Signed-off-by: Anatolij Gustschin <agust@denx.de> Cc: Li Yang <leoli@freescale.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c147
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.h2
-rw-r--r--drivers/usb/host/ehci-fsl.c66
-rw-r--r--drivers/usb/host/ehci-hub.c8
-rw-r--r--drivers/usb/host/ehci.h4
-rw-r--r--include/linux/fsl_devices.h1
6 files changed, 213 insertions, 15 deletions
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 28b3a9f25f3b..999eafe89653 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -353,6 +353,19 @@ static void dr_controller_stop(struct fsl_udc *udc)
353{ 353{
354 unsigned int tmp; 354 unsigned int tmp;
355 355
356 pr_debug("%s\n", __func__);
357
358 /* if we're in OTG mode, and the Host is currently using the port,
359 * stop now and don't rip the controller out from under the
360 * ehci driver
361 */
362 if (udc->gadget.is_otg) {
363 if (!(fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID)) {
364 pr_debug("udc: Leaving early\n");
365 return;
366 }
367 }
368
356 /* disable all INTR */ 369 /* disable all INTR */
357 fsl_writel(0, &dr_regs->usbintr); 370 fsl_writel(0, &dr_regs->usbintr);
358 371
@@ -1668,6 +1681,9 @@ static void port_change_irq(struct fsl_udc *udc)
1668{ 1681{
1669 u32 speed; 1682 u32 speed;
1670 1683
1684 if (udc->bus_reset)
1685 udc->bus_reset = 0;
1686
1671 /* Bus resetting is finished */ 1687 /* Bus resetting is finished */
1672 if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET)) { 1688 if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET)) {
1673 /* Get the speed */ 1689 /* Get the speed */
@@ -1775,6 +1791,8 @@ static void reset_irq(struct fsl_udc *udc)
1775 1791
1776 if (fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET) { 1792 if (fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET) {
1777 VDBG("Bus reset"); 1793 VDBG("Bus reset");
1794 /* Bus is reseting */
1795 udc->bus_reset = 1;
1778 /* Reset all the queues, include XD, dTD, EP queue 1796 /* Reset all the queues, include XD, dTD, EP queue
1779 * head and TR Queue */ 1797 * head and TR Queue */
1780 reset_queues(udc); 1798 reset_queues(udc);
@@ -1852,6 +1870,7 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
1852 1870
1853 /* Reset Received */ 1871 /* Reset Received */
1854 if (irq_src & USB_STS_RESET) { 1872 if (irq_src & USB_STS_RESET) {
1873 VDBG("reset int");
1855 reset_irq(udc); 1874 reset_irq(udc);
1856 status = IRQ_HANDLED; 1875 status = IRQ_HANDLED;
1857 } 1876 }
@@ -1909,11 +1928,30 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
1909 goto out; 1928 goto out;
1910 } 1929 }
1911 1930
1912 /* Enable DR IRQ reg and Set usbcmd reg Run bit */ 1931 if (udc_controller->transceiver) {
1913 dr_controller_run(udc_controller); 1932 /* Suspend the controller until OTG enable it */
1914 udc_controller->usb_state = USB_STATE_ATTACHED; 1933 udc_controller->stopped = 1;
1915 udc_controller->ep0_state = WAIT_FOR_SETUP; 1934 printk(KERN_INFO "Suspend udc for OTG auto detect\n");
1916 udc_controller->ep0_dir = 0; 1935
1936 /* connect to bus through transceiver */
1937 if (udc_controller->transceiver) {
1938 retval = otg_set_peripheral(udc_controller->transceiver,
1939 &udc_controller->gadget);
1940 if (retval < 0) {
1941 ERR("can't bind to transceiver\n");
1942 driver->unbind(&udc_controller->gadget);
1943 udc_controller->gadget.dev.driver = 0;
1944 udc_controller->driver = 0;
1945 return retval;
1946 }
1947 }
1948 } else {
1949 /* Enable DR IRQ reg and set USBCMD reg Run bit */
1950 dr_controller_run(udc_controller);
1951 udc_controller->usb_state = USB_STATE_ATTACHED;
1952 udc_controller->ep0_state = WAIT_FOR_SETUP;
1953 udc_controller->ep0_dir = 0;
1954 }
1917 printk(KERN_INFO "%s: bind to driver %s\n", 1955 printk(KERN_INFO "%s: bind to driver %s\n",
1918 udc_controller->gadget.name, driver->driver.name); 1956 udc_controller->gadget.name, driver->driver.name);
1919 1957
@@ -2374,17 +2412,30 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
2374 spin_lock_init(&udc_controller->lock); 2412 spin_lock_init(&udc_controller->lock);
2375 udc_controller->stopped = 1; 2413 udc_controller->stopped = 1;
2376 2414
2415#ifdef CONFIG_USB_OTG
2416 if (pdata->operating_mode == FSL_USB2_DR_OTG) {
2417 udc_controller->transceiver = otg_get_transceiver();
2418 if (!udc_controller->transceiver) {
2419 ERR("Can't find OTG driver!\n");
2420 ret = -ENODEV;
2421 goto err_kfree;
2422 }
2423 }
2424#endif
2425
2377 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2426 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2378 if (!res) { 2427 if (!res) {
2379 ret = -ENXIO; 2428 ret = -ENXIO;
2380 goto err_kfree; 2429 goto err_kfree;
2381 } 2430 }
2382 2431
2383 if (!request_mem_region(res->start, res->end - res->start + 1, 2432 if (pdata->operating_mode == FSL_USB2_DR_DEVICE) {
2384 driver_name)) { 2433 if (!request_mem_region(res->start, res->end - res->start + 1,
2385 ERR("request mem region for %s failed\n", pdev->name); 2434 driver_name)) {
2386 ret = -EBUSY; 2435 ERR("request mem region for %s failed\n", pdev->name);
2387 goto err_kfree; 2436 ret = -EBUSY;
2437 goto err_kfree;
2438 }
2388 } 2439 }
2389 2440
2390 dr_regs = ioremap(res->start, resource_size(res)); 2441 dr_regs = ioremap(res->start, resource_size(res));
@@ -2455,9 +2506,11 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
2455 goto err_free_irq; 2506 goto err_free_irq;
2456 } 2507 }
2457 2508
2458 /* initialize usb hw reg except for regs for EP, 2509 if (!udc_controller->transceiver) {
2459 * leave usbintr reg untouched */ 2510 /* initialize usb hw reg except for regs for EP,
2460 dr_controller_setup(udc_controller); 2511 * leave usbintr reg untouched */
2512 dr_controller_setup(udc_controller);
2513 }
2461 2514
2462 fsl_udc_clk_finalize(pdev); 2515 fsl_udc_clk_finalize(pdev);
2463 2516
@@ -2477,6 +2530,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
2477 if (ret < 0) 2530 if (ret < 0)
2478 goto err_free_irq; 2531 goto err_free_irq;
2479 2532
2533 if (udc_controller->transceiver)
2534 udc_controller->gadget.is_otg = 1;
2535
2480 /* setup QH and epctrl for ep0 */ 2536 /* setup QH and epctrl for ep0 */
2481 ep0_setup(udc_controller); 2537 ep0_setup(udc_controller);
2482 2538
@@ -2521,7 +2577,8 @@ err_iounmap:
2521err_iounmap_noclk: 2577err_iounmap_noclk:
2522 iounmap(dr_regs); 2578 iounmap(dr_regs);
2523err_release_mem_region: 2579err_release_mem_region:
2524 release_mem_region(res->start, res->end - res->start + 1); 2580 if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
2581 release_mem_region(res->start, res->end - res->start + 1);
2525err_kfree: 2582err_kfree:
2526 kfree(udc_controller); 2583 kfree(udc_controller);
2527 udc_controller = NULL; 2584 udc_controller = NULL;
@@ -2555,7 +2612,8 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
2555 dma_pool_destroy(udc_controller->td_pool); 2612 dma_pool_destroy(udc_controller->td_pool);
2556 free_irq(udc_controller->irq, udc_controller); 2613 free_irq(udc_controller->irq, udc_controller);
2557 iounmap(dr_regs); 2614 iounmap(dr_regs);
2558 release_mem_region(res->start, res->end - res->start + 1); 2615 if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
2616 release_mem_region(res->start, res->end - res->start + 1);
2559 2617
2560 device_unregister(&udc_controller->gadget.dev); 2618 device_unregister(&udc_controller->gadget.dev);
2561 /* free udc --wait for the release() finished */ 2619 /* free udc --wait for the release() finished */
@@ -2598,6 +2656,62 @@ static int fsl_udc_resume(struct platform_device *pdev)
2598 return 0; 2656 return 0;
2599} 2657}
2600 2658
2659static int fsl_udc_otg_suspend(struct device *dev, pm_message_t state)
2660{
2661 struct fsl_udc *udc = udc_controller;
2662 u32 mode, usbcmd;
2663
2664 mode = fsl_readl(&dr_regs->usbmode) & USB_MODE_CTRL_MODE_MASK;
2665
2666 pr_debug("%s(): mode 0x%x stopped %d\n", __func__, mode, udc->stopped);
2667
2668 /*
2669 * If the controller is already stopped, then this must be a
2670 * PM suspend. Remember this fact, so that we will leave the
2671 * controller stopped at PM resume time.
2672 */
2673 if (udc->stopped) {
2674 pr_debug("gadget already stopped, leaving early\n");
2675 udc->already_stopped = 1;
2676 return 0;
2677 }
2678
2679 if (mode != USB_MODE_CTRL_MODE_DEVICE) {
2680 pr_debug("gadget not in device mode, leaving early\n");
2681 return 0;
2682 }
2683
2684 /* stop the controller */
2685 usbcmd = fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP;
2686 fsl_writel(usbcmd, &dr_regs->usbcmd);
2687
2688 udc->stopped = 1;
2689
2690 pr_info("USB Gadget suspended\n");
2691
2692 return 0;
2693}
2694
2695static int fsl_udc_otg_resume(struct device *dev)
2696{
2697 pr_debug("%s(): stopped %d already_stopped %d\n", __func__,
2698 udc_controller->stopped, udc_controller->already_stopped);
2699
2700 /*
2701 * If the controller was stopped at suspend time, then
2702 * don't resume it now.
2703 */
2704 if (udc_controller->already_stopped) {
2705 udc_controller->already_stopped = 0;
2706 pr_debug("gadget was already stopped, leaving early\n");
2707 return 0;
2708 }
2709
2710 pr_info("USB Gadget resume\n");
2711
2712 return fsl_udc_resume(NULL);
2713}
2714
2601/*------------------------------------------------------------------------- 2715/*-------------------------------------------------------------------------
2602 Register entry point for the peripheral controller driver 2716 Register entry point for the peripheral controller driver
2603--------------------------------------------------------------------------*/ 2717--------------------------------------------------------------------------*/
@@ -2610,6 +2724,9 @@ static struct platform_driver udc_driver = {
2610 .driver = { 2724 .driver = {
2611 .name = (char *)driver_name, 2725 .name = (char *)driver_name,
2612 .owner = THIS_MODULE, 2726 .owner = THIS_MODULE,
2727 /* udc suspend/resume called from OTG driver */
2728 .suspend = fsl_udc_otg_suspend,
2729 .resume = fsl_udc_otg_resume,
2613 }, 2730 },
2614}; 2731};
2615 2732
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index 5647cc21b84c..1d51be83fda8 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -476,6 +476,7 @@ struct fsl_udc {
476 unsigned vbus_active:1; 476 unsigned vbus_active:1;
477 unsigned stopped:1; 477 unsigned stopped:1;
478 unsigned remote_wakeup:1; 478 unsigned remote_wakeup:1;
479 unsigned already_stopped:1;
479 unsigned big_endian_desc:1; 480 unsigned big_endian_desc:1;
480 481
481 struct ep_queue_head *ep_qh; /* Endpoints Queue-Head */ 482 struct ep_queue_head *ep_qh; /* Endpoints Queue-Head */
@@ -487,6 +488,7 @@ struct fsl_udc {
487 dma_addr_t ep_qh_dma; /* dma address of QH */ 488 dma_addr_t ep_qh_dma; /* dma address of QH */
488 489
489 u32 max_pipes; /* Device max pipes */ 490 u32 max_pipes; /* Device max pipes */
491 u32 bus_reset; /* Device is bus resetting */
490 u32 resume_state; /* USB state to resume */ 492 u32 resume_state; /* USB state to resume */
491 u32 usb_state; /* USB current state */ 493 u32 usb_state; /* USB current state */
492 u32 ep0_state; /* Endpoint zero state */ 494 u32 ep0_state; /* Endpoint zero state */
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index caf3d4ac42bd..623732a312dd 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -117,6 +117,9 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
117 117
118 pdata->regs = hcd->regs; 118 pdata->regs = hcd->regs;
119 119
120 if (pdata->power_budget)
121 hcd->power_budget = pdata->power_budget;
122
120 /* 123 /*
121 * do platform specific init: check the clock, grab/config pins, etc. 124 * do platform specific init: check the clock, grab/config pins, etc.
122 */ 125 */
@@ -134,6 +137,30 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
134 retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); 137 retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
135 if (retval != 0) 138 if (retval != 0)
136 goto err4; 139 goto err4;
140
141#ifdef CONFIG_USB_OTG
142 if (pdata->operating_mode == FSL_USB2_DR_OTG) {
143 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
144
145 ehci->transceiver = otg_get_transceiver();
146 dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, transceiver=0x%p\n",
147 hcd, ehci, ehci->transceiver);
148
149 if (ehci->transceiver) {
150 retval = otg_set_host(ehci->transceiver,
151 &ehci_to_hcd(ehci)->self);
152 if (retval) {
153 if (ehci->transceiver)
154 put_device(ehci->transceiver->dev);
155 goto err4;
156 }
157 } else {
158 dev_err(&pdev->dev, "can't find transceiver\n");
159 retval = -ENODEV;
160 goto err4;
161 }
162 }
163#endif
137 return retval; 164 return retval;
138 165
139 err4: 166 err4:
@@ -164,6 +191,12 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
164 struct platform_device *pdev) 191 struct platform_device *pdev)
165{ 192{
166 struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; 193 struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
194 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
195
196 if (ehci->transceiver) {
197 otg_set_host(ehci->transceiver, NULL);
198 put_device(ehci->transceiver->dev);
199 }
167 200
168 usb_remove_hcd(hcd); 201 usb_remove_hcd(hcd);
169 202
@@ -544,6 +577,38 @@ static struct dev_pm_ops ehci_fsl_pm_ops = {
544#define EHCI_FSL_PM_OPS NULL 577#define EHCI_FSL_PM_OPS NULL
545#endif /* CONFIG_PM */ 578#endif /* CONFIG_PM */
546 579
580#ifdef CONFIG_USB_OTG
581static int ehci_start_port_reset(struct usb_hcd *hcd, unsigned port)
582{
583 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
584 u32 status;
585
586 if (!port)
587 return -EINVAL;
588
589 port--;
590
591 /* start port reset before HNP protocol time out */
592 status = readl(&ehci->regs->port_status[port]);
593 if (!(status & PORT_CONNECT))
594 return -ENODEV;
595
596 /* khubd will finish the reset later */
597 if (ehci_is_TDI(ehci)) {
598 writel(PORT_RESET |
599 (status & ~(PORT_CSC | PORT_PEC | PORT_OCC)),
600 &ehci->regs->port_status[port]);
601 } else {
602 writel(PORT_RESET, &ehci->regs->port_status[port]);
603 }
604
605 return 0;
606}
607#else
608#define ehci_start_port_reset NULL
609#endif /* CONFIG_USB_OTG */
610
611
547static const struct hc_driver ehci_fsl_hc_driver = { 612static const struct hc_driver ehci_fsl_hc_driver = {
548 .description = hcd_name, 613 .description = hcd_name,
549 .product_desc = "Freescale On-Chip EHCI Host Controller", 614 .product_desc = "Freescale On-Chip EHCI Host Controller",
@@ -583,6 +648,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
583 .hub_control = ehci_hub_control, 648 .hub_control = ehci_hub_control,
584 .bus_suspend = ehci_bus_suspend, 649 .bus_suspend = ehci_bus_suspend,
585 .bus_resume = ehci_bus_resume, 650 .bus_resume = ehci_bus_resume,
651 .start_port_reset = ehci_start_port_reset,
586 .relinquish_port = ehci_relinquish_port, 652 .relinquish_port = ehci_relinquish_port,
587 .port_handed_over = ehci_port_handed_over, 653 .port_handed_over = ehci_port_handed_over,
588 654
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 1a21799195af..ea6184bf48d0 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -27,6 +27,7 @@
27 */ 27 */
28 28
29/*-------------------------------------------------------------------------*/ 29/*-------------------------------------------------------------------------*/
30#include <linux/usb/otg.h>
30 31
31#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) 32#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
32 33
@@ -801,6 +802,13 @@ static int ehci_hub_control (
801 goto error; 802 goto error;
802 if (ehci->no_selective_suspend) 803 if (ehci->no_selective_suspend)
803 break; 804 break;
805#ifdef CONFIG_USB_OTG
806 if ((hcd->self.otg_port == (wIndex + 1))
807 && hcd->self.b_hnp_enable) {
808 otg_start_hnp(ehci->transceiver);
809 break;
810 }
811#endif
804 if (!(temp & PORT_SUSPEND)) 812 if (!(temp & PORT_SUSPEND))
805 break; 813 break;
806 if ((temp & PORT_PE) == 0) 814 if ((temp & PORT_PE) == 0)
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 168f1a88c4d0..e9ba8e252489 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -161,6 +161,10 @@ struct ehci_hcd { /* one per controller */
161#ifdef DEBUG 161#ifdef DEBUG
162 struct dentry *debug_dir; 162 struct dentry *debug_dir;
163#endif 163#endif
164 /*
165 * OTG controllers and transceivers need software interaction
166 */
167 struct otg_transceiver *transceiver;
164}; 168};
165 169
166/* convert between an HCD pointer and the corresponding EHCI_HCD */ 170/* convert between an HCD pointer and the corresponding EHCI_HCD */
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 3773c5dab8f5..fffdf00f87b9 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -72,6 +72,7 @@ struct fsl_usb2_platform_data {
72 void (*exit)(struct platform_device *); 72 void (*exit)(struct platform_device *);
73 void __iomem *regs; /* ioremap'd register base */ 73 void __iomem *regs; /* ioremap'd register base */
74 struct clk *clk; 74 struct clk *clk;
75 unsigned power_budget; /* hcd->power_budget */
75 unsigned big_endian_mmio:1; 76 unsigned big_endian_mmio:1;
76 unsigned big_endian_desc:1; 77 unsigned big_endian_desc:1;
77 unsigned es:1; /* need USBMODE:ES */ 78 unsigned es:1; /* need USBMODE:ES */