diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-07 16:16:28 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-07 16:16:28 -0500 |
commit | 3e5b08cbbf78bedd316904ab0cf3b27119433ee5 (patch) | |
tree | 0365745c1b7441c1868551c024410c829c3accc6 /drivers/usb/host | |
parent | da40d036fd716f0efb2917076220814b1e927ae1 (diff) | |
parent | 2af10844eb6ed104f9505bf3a7ba3ceb02264f31 (diff) |
Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (144 commits)
USB: add support for Dream Cheeky DL100B Webmail Notifier (1d34:0004)
USB: serial: ftdi_sio: add support for TIOCSERGETLSR
USB: ehci-mxc: Setup portsc register prior to accessing OTG viewport
USB: atmel_usba_udc: fix freeing irq in usba_udc_remove()
usb: ehci-omap: fix tll channel enable mask
usb: ohci-omap3: fix trivial typo
USB: gadget: ci13xxx: don't assume that PAGE_SIZE is 4096
USB: gadget: ci13xxx: fix complete() callback for no_interrupt rq's
USB: gadget: update ci13xxx to work with g_ether
USB: gadgets: ci13xxx: fix probing of compiled-in gadget drivers
Revert "USB: musb: pm: don't rely fully on clock support"
Revert "USB: musb: blackfin: pm: make it work"
USB: uas: Use GFP_NOIO instead of GFP_KERNEL in I/O submission path
USB: uas: Ensure we only bind to a UAS interface
USB: uas: Rename sense pipe and sense urb to status pipe and status urb
USB: uas: Use kzalloc instead of kmalloc
USB: uas: Fix up the Sense IU
usb: musb: core: kill unneeded #include's
DA8xx: assign name to MUSB IRQ resource
usb: gadget: g_ncm added
...
Manually fix up trivial conflicts in USB Kconfig changes in:
arch/arm/mach-omap2/Kconfig
arch/sh/Kconfig
drivers/usb/Kconfig
drivers/usb/host/ehci-hcd.c
and annoying chip clock data conflicts in:
arch/arm/mach-omap2/clock3xxx_data.c
arch/arm/mach-omap2/clock44xx_data.c
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/Kconfig | 19 | ||||
-rw-r--r-- | drivers/usb/host/ehci-atmel.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/ehci-dbg.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 30 | ||||
-rw-r--r-- | drivers/usb/host/ehci-msm.c | 345 | ||||
-rw-r--r-- | drivers/usb/host/ehci-mxc.c | 29 | ||||
-rw-r--r-- | drivers/usb/host/ehci-omap.c | 316 | ||||
-rw-r--r-- | drivers/usb/host/ehci-pci.c | 39 | ||||
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 79 | ||||
-rw-r--r-- | drivers/usb/host/ehci-sh.c | 243 | ||||
-rw-r--r-- | drivers/usb/host/ehci-spear.c | 212 | ||||
-rw-r--r-- | drivers/usb/host/ehci-vt8500.c | 172 | ||||
-rw-r--r-- | drivers/usb/host/ehci-w90x900.c | 3 | ||||
-rw-r--r-- | drivers/usb/host/ehci-xilinx-of.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 1 | ||||
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/ohci-omap3.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ohci-sh.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ohci-spear.c | 240 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/uhci-q.c | 12 | ||||
-rw-r--r-- | drivers/usb/host/whci/hcd.c | 2 |
22 files changed, 1665 insertions, 94 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f8970d151d2a..24046c0f5878 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -133,6 +133,25 @@ config USB_EHCI_MXC | |||
133 | ---help--- | 133 | ---help--- |
134 | Variation of ARC USB block used in some Freescale chips. | 134 | Variation of ARC USB block used in some Freescale chips. |
135 | 135 | ||
136 | config USB_EHCI_HCD_OMAP | ||
137 | bool "EHCI support for OMAP3 and later chips" | ||
138 | depends on USB_EHCI_HCD && ARCH_OMAP | ||
139 | default y | ||
140 | --- help --- | ||
141 | Enables support for the on-chip EHCI controller on | ||
142 | OMAP3 and later chips. | ||
143 | |||
144 | config USB_EHCI_MSM | ||
145 | bool "Support for MSM on-chip EHCI USB controller" | ||
146 | depends on USB_EHCI_HCD && ARCH_MSM | ||
147 | select USB_EHCI_ROOT_HUB_TT | ||
148 | select USB_MSM_OTG_72K | ||
149 | ---help--- | ||
150 | Enables support for the USB Host controller present on the | ||
151 | Qualcomm chipsets. Root Hub has inbuilt TT. | ||
152 | This driver depends on OTG driver for PHY initialization, | ||
153 | clock management, powering up VBUS, and power management. | ||
154 | |||
136 | config USB_EHCI_HCD_PPC_OF | 155 | config USB_EHCI_HCD_PPC_OF |
137 | bool "EHCI support for PPC USB controller on OF platform bus" | 156 | bool "EHCI support for PPC USB controller on OF platform bus" |
138 | depends on USB_EHCI_HCD && PPC_OF | 157 | depends on USB_EHCI_HCD && PPC_OF |
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 51bd0edf544f..d6a69d514a84 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c | |||
@@ -99,6 +99,7 @@ static const struct hc_driver ehci_atmel_hc_driver = { | |||
99 | .urb_enqueue = ehci_urb_enqueue, | 99 | .urb_enqueue = ehci_urb_enqueue, |
100 | .urb_dequeue = ehci_urb_dequeue, | 100 | .urb_dequeue = ehci_urb_dequeue, |
101 | .endpoint_disable = ehci_endpoint_disable, | 101 | .endpoint_disable = ehci_endpoint_disable, |
102 | .endpoint_reset = ehci_endpoint_reset, | ||
102 | 103 | ||
103 | /* scheduling support */ | 104 | /* scheduling support */ |
104 | .get_frame_number = ehci_get_frame, | 105 | .get_frame_number = ehci_get_frame, |
@@ -110,6 +111,8 @@ static const struct hc_driver ehci_atmel_hc_driver = { | |||
110 | .bus_resume = ehci_bus_resume, | 111 | .bus_resume = ehci_bus_resume, |
111 | .relinquish_port = ehci_relinquish_port, | 112 | .relinquish_port = ehci_relinquish_port, |
112 | .port_handed_over = ehci_port_handed_over, | 113 | .port_handed_over = ehci_port_handed_over, |
114 | |||
115 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
113 | }; | 116 | }; |
114 | 117 | ||
115 | static int __init ehci_atmel_drv_probe(struct platform_device *pdev) | 118 | static int __init ehci_atmel_drv_probe(struct platform_device *pdev) |
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 6e2599661b5b..3be238a24cc5 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
@@ -879,7 +879,7 @@ static int fill_buffer(struct debug_buffer *buf) | |||
879 | int ret = 0; | 879 | int ret = 0; |
880 | 880 | ||
881 | if (!buf->output_buf) | 881 | if (!buf->output_buf) |
882 | buf->output_buf = (char *)vmalloc(buf->alloc_size); | 882 | buf->output_buf = vmalloc(buf->alloc_size); |
883 | 883 | ||
884 | if (!buf->output_buf) { | 884 | if (!buf->output_buf) { |
885 | ret = -ENOMEM; | 885 | ret = -ENOMEM; |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index d0c8f7c03e05..6fee3cd58efe 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -114,6 +114,9 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us\n"); | |||
114 | 114 | ||
115 | #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) | 115 | #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) |
116 | 116 | ||
117 | /* for ASPM quirk of ISOC on AMD SB800 */ | ||
118 | static struct pci_dev *amd_nb_dev; | ||
119 | |||
117 | /*-------------------------------------------------------------------------*/ | 120 | /*-------------------------------------------------------------------------*/ |
118 | 121 | ||
119 | #include "ehci.h" | 122 | #include "ehci.h" |
@@ -529,6 +532,11 @@ static void ehci_stop (struct usb_hcd *hcd) | |||
529 | spin_unlock_irq (&ehci->lock); | 532 | spin_unlock_irq (&ehci->lock); |
530 | ehci_mem_cleanup (ehci); | 533 | ehci_mem_cleanup (ehci); |
531 | 534 | ||
535 | if (amd_nb_dev) { | ||
536 | pci_dev_put(amd_nb_dev); | ||
537 | amd_nb_dev = NULL; | ||
538 | } | ||
539 | |||
532 | #ifdef EHCI_STATS | 540 | #ifdef EHCI_STATS |
533 | ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", | 541 | ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", |
534 | ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, | 542 | ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, |
@@ -1166,12 +1174,17 @@ MODULE_LICENSE ("GPL"); | |||
1166 | #define PLATFORM_DRIVER ehci_mxc_driver | 1174 | #define PLATFORM_DRIVER ehci_mxc_driver |
1167 | #endif | 1175 | #endif |
1168 | 1176 | ||
1177 | #ifdef CONFIG_CPU_SUBTYPE_SH7786 | ||
1178 | #include "ehci-sh.c" | ||
1179 | #define PLATFORM_DRIVER ehci_hcd_sh_driver | ||
1180 | #endif | ||
1181 | |||
1169 | #ifdef CONFIG_SOC_AU1200 | 1182 | #ifdef CONFIG_SOC_AU1200 |
1170 | #include "ehci-au1xxx.c" | 1183 | #include "ehci-au1xxx.c" |
1171 | #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver | 1184 | #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver |
1172 | #endif | 1185 | #endif |
1173 | 1186 | ||
1174 | #ifdef CONFIG_ARCH_OMAP3 | 1187 | #ifdef CONFIG_USB_EHCI_HCD_OMAP |
1175 | #include "ehci-omap.c" | 1188 | #include "ehci-omap.c" |
1176 | #define PLATFORM_DRIVER ehci_hcd_omap_driver | 1189 | #define PLATFORM_DRIVER ehci_hcd_omap_driver |
1177 | #endif | 1190 | #endif |
@@ -1221,6 +1234,21 @@ MODULE_LICENSE ("GPL"); | |||
1221 | #define PLATFORM_DRIVER cns3xxx_ehci_driver | 1234 | #define PLATFORM_DRIVER cns3xxx_ehci_driver |
1222 | #endif | 1235 | #endif |
1223 | 1236 | ||
1237 | #ifdef CONFIG_ARCH_VT8500 | ||
1238 | #include "ehci-vt8500.c" | ||
1239 | #define PLATFORM_DRIVER vt8500_ehci_driver | ||
1240 | #endif | ||
1241 | |||
1242 | #ifdef CONFIG_PLAT_SPEAR | ||
1243 | #include "ehci-spear.c" | ||
1244 | #define PLATFORM_DRIVER spear_ehci_hcd_driver | ||
1245 | #endif | ||
1246 | |||
1247 | #ifdef CONFIG_USB_EHCI_MSM | ||
1248 | #include "ehci-msm.c" | ||
1249 | #define PLATFORM_DRIVER ehci_msm_driver | ||
1250 | #endif | ||
1251 | |||
1224 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ | 1252 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ |
1225 | !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ | 1253 | !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ |
1226 | !defined(XILINX_OF_PLATFORM_DRIVER) | 1254 | !defined(XILINX_OF_PLATFORM_DRIVER) |
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c new file mode 100644 index 000000000000..413f4deca532 --- /dev/null +++ b/drivers/usb/host/ehci-msm.c | |||
@@ -0,0 +1,345 @@ | |||
1 | /* ehci-msm.c - HSUSB Host Controller Driver Implementation | ||
2 | * | ||
3 | * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. | ||
4 | * | ||
5 | * Partly derived from ehci-fsl.c and ehci-hcd.c | ||
6 | * Copyright (c) 2000-2004 by David Brownell | ||
7 | * Copyright (c) 2005 MontaVista Software | ||
8 | * | ||
9 | * All source code in this file is licensed under the following license except | ||
10 | * where indicated. | ||
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 version 2 as published | ||
14 | * by the Free Software Foundation. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
19 | * | ||
20 | * See the GNU General Public License for more details. | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, you can find it at http://www.fsf.org | ||
23 | */ | ||
24 | |||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/clk.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/pm_runtime.h> | ||
29 | |||
30 | #include <linux/usb/otg.h> | ||
31 | #include <linux/usb/msm_hsusb_hw.h> | ||
32 | |||
33 | #define MSM_USB_BASE (hcd->regs) | ||
34 | |||
35 | static struct otg_transceiver *otg; | ||
36 | |||
37 | /* | ||
38 | * ehci_run defined in drivers/usb/host/ehci-hcd.c reset the controller and | ||
39 | * the configuration settings in ehci_msm_reset vanish after controller is | ||
40 | * reset. Resetting the controler in ehci_run seems to be un-necessary | ||
41 | * provided HCD reset the controller before calling ehci_run. Most of the HCD | ||
42 | * do but some are not. So this function is same as ehci_run but we don't | ||
43 | * reset the controller here. | ||
44 | */ | ||
45 | static int ehci_msm_run(struct usb_hcd *hcd) | ||
46 | { | ||
47 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
48 | u32 temp; | ||
49 | u32 hcc_params; | ||
50 | |||
51 | hcd->uses_new_polling = 1; | ||
52 | |||
53 | ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); | ||
54 | ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next); | ||
55 | |||
56 | /* | ||
57 | * hcc_params controls whether ehci->regs->segment must (!!!) | ||
58 | * be used; it constrains QH/ITD/SITD and QTD locations. | ||
59 | * pci_pool consistent memory always uses segment zero. | ||
60 | * streaming mappings for I/O buffers, like pci_map_single(), | ||
61 | * can return segments above 4GB, if the device allows. | ||
62 | * | ||
63 | * NOTE: the dma mask is visible through dma_supported(), so | ||
64 | * drivers can pass this info along ... like NETIF_F_HIGHDMA, | ||
65 | * Scsi_Host.highmem_io, and so forth. It's readonly to all | ||
66 | * host side drivers though. | ||
67 | */ | ||
68 | hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); | ||
69 | if (HCC_64BIT_ADDR(hcc_params)) | ||
70 | ehci_writel(ehci, 0, &ehci->regs->segment); | ||
71 | |||
72 | /* | ||
73 | * Philips, Intel, and maybe others need CMD_RUN before the | ||
74 | * root hub will detect new devices (why?); NEC doesn't | ||
75 | */ | ||
76 | ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); | ||
77 | ehci->command |= CMD_RUN; | ||
78 | ehci_writel(ehci, ehci->command, &ehci->regs->command); | ||
79 | dbg_cmd(ehci, "init", ehci->command); | ||
80 | |||
81 | /* | ||
82 | * Start, enabling full USB 2.0 functionality ... usb 1.1 devices | ||
83 | * are explicitly handed to companion controller(s), so no TT is | ||
84 | * involved with the root hub. (Except where one is integrated, | ||
85 | * and there's no companion controller unless maybe for USB OTG.) | ||
86 | * | ||
87 | * Turning on the CF flag will transfer ownership of all ports | ||
88 | * from the companions to the EHCI controller. If any of the | ||
89 | * companions are in the middle of a port reset at the time, it | ||
90 | * could cause trouble. Write-locking ehci_cf_port_reset_rwsem | ||
91 | * guarantees that no resets are in progress. After we set CF, | ||
92 | * a short delay lets the hardware catch up; new resets shouldn't | ||
93 | * be started before the port switching actions could complete. | ||
94 | */ | ||
95 | down_write(&ehci_cf_port_reset_rwsem); | ||
96 | hcd->state = HC_STATE_RUNNING; | ||
97 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); | ||
98 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ | ||
99 | usleep_range(5000, 5500); | ||
100 | up_write(&ehci_cf_port_reset_rwsem); | ||
101 | ehci->last_periodic_enable = ktime_get_real(); | ||
102 | |||
103 | temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
104 | ehci_info(ehci, | ||
105 | "USB %x.%x started, EHCI %x.%02x%s\n", | ||
106 | ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), | ||
107 | temp >> 8, temp & 0xff, | ||
108 | ignore_oc ? ", overcurrent ignored" : ""); | ||
109 | |||
110 | ehci_writel(ehci, INTR_MASK, | ||
111 | &ehci->regs->intr_enable); /* Turn On Interrupts */ | ||
112 | |||
113 | /* GRR this is run-once init(), being done every time the HC starts. | ||
114 | * So long as they're part of class devices, we can't do it init() | ||
115 | * since the class device isn't created that early. | ||
116 | */ | ||
117 | create_debug_files(ehci); | ||
118 | create_companion_file(ehci); | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static int ehci_msm_reset(struct usb_hcd *hcd) | ||
124 | { | ||
125 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
126 | int retval; | ||
127 | |||
128 | ehci->caps = USB_CAPLENGTH; | ||
129 | ehci->regs = USB_CAPLENGTH + | ||
130 | HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
131 | |||
132 | /* cache the data to minimize the chip reads*/ | ||
133 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
134 | |||
135 | hcd->has_tt = 1; | ||
136 | ehci->sbrn = HCD_USB2; | ||
137 | |||
138 | /* data structure init */ | ||
139 | retval = ehci_init(hcd); | ||
140 | if (retval) | ||
141 | return retval; | ||
142 | |||
143 | retval = ehci_reset(ehci); | ||
144 | if (retval) | ||
145 | return retval; | ||
146 | |||
147 | /* bursts of unspecified length. */ | ||
148 | writel(0, USB_AHBBURST); | ||
149 | /* Use the AHB transactor */ | ||
150 | writel(0, USB_AHBMODE); | ||
151 | /* Disable streaming mode and select host mode */ | ||
152 | writel(0x13, USB_USBMODE); | ||
153 | |||
154 | ehci_port_power(ehci, 1); | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static struct hc_driver msm_hc_driver = { | ||
159 | .description = hcd_name, | ||
160 | .product_desc = "Qualcomm On-Chip EHCI Host Controller", | ||
161 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
162 | |||
163 | /* | ||
164 | * generic hardware linkage | ||
165 | */ | ||
166 | .irq = ehci_irq, | ||
167 | .flags = HCD_USB2 | HCD_MEMORY, | ||
168 | |||
169 | .reset = ehci_msm_reset, | ||
170 | .start = ehci_msm_run, | ||
171 | |||
172 | .stop = ehci_stop, | ||
173 | .shutdown = ehci_shutdown, | ||
174 | |||
175 | /* | ||
176 | * managing i/o requests and associated device resources | ||
177 | */ | ||
178 | .urb_enqueue = ehci_urb_enqueue, | ||
179 | .urb_dequeue = ehci_urb_dequeue, | ||
180 | .endpoint_disable = ehci_endpoint_disable, | ||
181 | .endpoint_reset = ehci_endpoint_reset, | ||
182 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
183 | |||
184 | /* | ||
185 | * scheduling support | ||
186 | */ | ||
187 | .get_frame_number = ehci_get_frame, | ||
188 | |||
189 | /* | ||
190 | * root hub support | ||
191 | */ | ||
192 | .hub_status_data = ehci_hub_status_data, | ||
193 | .hub_control = ehci_hub_control, | ||
194 | .relinquish_port = ehci_relinquish_port, | ||
195 | .port_handed_over = ehci_port_handed_over, | ||
196 | |||
197 | /* | ||
198 | * PM support | ||
199 | */ | ||
200 | .bus_suspend = ehci_bus_suspend, | ||
201 | .bus_resume = ehci_bus_resume, | ||
202 | }; | ||
203 | |||
204 | static int ehci_msm_probe(struct platform_device *pdev) | ||
205 | { | ||
206 | struct usb_hcd *hcd; | ||
207 | struct resource *res; | ||
208 | int ret; | ||
209 | |||
210 | dev_dbg(&pdev->dev, "ehci_msm proble\n"); | ||
211 | |||
212 | hcd = usb_create_hcd(&msm_hc_driver, &pdev->dev, dev_name(&pdev->dev)); | ||
213 | if (!hcd) { | ||
214 | dev_err(&pdev->dev, "Unable to create HCD\n"); | ||
215 | return -ENOMEM; | ||
216 | } | ||
217 | |||
218 | hcd->irq = platform_get_irq(pdev, 0); | ||
219 | if (hcd->irq < 0) { | ||
220 | dev_err(&pdev->dev, "Unable to get IRQ resource\n"); | ||
221 | ret = hcd->irq; | ||
222 | goto put_hcd; | ||
223 | } | ||
224 | |||
225 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
226 | if (!res) { | ||
227 | dev_err(&pdev->dev, "Unable to get memory resource\n"); | ||
228 | ret = -ENODEV; | ||
229 | goto put_hcd; | ||
230 | } | ||
231 | |||
232 | hcd->rsrc_start = res->start; | ||
233 | hcd->rsrc_len = resource_size(res); | ||
234 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
235 | if (!hcd->regs) { | ||
236 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
237 | ret = -ENOMEM; | ||
238 | goto put_hcd; | ||
239 | } | ||
240 | |||
241 | /* | ||
242 | * OTG driver takes care of PHY initialization, clock management, | ||
243 | * powering up VBUS, mapping of registers address space and power | ||
244 | * management. | ||
245 | */ | ||
246 | otg = otg_get_transceiver(); | ||
247 | if (!otg) { | ||
248 | dev_err(&pdev->dev, "unable to find transceiver\n"); | ||
249 | ret = -ENODEV; | ||
250 | goto unmap; | ||
251 | } | ||
252 | |||
253 | ret = otg_set_host(otg, &hcd->self); | ||
254 | if (ret < 0) { | ||
255 | dev_err(&pdev->dev, "unable to register with transceiver\n"); | ||
256 | goto put_transceiver; | ||
257 | } | ||
258 | |||
259 | device_init_wakeup(&pdev->dev, 1); | ||
260 | /* | ||
261 | * OTG device parent of HCD takes care of putting | ||
262 | * hardware into low power mode. | ||
263 | */ | ||
264 | pm_runtime_no_callbacks(&pdev->dev); | ||
265 | pm_runtime_enable(&pdev->dev); | ||
266 | |||
267 | return 0; | ||
268 | |||
269 | put_transceiver: | ||
270 | otg_put_transceiver(otg); | ||
271 | unmap: | ||
272 | iounmap(hcd->regs); | ||
273 | put_hcd: | ||
274 | usb_put_hcd(hcd); | ||
275 | |||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | static int __devexit ehci_msm_remove(struct platform_device *pdev) | ||
280 | { | ||
281 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
282 | |||
283 | device_init_wakeup(&pdev->dev, 0); | ||
284 | pm_runtime_disable(&pdev->dev); | ||
285 | pm_runtime_set_suspended(&pdev->dev); | ||
286 | |||
287 | otg_set_host(otg, NULL); | ||
288 | otg_put_transceiver(otg); | ||
289 | |||
290 | usb_put_hcd(hcd); | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | #ifdef CONFIG_PM | ||
296 | static int ehci_msm_pm_suspend(struct device *dev) | ||
297 | { | ||
298 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
299 | bool wakeup = device_may_wakeup(dev); | ||
300 | |||
301 | dev_dbg(dev, "ehci-msm PM suspend\n"); | ||
302 | |||
303 | /* | ||
304 | * EHCI helper function has also the same check before manipulating | ||
305 | * port wakeup flags. We do check here the same condition before | ||
306 | * calling the same helper function to avoid bringing hardware | ||
307 | * from Low power mode when there is no need for adjusting port | ||
308 | * wakeup flags. | ||
309 | */ | ||
310 | if (hcd->self.root_hub->do_remote_wakeup && !wakeup) { | ||
311 | pm_runtime_resume(dev); | ||
312 | ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), | ||
313 | wakeup); | ||
314 | } | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int ehci_msm_pm_resume(struct device *dev) | ||
320 | { | ||
321 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
322 | |||
323 | dev_dbg(dev, "ehci-msm PM resume\n"); | ||
324 | ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd)); | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | #else | ||
329 | #define ehci_msm_pm_suspend NULL | ||
330 | #define ehci_msm_pm_resume NULL | ||
331 | #endif | ||
332 | |||
333 | static const struct dev_pm_ops ehci_msm_dev_pm_ops = { | ||
334 | .suspend = ehci_msm_pm_suspend, | ||
335 | .resume = ehci_msm_pm_resume, | ||
336 | }; | ||
337 | |||
338 | static struct platform_driver ehci_msm_driver = { | ||
339 | .probe = ehci_msm_probe, | ||
340 | .remove = __devexit_p(ehci_msm_remove), | ||
341 | .driver = { | ||
342 | .name = "msm_hsusb_host", | ||
343 | .pm = &ehci_msm_dev_pm_ops, | ||
344 | }, | ||
345 | }; | ||
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index a22d2df769a9..fa59b26fc5bc 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c | |||
@@ -36,14 +36,8 @@ struct ehci_mxc_priv { | |||
36 | static int ehci_mxc_setup(struct usb_hcd *hcd) | 36 | static int ehci_mxc_setup(struct usb_hcd *hcd) |
37 | { | 37 | { |
38 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 38 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
39 | struct device *dev = hcd->self.controller; | ||
40 | struct mxc_usbh_platform_data *pdata = dev_get_platdata(dev); | ||
41 | int retval; | 39 | int retval; |
42 | 40 | ||
43 | /* EHCI registers start at offset 0x100 */ | ||
44 | ehci->caps = hcd->regs + 0x100; | ||
45 | ehci->regs = hcd->regs + 0x100 + | ||
46 | HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
47 | dbg_hcs_params(ehci, "reset"); | 41 | dbg_hcs_params(ehci, "reset"); |
48 | dbg_hcc_params(ehci, "reset"); | 42 | dbg_hcc_params(ehci, "reset"); |
49 | 43 | ||
@@ -65,12 +59,6 @@ static int ehci_mxc_setup(struct usb_hcd *hcd) | |||
65 | 59 | ||
66 | ehci_reset(ehci); | 60 | ehci_reset(ehci); |
67 | 61 | ||
68 | /* set up the PORTSCx register */ | ||
69 | ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]); | ||
70 | |||
71 | /* is this really needed? */ | ||
72 | msleep(10); | ||
73 | |||
74 | ehci_port_power(ehci, 0); | 62 | ehci_port_power(ehci, 0); |
75 | return 0; | 63 | return 0; |
76 | } | 64 | } |
@@ -100,6 +88,7 @@ static const struct hc_driver ehci_mxc_hc_driver = { | |||
100 | .urb_enqueue = ehci_urb_enqueue, | 88 | .urb_enqueue = ehci_urb_enqueue, |
101 | .urb_dequeue = ehci_urb_dequeue, | 89 | .urb_dequeue = ehci_urb_dequeue, |
102 | .endpoint_disable = ehci_endpoint_disable, | 90 | .endpoint_disable = ehci_endpoint_disable, |
91 | .endpoint_reset = ehci_endpoint_reset, | ||
103 | 92 | ||
104 | /* | 93 | /* |
105 | * scheduling support | 94 | * scheduling support |
@@ -115,6 +104,8 @@ static const struct hc_driver ehci_mxc_hc_driver = { | |||
115 | .bus_resume = ehci_bus_resume, | 104 | .bus_resume = ehci_bus_resume, |
116 | .relinquish_port = ehci_relinquish_port, | 105 | .relinquish_port = ehci_relinquish_port, |
117 | .port_handed_over = ehci_port_handed_over, | 106 | .port_handed_over = ehci_port_handed_over, |
107 | |||
108 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
118 | }; | 109 | }; |
119 | 110 | ||
120 | static int ehci_mxc_drv_probe(struct platform_device *pdev) | 111 | static int ehci_mxc_drv_probe(struct platform_device *pdev) |
@@ -125,6 +116,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
125 | int irq, ret; | 116 | int irq, ret; |
126 | struct ehci_mxc_priv *priv; | 117 | struct ehci_mxc_priv *priv; |
127 | struct device *dev = &pdev->dev; | 118 | struct device *dev = &pdev->dev; |
119 | struct ehci_hcd *ehci; | ||
128 | 120 | ||
129 | dev_info(&pdev->dev, "initializing i.MX USB Controller\n"); | 121 | dev_info(&pdev->dev, "initializing i.MX USB Controller\n"); |
130 | 122 | ||
@@ -212,6 +204,19 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
212 | if (ret < 0) | 204 | if (ret < 0) |
213 | goto err_init; | 205 | goto err_init; |
214 | 206 | ||
207 | ehci = hcd_to_ehci(hcd); | ||
208 | |||
209 | /* EHCI registers start at offset 0x100 */ | ||
210 | ehci->caps = hcd->regs + 0x100; | ||
211 | ehci->regs = hcd->regs + 0x100 + | ||
212 | HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
213 | |||
214 | /* set up the PORTSCx register */ | ||
215 | ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]); | ||
216 | |||
217 | /* is this really needed? */ | ||
218 | msleep(10); | ||
219 | |||
215 | /* Initialize the transceiver */ | 220 | /* Initialize the transceiver */ |
216 | if (pdata->otg) { | 221 | if (pdata->otg) { |
217 | pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET; | 222 | pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET; |
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 116ae280053a..680f2ef4e59f 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c | |||
@@ -1,11 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * ehci-omap.c - driver for USBHOST on OMAP 34xx processor | 2 | * ehci-omap.c - driver for USBHOST on OMAP3/4 processors |
3 | * | 3 | * |
4 | * Bus Glue for OMAP34xx USBHOST 3 port EHCI controller | 4 | * Bus Glue for the EHCI controllers in OMAP3/4 |
5 | * Tested on OMAP3430 ES2.0 SDP | 5 | * Tested on several OMAP3 boards, and OMAP4 Pandaboard |
6 | * | 6 | * |
7 | * Copyright (C) 2007-2008 Texas Instruments, Inc. | 7 | * Copyright (C) 2007-2010 Texas Instruments, Inc. |
8 | * Author: Vikram Pandita <vikram.pandita@ti.com> | 8 | * Author: Vikram Pandita <vikram.pandita@ti.com> |
9 | * Author: Anand Gadiyar <gadiyar@ti.com> | ||
9 | * | 10 | * |
10 | * Copyright (C) 2009 Nokia Corporation | 11 | * Copyright (C) 2009 Nokia Corporation |
11 | * Contact: Felipe Balbi <felipe.balbi@nokia.com> | 12 | * Contact: Felipe Balbi <felipe.balbi@nokia.com> |
@@ -26,11 +27,14 @@ | |||
26 | * along with this program; if not, write to the Free Software | 27 | * along with this program; if not, write to the Free Software |
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 28 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
28 | * | 29 | * |
29 | * TODO (last updated Feb 12, 2010): | 30 | * TODO (last updated Nov 21, 2010): |
30 | * - add kernel-doc | 31 | * - add kernel-doc |
31 | * - enable AUTOIDLE | 32 | * - enable AUTOIDLE |
32 | * - add suspend/resume | 33 | * - add suspend/resume |
33 | * - move workarounds to board-files | 34 | * - move workarounds to board-files |
35 | * - factor out code common to OHCI | ||
36 | * - add HSIC and TLL support | ||
37 | * - convert to use hwmod and runtime PM | ||
34 | */ | 38 | */ |
35 | 39 | ||
36 | #include <linux/platform_device.h> | 40 | #include <linux/platform_device.h> |
@@ -86,9 +90,9 @@ | |||
86 | #define OMAP_TLL_ULPI_SCRATCH_REGISTER(num) (0x816 + 0x100 * num) | 90 | #define OMAP_TLL_ULPI_SCRATCH_REGISTER(num) (0x816 + 0x100 * num) |
87 | 91 | ||
88 | #define OMAP_TLL_CHANNEL_COUNT 3 | 92 | #define OMAP_TLL_CHANNEL_COUNT 3 |
89 | #define OMAP_TLL_CHANNEL_1_EN_MASK (1 << 1) | 93 | #define OMAP_TLL_CHANNEL_1_EN_MASK (1 << 0) |
90 | #define OMAP_TLL_CHANNEL_2_EN_MASK (1 << 2) | 94 | #define OMAP_TLL_CHANNEL_2_EN_MASK (1 << 1) |
91 | #define OMAP_TLL_CHANNEL_3_EN_MASK (1 << 4) | 95 | #define OMAP_TLL_CHANNEL_3_EN_MASK (1 << 2) |
92 | 96 | ||
93 | /* UHH Register Set */ | 97 | /* UHH Register Set */ |
94 | #define OMAP_UHH_REVISION (0x00) | 98 | #define OMAP_UHH_REVISION (0x00) |
@@ -114,6 +118,23 @@ | |||
114 | #define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9) | 118 | #define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9) |
115 | #define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10) | 119 | #define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10) |
116 | 120 | ||
121 | /* OMAP4-specific defines */ | ||
122 | #define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR (3 << 2) | ||
123 | #define OMAP4_UHH_SYSCONFIG_NOIDLE (1 << 2) | ||
124 | |||
125 | #define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR (3 << 4) | ||
126 | #define OMAP4_UHH_SYSCONFIG_NOSTDBY (1 << 4) | ||
127 | #define OMAP4_UHH_SYSCONFIG_SOFTRESET (1 << 0) | ||
128 | |||
129 | #define OMAP4_P1_MODE_CLEAR (3 << 16) | ||
130 | #define OMAP4_P1_MODE_TLL (1 << 16) | ||
131 | #define OMAP4_P1_MODE_HSIC (3 << 16) | ||
132 | #define OMAP4_P2_MODE_CLEAR (3 << 18) | ||
133 | #define OMAP4_P2_MODE_TLL (1 << 18) | ||
134 | #define OMAP4_P2_MODE_HSIC (3 << 18) | ||
135 | |||
136 | #define OMAP_REV2_TLL_CHANNEL_COUNT 2 | ||
137 | |||
117 | #define OMAP_UHH_DEBUG_CSR (0x44) | 138 | #define OMAP_UHH_DEBUG_CSR (0x44) |
118 | 139 | ||
119 | /* EHCI Register Set */ | 140 | /* EHCI Register Set */ |
@@ -127,6 +148,17 @@ | |||
127 | #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 | 148 | #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 |
128 | #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 | 149 | #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 |
129 | 150 | ||
151 | /* Values of UHH_REVISION - Note: these are not given in the TRM */ | ||
152 | #define OMAP_EHCI_REV1 0x00000010 /* OMAP3 */ | ||
153 | #define OMAP_EHCI_REV2 0x50700100 /* OMAP4 */ | ||
154 | |||
155 | #define is_omap_ehci_rev1(x) (x->omap_ehci_rev == OMAP_EHCI_REV1) | ||
156 | #define is_omap_ehci_rev2(x) (x->omap_ehci_rev == OMAP_EHCI_REV2) | ||
157 | |||
158 | #define is_ehci_phy_mode(x) (x == EHCI_HCD_OMAP_MODE_PHY) | ||
159 | #define is_ehci_tll_mode(x) (x == EHCI_HCD_OMAP_MODE_TLL) | ||
160 | #define is_ehci_hsic_mode(x) (x == EHCI_HCD_OMAP_MODE_HSIC) | ||
161 | |||
130 | /*-------------------------------------------------------------------------*/ | 162 | /*-------------------------------------------------------------------------*/ |
131 | 163 | ||
132 | static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val) | 164 | static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val) |
@@ -156,10 +188,14 @@ struct ehci_hcd_omap { | |||
156 | struct device *dev; | 188 | struct device *dev; |
157 | 189 | ||
158 | struct clk *usbhost_ick; | 190 | struct clk *usbhost_ick; |
159 | struct clk *usbhost2_120m_fck; | 191 | struct clk *usbhost_hs_fck; |
160 | struct clk *usbhost1_48m_fck; | 192 | struct clk *usbhost_fs_fck; |
161 | struct clk *usbtll_fck; | 193 | struct clk *usbtll_fck; |
162 | struct clk *usbtll_ick; | 194 | struct clk *usbtll_ick; |
195 | struct clk *xclk60mhsp1_ck; | ||
196 | struct clk *xclk60mhsp2_ck; | ||
197 | struct clk *utmi_p1_fck; | ||
198 | struct clk *utmi_p2_fck; | ||
163 | 199 | ||
164 | /* FIXME the following two workarounds are | 200 | /* FIXME the following two workarounds are |
165 | * board specific not silicon-specific so these | 201 | * board specific not silicon-specific so these |
@@ -176,6 +212,9 @@ struct ehci_hcd_omap { | |||
176 | /* phy reset workaround */ | 212 | /* phy reset workaround */ |
177 | int phy_reset; | 213 | int phy_reset; |
178 | 214 | ||
215 | /* IP revision */ | ||
216 | u32 omap_ehci_rev; | ||
217 | |||
179 | /* desired phy_mode: TLL, PHY */ | 218 | /* desired phy_mode: TLL, PHY */ |
180 | enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS]; | 219 | enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS]; |
181 | 220 | ||
@@ -191,13 +230,14 @@ struct ehci_hcd_omap { | |||
191 | 230 | ||
192 | /*-------------------------------------------------------------------------*/ | 231 | /*-------------------------------------------------------------------------*/ |
193 | 232 | ||
194 | static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask) | 233 | static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask, |
234 | u8 tll_channel_count) | ||
195 | { | 235 | { |
196 | unsigned reg; | 236 | unsigned reg; |
197 | int i; | 237 | int i; |
198 | 238 | ||
199 | /* Program the 3 TLL channels upfront */ | 239 | /* Program the 3 TLL channels upfront */ |
200 | for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { | 240 | for (i = 0; i < tll_channel_count; i++) { |
201 | reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); | 241 | reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); |
202 | 242 | ||
203 | /* Disable AutoIdle, BitStuffing and use SDR Mode */ | 243 | /* Disable AutoIdle, BitStuffing and use SDR Mode */ |
@@ -217,7 +257,7 @@ static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask) | |||
217 | ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); | 257 | ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); |
218 | 258 | ||
219 | /* Enable channels now */ | 259 | /* Enable channels now */ |
220 | for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { | 260 | for (i = 0; i < tll_channel_count; i++) { |
221 | reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); | 261 | reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); |
222 | 262 | ||
223 | /* Enable only the reg that is needed */ | 263 | /* Enable only the reg that is needed */ |
@@ -286,19 +326,19 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
286 | } | 326 | } |
287 | clk_enable(omap->usbhost_ick); | 327 | clk_enable(omap->usbhost_ick); |
288 | 328 | ||
289 | omap->usbhost2_120m_fck = clk_get(omap->dev, "usbhost_120m_fck"); | 329 | omap->usbhost_hs_fck = clk_get(omap->dev, "hs_fck"); |
290 | if (IS_ERR(omap->usbhost2_120m_fck)) { | 330 | if (IS_ERR(omap->usbhost_hs_fck)) { |
291 | ret = PTR_ERR(omap->usbhost2_120m_fck); | 331 | ret = PTR_ERR(omap->usbhost_hs_fck); |
292 | goto err_host_120m_fck; | 332 | goto err_host_120m_fck; |
293 | } | 333 | } |
294 | clk_enable(omap->usbhost2_120m_fck); | 334 | clk_enable(omap->usbhost_hs_fck); |
295 | 335 | ||
296 | omap->usbhost1_48m_fck = clk_get(omap->dev, "usbhost_48m_fck"); | 336 | omap->usbhost_fs_fck = clk_get(omap->dev, "fs_fck"); |
297 | if (IS_ERR(omap->usbhost1_48m_fck)) { | 337 | if (IS_ERR(omap->usbhost_fs_fck)) { |
298 | ret = PTR_ERR(omap->usbhost1_48m_fck); | 338 | ret = PTR_ERR(omap->usbhost_fs_fck); |
299 | goto err_host_48m_fck; | 339 | goto err_host_48m_fck; |
300 | } | 340 | } |
301 | clk_enable(omap->usbhost1_48m_fck); | 341 | clk_enable(omap->usbhost_fs_fck); |
302 | 342 | ||
303 | if (omap->phy_reset) { | 343 | if (omap->phy_reset) { |
304 | /* Refer: ISSUE1 */ | 344 | /* Refer: ISSUE1 */ |
@@ -333,6 +373,80 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
333 | } | 373 | } |
334 | clk_enable(omap->usbtll_ick); | 374 | clk_enable(omap->usbtll_ick); |
335 | 375 | ||
376 | omap->omap_ehci_rev = ehci_omap_readl(omap->uhh_base, | ||
377 | OMAP_UHH_REVISION); | ||
378 | dev_dbg(omap->dev, "OMAP UHH_REVISION 0x%x\n", | ||
379 | omap->omap_ehci_rev); | ||
380 | |||
381 | /* | ||
382 | * Enable per-port clocks as needed (newer controllers only). | ||
383 | * - External ULPI clock for PHY mode | ||
384 | * - Internal clocks for TLL and HSIC modes (TODO) | ||
385 | */ | ||
386 | if (is_omap_ehci_rev2(omap)) { | ||
387 | switch (omap->port_mode[0]) { | ||
388 | case EHCI_HCD_OMAP_MODE_PHY: | ||
389 | omap->xclk60mhsp1_ck = clk_get(omap->dev, | ||
390 | "xclk60mhsp1_ck"); | ||
391 | if (IS_ERR(omap->xclk60mhsp1_ck)) { | ||
392 | ret = PTR_ERR(omap->xclk60mhsp1_ck); | ||
393 | dev_err(omap->dev, | ||
394 | "Unable to get Port1 ULPI clock\n"); | ||
395 | } | ||
396 | |||
397 | omap->utmi_p1_fck = clk_get(omap->dev, | ||
398 | "utmi_p1_gfclk"); | ||
399 | if (IS_ERR(omap->utmi_p1_fck)) { | ||
400 | ret = PTR_ERR(omap->utmi_p1_fck); | ||
401 | dev_err(omap->dev, | ||
402 | "Unable to get utmi_p1_fck\n"); | ||
403 | } | ||
404 | |||
405 | ret = clk_set_parent(omap->utmi_p1_fck, | ||
406 | omap->xclk60mhsp1_ck); | ||
407 | if (ret != 0) { | ||
408 | dev_err(omap->dev, | ||
409 | "Unable to set P1 f-clock\n"); | ||
410 | } | ||
411 | break; | ||
412 | case EHCI_HCD_OMAP_MODE_TLL: | ||
413 | /* TODO */ | ||
414 | default: | ||
415 | break; | ||
416 | } | ||
417 | switch (omap->port_mode[1]) { | ||
418 | case EHCI_HCD_OMAP_MODE_PHY: | ||
419 | omap->xclk60mhsp2_ck = clk_get(omap->dev, | ||
420 | "xclk60mhsp2_ck"); | ||
421 | if (IS_ERR(omap->xclk60mhsp2_ck)) { | ||
422 | ret = PTR_ERR(omap->xclk60mhsp2_ck); | ||
423 | dev_err(omap->dev, | ||
424 | "Unable to get Port2 ULPI clock\n"); | ||
425 | } | ||
426 | |||
427 | omap->utmi_p2_fck = clk_get(omap->dev, | ||
428 | "utmi_p2_gfclk"); | ||
429 | if (IS_ERR(omap->utmi_p2_fck)) { | ||
430 | ret = PTR_ERR(omap->utmi_p2_fck); | ||
431 | dev_err(omap->dev, | ||
432 | "Unable to get utmi_p2_fck\n"); | ||
433 | } | ||
434 | |||
435 | ret = clk_set_parent(omap->utmi_p2_fck, | ||
436 | omap->xclk60mhsp2_ck); | ||
437 | if (ret != 0) { | ||
438 | dev_err(omap->dev, | ||
439 | "Unable to set P2 f-clock\n"); | ||
440 | } | ||
441 | break; | ||
442 | case EHCI_HCD_OMAP_MODE_TLL: | ||
443 | /* TODO */ | ||
444 | default: | ||
445 | break; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | |||
336 | /* perform TLL soft reset, and wait until reset is complete */ | 450 | /* perform TLL soft reset, and wait until reset is complete */ |
337 | ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, | 451 | ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, |
338 | OMAP_USBTLL_SYSCONFIG_SOFTRESET); | 452 | OMAP_USBTLL_SYSCONFIG_SOFTRESET); |
@@ -360,12 +474,20 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
360 | 474 | ||
361 | /* Put UHH in NoIdle/NoStandby mode */ | 475 | /* Put UHH in NoIdle/NoStandby mode */ |
362 | reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); | 476 | reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); |
363 | reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP | 477 | if (is_omap_ehci_rev1(omap)) { |
364 | | OMAP_UHH_SYSCONFIG_SIDLEMODE | 478 | reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP |
365 | | OMAP_UHH_SYSCONFIG_CACTIVITY | 479 | | OMAP_UHH_SYSCONFIG_SIDLEMODE |
366 | | OMAP_UHH_SYSCONFIG_MIDLEMODE); | 480 | | OMAP_UHH_SYSCONFIG_CACTIVITY |
367 | reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; | 481 | | OMAP_UHH_SYSCONFIG_MIDLEMODE); |
482 | reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; | ||
483 | |||
368 | 484 | ||
485 | } else if (is_omap_ehci_rev2(omap)) { | ||
486 | reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; | ||
487 | reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; | ||
488 | reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; | ||
489 | reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; | ||
490 | } | ||
369 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); | 491 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); |
370 | 492 | ||
371 | reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); | 493 | reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); |
@@ -376,40 +498,56 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
376 | | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); | 498 | | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); |
377 | reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; | 499 | reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; |
378 | 500 | ||
379 | if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) | 501 | if (is_omap_ehci_rev1(omap)) { |
380 | reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; | 502 | if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) |
381 | if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) | 503 | reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; |
382 | reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; | 504 | if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) |
383 | if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) | 505 | reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; |
384 | reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; | 506 | if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) |
385 | 507 | reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; | |
386 | /* Bypass the TLL module for PHY mode operation */ | 508 | |
387 | if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) { | 509 | /* Bypass the TLL module for PHY mode operation */ |
388 | dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n"); | 510 | if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) { |
389 | if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) || | 511 | dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n"); |
390 | (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) || | 512 | if (is_ehci_phy_mode(omap->port_mode[0]) || |
391 | (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY)) | 513 | is_ehci_phy_mode(omap->port_mode[1]) || |
392 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; | 514 | is_ehci_phy_mode(omap->port_mode[2])) |
393 | else | 515 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; |
394 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; | 516 | else |
395 | } else { | 517 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; |
396 | dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); | 518 | } else { |
397 | if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) | 519 | dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); |
398 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | 520 | if (is_ehci_phy_mode(omap->port_mode[0])) |
399 | else if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) | 521 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; |
400 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | 522 | else if (is_ehci_tll_mode(omap->port_mode[0])) |
401 | 523 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | |
402 | if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) | 524 | |
403 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; | 525 | if (is_ehci_phy_mode(omap->port_mode[1])) |
404 | else if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) | 526 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; |
405 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; | 527 | else if (is_ehci_tll_mode(omap->port_mode[1])) |
406 | 528 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; | |
407 | if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY) | 529 | |
408 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; | 530 | if (is_ehci_phy_mode(omap->port_mode[2])) |
409 | else if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) | 531 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; |
410 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; | 532 | else if (is_ehci_tll_mode(omap->port_mode[2])) |
533 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; | ||
534 | } | ||
535 | } else if (is_omap_ehci_rev2(omap)) { | ||
536 | /* Clear port mode fields for PHY mode*/ | ||
537 | reg &= ~OMAP4_P1_MODE_CLEAR; | ||
538 | reg &= ~OMAP4_P2_MODE_CLEAR; | ||
539 | |||
540 | if (is_ehci_tll_mode(omap->port_mode[0])) | ||
541 | reg |= OMAP4_P1_MODE_TLL; | ||
542 | else if (is_ehci_hsic_mode(omap->port_mode[0])) | ||
543 | reg |= OMAP4_P1_MODE_HSIC; | ||
411 | 544 | ||
545 | if (is_ehci_tll_mode(omap->port_mode[1])) | ||
546 | reg |= OMAP4_P2_MODE_TLL; | ||
547 | else if (is_ehci_hsic_mode(omap->port_mode[1])) | ||
548 | reg |= OMAP4_P2_MODE_HSIC; | ||
412 | } | 549 | } |
550 | |||
413 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); | 551 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); |
414 | dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); | 552 | dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); |
415 | 553 | ||
@@ -438,7 +576,7 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
438 | tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; | 576 | tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; |
439 | 577 | ||
440 | /* Enable UTMI mode for required TLL channels */ | 578 | /* Enable UTMI mode for required TLL channels */ |
441 | omap_usb_utmi_init(omap, tll_ch_mask); | 579 | omap_usb_utmi_init(omap, tll_ch_mask, OMAP_TLL_CHANNEL_COUNT); |
442 | } | 580 | } |
443 | 581 | ||
444 | if (omap->phy_reset) { | 582 | if (omap->phy_reset) { |
@@ -464,6 +602,14 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
464 | return 0; | 602 | return 0; |
465 | 603 | ||
466 | err_sys_status: | 604 | err_sys_status: |
605 | clk_disable(omap->utmi_p2_fck); | ||
606 | clk_put(omap->utmi_p2_fck); | ||
607 | clk_disable(omap->xclk60mhsp2_ck); | ||
608 | clk_put(omap->xclk60mhsp2_ck); | ||
609 | clk_disable(omap->utmi_p1_fck); | ||
610 | clk_put(omap->utmi_p1_fck); | ||
611 | clk_disable(omap->xclk60mhsp1_ck); | ||
612 | clk_put(omap->xclk60mhsp1_ck); | ||
467 | clk_disable(omap->usbtll_ick); | 613 | clk_disable(omap->usbtll_ick); |
468 | clk_put(omap->usbtll_ick); | 614 | clk_put(omap->usbtll_ick); |
469 | 615 | ||
@@ -472,8 +618,8 @@ err_tll_ick: | |||
472 | clk_put(omap->usbtll_fck); | 618 | clk_put(omap->usbtll_fck); |
473 | 619 | ||
474 | err_tll_fck: | 620 | err_tll_fck: |
475 | clk_disable(omap->usbhost1_48m_fck); | 621 | clk_disable(omap->usbhost_fs_fck); |
476 | clk_put(omap->usbhost1_48m_fck); | 622 | clk_put(omap->usbhost_fs_fck); |
477 | 623 | ||
478 | if (omap->phy_reset) { | 624 | if (omap->phy_reset) { |
479 | if (gpio_is_valid(omap->reset_gpio_port[0])) | 625 | if (gpio_is_valid(omap->reset_gpio_port[0])) |
@@ -484,8 +630,8 @@ err_tll_fck: | |||
484 | } | 630 | } |
485 | 631 | ||
486 | err_host_48m_fck: | 632 | err_host_48m_fck: |
487 | clk_disable(omap->usbhost2_120m_fck); | 633 | clk_disable(omap->usbhost_hs_fck); |
488 | clk_put(omap->usbhost2_120m_fck); | 634 | clk_put(omap->usbhost_hs_fck); |
489 | 635 | ||
490 | err_host_120m_fck: | 636 | err_host_120m_fck: |
491 | clk_disable(omap->usbhost_ick); | 637 | clk_disable(omap->usbhost_ick); |
@@ -503,6 +649,8 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
503 | 649 | ||
504 | /* Reset OMAP modules for insmod/rmmod to work */ | 650 | /* Reset OMAP modules for insmod/rmmod to work */ |
505 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, | 651 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, |
652 | is_omap_ehci_rev2(omap) ? | ||
653 | OMAP4_UHH_SYSCONFIG_SOFTRESET : | ||
506 | OMAP_UHH_SYSCONFIG_SOFTRESET); | 654 | OMAP_UHH_SYSCONFIG_SOFTRESET); |
507 | while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) | 655 | while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) |
508 | & (1 << 0))) { | 656 | & (1 << 0))) { |
@@ -550,16 +698,16 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
550 | omap->usbhost_ick = NULL; | 698 | omap->usbhost_ick = NULL; |
551 | } | 699 | } |
552 | 700 | ||
553 | if (omap->usbhost1_48m_fck != NULL) { | 701 | if (omap->usbhost_fs_fck != NULL) { |
554 | clk_disable(omap->usbhost1_48m_fck); | 702 | clk_disable(omap->usbhost_fs_fck); |
555 | clk_put(omap->usbhost1_48m_fck); | 703 | clk_put(omap->usbhost_fs_fck); |
556 | omap->usbhost1_48m_fck = NULL; | 704 | omap->usbhost_fs_fck = NULL; |
557 | } | 705 | } |
558 | 706 | ||
559 | if (omap->usbhost2_120m_fck != NULL) { | 707 | if (omap->usbhost_hs_fck != NULL) { |
560 | clk_disable(omap->usbhost2_120m_fck); | 708 | clk_disable(omap->usbhost_hs_fck); |
561 | clk_put(omap->usbhost2_120m_fck); | 709 | clk_put(omap->usbhost_hs_fck); |
562 | omap->usbhost2_120m_fck = NULL; | 710 | omap->usbhost_hs_fck = NULL; |
563 | } | 711 | } |
564 | 712 | ||
565 | if (omap->usbtll_ick != NULL) { | 713 | if (omap->usbtll_ick != NULL) { |
@@ -568,6 +716,32 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
568 | omap->usbtll_ick = NULL; | 716 | omap->usbtll_ick = NULL; |
569 | } | 717 | } |
570 | 718 | ||
719 | if (is_omap_ehci_rev2(omap)) { | ||
720 | if (omap->xclk60mhsp1_ck != NULL) { | ||
721 | clk_disable(omap->xclk60mhsp1_ck); | ||
722 | clk_put(omap->xclk60mhsp1_ck); | ||
723 | omap->xclk60mhsp1_ck = NULL; | ||
724 | } | ||
725 | |||
726 | if (omap->utmi_p1_fck != NULL) { | ||
727 | clk_disable(omap->utmi_p1_fck); | ||
728 | clk_put(omap->utmi_p1_fck); | ||
729 | omap->utmi_p1_fck = NULL; | ||
730 | } | ||
731 | |||
732 | if (omap->xclk60mhsp2_ck != NULL) { | ||
733 | clk_disable(omap->xclk60mhsp2_ck); | ||
734 | clk_put(omap->xclk60mhsp2_ck); | ||
735 | omap->xclk60mhsp2_ck = NULL; | ||
736 | } | ||
737 | |||
738 | if (omap->utmi_p2_fck != NULL) { | ||
739 | clk_disable(omap->utmi_p2_fck); | ||
740 | clk_put(omap->utmi_p2_fck); | ||
741 | omap->utmi_p2_fck = NULL; | ||
742 | } | ||
743 | } | ||
744 | |||
571 | if (omap->phy_reset) { | 745 | if (omap->phy_reset) { |
572 | if (gpio_is_valid(omap->reset_gpio_port[0])) | 746 | if (gpio_is_valid(omap->reset_gpio_port[0])) |
573 | gpio_free(omap->reset_gpio_port[0]); | 747 | gpio_free(omap->reset_gpio_port[0]); |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 655f3c9f88bf..76179c39c0e3 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -22,6 +22,9 @@ | |||
22 | #error "This file is PCI bus glue. CONFIG_PCI must be defined." | 22 | #error "This file is PCI bus glue. CONFIG_PCI must be defined." |
23 | #endif | 23 | #endif |
24 | 24 | ||
25 | /* defined here to avoid adding to pci_ids.h for single instance use */ | ||
26 | #define PCI_DEVICE_ID_INTEL_CE4100_USB 0x2e70 | ||
27 | |||
25 | /*-------------------------------------------------------------------------*/ | 28 | /*-------------------------------------------------------------------------*/ |
26 | 29 | ||
27 | /* called after powerup, by probe or system-pm "wakeup" */ | 30 | /* called after powerup, by probe or system-pm "wakeup" */ |
@@ -41,6 +44,35 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) | |||
41 | return 0; | 44 | return 0; |
42 | } | 45 | } |
43 | 46 | ||
47 | static int ehci_quirk_amd_SB800(struct ehci_hcd *ehci) | ||
48 | { | ||
49 | struct pci_dev *amd_smbus_dev; | ||
50 | u8 rev = 0; | ||
51 | |||
52 | amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL); | ||
53 | if (!amd_smbus_dev) | ||
54 | return 0; | ||
55 | |||
56 | pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); | ||
57 | if (rev < 0x40) { | ||
58 | pci_dev_put(amd_smbus_dev); | ||
59 | amd_smbus_dev = NULL; | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | if (!amd_nb_dev) | ||
64 | amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL); | ||
65 | if (!amd_nb_dev) | ||
66 | ehci_err(ehci, "QUIRK: unable to get AMD NB device\n"); | ||
67 | |||
68 | ehci_info(ehci, "QUIRK: Enable AMD SB800 L1 fix\n"); | ||
69 | |||
70 | pci_dev_put(amd_smbus_dev); | ||
71 | amd_smbus_dev = NULL; | ||
72 | |||
73 | return 1; | ||
74 | } | ||
75 | |||
44 | /* called during probe() after chip reset completes */ | 76 | /* called during probe() after chip reset completes */ |
45 | static int ehci_pci_setup(struct usb_hcd *hcd) | 77 | static int ehci_pci_setup(struct usb_hcd *hcd) |
46 | { | 78 | { |
@@ -99,6 +131,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
99 | /* cache this readonly data; minimize chip reads */ | 131 | /* cache this readonly data; minimize chip reads */ |
100 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | 132 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); |
101 | 133 | ||
134 | if (ehci_quirk_amd_SB800(ehci)) | ||
135 | ehci->amd_l1_fix = 1; | ||
136 | |||
102 | retval = ehci_halt(ehci); | 137 | retval = ehci_halt(ehci); |
103 | if (retval) | 138 | if (retval) |
104 | return retval; | 139 | return retval; |
@@ -137,6 +172,10 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
137 | ehci_info(ehci, "disable lpm for langwell/penwell\n"); | 172 | ehci_info(ehci, "disable lpm for langwell/penwell\n"); |
138 | ehci->has_lpm = 0; | 173 | ehci->has_lpm = 0; |
139 | } | 174 | } |
175 | if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) { | ||
176 | hcd->has_tt = 1; | ||
177 | tdi_reset(ehci); | ||
178 | } | ||
140 | break; | 179 | break; |
141 | case PCI_VENDOR_ID_TDI: | 180 | case PCI_VENDOR_ID_TDI: |
142 | if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { | 181 | if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index d9f78eb26572..aa46f57f9ec8 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -1590,6 +1590,63 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) | |||
1590 | *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); | 1590 | *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); |
1591 | } | 1591 | } |
1592 | 1592 | ||
1593 | #define AB_REG_BAR_LOW 0xe0 | ||
1594 | #define AB_REG_BAR_HIGH 0xe1 | ||
1595 | #define AB_INDX(addr) ((addr) + 0x00) | ||
1596 | #define AB_DATA(addr) ((addr) + 0x04) | ||
1597 | #define NB_PCIE_INDX_ADDR 0xe0 | ||
1598 | #define NB_PCIE_INDX_DATA 0xe4 | ||
1599 | #define NB_PIF0_PWRDOWN_0 0x01100012 | ||
1600 | #define NB_PIF0_PWRDOWN_1 0x01100013 | ||
1601 | |||
1602 | static void ehci_quirk_amd_L1(struct ehci_hcd *ehci, int disable) | ||
1603 | { | ||
1604 | u32 addr, addr_low, addr_high, val; | ||
1605 | |||
1606 | outb_p(AB_REG_BAR_LOW, 0xcd6); | ||
1607 | addr_low = inb_p(0xcd7); | ||
1608 | outb_p(AB_REG_BAR_HIGH, 0xcd6); | ||
1609 | addr_high = inb_p(0xcd7); | ||
1610 | addr = addr_high << 8 | addr_low; | ||
1611 | outl_p(0x30, AB_INDX(addr)); | ||
1612 | outl_p(0x40, AB_DATA(addr)); | ||
1613 | outl_p(0x34, AB_INDX(addr)); | ||
1614 | val = inl_p(AB_DATA(addr)); | ||
1615 | |||
1616 | if (disable) { | ||
1617 | val &= ~0x8; | ||
1618 | val |= (1 << 4) | (1 << 9); | ||
1619 | } else { | ||
1620 | val |= 0x8; | ||
1621 | val &= ~((1 << 4) | (1 << 9)); | ||
1622 | } | ||
1623 | outl_p(val, AB_DATA(addr)); | ||
1624 | |||
1625 | if (amd_nb_dev) { | ||
1626 | addr = NB_PIF0_PWRDOWN_0; | ||
1627 | pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr); | ||
1628 | pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val); | ||
1629 | if (disable) | ||
1630 | val &= ~(0x3f << 7); | ||
1631 | else | ||
1632 | val |= 0x3f << 7; | ||
1633 | |||
1634 | pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val); | ||
1635 | |||
1636 | addr = NB_PIF0_PWRDOWN_1; | ||
1637 | pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr); | ||
1638 | pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val); | ||
1639 | if (disable) | ||
1640 | val &= ~(0x3f << 7); | ||
1641 | else | ||
1642 | val |= 0x3f << 7; | ||
1643 | |||
1644 | pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val); | ||
1645 | } | ||
1646 | |||
1647 | return; | ||
1648 | } | ||
1649 | |||
1593 | /* fit urb's itds into the selected schedule slot; activate as needed */ | 1650 | /* fit urb's itds into the selected schedule slot; activate as needed */ |
1594 | static int | 1651 | static int |
1595 | itd_link_urb ( | 1652 | itd_link_urb ( |
@@ -1616,6 +1673,12 @@ itd_link_urb ( | |||
1616 | urb->interval, | 1673 | urb->interval, |
1617 | next_uframe >> 3, next_uframe & 0x7); | 1674 | next_uframe >> 3, next_uframe & 0x7); |
1618 | } | 1675 | } |
1676 | |||
1677 | if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { | ||
1678 | if (ehci->amd_l1_fix == 1) | ||
1679 | ehci_quirk_amd_L1(ehci, 1); | ||
1680 | } | ||
1681 | |||
1619 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; | 1682 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; |
1620 | 1683 | ||
1621 | /* fill iTDs uframe by uframe */ | 1684 | /* fill iTDs uframe by uframe */ |
@@ -1740,6 +1803,11 @@ itd_complete ( | |||
1740 | (void) disable_periodic(ehci); | 1803 | (void) disable_periodic(ehci); |
1741 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; | 1804 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; |
1742 | 1805 | ||
1806 | if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { | ||
1807 | if (ehci->amd_l1_fix == 1) | ||
1808 | ehci_quirk_amd_L1(ehci, 0); | ||
1809 | } | ||
1810 | |||
1743 | if (unlikely(list_is_singular(&stream->td_list))) { | 1811 | if (unlikely(list_is_singular(&stream->td_list))) { |
1744 | ehci_to_hcd(ehci)->self.bandwidth_allocated | 1812 | ehci_to_hcd(ehci)->self.bandwidth_allocated |
1745 | -= stream->bandwidth; | 1813 | -= stream->bandwidth; |
@@ -2025,6 +2093,12 @@ sitd_link_urb ( | |||
2025 | (next_uframe >> 3) & (ehci->periodic_size - 1), | 2093 | (next_uframe >> 3) & (ehci->periodic_size - 1), |
2026 | stream->interval, hc32_to_cpu(ehci, stream->splits)); | 2094 | stream->interval, hc32_to_cpu(ehci, stream->splits)); |
2027 | } | 2095 | } |
2096 | |||
2097 | if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { | ||
2098 | if (ehci->amd_l1_fix == 1) | ||
2099 | ehci_quirk_amd_L1(ehci, 1); | ||
2100 | } | ||
2101 | |||
2028 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; | 2102 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; |
2029 | 2103 | ||
2030 | /* fill sITDs frame by frame */ | 2104 | /* fill sITDs frame by frame */ |
@@ -2125,6 +2199,11 @@ sitd_complete ( | |||
2125 | (void) disable_periodic(ehci); | 2199 | (void) disable_periodic(ehci); |
2126 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; | 2200 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; |
2127 | 2201 | ||
2202 | if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { | ||
2203 | if (ehci->amd_l1_fix == 1) | ||
2204 | ehci_quirk_amd_L1(ehci, 0); | ||
2205 | } | ||
2206 | |||
2128 | if (list_is_singular(&stream->td_list)) { | 2207 | if (list_is_singular(&stream->td_list)) { |
2129 | ehci_to_hcd(ehci)->self.bandwidth_allocated | 2208 | ehci_to_hcd(ehci)->self.bandwidth_allocated |
2130 | -= stream->bandwidth; | 2209 | -= stream->bandwidth; |
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c new file mode 100644 index 000000000000..595f70f42b52 --- /dev/null +++ b/drivers/usb/host/ehci-sh.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /* | ||
2 | * SuperH EHCI host controller driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Paul Mundt | ||
5 | * | ||
6 | * Based on ohci-sh.c and ehci-atmel.c. | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file "COPYING" in the main directory of this archive | ||
10 | * for more details. | ||
11 | */ | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/clk.h> | ||
14 | |||
15 | struct ehci_sh_priv { | ||
16 | struct clk *iclk, *fclk; | ||
17 | struct usb_hcd *hcd; | ||
18 | }; | ||
19 | |||
20 | static int ehci_sh_reset(struct usb_hcd *hcd) | ||
21 | { | ||
22 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
23 | int ret; | ||
24 | |||
25 | ehci->caps = hcd->regs; | ||
26 | ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, | ||
27 | &ehci->caps->hc_capbase)); | ||
28 | |||
29 | dbg_hcs_params(ehci, "reset"); | ||
30 | dbg_hcc_params(ehci, "reset"); | ||
31 | |||
32 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
33 | |||
34 | ret = ehci_halt(ehci); | ||
35 | if (unlikely(ret)) | ||
36 | return ret; | ||
37 | |||
38 | ret = ehci_init(hcd); | ||
39 | if (unlikely(ret)) | ||
40 | return ret; | ||
41 | |||
42 | ehci->sbrn = 0x20; | ||
43 | |||
44 | ehci_reset(ehci); | ||
45 | ehci_port_power(ehci, 0); | ||
46 | |||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | static const struct hc_driver ehci_sh_hc_driver = { | ||
51 | .description = hcd_name, | ||
52 | .product_desc = "SuperH EHCI", | ||
53 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
54 | |||
55 | /* | ||
56 | * generic hardware linkage | ||
57 | */ | ||
58 | .irq = ehci_irq, | ||
59 | .flags = HCD_USB2 | HCD_MEMORY, | ||
60 | |||
61 | /* | ||
62 | * basic lifecycle operations | ||
63 | */ | ||
64 | .reset = ehci_sh_reset, | ||
65 | .start = ehci_run, | ||
66 | .stop = ehci_stop, | ||
67 | .shutdown = ehci_shutdown, | ||
68 | |||
69 | /* | ||
70 | * managing i/o requests and associated device resources | ||
71 | */ | ||
72 | .urb_enqueue = ehci_urb_enqueue, | ||
73 | .urb_dequeue = ehci_urb_dequeue, | ||
74 | .endpoint_disable = ehci_endpoint_disable, | ||
75 | .endpoint_reset = ehci_endpoint_reset, | ||
76 | |||
77 | /* | ||
78 | * scheduling support | ||
79 | */ | ||
80 | .get_frame_number = ehci_get_frame, | ||
81 | |||
82 | /* | ||
83 | * root hub support | ||
84 | */ | ||
85 | .hub_status_data = ehci_hub_status_data, | ||
86 | .hub_control = ehci_hub_control, | ||
87 | |||
88 | #ifdef CONFIG_PM | ||
89 | .bus_suspend = ehci_bus_suspend, | ||
90 | .bus_resume = ehci_bus_resume, | ||
91 | #endif | ||
92 | |||
93 | .relinquish_port = ehci_relinquish_port, | ||
94 | .port_handed_over = ehci_port_handed_over, | ||
95 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
96 | }; | ||
97 | |||
98 | static int ehci_hcd_sh_probe(struct platform_device *pdev) | ||
99 | { | ||
100 | const struct hc_driver *driver = &ehci_sh_hc_driver; | ||
101 | struct resource *res; | ||
102 | struct ehci_sh_priv *priv; | ||
103 | struct usb_hcd *hcd; | ||
104 | int irq, ret; | ||
105 | |||
106 | if (usb_disabled()) | ||
107 | return -ENODEV; | ||
108 | |||
109 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
110 | if (!res) { | ||
111 | dev_err(&pdev->dev, | ||
112 | "Found HC with no register addr. Check %s setup!\n", | ||
113 | dev_name(&pdev->dev)); | ||
114 | ret = -ENODEV; | ||
115 | goto fail_create_hcd; | ||
116 | } | ||
117 | |||
118 | irq = platform_get_irq(pdev, 0); | ||
119 | if (irq <= 0) { | ||
120 | dev_err(&pdev->dev, | ||
121 | "Found HC with no IRQ. Check %s setup!\n", | ||
122 | dev_name(&pdev->dev)); | ||
123 | ret = -ENODEV; | ||
124 | goto fail_create_hcd; | ||
125 | } | ||
126 | |||
127 | /* initialize hcd */ | ||
128 | hcd = usb_create_hcd(&ehci_sh_hc_driver, &pdev->dev, | ||
129 | dev_name(&pdev->dev)); | ||
130 | if (!hcd) { | ||
131 | ret = -ENOMEM; | ||
132 | goto fail_create_hcd; | ||
133 | } | ||
134 | |||
135 | hcd->rsrc_start = res->start; | ||
136 | hcd->rsrc_len = resource_size(res); | ||
137 | |||
138 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, | ||
139 | driver->description)) { | ||
140 | dev_dbg(&pdev->dev, "controller already in use\n"); | ||
141 | ret = -EBUSY; | ||
142 | goto fail_request_resource; | ||
143 | } | ||
144 | |||
145 | hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); | ||
146 | if (hcd->regs == NULL) { | ||
147 | dev_dbg(&pdev->dev, "error mapping memory\n"); | ||
148 | ret = -ENXIO; | ||
149 | goto fail_ioremap; | ||
150 | } | ||
151 | |||
152 | priv = kmalloc(sizeof(struct ehci_sh_priv), GFP_KERNEL); | ||
153 | if (!priv) { | ||
154 | dev_dbg(&pdev->dev, "error allocating priv data\n"); | ||
155 | ret = -ENOMEM; | ||
156 | goto fail_alloc; | ||
157 | } | ||
158 | |||
159 | /* These are optional, we don't care if they fail */ | ||
160 | priv->fclk = clk_get(&pdev->dev, "usb_fck"); | ||
161 | if (IS_ERR(priv->fclk)) | ||
162 | priv->fclk = NULL; | ||
163 | |||
164 | priv->iclk = clk_get(&pdev->dev, "usb_ick"); | ||
165 | if (IS_ERR(priv->iclk)) | ||
166 | priv->iclk = NULL; | ||
167 | |||
168 | clk_enable(priv->fclk); | ||
169 | clk_enable(priv->iclk); | ||
170 | |||
171 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | ||
172 | if (ret != 0) { | ||
173 | dev_err(&pdev->dev, "Failed to add hcd"); | ||
174 | goto fail_add_hcd; | ||
175 | } | ||
176 | |||
177 | priv->hcd = hcd; | ||
178 | platform_set_drvdata(pdev, priv); | ||
179 | |||
180 | return ret; | ||
181 | |||
182 | fail_add_hcd: | ||
183 | clk_disable(priv->iclk); | ||
184 | clk_disable(priv->fclk); | ||
185 | |||
186 | clk_put(priv->iclk); | ||
187 | clk_put(priv->fclk); | ||
188 | |||
189 | kfree(priv); | ||
190 | fail_alloc: | ||
191 | iounmap(hcd->regs); | ||
192 | fail_ioremap: | ||
193 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
194 | fail_request_resource: | ||
195 | usb_put_hcd(hcd); | ||
196 | fail_create_hcd: | ||
197 | dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), ret); | ||
198 | |||
199 | return ret; | ||
200 | } | ||
201 | |||
202 | static int __exit ehci_hcd_sh_remove(struct platform_device *pdev) | ||
203 | { | ||
204 | struct ehci_sh_priv *priv = platform_get_drvdata(pdev); | ||
205 | struct usb_hcd *hcd = priv->hcd; | ||
206 | |||
207 | usb_remove_hcd(hcd); | ||
208 | iounmap(hcd->regs); | ||
209 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
210 | usb_put_hcd(hcd); | ||
211 | platform_set_drvdata(pdev, NULL); | ||
212 | |||
213 | clk_disable(priv->fclk); | ||
214 | clk_disable(priv->iclk); | ||
215 | |||
216 | clk_put(priv->fclk); | ||
217 | clk_put(priv->iclk); | ||
218 | |||
219 | kfree(priv); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static void ehci_hcd_sh_shutdown(struct platform_device *pdev) | ||
225 | { | ||
226 | struct ehci_sh_priv *priv = platform_get_drvdata(pdev); | ||
227 | struct usb_hcd *hcd = priv->hcd; | ||
228 | |||
229 | if (hcd->driver->shutdown) | ||
230 | hcd->driver->shutdown(hcd); | ||
231 | } | ||
232 | |||
233 | static struct platform_driver ehci_hcd_sh_driver = { | ||
234 | .probe = ehci_hcd_sh_probe, | ||
235 | .remove = __exit_p(ehci_hcd_sh_remove), | ||
236 | .shutdown = ehci_hcd_sh_shutdown, | ||
237 | .driver = { | ||
238 | .name = "sh_ehci", | ||
239 | .owner = THIS_MODULE, | ||
240 | }, | ||
241 | }; | ||
242 | |||
243 | MODULE_ALIAS("platform:sh_ehci"); | ||
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c new file mode 100644 index 000000000000..75c00873443d --- /dev/null +++ b/drivers/usb/host/ehci-spear.c | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | * Driver for EHCI HCD on SPEAR SOC | ||
3 | * | ||
4 | * Copyright (C) 2010 ST Micro Electronics, | ||
5 | * Deepak Sikri <deepak.sikri@st.com> | ||
6 | * | ||
7 | * Based on various ehci-*.c drivers | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file COPYING in the main directory of this archive for | ||
11 | * more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/clk.h> | ||
16 | |||
17 | struct spear_ehci { | ||
18 | struct ehci_hcd ehci; | ||
19 | struct clk *clk; | ||
20 | }; | ||
21 | |||
22 | #define to_spear_ehci(hcd) (struct spear_ehci *)hcd_to_ehci(hcd) | ||
23 | |||
24 | static void spear_start_ehci(struct spear_ehci *ehci) | ||
25 | { | ||
26 | clk_enable(ehci->clk); | ||
27 | } | ||
28 | |||
29 | static void spear_stop_ehci(struct spear_ehci *ehci) | ||
30 | { | ||
31 | clk_disable(ehci->clk); | ||
32 | } | ||
33 | |||
34 | static int ehci_spear_setup(struct usb_hcd *hcd) | ||
35 | { | ||
36 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
37 | int retval = 0; | ||
38 | |||
39 | /* registers start at offset 0x0 */ | ||
40 | ehci->caps = hcd->regs; | ||
41 | ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, | ||
42 | &ehci->caps->hc_capbase)); | ||
43 | /* cache this readonly data; minimize chip reads */ | ||
44 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
45 | retval = ehci_halt(ehci); | ||
46 | if (retval) | ||
47 | return retval; | ||
48 | |||
49 | retval = ehci_init(hcd); | ||
50 | if (retval) | ||
51 | return retval; | ||
52 | |||
53 | ehci_reset(ehci); | ||
54 | ehci_port_power(ehci, 0); | ||
55 | |||
56 | return retval; | ||
57 | } | ||
58 | |||
59 | static const struct hc_driver ehci_spear_hc_driver = { | ||
60 | .description = hcd_name, | ||
61 | .product_desc = "SPEAr EHCI", | ||
62 | .hcd_priv_size = sizeof(struct spear_ehci), | ||
63 | |||
64 | /* generic hardware linkage */ | ||
65 | .irq = ehci_irq, | ||
66 | .flags = HCD_MEMORY | HCD_USB2, | ||
67 | |||
68 | /* basic lifecycle operations */ | ||
69 | .reset = ehci_spear_setup, | ||
70 | .start = ehci_run, | ||
71 | .stop = ehci_stop, | ||
72 | .shutdown = ehci_shutdown, | ||
73 | |||
74 | /* managing i/o requests and associated device resources */ | ||
75 | .urb_enqueue = ehci_urb_enqueue, | ||
76 | .urb_dequeue = ehci_urb_dequeue, | ||
77 | .endpoint_disable = ehci_endpoint_disable, | ||
78 | .endpoint_reset = ehci_endpoint_reset, | ||
79 | |||
80 | /* scheduling support */ | ||
81 | .get_frame_number = ehci_get_frame, | ||
82 | |||
83 | /* root hub support */ | ||
84 | .hub_status_data = ehci_hub_status_data, | ||
85 | .hub_control = ehci_hub_control, | ||
86 | .bus_suspend = ehci_bus_suspend, | ||
87 | .bus_resume = ehci_bus_resume, | ||
88 | .relinquish_port = ehci_relinquish_port, | ||
89 | .port_handed_over = ehci_port_handed_over, | ||
90 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
91 | }; | ||
92 | |||
93 | static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) | ||
94 | { | ||
95 | struct usb_hcd *hcd ; | ||
96 | struct spear_ehci *ehci; | ||
97 | struct resource *res; | ||
98 | struct clk *usbh_clk; | ||
99 | const struct hc_driver *driver = &ehci_spear_hc_driver; | ||
100 | int *pdata = pdev->dev.platform_data; | ||
101 | int irq, retval; | ||
102 | char clk_name[20] = "usbh_clk"; | ||
103 | |||
104 | if (pdata == NULL) | ||
105 | return -EFAULT; | ||
106 | |||
107 | if (usb_disabled()) | ||
108 | return -ENODEV; | ||
109 | |||
110 | irq = platform_get_irq(pdev, 0); | ||
111 | if (irq < 0) { | ||
112 | retval = irq; | ||
113 | goto fail_irq_get; | ||
114 | } | ||
115 | |||
116 | if (*pdata >= 0) | ||
117 | sprintf(clk_name, "usbh.%01d_clk", *pdata); | ||
118 | |||
119 | usbh_clk = clk_get(NULL, clk_name); | ||
120 | if (IS_ERR(usbh_clk)) { | ||
121 | dev_err(&pdev->dev, "Error getting interface clock\n"); | ||
122 | retval = PTR_ERR(usbh_clk); | ||
123 | goto fail_get_usbh_clk; | ||
124 | } | ||
125 | |||
126 | hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); | ||
127 | if (!hcd) { | ||
128 | retval = -ENOMEM; | ||
129 | goto fail_create_hcd; | ||
130 | } | ||
131 | |||
132 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
133 | if (!res) { | ||
134 | retval = -ENODEV; | ||
135 | goto fail_request_resource; | ||
136 | } | ||
137 | |||
138 | hcd->rsrc_start = res->start; | ||
139 | hcd->rsrc_len = resource_size(res); | ||
140 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, | ||
141 | driver->description)) { | ||
142 | retval = -EBUSY; | ||
143 | goto fail_request_resource; | ||
144 | } | ||
145 | |||
146 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
147 | if (hcd->regs == NULL) { | ||
148 | dev_dbg(&pdev->dev, "error mapping memory\n"); | ||
149 | retval = -ENOMEM; | ||
150 | goto fail_ioremap; | ||
151 | } | ||
152 | |||
153 | ehci = (struct spear_ehci *)hcd_to_ehci(hcd); | ||
154 | ehci->clk = usbh_clk; | ||
155 | |||
156 | spear_start_ehci(ehci); | ||
157 | retval = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_DISABLED); | ||
158 | if (retval) | ||
159 | goto fail_add_hcd; | ||
160 | |||
161 | return retval; | ||
162 | |||
163 | fail_add_hcd: | ||
164 | spear_stop_ehci(ehci); | ||
165 | iounmap(hcd->regs); | ||
166 | fail_ioremap: | ||
167 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
168 | fail_request_resource: | ||
169 | usb_put_hcd(hcd); | ||
170 | fail_create_hcd: | ||
171 | clk_put(usbh_clk); | ||
172 | fail_get_usbh_clk: | ||
173 | fail_irq_get: | ||
174 | dev_err(&pdev->dev, "init fail, %d\n", retval); | ||
175 | |||
176 | return retval ; | ||
177 | } | ||
178 | |||
179 | static int spear_ehci_hcd_drv_remove(struct platform_device *pdev) | ||
180 | { | ||
181 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
182 | struct spear_ehci *ehci_p = to_spear_ehci(hcd); | ||
183 | |||
184 | if (!hcd) | ||
185 | return 0; | ||
186 | if (in_interrupt()) | ||
187 | BUG(); | ||
188 | usb_remove_hcd(hcd); | ||
189 | |||
190 | if (ehci_p->clk) | ||
191 | spear_stop_ehci(ehci_p); | ||
192 | iounmap(hcd->regs); | ||
193 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
194 | usb_put_hcd(hcd); | ||
195 | |||
196 | if (ehci_p->clk) | ||
197 | clk_put(ehci_p->clk); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static struct platform_driver spear_ehci_hcd_driver = { | ||
203 | .probe = spear_ehci_hcd_drv_probe, | ||
204 | .remove = spear_ehci_hcd_drv_remove, | ||
205 | .shutdown = usb_hcd_platform_shutdown, | ||
206 | .driver = { | ||
207 | .name = "spear-ehci", | ||
208 | .bus = &platform_bus_type | ||
209 | } | ||
210 | }; | ||
211 | |||
212 | MODULE_ALIAS("platform:spear-ehci"); | ||
diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c new file mode 100644 index 000000000000..20168062035a --- /dev/null +++ b/drivers/usb/host/ehci-vt8500.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * drivers/usb/host/ehci-vt8500.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> | ||
5 | * | ||
6 | * Based on ehci-au1xxx.c | ||
7 | * | ||
8 | * This software is licensed under the terms of the GNU General Public | ||
9 | * License version 2, as published by the Free Software Foundation, and | ||
10 | * may be copied, distributed, and modified under those terms. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/platform_device.h> | ||
20 | |||
21 | static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev) | ||
22 | { | ||
23 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
24 | int rc = 0; | ||
25 | |||
26 | if (!udev->parent) /* udev is root hub itself, impossible */ | ||
27 | rc = -1; | ||
28 | /* we only support lpm device connected to root hub yet */ | ||
29 | if (ehci->has_lpm && !udev->parent->parent) { | ||
30 | rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum); | ||
31 | if (!rc) | ||
32 | rc = ehci_lpm_check(ehci, udev->portnum); | ||
33 | } | ||
34 | return rc; | ||
35 | } | ||
36 | |||
37 | static const struct hc_driver vt8500_ehci_hc_driver = { | ||
38 | .description = hcd_name, | ||
39 | .product_desc = "VT8500 EHCI", | ||
40 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
41 | |||
42 | /* | ||
43 | * generic hardware linkage | ||
44 | */ | ||
45 | .irq = ehci_irq, | ||
46 | .flags = HCD_MEMORY | HCD_USB2, | ||
47 | |||
48 | /* | ||
49 | * basic lifecycle operations | ||
50 | */ | ||
51 | .reset = ehci_init, | ||
52 | .start = ehci_run, | ||
53 | .stop = ehci_stop, | ||
54 | .shutdown = ehci_shutdown, | ||
55 | |||
56 | /* | ||
57 | * managing i/o requests and associated device resources | ||
58 | */ | ||
59 | .urb_enqueue = ehci_urb_enqueue, | ||
60 | .urb_dequeue = ehci_urb_dequeue, | ||
61 | .endpoint_disable = ehci_endpoint_disable, | ||
62 | .endpoint_reset = ehci_endpoint_reset, | ||
63 | |||
64 | /* | ||
65 | * scheduling support | ||
66 | */ | ||
67 | .get_frame_number = ehci_get_frame, | ||
68 | |||
69 | /* | ||
70 | * root hub support | ||
71 | */ | ||
72 | .hub_status_data = ehci_hub_status_data, | ||
73 | .hub_control = ehci_hub_control, | ||
74 | .bus_suspend = ehci_bus_suspend, | ||
75 | .bus_resume = ehci_bus_resume, | ||
76 | .relinquish_port = ehci_relinquish_port, | ||
77 | .port_handed_over = ehci_port_handed_over, | ||
78 | |||
79 | /* | ||
80 | * call back when device connected and addressed | ||
81 | */ | ||
82 | .update_device = ehci_update_device, | ||
83 | |||
84 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
85 | }; | ||
86 | |||
87 | static int vt8500_ehci_drv_probe(struct platform_device *pdev) | ||
88 | { | ||
89 | struct usb_hcd *hcd; | ||
90 | struct ehci_hcd *ehci; | ||
91 | struct resource *res; | ||
92 | int ret; | ||
93 | |||
94 | if (usb_disabled()) | ||
95 | return -ENODEV; | ||
96 | |||
97 | if (pdev->resource[1].flags != IORESOURCE_IRQ) { | ||
98 | pr_debug("resource[1] is not IORESOURCE_IRQ"); | ||
99 | return -ENOMEM; | ||
100 | } | ||
101 | hcd = usb_create_hcd(&vt8500_ehci_hc_driver, &pdev->dev, "VT8500"); | ||
102 | if (!hcd) | ||
103 | return -ENOMEM; | ||
104 | |||
105 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
106 | hcd->rsrc_start = res->start; | ||
107 | hcd->rsrc_len = resource_size(res); | ||
108 | |||
109 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
110 | pr_debug("request_mem_region failed"); | ||
111 | ret = -EBUSY; | ||
112 | goto err1; | ||
113 | } | ||
114 | |||
115 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
116 | if (!hcd->regs) { | ||
117 | pr_debug("ioremap failed"); | ||
118 | ret = -ENOMEM; | ||
119 | goto err2; | ||
120 | } | ||
121 | |||
122 | ehci = hcd_to_ehci(hcd); | ||
123 | ehci->caps = hcd->regs; | ||
124 | ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase)); | ||
125 | |||
126 | dbg_hcs_params(ehci, "reset"); | ||
127 | dbg_hcc_params(ehci, "reset"); | ||
128 | |||
129 | /* cache this readonly data; minimize chip reads */ | ||
130 | ehci->hcs_params = readl(&ehci->caps->hcs_params); | ||
131 | |||
132 | ehci_port_power(ehci, 1); | ||
133 | |||
134 | ret = usb_add_hcd(hcd, pdev->resource[1].start, | ||
135 | IRQF_DISABLED | IRQF_SHARED); | ||
136 | if (ret == 0) { | ||
137 | platform_set_drvdata(pdev, hcd); | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | iounmap(hcd->regs); | ||
142 | err2: | ||
143 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
144 | err1: | ||
145 | usb_put_hcd(hcd); | ||
146 | return ret; | ||
147 | } | ||
148 | |||
149 | static int vt8500_ehci_drv_remove(struct platform_device *pdev) | ||
150 | { | ||
151 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
152 | |||
153 | usb_remove_hcd(hcd); | ||
154 | iounmap(hcd->regs); | ||
155 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
156 | usb_put_hcd(hcd); | ||
157 | platform_set_drvdata(pdev, NULL); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static struct platform_driver vt8500_ehci_driver = { | ||
163 | .probe = vt8500_ehci_drv_probe, | ||
164 | .remove = vt8500_ehci_drv_remove, | ||
165 | .shutdown = usb_hcd_platform_shutdown, | ||
166 | .driver = { | ||
167 | .name = "vt8500-ehci", | ||
168 | .owner = THIS_MODULE, | ||
169 | } | ||
170 | }; | ||
171 | |||
172 | MODULE_ALIAS("platform:vt8500-ehci"); | ||
diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c index cfa21ea20f82..6bc35809a5c6 100644 --- a/drivers/usb/host/ehci-w90x900.c +++ b/drivers/usb/host/ehci-w90x900.c | |||
@@ -130,6 +130,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = { | |||
130 | .urb_enqueue = ehci_urb_enqueue, | 130 | .urb_enqueue = ehci_urb_enqueue, |
131 | .urb_dequeue = ehci_urb_dequeue, | 131 | .urb_dequeue = ehci_urb_dequeue, |
132 | .endpoint_disable = ehci_endpoint_disable, | 132 | .endpoint_disable = ehci_endpoint_disable, |
133 | .endpoint_reset = ehci_endpoint_reset, | ||
133 | 134 | ||
134 | /* | 135 | /* |
135 | * scheduling support | 136 | * scheduling support |
@@ -147,6 +148,8 @@ static const struct hc_driver ehci_w90x900_hc_driver = { | |||
147 | #endif | 148 | #endif |
148 | .relinquish_port = ehci_relinquish_port, | 149 | .relinquish_port = ehci_relinquish_port, |
149 | .port_handed_over = ehci_port_handed_over, | 150 | .port_handed_over = ehci_port_handed_over, |
151 | |||
152 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
150 | }; | 153 | }; |
151 | 154 | ||
152 | static int __devinit ehci_w90x900_probe(struct platform_device *pdev) | 155 | static int __devinit ehci_w90x900_probe(struct platform_device *pdev) |
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 6c8076ad821d..e8f4f36fdf0b 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c | |||
@@ -117,6 +117,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { | |||
117 | .urb_enqueue = ehci_urb_enqueue, | 117 | .urb_enqueue = ehci_urb_enqueue, |
118 | .urb_dequeue = ehci_urb_dequeue, | 118 | .urb_dequeue = ehci_urb_dequeue, |
119 | .endpoint_disable = ehci_endpoint_disable, | 119 | .endpoint_disable = ehci_endpoint_disable, |
120 | .endpoint_reset = ehci_endpoint_reset, | ||
120 | 121 | ||
121 | /* | 122 | /* |
122 | * scheduling support | 123 | * scheduling support |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index ba8eab366b82..799ac16a54b4 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -131,6 +131,7 @@ struct ehci_hcd { /* one per controller */ | |||
131 | unsigned has_amcc_usb23:1; | 131 | unsigned has_amcc_usb23:1; |
132 | unsigned need_io_watchdog:1; | 132 | unsigned need_io_watchdog:1; |
133 | unsigned broken_periodic:1; | 133 | unsigned broken_periodic:1; |
134 | unsigned amd_l1_fix:1; | ||
134 | unsigned fs_i_thresh:1; /* Intel iso scheduling */ | 135 | unsigned fs_i_thresh:1; /* Intel iso scheduling */ |
135 | unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/ | 136 | unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/ |
136 | 137 | ||
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 5cb6731ba443..9751647665df 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -1081,6 +1081,11 @@ MODULE_LICENSE ("GPL"); | |||
1081 | #define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver | 1081 | #define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver |
1082 | #endif | 1082 | #endif |
1083 | 1083 | ||
1084 | #ifdef CONFIG_PLAT_SPEAR | ||
1085 | #include "ohci-spear.c" | ||
1086 | #define PLATFORM_DRIVER spear_ohci_hcd_driver | ||
1087 | #endif | ||
1088 | |||
1084 | #ifdef CONFIG_PPC_PS3 | 1089 | #ifdef CONFIG_PPC_PS3 |
1085 | #include "ohci-ps3.c" | 1090 | #include "ohci-ps3.c" |
1086 | #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver | 1091 | #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver |
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index 2cc8a504b18c..a37d5993e4e3 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c | |||
@@ -648,7 +648,7 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) | |||
648 | 648 | ||
649 | ret = omap3_start_ohci(omap, hcd); | 649 | ret = omap3_start_ohci(omap, hcd); |
650 | if (ret) { | 650 | if (ret) { |
651 | dev_dbg(&pdev->dev, "failed to start ehci\n"); | 651 | dev_dbg(&pdev->dev, "failed to start ohci\n"); |
652 | goto err_start; | 652 | goto err_start; |
653 | } | 653 | } |
654 | 654 | ||
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c index 0b35d22cc70e..f47867ff78c7 100644 --- a/drivers/usb/host/ohci-sh.c +++ b/drivers/usb/host/ohci-sh.c | |||
@@ -109,7 +109,7 @@ static int ohci_hcd_sh_probe(struct platform_device *pdev) | |||
109 | hcd->regs = (void __iomem *)res->start; | 109 | hcd->regs = (void __iomem *)res->start; |
110 | hcd->rsrc_start = res->start; | 110 | hcd->rsrc_start = res->start; |
111 | hcd->rsrc_len = resource_size(res); | 111 | hcd->rsrc_len = resource_size(res); |
112 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); | 112 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); |
113 | if (ret != 0) { | 113 | if (ret != 0) { |
114 | err("Failed to add hcd"); | 114 | err("Failed to add hcd"); |
115 | usb_put_hcd(hcd); | 115 | usb_put_hcd(hcd); |
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c new file mode 100644 index 000000000000..4fd4bea9ac7a --- /dev/null +++ b/drivers/usb/host/ohci-spear.c | |||
@@ -0,0 +1,240 @@ | |||
1 | /* | ||
2 | * OHCI HCD (Host Controller Driver) for USB. | ||
3 | * | ||
4 | * Copyright (C) 2010 ST Microelectronics. | ||
5 | * Deepak Sikri<deepak.sikri@st.com> | ||
6 | * | ||
7 | * Based on various ohci-*.c drivers | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public | ||
10 | * License version 2. This program is licensed "as is" without any | ||
11 | * warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/signal.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/clk.h> | ||
17 | |||
18 | struct spear_ohci { | ||
19 | struct ohci_hcd ohci; | ||
20 | struct clk *clk; | ||
21 | }; | ||
22 | |||
23 | #define to_spear_ohci(hcd) (struct spear_ohci *)hcd_to_ohci(hcd) | ||
24 | |||
25 | static void spear_start_ohci(struct spear_ohci *ohci) | ||
26 | { | ||
27 | clk_enable(ohci->clk); | ||
28 | } | ||
29 | |||
30 | static void spear_stop_ohci(struct spear_ohci *ohci) | ||
31 | { | ||
32 | clk_disable(ohci->clk); | ||
33 | } | ||
34 | |||
35 | static int __devinit ohci_spear_start(struct usb_hcd *hcd) | ||
36 | { | ||
37 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
38 | int ret; | ||
39 | |||
40 | ret = ohci_init(ohci); | ||
41 | if (ret < 0) | ||
42 | return ret; | ||
43 | ohci->regs = hcd->regs; | ||
44 | |||
45 | ret = ohci_run(ohci); | ||
46 | if (ret < 0) { | ||
47 | dev_err(hcd->self.controller, "can't start\n"); | ||
48 | ohci_stop(hcd); | ||
49 | return ret; | ||
50 | } | ||
51 | |||
52 | create_debug_files(ohci); | ||
53 | |||
54 | #ifdef DEBUG | ||
55 | ohci_dump(ohci, 1); | ||
56 | #endif | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static const struct hc_driver ohci_spear_hc_driver = { | ||
61 | .description = hcd_name, | ||
62 | .product_desc = "SPEAr OHCI", | ||
63 | .hcd_priv_size = sizeof(struct spear_ohci), | ||
64 | |||
65 | /* generic hardware linkage */ | ||
66 | .irq = ohci_irq, | ||
67 | .flags = HCD_USB11 | HCD_MEMORY, | ||
68 | |||
69 | /* basic lifecycle operations */ | ||
70 | .start = ohci_spear_start, | ||
71 | .stop = ohci_stop, | ||
72 | .shutdown = ohci_shutdown, | ||
73 | #ifdef CONFIG_PM | ||
74 | .bus_suspend = ohci_bus_suspend, | ||
75 | .bus_resume = ohci_bus_resume, | ||
76 | #endif | ||
77 | |||
78 | /* managing i/o requests and associated device resources */ | ||
79 | .urb_enqueue = ohci_urb_enqueue, | ||
80 | .urb_dequeue = ohci_urb_dequeue, | ||
81 | .endpoint_disable = ohci_endpoint_disable, | ||
82 | |||
83 | /* scheduling support */ | ||
84 | .get_frame_number = ohci_get_frame, | ||
85 | |||
86 | /* root hub support */ | ||
87 | .hub_status_data = ohci_hub_status_data, | ||
88 | .hub_control = ohci_hub_control, | ||
89 | |||
90 | .start_port_reset = ohci_start_port_reset, | ||
91 | }; | ||
92 | |||
93 | static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) | ||
94 | { | ||
95 | const struct hc_driver *driver = &ohci_spear_hc_driver; | ||
96 | struct usb_hcd *hcd = NULL; | ||
97 | struct clk *usbh_clk; | ||
98 | struct spear_ohci *ohci_p; | ||
99 | struct resource *res; | ||
100 | int retval, irq; | ||
101 | int *pdata = pdev->dev.platform_data; | ||
102 | char clk_name[20] = "usbh_clk"; | ||
103 | |||
104 | if (pdata == NULL) | ||
105 | return -EFAULT; | ||
106 | |||
107 | irq = platform_get_irq(pdev, 0); | ||
108 | if (irq < 0) { | ||
109 | retval = irq; | ||
110 | goto fail_irq_get; | ||
111 | } | ||
112 | |||
113 | if (*pdata >= 0) | ||
114 | sprintf(clk_name, "usbh.%01d_clk", *pdata); | ||
115 | |||
116 | usbh_clk = clk_get(NULL, clk_name); | ||
117 | if (IS_ERR(usbh_clk)) { | ||
118 | dev_err(&pdev->dev, "Error getting interface clock\n"); | ||
119 | retval = PTR_ERR(usbh_clk); | ||
120 | goto fail_get_usbh_clk; | ||
121 | } | ||
122 | |||
123 | hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); | ||
124 | if (!hcd) { | ||
125 | retval = -ENOMEM; | ||
126 | goto fail_create_hcd; | ||
127 | } | ||
128 | |||
129 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
130 | if (!res) { | ||
131 | retval = -ENODEV; | ||
132 | goto fail_request_resource; | ||
133 | } | ||
134 | |||
135 | hcd->rsrc_start = pdev->resource[0].start; | ||
136 | hcd->rsrc_len = resource_size(res); | ||
137 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
138 | dev_dbg(&pdev->dev, "request_mem_region failed\n"); | ||
139 | retval = -EBUSY; | ||
140 | goto fail_request_resource; | ||
141 | } | ||
142 | |||
143 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
144 | if (!hcd->regs) { | ||
145 | dev_dbg(&pdev->dev, "ioremap failed\n"); | ||
146 | retval = -ENOMEM; | ||
147 | goto fail_ioremap; | ||
148 | } | ||
149 | |||
150 | ohci_p = (struct spear_ohci *)hcd_to_ohci(hcd); | ||
151 | ohci_p->clk = usbh_clk; | ||
152 | spear_start_ohci(ohci_p); | ||
153 | ohci_hcd_init(hcd_to_ohci(hcd)); | ||
154 | |||
155 | retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), IRQF_DISABLED); | ||
156 | if (retval == 0) | ||
157 | return retval; | ||
158 | |||
159 | spear_stop_ohci(ohci_p); | ||
160 | iounmap(hcd->regs); | ||
161 | fail_ioremap: | ||
162 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
163 | fail_request_resource: | ||
164 | usb_put_hcd(hcd); | ||
165 | fail_create_hcd: | ||
166 | clk_put(usbh_clk); | ||
167 | fail_get_usbh_clk: | ||
168 | fail_irq_get: | ||
169 | dev_err(&pdev->dev, "init fail, %d\n", retval); | ||
170 | |||
171 | return retval; | ||
172 | } | ||
173 | |||
174 | static int spear_ohci_hcd_drv_remove(struct platform_device *pdev) | ||
175 | { | ||
176 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
177 | struct spear_ohci *ohci_p = to_spear_ohci(hcd); | ||
178 | |||
179 | usb_remove_hcd(hcd); | ||
180 | if (ohci_p->clk) | ||
181 | spear_stop_ohci(ohci_p); | ||
182 | |||
183 | iounmap(hcd->regs); | ||
184 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
185 | usb_put_hcd(hcd); | ||
186 | |||
187 | if (ohci_p->clk) | ||
188 | clk_put(ohci_p->clk); | ||
189 | platform_set_drvdata(pdev, NULL); | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | #if defined(CONFIG_PM) | ||
194 | static int spear_ohci_hcd_drv_suspend(struct platform_device *dev, | ||
195 | pm_message_t message) | ||
196 | { | ||
197 | struct usb_hcd *hcd = platform_get_drvdata(dev); | ||
198 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
199 | struct spear_ohci *ohci_p = to_spear_ohci(hcd); | ||
200 | |||
201 | if (time_before(jiffies, ohci->next_statechange)) | ||
202 | msleep(5); | ||
203 | ohci->next_statechange = jiffies; | ||
204 | |||
205 | spear_stop_ohci(ohci_p); | ||
206 | ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED; | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static int spear_ohci_hcd_drv_resume(struct platform_device *dev) | ||
211 | { | ||
212 | struct usb_hcd *hcd = platform_get_drvdata(dev); | ||
213 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
214 | struct spear_ohci *ohci_p = to_spear_ohci(hcd); | ||
215 | |||
216 | if (time_before(jiffies, ohci->next_statechange)) | ||
217 | msleep(5); | ||
218 | ohci->next_statechange = jiffies; | ||
219 | |||
220 | spear_start_ohci(ohci_p); | ||
221 | ohci_finish_controller_resume(hcd); | ||
222 | return 0; | ||
223 | } | ||
224 | #endif | ||
225 | |||
226 | /* Driver definition to register with the platform bus */ | ||
227 | static struct platform_driver spear_ohci_hcd_driver = { | ||
228 | .probe = spear_ohci_hcd_drv_probe, | ||
229 | .remove = spear_ohci_hcd_drv_remove, | ||
230 | #ifdef CONFIG_PM | ||
231 | .suspend = spear_ohci_hcd_drv_suspend, | ||
232 | .resume = spear_ohci_hcd_drv_resume, | ||
233 | #endif | ||
234 | .driver = { | ||
235 | .owner = THIS_MODULE, | ||
236 | .name = "spear-ohci", | ||
237 | }, | ||
238 | }; | ||
239 | |||
240 | MODULE_ALIAS("platform:spear-ohci"); | ||
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index f52d04db28f4..cee867829ec9 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -569,7 +569,7 @@ static int uhci_init(struct usb_hcd *hcd) | |||
569 | */ | 569 | */ |
570 | static void uhci_shutdown(struct pci_dev *pdev) | 570 | static void uhci_shutdown(struct pci_dev *pdev) |
571 | { | 571 | { |
572 | struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev); | 572 | struct usb_hcd *hcd = pci_get_drvdata(pdev); |
573 | 573 | ||
574 | uhci_hc_died(hcd_to_uhci(hcd)); | 574 | uhci_hc_died(hcd_to_uhci(hcd)); |
575 | } | 575 | } |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 2090b45eb606..af77abb5c68b 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
@@ -29,7 +29,7 @@ static void uhci_set_next_interrupt(struct uhci_hcd *uhci) | |||
29 | { | 29 | { |
30 | if (uhci->is_stopped) | 30 | if (uhci->is_stopped) |
31 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); | 31 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); |
32 | uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); | 32 | uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); |
33 | } | 33 | } |
34 | 34 | ||
35 | static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci) | 35 | static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci) |
@@ -195,7 +195,9 @@ static inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci, | |||
195 | } else { | 195 | } else { |
196 | struct uhci_td *ntd; | 196 | struct uhci_td *ntd; |
197 | 197 | ||
198 | ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list); | 198 | ntd = list_entry(td->fl_list.next, |
199 | struct uhci_td, | ||
200 | fl_list); | ||
199 | uhci->frame[td->frame] = LINK_TO_TD(ntd); | 201 | uhci->frame[td->frame] = LINK_TO_TD(ntd); |
200 | uhci->frame_cpu[td->frame] = ntd; | 202 | uhci->frame_cpu[td->frame] = ntd; |
201 | } | 203 | } |
@@ -728,7 +730,7 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, | |||
728 | 730 | ||
729 | urbp->urb = urb; | 731 | urbp->urb = urb; |
730 | urb->hcpriv = urbp; | 732 | urb->hcpriv = urbp; |
731 | 733 | ||
732 | INIT_LIST_HEAD(&urbp->node); | 734 | INIT_LIST_HEAD(&urbp->node); |
733 | INIT_LIST_HEAD(&urbp->td_list); | 735 | INIT_LIST_HEAD(&urbp->td_list); |
734 | 736 | ||
@@ -846,7 +848,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
846 | 848 | ||
847 | /* Alternate Data0/1 (start with Data1) */ | 849 | /* Alternate Data0/1 (start with Data1) */ |
848 | destination ^= TD_TOKEN_TOGGLE; | 850 | destination ^= TD_TOKEN_TOGGLE; |
849 | 851 | ||
850 | uhci_add_td_to_urbp(td, urbp); | 852 | uhci_add_td_to_urbp(td, urbp); |
851 | uhci_fill_td(td, status, destination | uhci_explen(pktsze), | 853 | uhci_fill_td(td, status, destination | uhci_explen(pktsze), |
852 | data); | 854 | data); |
@@ -857,7 +859,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, | |||
857 | } | 859 | } |
858 | 860 | ||
859 | /* | 861 | /* |
860 | * Build the final TD for control status | 862 | * Build the final TD for control status |
861 | */ | 863 | */ |
862 | td = uhci_alloc_td(uhci); | 864 | td = uhci_alloc_td(uhci); |
863 | if (!td) | 865 | if (!td) |
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c index 72b6892fda67..9546f6cd01f0 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/usb/host/whci/hcd.c | |||
@@ -356,7 +356,7 @@ static void __exit whci_hc_driver_exit(void) | |||
356 | module_exit(whci_hc_driver_exit); | 356 | module_exit(whci_hc_driver_exit); |
357 | 357 | ||
358 | /* PCI device ID's that we handle (so it gets loaded) */ | 358 | /* PCI device ID's that we handle (so it gets loaded) */ |
359 | static struct pci_device_id whci_hcd_id_table[] = { | 359 | static struct pci_device_id __used whci_hcd_id_table[] = { |
360 | { PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI, ~0) }, | 360 | { PCI_DEVICE_CLASS(PCI_CLASS_WIRELESS_WHCI, ~0) }, |
361 | { /* empty last entry */ } | 361 | { /* empty last entry */ } |
362 | }; | 362 | }; |