aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
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 /drivers/usb/host
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>
Diffstat (limited to 'drivers/usb/host')
-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
3 files changed, 78 insertions, 0 deletions
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 */