diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 18:04:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 18:04:26 -0400 |
commit | 971f115a50afbe409825c9f3399d5a3b9aca4381 (patch) | |
tree | cb42dc07a032e325f22b64d961587c081225c6d6 /drivers/usb/musb | |
parent | 2e270d84223262a38d4755c61d55f5c73ea89e56 (diff) | |
parent | 500132a0f26ad7d9916102193cbc6c1b1becb373 (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: (172 commits)
USB: Add support for SuperSpeed isoc endpoints
xhci: Clean up cycle bit math used during stalls.
xhci: Fix cycle bit calculation during stall handling.
xhci: Update internal dequeue pointers after stalls.
USB: Disable auto-suspend for USB 3.0 hubs.
USB: Remove bogus USB_PORT_STAT_SUPER_SPEED symbol.
xhci: Return canceled URBs immediately when host is halted.
xhci: Fixes for suspend/resume of shared HCDs.
xhci: Fix re-init on power loss after resume.
xhci: Make roothub functions deal with device removal.
xhci: Limit roothub ports to 15 USB3 & 31 USB2 ports.
xhci: Return a USB 3.0 hub descriptor for USB3 roothub.
xhci: Register second xHCI roothub.
xhci: Change xhci_find_slot_id_by_port() API.
xhci: Refactor bus suspend state into a struct.
xhci: Index with a port array instead of PORTSC addresses.
USB: Set usb_hcd->state and flags for shared roothubs.
usb: Make core allocate resources per PCI-device.
usb: Store bus type in usb_hcd, not in driver flags.
usb: Change usb_hcd->bandwidth_mutex to a pointer.
...
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r-- | drivers/usb/musb/musb_core.c | 65 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.h | 8 | ||||
-rw-r--r-- | drivers/usb/musb/musb_gadget.c | 217 | ||||
-rw-r--r-- | drivers/usb/musb/musb_gadget.h | 7 | ||||
-rw-r--r-- | drivers/usb/musb/musb_gadget_ep0.c | 24 | ||||
-rw-r--r-- | drivers/usb/musb/musb_host.c | 4 | ||||
-rw-r--r-- | drivers/usb/musb/musb_virthub.c | 4 | ||||
-rw-r--r-- | drivers/usb/musb/omap2430.c | 176 | ||||
-rw-r--r-- | drivers/usb/musb/tusb6010_omap.c | 4 |
9 files changed, 275 insertions, 234 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index c292d5c499e7..a914010d9d12 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
@@ -1950,31 +1950,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
1950 | goto fail0; | 1950 | goto fail0; |
1951 | } | 1951 | } |
1952 | 1952 | ||
1953 | switch (plat->mode) { | ||
1954 | case MUSB_HOST: | ||
1955 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
1956 | break; | ||
1957 | #else | ||
1958 | goto bad_config; | ||
1959 | #endif | ||
1960 | case MUSB_PERIPHERAL: | ||
1961 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
1962 | break; | ||
1963 | #else | ||
1964 | goto bad_config; | ||
1965 | #endif | ||
1966 | case MUSB_OTG: | ||
1967 | #ifdef CONFIG_USB_MUSB_OTG | ||
1968 | break; | ||
1969 | #else | ||
1970 | bad_config: | ||
1971 | #endif | ||
1972 | default: | ||
1973 | dev_err(dev, "incompatible Kconfig role setting\n"); | ||
1974 | status = -EINVAL; | ||
1975 | goto fail0; | ||
1976 | } | ||
1977 | |||
1978 | /* allocate */ | 1953 | /* allocate */ |
1979 | musb = allocate_instance(dev, plat->config, ctrl); | 1954 | musb = allocate_instance(dev, plat->config, ctrl); |
1980 | if (!musb) { | 1955 | if (!musb) { |
@@ -1982,6 +1957,10 @@ bad_config: | |||
1982 | goto fail0; | 1957 | goto fail0; |
1983 | } | 1958 | } |
1984 | 1959 | ||
1960 | pm_runtime_use_autosuspend(musb->controller); | ||
1961 | pm_runtime_set_autosuspend_delay(musb->controller, 200); | ||
1962 | pm_runtime_enable(musb->controller); | ||
1963 | |||
1985 | spin_lock_init(&musb->lock); | 1964 | spin_lock_init(&musb->lock); |
1986 | musb->board_mode = plat->mode; | 1965 | musb->board_mode = plat->mode; |
1987 | musb->board_set_power = plat->set_power; | 1966 | musb->board_set_power = plat->set_power; |
@@ -2117,6 +2096,8 @@ bad_config: | |||
2117 | if (status < 0) | 2096 | if (status < 0) |
2118 | goto fail3; | 2097 | goto fail3; |
2119 | 2098 | ||
2099 | pm_runtime_put(musb->controller); | ||
2100 | |||
2120 | status = musb_init_debugfs(musb); | 2101 | status = musb_init_debugfs(musb); |
2121 | if (status < 0) | 2102 | if (status < 0) |
2122 | goto fail4; | 2103 | goto fail4; |
@@ -2216,9 +2197,11 @@ static int __exit musb_remove(struct platform_device *pdev) | |||
2216 | * - Peripheral mode: peripheral is deactivated (or never-activated) | 2197 | * - Peripheral mode: peripheral is deactivated (or never-activated) |
2217 | * - OTG mode: both roles are deactivated (or never-activated) | 2198 | * - OTG mode: both roles are deactivated (or never-activated) |
2218 | */ | 2199 | */ |
2200 | pm_runtime_get_sync(musb->controller); | ||
2219 | musb_exit_debugfs(musb); | 2201 | musb_exit_debugfs(musb); |
2220 | musb_shutdown(pdev); | 2202 | musb_shutdown(pdev); |
2221 | 2203 | ||
2204 | pm_runtime_put(musb->controller); | ||
2222 | musb_free(musb); | 2205 | musb_free(musb); |
2223 | iounmap(ctrl_base); | 2206 | iounmap(ctrl_base); |
2224 | device_init_wakeup(&pdev->dev, 0); | 2207 | device_init_wakeup(&pdev->dev, 0); |
@@ -2404,9 +2387,41 @@ static int musb_resume_noirq(struct device *dev) | |||
2404 | return 0; | 2387 | return 0; |
2405 | } | 2388 | } |
2406 | 2389 | ||
2390 | static int musb_runtime_suspend(struct device *dev) | ||
2391 | { | ||
2392 | struct musb *musb = dev_to_musb(dev); | ||
2393 | |||
2394 | musb_save_context(musb); | ||
2395 | |||
2396 | return 0; | ||
2397 | } | ||
2398 | |||
2399 | static int musb_runtime_resume(struct device *dev) | ||
2400 | { | ||
2401 | struct musb *musb = dev_to_musb(dev); | ||
2402 | static int first = 1; | ||
2403 | |||
2404 | /* | ||
2405 | * When pm_runtime_get_sync called for the first time in driver | ||
2406 | * init, some of the structure is still not initialized which is | ||
2407 | * used in restore function. But clock needs to be | ||
2408 | * enabled before any register access, so | ||
2409 | * pm_runtime_get_sync has to be called. | ||
2410 | * Also context restore without save does not make | ||
2411 | * any sense | ||
2412 | */ | ||
2413 | if (!first) | ||
2414 | musb_restore_context(musb); | ||
2415 | first = 0; | ||
2416 | |||
2417 | return 0; | ||
2418 | } | ||
2419 | |||
2407 | static const struct dev_pm_ops musb_dev_pm_ops = { | 2420 | static const struct dev_pm_ops musb_dev_pm_ops = { |
2408 | .suspend = musb_suspend, | 2421 | .suspend = musb_suspend, |
2409 | .resume_noirq = musb_resume_noirq, | 2422 | .resume_noirq = musb_resume_noirq, |
2423 | .runtime_suspend = musb_runtime_suspend, | ||
2424 | .runtime_resume = musb_runtime_resume, | ||
2410 | }; | 2425 | }; |
2411 | 2426 | ||
2412 | #define MUSB_DEV_PM_OPS (&musb_dev_pm_ops) | 2427 | #define MUSB_DEV_PM_OPS (&musb_dev_pm_ops) |
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index e6400be8a0f8..4f0dd2ed3964 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h | |||
@@ -328,7 +328,7 @@ struct musb_hw_ep { | |||
328 | #endif | 328 | #endif |
329 | }; | 329 | }; |
330 | 330 | ||
331 | static inline struct usb_request *next_in_request(struct musb_hw_ep *hw_ep) | 331 | static inline struct musb_request *next_in_request(struct musb_hw_ep *hw_ep) |
332 | { | 332 | { |
333 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | 333 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC |
334 | return next_request(&hw_ep->ep_in); | 334 | return next_request(&hw_ep->ep_in); |
@@ -337,7 +337,7 @@ static inline struct usb_request *next_in_request(struct musb_hw_ep *hw_ep) | |||
337 | #endif | 337 | #endif |
338 | } | 338 | } |
339 | 339 | ||
340 | static inline struct usb_request *next_out_request(struct musb_hw_ep *hw_ep) | 340 | static inline struct musb_request *next_out_request(struct musb_hw_ep *hw_ep) |
341 | { | 341 | { |
342 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | 342 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC |
343 | return next_request(&hw_ep->ep_out); | 343 | return next_request(&hw_ep->ep_out); |
@@ -358,10 +358,6 @@ struct musb_csr_regs { | |||
358 | 358 | ||
359 | struct musb_context_registers { | 359 | struct musb_context_registers { |
360 | 360 | ||
361 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ | ||
362 | defined(CONFIG_ARCH_OMAP4) | ||
363 | u32 otg_sysconfig, otg_forcestandby; | ||
364 | #endif | ||
365 | u8 power; | 361 | u8 power; |
366 | u16 intrtxe, intrrxe; | 362 | u16 intrtxe, intrrxe; |
367 | u8 intrusbe; | 363 | u8 intrusbe; |
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 2fe304611dcf..5c7b321d3959 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c | |||
@@ -189,7 +189,7 @@ __acquires(ep->musb->lock) | |||
189 | 189 | ||
190 | req = to_musb_request(request); | 190 | req = to_musb_request(request); |
191 | 191 | ||
192 | list_del(&request->list); | 192 | list_del(&req->list); |
193 | if (req->request.status == -EINPROGRESS) | 193 | if (req->request.status == -EINPROGRESS) |
194 | req->request.status = status; | 194 | req->request.status = status; |
195 | musb = req->musb; | 195 | musb = req->musb; |
@@ -251,9 +251,8 @@ static void nuke(struct musb_ep *ep, const int status) | |||
251 | ep->dma = NULL; | 251 | ep->dma = NULL; |
252 | } | 252 | } |
253 | 253 | ||
254 | while (!list_empty(&(ep->req_list))) { | 254 | while (!list_empty(&ep->req_list)) { |
255 | req = container_of(ep->req_list.next, struct musb_request, | 255 | req = list_first_entry(&ep->req_list, struct musb_request, list); |
256 | request.list); | ||
257 | musb_g_giveback(ep, &req->request, status); | 256 | musb_g_giveback(ep, &req->request, status); |
258 | } | 257 | } |
259 | } | 258 | } |
@@ -485,6 +484,7 @@ static void txstate(struct musb *musb, struct musb_request *req) | |||
485 | void musb_g_tx(struct musb *musb, u8 epnum) | 484 | void musb_g_tx(struct musb *musb, u8 epnum) |
486 | { | 485 | { |
487 | u16 csr; | 486 | u16 csr; |
487 | struct musb_request *req; | ||
488 | struct usb_request *request; | 488 | struct usb_request *request; |
489 | u8 __iomem *mbase = musb->mregs; | 489 | u8 __iomem *mbase = musb->mregs; |
490 | struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_in; | 490 | struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_in; |
@@ -492,7 +492,8 @@ void musb_g_tx(struct musb *musb, u8 epnum) | |||
492 | struct dma_channel *dma; | 492 | struct dma_channel *dma; |
493 | 493 | ||
494 | musb_ep_select(mbase, epnum); | 494 | musb_ep_select(mbase, epnum); |
495 | request = next_request(musb_ep); | 495 | req = next_request(musb_ep); |
496 | request = &req->request; | ||
496 | 497 | ||
497 | csr = musb_readw(epio, MUSB_TXCSR); | 498 | csr = musb_readw(epio, MUSB_TXCSR); |
498 | DBG(4, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr); | 499 | DBG(4, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr); |
@@ -571,15 +572,15 @@ void musb_g_tx(struct musb *musb, u8 epnum) | |||
571 | 572 | ||
572 | if (request->actual == request->length) { | 573 | if (request->actual == request->length) { |
573 | musb_g_giveback(musb_ep, request, 0); | 574 | musb_g_giveback(musb_ep, request, 0); |
574 | request = musb_ep->desc ? next_request(musb_ep) : NULL; | 575 | req = musb_ep->desc ? next_request(musb_ep) : NULL; |
575 | if (!request) { | 576 | if (!req) { |
576 | DBG(4, "%s idle now\n", | 577 | DBG(4, "%s idle now\n", |
577 | musb_ep->end_point.name); | 578 | musb_ep->end_point.name); |
578 | return; | 579 | return; |
579 | } | 580 | } |
580 | } | 581 | } |
581 | 582 | ||
582 | txstate(musb, to_musb_request(request)); | 583 | txstate(musb, req); |
583 | } | 584 | } |
584 | } | 585 | } |
585 | 586 | ||
@@ -821,6 +822,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) | |||
821 | void musb_g_rx(struct musb *musb, u8 epnum) | 822 | void musb_g_rx(struct musb *musb, u8 epnum) |
822 | { | 823 | { |
823 | u16 csr; | 824 | u16 csr; |
825 | struct musb_request *req; | ||
824 | struct usb_request *request; | 826 | struct usb_request *request; |
825 | void __iomem *mbase = musb->mregs; | 827 | void __iomem *mbase = musb->mregs; |
826 | struct musb_ep *musb_ep; | 828 | struct musb_ep *musb_ep; |
@@ -835,10 +837,12 @@ void musb_g_rx(struct musb *musb, u8 epnum) | |||
835 | 837 | ||
836 | musb_ep_select(mbase, epnum); | 838 | musb_ep_select(mbase, epnum); |
837 | 839 | ||
838 | request = next_request(musb_ep); | 840 | req = next_request(musb_ep); |
839 | if (!request) | 841 | if (!req) |
840 | return; | 842 | return; |
841 | 843 | ||
844 | request = &req->request; | ||
845 | |||
842 | csr = musb_readw(epio, MUSB_RXCSR); | 846 | csr = musb_readw(epio, MUSB_RXCSR); |
843 | dma = is_dma_capable() ? musb_ep->dma : NULL; | 847 | dma = is_dma_capable() ? musb_ep->dma : NULL; |
844 | 848 | ||
@@ -914,15 +918,15 @@ void musb_g_rx(struct musb *musb, u8 epnum) | |||
914 | #endif | 918 | #endif |
915 | musb_g_giveback(musb_ep, request, 0); | 919 | musb_g_giveback(musb_ep, request, 0); |
916 | 920 | ||
917 | request = next_request(musb_ep); | 921 | req = next_request(musb_ep); |
918 | if (!request) | 922 | if (!req) |
919 | return; | 923 | return; |
920 | } | 924 | } |
921 | #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA) | 925 | #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA) |
922 | exit: | 926 | exit: |
923 | #endif | 927 | #endif |
924 | /* Analyze request */ | 928 | /* Analyze request */ |
925 | rxstate(musb, to_musb_request(request)); | 929 | rxstate(musb, req); |
926 | } | 930 | } |
927 | 931 | ||
928 | /* ------------------------------------------------------------ */ | 932 | /* ------------------------------------------------------------ */ |
@@ -974,7 +978,7 @@ static int musb_gadget_enable(struct usb_ep *ep, | |||
974 | ok = musb->hb_iso_rx; | 978 | ok = musb->hb_iso_rx; |
975 | 979 | ||
976 | if (!ok) { | 980 | if (!ok) { |
977 | DBG(4, "%s: not support ISO high bandwidth\n", __func__); | 981 | DBG(4, "no support for high bandwidth ISO\n"); |
978 | goto fail; | 982 | goto fail; |
979 | } | 983 | } |
980 | musb_ep->hb_mult = (tmp >> 11) & 3; | 984 | musb_ep->hb_mult = (tmp >> 11) & 3; |
@@ -998,7 +1002,7 @@ static int musb_gadget_enable(struct usb_ep *ep, | |||
998 | goto fail; | 1002 | goto fail; |
999 | 1003 | ||
1000 | if (tmp > hw_ep->max_packet_sz_tx) { | 1004 | if (tmp > hw_ep->max_packet_sz_tx) { |
1001 | DBG(4, "%s: packet size beyond hw fifo size\n", __func__); | 1005 | DBG(4, "packet size beyond hardware FIFO size\n"); |
1002 | goto fail; | 1006 | goto fail; |
1003 | } | 1007 | } |
1004 | 1008 | ||
@@ -1038,7 +1042,7 @@ static int musb_gadget_enable(struct usb_ep *ep, | |||
1038 | goto fail; | 1042 | goto fail; |
1039 | 1043 | ||
1040 | if (tmp > hw_ep->max_packet_sz_rx) { | 1044 | if (tmp > hw_ep->max_packet_sz_rx) { |
1041 | DBG(4, "%s: packet size beyond hw fifo size\n", __func__); | 1045 | DBG(4, "packet size beyond hardware FIFO size\n"); |
1042 | goto fail; | 1046 | goto fail; |
1043 | } | 1047 | } |
1044 | 1048 | ||
@@ -1171,7 +1175,6 @@ struct usb_request *musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) | |||
1171 | return NULL; | 1175 | return NULL; |
1172 | } | 1176 | } |
1173 | 1177 | ||
1174 | INIT_LIST_HEAD(&request->request.list); | ||
1175 | request->request.dma = DMA_ADDR_INVALID; | 1178 | request->request.dma = DMA_ADDR_INVALID; |
1176 | request->epnum = musb_ep->current_epnum; | 1179 | request->epnum = musb_ep->current_epnum; |
1177 | request->ep = musb_ep; | 1180 | request->ep = musb_ep; |
@@ -1257,10 +1260,10 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, | |||
1257 | } | 1260 | } |
1258 | 1261 | ||
1259 | /* add request to the list */ | 1262 | /* add request to the list */ |
1260 | list_add_tail(&(request->request.list), &(musb_ep->req_list)); | 1263 | list_add_tail(&request->list, &musb_ep->req_list); |
1261 | 1264 | ||
1262 | /* it this is the head of the queue, start i/o ... */ | 1265 | /* it this is the head of the queue, start i/o ... */ |
1263 | if (!musb_ep->busy && &request->request.list == musb_ep->req_list.next) | 1266 | if (!musb_ep->busy && &request->list == musb_ep->req_list.next) |
1264 | musb_ep_restart(musb, request); | 1267 | musb_ep_restart(musb, request); |
1265 | 1268 | ||
1266 | cleanup: | 1269 | cleanup: |
@@ -1271,7 +1274,8 @@ cleanup: | |||
1271 | static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request) | 1274 | static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request) |
1272 | { | 1275 | { |
1273 | struct musb_ep *musb_ep = to_musb_ep(ep); | 1276 | struct musb_ep *musb_ep = to_musb_ep(ep); |
1274 | struct usb_request *r; | 1277 | struct musb_request *req = to_musb_request(request); |
1278 | struct musb_request *r; | ||
1275 | unsigned long flags; | 1279 | unsigned long flags; |
1276 | int status = 0; | 1280 | int status = 0; |
1277 | struct musb *musb = musb_ep->musb; | 1281 | struct musb *musb = musb_ep->musb; |
@@ -1282,10 +1286,10 @@ static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request) | |||
1282 | spin_lock_irqsave(&musb->lock, flags); | 1286 | spin_lock_irqsave(&musb->lock, flags); |
1283 | 1287 | ||
1284 | list_for_each_entry(r, &musb_ep->req_list, list) { | 1288 | list_for_each_entry(r, &musb_ep->req_list, list) { |
1285 | if (r == request) | 1289 | if (r == req) |
1286 | break; | 1290 | break; |
1287 | } | 1291 | } |
1288 | if (r != request) { | 1292 | if (r != req) { |
1289 | DBG(3, "request %p not queued to %s\n", request, ep->name); | 1293 | DBG(3, "request %p not queued to %s\n", request, ep->name); |
1290 | status = -EINVAL; | 1294 | status = -EINVAL; |
1291 | goto done; | 1295 | goto done; |
@@ -1349,7 +1353,7 @@ static int musb_gadget_set_halt(struct usb_ep *ep, int value) | |||
1349 | 1353 | ||
1350 | musb_ep_select(mbase, epnum); | 1354 | musb_ep_select(mbase, epnum); |
1351 | 1355 | ||
1352 | request = to_musb_request(next_request(musb_ep)); | 1356 | request = next_request(musb_ep); |
1353 | if (value) { | 1357 | if (value) { |
1354 | if (request) { | 1358 | if (request) { |
1355 | DBG(3, "request in progress, cannot halt %s\n", | 1359 | DBG(3, "request in progress, cannot halt %s\n", |
@@ -1801,90 +1805,105 @@ void musb_gadget_cleanup(struct musb *musb) | |||
1801 | int usb_gadget_probe_driver(struct usb_gadget_driver *driver, | 1805 | int usb_gadget_probe_driver(struct usb_gadget_driver *driver, |
1802 | int (*bind)(struct usb_gadget *)) | 1806 | int (*bind)(struct usb_gadget *)) |
1803 | { | 1807 | { |
1804 | int retval; | 1808 | struct musb *musb = the_gadget; |
1805 | unsigned long flags; | 1809 | unsigned long flags; |
1806 | struct musb *musb = the_gadget; | 1810 | int retval = -EINVAL; |
1807 | 1811 | ||
1808 | if (!driver | 1812 | if (!driver |
1809 | || driver->speed != USB_SPEED_HIGH | 1813 | || driver->speed != USB_SPEED_HIGH |
1810 | || !bind || !driver->setup) | 1814 | || !bind || !driver->setup) |
1811 | return -EINVAL; | 1815 | goto err0; |
1812 | 1816 | ||
1813 | /* driver must be initialized to support peripheral mode */ | 1817 | /* driver must be initialized to support peripheral mode */ |
1814 | if (!musb) { | 1818 | if (!musb) { |
1815 | DBG(1, "%s, no dev??\n", __func__); | 1819 | DBG(1, "no dev??\n"); |
1816 | return -ENODEV; | 1820 | retval = -ENODEV; |
1821 | goto err0; | ||
1817 | } | 1822 | } |
1818 | 1823 | ||
1824 | pm_runtime_get_sync(musb->controller); | ||
1825 | |||
1819 | DBG(3, "registering driver %s\n", driver->function); | 1826 | DBG(3, "registering driver %s\n", driver->function); |
1820 | spin_lock_irqsave(&musb->lock, flags); | ||
1821 | 1827 | ||
1822 | if (musb->gadget_driver) { | 1828 | if (musb->gadget_driver) { |
1823 | DBG(1, "%s is already bound to %s\n", | 1829 | DBG(1, "%s is already bound to %s\n", |
1824 | musb_driver_name, | 1830 | musb_driver_name, |
1825 | musb->gadget_driver->driver.name); | 1831 | musb->gadget_driver->driver.name); |
1826 | retval = -EBUSY; | 1832 | retval = -EBUSY; |
1827 | } else { | 1833 | goto err0; |
1828 | musb->gadget_driver = driver; | ||
1829 | musb->g.dev.driver = &driver->driver; | ||
1830 | driver->driver.bus = NULL; | ||
1831 | musb->softconnect = 1; | ||
1832 | retval = 0; | ||
1833 | } | 1834 | } |
1834 | 1835 | ||
1836 | spin_lock_irqsave(&musb->lock, flags); | ||
1837 | musb->gadget_driver = driver; | ||
1838 | musb->g.dev.driver = &driver->driver; | ||
1839 | driver->driver.bus = NULL; | ||
1840 | musb->softconnect = 1; | ||
1835 | spin_unlock_irqrestore(&musb->lock, flags); | 1841 | spin_unlock_irqrestore(&musb->lock, flags); |
1836 | 1842 | ||
1837 | if (retval == 0) { | 1843 | retval = bind(&musb->g); |
1838 | retval = bind(&musb->g); | 1844 | if (retval) { |
1839 | if (retval != 0) { | 1845 | DBG(3, "bind to driver %s failed --> %d\n", |
1840 | DBG(3, "bind to driver %s failed --> %d\n", | 1846 | driver->driver.name, retval); |
1841 | driver->driver.name, retval); | 1847 | goto err1; |
1842 | musb->gadget_driver = NULL; | 1848 | } |
1843 | musb->g.dev.driver = NULL; | ||
1844 | } | ||
1845 | 1849 | ||
1846 | spin_lock_irqsave(&musb->lock, flags); | 1850 | spin_lock_irqsave(&musb->lock, flags); |
1847 | 1851 | ||
1848 | otg_set_peripheral(musb->xceiv, &musb->g); | 1852 | otg_set_peripheral(musb->xceiv, &musb->g); |
1849 | musb->xceiv->state = OTG_STATE_B_IDLE; | 1853 | musb->xceiv->state = OTG_STATE_B_IDLE; |
1850 | musb->is_active = 1; | 1854 | musb->is_active = 1; |
1851 | 1855 | ||
1852 | /* FIXME this ignores the softconnect flag. Drivers are | 1856 | /* |
1853 | * allowed hold the peripheral inactive until for example | 1857 | * FIXME this ignores the softconnect flag. Drivers are |
1854 | * userspace hooks up printer hardware or DSP codecs, so | 1858 | * allowed hold the peripheral inactive until for example |
1855 | * hosts only see fully functional devices. | 1859 | * userspace hooks up printer hardware or DSP codecs, so |
1856 | */ | 1860 | * hosts only see fully functional devices. |
1861 | */ | ||
1857 | 1862 | ||
1858 | if (!is_otg_enabled(musb)) | 1863 | if (!is_otg_enabled(musb)) |
1859 | musb_start(musb); | 1864 | musb_start(musb); |
1860 | 1865 | ||
1861 | otg_set_peripheral(musb->xceiv, &musb->g); | 1866 | otg_set_peripheral(musb->xceiv, &musb->g); |
1862 | 1867 | ||
1863 | spin_unlock_irqrestore(&musb->lock, flags); | 1868 | spin_unlock_irqrestore(&musb->lock, flags); |
1864 | 1869 | ||
1865 | if (is_otg_enabled(musb)) { | 1870 | if (is_otg_enabled(musb)) { |
1866 | struct usb_hcd *hcd = musb_to_hcd(musb); | 1871 | struct usb_hcd *hcd = musb_to_hcd(musb); |
1867 | 1872 | ||
1868 | DBG(3, "OTG startup...\n"); | 1873 | DBG(3, "OTG startup...\n"); |
1869 | 1874 | ||
1870 | /* REVISIT: funcall to other code, which also | 1875 | /* REVISIT: funcall to other code, which also |
1871 | * handles power budgeting ... this way also | 1876 | * handles power budgeting ... this way also |
1872 | * ensures HdrcStart is indirectly called. | 1877 | * ensures HdrcStart is indirectly called. |
1873 | */ | 1878 | */ |
1874 | retval = usb_add_hcd(musb_to_hcd(musb), -1, 0); | 1879 | retval = usb_add_hcd(musb_to_hcd(musb), -1, 0); |
1875 | if (retval < 0) { | 1880 | if (retval < 0) { |
1876 | DBG(1, "add_hcd failed, %d\n", retval); | 1881 | DBG(1, "add_hcd failed, %d\n", retval); |
1877 | spin_lock_irqsave(&musb->lock, flags); | 1882 | goto err2; |
1878 | otg_set_peripheral(musb->xceiv, NULL); | 1883 | |
1879 | musb->gadget_driver = NULL; | 1884 | if ((musb->xceiv->last_event == USB_EVENT_ID) |
1880 | musb->g.dev.driver = NULL; | 1885 | && musb->xceiv->set_vbus) |
1881 | spin_unlock_irqrestore(&musb->lock, flags); | 1886 | otg_set_vbus(musb->xceiv, 1); |
1882 | } else { | ||
1883 | hcd->self.uses_pio_for_control = 1; | ||
1884 | } | ||
1885 | } | 1887 | } |
1888 | |||
1889 | hcd->self.uses_pio_for_control = 1; | ||
1890 | |||
1891 | if (musb->xceiv->last_event == USB_EVENT_NONE) | ||
1892 | pm_runtime_put(musb->controller); | ||
1893 | |||
1886 | } | 1894 | } |
1887 | 1895 | ||
1896 | return 0; | ||
1897 | |||
1898 | err2: | ||
1899 | if (!is_otg_enabled(musb)) | ||
1900 | musb_stop(musb); | ||
1901 | |||
1902 | err1: | ||
1903 | musb->gadget_driver = NULL; | ||
1904 | musb->g.dev.driver = NULL; | ||
1905 | |||
1906 | err0: | ||
1888 | return retval; | 1907 | return retval; |
1889 | } | 1908 | } |
1890 | EXPORT_SYMBOL(usb_gadget_probe_driver); | 1909 | EXPORT_SYMBOL(usb_gadget_probe_driver); |
@@ -1939,14 +1958,20 @@ static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver) | |||
1939 | */ | 1958 | */ |
1940 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | 1959 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) |
1941 | { | 1960 | { |
1942 | unsigned long flags; | ||
1943 | int retval = 0; | ||
1944 | struct musb *musb = the_gadget; | 1961 | struct musb *musb = the_gadget; |
1962 | unsigned long flags; | ||
1945 | 1963 | ||
1946 | if (!driver || !driver->unbind || !musb) | 1964 | if (!driver || !driver->unbind || !musb) |
1947 | return -EINVAL; | 1965 | return -EINVAL; |
1948 | 1966 | ||
1949 | /* REVISIT always use otg_set_peripheral() here too; | 1967 | if (!musb->gadget_driver) |
1968 | return -EINVAL; | ||
1969 | |||
1970 | if (musb->xceiv->last_event == USB_EVENT_NONE) | ||
1971 | pm_runtime_get_sync(musb->controller); | ||
1972 | |||
1973 | /* | ||
1974 | * REVISIT always use otg_set_peripheral() here too; | ||
1950 | * this needs to shut down the OTG engine. | 1975 | * this needs to shut down the OTG engine. |
1951 | */ | 1976 | */ |
1952 | 1977 | ||
@@ -1956,29 +1981,26 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
1956 | musb_hnp_stop(musb); | 1981 | musb_hnp_stop(musb); |
1957 | #endif | 1982 | #endif |
1958 | 1983 | ||
1959 | if (musb->gadget_driver == driver) { | 1984 | (void) musb_gadget_vbus_draw(&musb->g, 0); |
1960 | 1985 | ||
1961 | (void) musb_gadget_vbus_draw(&musb->g, 0); | 1986 | musb->xceiv->state = OTG_STATE_UNDEFINED; |
1987 | stop_activity(musb, driver); | ||
1988 | otg_set_peripheral(musb->xceiv, NULL); | ||
1962 | 1989 | ||
1963 | musb->xceiv->state = OTG_STATE_UNDEFINED; | 1990 | DBG(3, "unregistering driver %s\n", driver->function); |
1964 | stop_activity(musb, driver); | ||
1965 | otg_set_peripheral(musb->xceiv, NULL); | ||
1966 | 1991 | ||
1967 | DBG(3, "unregistering driver %s\n", driver->function); | 1992 | spin_unlock_irqrestore(&musb->lock, flags); |
1968 | spin_unlock_irqrestore(&musb->lock, flags); | 1993 | driver->unbind(&musb->g); |
1969 | driver->unbind(&musb->g); | 1994 | spin_lock_irqsave(&musb->lock, flags); |
1970 | spin_lock_irqsave(&musb->lock, flags); | ||
1971 | 1995 | ||
1972 | musb->gadget_driver = NULL; | 1996 | musb->gadget_driver = NULL; |
1973 | musb->g.dev.driver = NULL; | 1997 | musb->g.dev.driver = NULL; |
1974 | 1998 | ||
1975 | musb->is_active = 0; | 1999 | musb->is_active = 0; |
1976 | musb_platform_try_idle(musb, 0); | 2000 | musb_platform_try_idle(musb, 0); |
1977 | } else | ||
1978 | retval = -EINVAL; | ||
1979 | spin_unlock_irqrestore(&musb->lock, flags); | 2001 | spin_unlock_irqrestore(&musb->lock, flags); |
1980 | 2002 | ||
1981 | if (is_otg_enabled(musb) && retval == 0) { | 2003 | if (is_otg_enabled(musb)) { |
1982 | usb_remove_hcd(musb_to_hcd(musb)); | 2004 | usb_remove_hcd(musb_to_hcd(musb)); |
1983 | /* FIXME we need to be able to register another | 2005 | /* FIXME we need to be able to register another |
1984 | * gadget driver here and have everything work; | 2006 | * gadget driver here and have everything work; |
@@ -1986,7 +2008,12 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
1986 | */ | 2008 | */ |
1987 | } | 2009 | } |
1988 | 2010 | ||
1989 | return retval; | 2011 | if (!is_otg_enabled(musb)) |
2012 | musb_stop(musb); | ||
2013 | |||
2014 | pm_runtime_put(musb->controller); | ||
2015 | |||
2016 | return 0; | ||
1990 | } | 2017 | } |
1991 | EXPORT_SYMBOL(usb_gadget_unregister_driver); | 2018 | EXPORT_SYMBOL(usb_gadget_unregister_driver); |
1992 | 2019 | ||
diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h index a55354fbccf5..66b7c5e0fb44 100644 --- a/drivers/usb/musb/musb_gadget.h +++ b/drivers/usb/musb/musb_gadget.h | |||
@@ -35,6 +35,8 @@ | |||
35 | #ifndef __MUSB_GADGET_H | 35 | #ifndef __MUSB_GADGET_H |
36 | #define __MUSB_GADGET_H | 36 | #define __MUSB_GADGET_H |
37 | 37 | ||
38 | #include <linux/list.h> | ||
39 | |||
38 | enum buffer_map_state { | 40 | enum buffer_map_state { |
39 | UN_MAPPED = 0, | 41 | UN_MAPPED = 0, |
40 | PRE_MAPPED, | 42 | PRE_MAPPED, |
@@ -43,6 +45,7 @@ enum buffer_map_state { | |||
43 | 45 | ||
44 | struct musb_request { | 46 | struct musb_request { |
45 | struct usb_request request; | 47 | struct usb_request request; |
48 | struct list_head list; | ||
46 | struct musb_ep *ep; | 49 | struct musb_ep *ep; |
47 | struct musb *musb; | 50 | struct musb *musb; |
48 | u8 tx; /* endpoint direction */ | 51 | u8 tx; /* endpoint direction */ |
@@ -94,13 +97,13 @@ static inline struct musb_ep *to_musb_ep(struct usb_ep *ep) | |||
94 | return ep ? container_of(ep, struct musb_ep, end_point) : NULL; | 97 | return ep ? container_of(ep, struct musb_ep, end_point) : NULL; |
95 | } | 98 | } |
96 | 99 | ||
97 | static inline struct usb_request *next_request(struct musb_ep *ep) | 100 | static inline struct musb_request *next_request(struct musb_ep *ep) |
98 | { | 101 | { |
99 | struct list_head *queue = &ep->req_list; | 102 | struct list_head *queue = &ep->req_list; |
100 | 103 | ||
101 | if (list_empty(queue)) | 104 | if (list_empty(queue)) |
102 | return NULL; | 105 | return NULL; |
103 | return container_of(queue->next, struct usb_request, list); | 106 | return container_of(queue->next, struct musb_request, list); |
104 | } | 107 | } |
105 | 108 | ||
106 | extern void musb_g_tx(struct musb *musb, u8 epnum); | 109 | extern void musb_g_tx(struct musb *musb, u8 epnum); |
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 6dd03f4c5f49..75a542e42fdf 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c | |||
@@ -304,8 +304,7 @@ __acquires(musb->lock) | |||
304 | } | 304 | } |
305 | 305 | ||
306 | /* Maybe start the first request in the queue */ | 306 | /* Maybe start the first request in the queue */ |
307 | request = to_musb_request( | 307 | request = next_request(musb_ep); |
308 | next_request(musb_ep)); | ||
309 | if (!musb_ep->busy && request) { | 308 | if (!musb_ep->busy && request) { |
310 | DBG(3, "restarting the request\n"); | 309 | DBG(3, "restarting the request\n"); |
311 | musb_ep_restart(musb, request); | 310 | musb_ep_restart(musb, request); |
@@ -491,10 +490,12 @@ stall: | |||
491 | static void ep0_rxstate(struct musb *musb) | 490 | static void ep0_rxstate(struct musb *musb) |
492 | { | 491 | { |
493 | void __iomem *regs = musb->control_ep->regs; | 492 | void __iomem *regs = musb->control_ep->regs; |
493 | struct musb_request *request; | ||
494 | struct usb_request *req; | 494 | struct usb_request *req; |
495 | u16 count, csr; | 495 | u16 count, csr; |
496 | 496 | ||
497 | req = next_ep0_request(musb); | 497 | request = next_ep0_request(musb); |
498 | req = &request->request; | ||
498 | 499 | ||
499 | /* read packet and ack; or stall because of gadget driver bug: | 500 | /* read packet and ack; or stall because of gadget driver bug: |
500 | * should have provided the rx buffer before setup() returned. | 501 | * should have provided the rx buffer before setup() returned. |
@@ -544,17 +545,20 @@ static void ep0_rxstate(struct musb *musb) | |||
544 | static void ep0_txstate(struct musb *musb) | 545 | static void ep0_txstate(struct musb *musb) |
545 | { | 546 | { |
546 | void __iomem *regs = musb->control_ep->regs; | 547 | void __iomem *regs = musb->control_ep->regs; |
547 | struct usb_request *request = next_ep0_request(musb); | 548 | struct musb_request *req = next_ep0_request(musb); |
549 | struct usb_request *request; | ||
548 | u16 csr = MUSB_CSR0_TXPKTRDY; | 550 | u16 csr = MUSB_CSR0_TXPKTRDY; |
549 | u8 *fifo_src; | 551 | u8 *fifo_src; |
550 | u8 fifo_count; | 552 | u8 fifo_count; |
551 | 553 | ||
552 | if (!request) { | 554 | if (!req) { |
553 | /* WARN_ON(1); */ | 555 | /* WARN_ON(1); */ |
554 | DBG(2, "odd; csr0 %04x\n", musb_readw(regs, MUSB_CSR0)); | 556 | DBG(2, "odd; csr0 %04x\n", musb_readw(regs, MUSB_CSR0)); |
555 | return; | 557 | return; |
556 | } | 558 | } |
557 | 559 | ||
560 | request = &req->request; | ||
561 | |||
558 | /* load the data */ | 562 | /* load the data */ |
559 | fifo_src = (u8 *) request->buf + request->actual; | 563 | fifo_src = (u8 *) request->buf + request->actual; |
560 | fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE, | 564 | fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE, |
@@ -598,7 +602,7 @@ static void ep0_txstate(struct musb *musb) | |||
598 | static void | 602 | static void |
599 | musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req) | 603 | musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req) |
600 | { | 604 | { |
601 | struct usb_request *r; | 605 | struct musb_request *r; |
602 | void __iomem *regs = musb->control_ep->regs; | 606 | void __iomem *regs = musb->control_ep->regs; |
603 | 607 | ||
604 | musb_read_fifo(&musb->endpoints[0], sizeof *req, (u8 *)req); | 608 | musb_read_fifo(&musb->endpoints[0], sizeof *req, (u8 *)req); |
@@ -616,7 +620,7 @@ musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req) | |||
616 | /* clean up any leftover transfers */ | 620 | /* clean up any leftover transfers */ |
617 | r = next_ep0_request(musb); | 621 | r = next_ep0_request(musb); |
618 | if (r) | 622 | if (r) |
619 | musb_g_ep0_giveback(musb, r); | 623 | musb_g_ep0_giveback(musb, &r->request); |
620 | 624 | ||
621 | /* For zero-data requests we want to delay the STATUS stage to | 625 | /* For zero-data requests we want to delay the STATUS stage to |
622 | * avoid SETUPEND errors. If we read data (OUT), delay accepting | 626 | * avoid SETUPEND errors. If we read data (OUT), delay accepting |
@@ -758,11 +762,11 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) | |||
758 | case MUSB_EP0_STAGE_STATUSOUT: | 762 | case MUSB_EP0_STAGE_STATUSOUT: |
759 | /* end of sequence #1: write to host (TX state) */ | 763 | /* end of sequence #1: write to host (TX state) */ |
760 | { | 764 | { |
761 | struct usb_request *req; | 765 | struct musb_request *req; |
762 | 766 | ||
763 | req = next_ep0_request(musb); | 767 | req = next_ep0_request(musb); |
764 | if (req) | 768 | if (req) |
765 | musb_g_ep0_giveback(musb, req); | 769 | musb_g_ep0_giveback(musb, &req->request); |
766 | } | 770 | } |
767 | 771 | ||
768 | /* | 772 | /* |
@@ -961,7 +965,7 @@ musb_g_ep0_queue(struct usb_ep *e, struct usb_request *r, gfp_t gfp_flags) | |||
961 | } | 965 | } |
962 | 966 | ||
963 | /* add request to the list */ | 967 | /* add request to the list */ |
964 | list_add_tail(&(req->request.list), &(ep->req_list)); | 968 | list_add_tail(&req->list, &ep->req_list); |
965 | 969 | ||
966 | DBG(3, "queue to %s (%s), length=%d\n", | 970 | DBG(3, "queue to %s (%s), length=%d\n", |
967 | ep->name, ep->is_in ? "IN/TX" : "OUT/RX", | 971 | ep->name, ep->is_in ? "IN/TX" : "OUT/RX", |
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 0f523d7db57b..5eef4a8847db 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c | |||
@@ -1335,7 +1335,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) | |||
1335 | if (length > qh->maxpacket) | 1335 | if (length > qh->maxpacket) |
1336 | length = qh->maxpacket; | 1336 | length = qh->maxpacket; |
1337 | /* Unmap the buffer so that CPU can use it */ | 1337 | /* Unmap the buffer so that CPU can use it */ |
1338 | unmap_urb_for_dma(musb_to_hcd(musb), urb); | 1338 | usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb); |
1339 | musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset); | 1339 | musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset); |
1340 | qh->segsize = length; | 1340 | qh->segsize = length; |
1341 | 1341 | ||
@@ -1757,7 +1757,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
1757 | 1757 | ||
1758 | if (!dma) { | 1758 | if (!dma) { |
1759 | /* Unmap the buffer so that CPU can use it */ | 1759 | /* Unmap the buffer so that CPU can use it */ |
1760 | unmap_urb_for_dma(musb_to_hcd(musb), urb); | 1760 | usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb); |
1761 | done = musb_host_packet_rx(musb, urb, | 1761 | done = musb_host_packet_rx(musb, urb, |
1762 | epnum, iso_err); | 1762 | epnum, iso_err); |
1763 | DBG(6, "read %spacket\n", done ? "last " : ""); | 1763 | DBG(6, "read %spacket\n", done ? "last " : ""); |
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index b46d1877e28e..489104a5ae14 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c | |||
@@ -305,8 +305,8 @@ int musb_hub_control( | |||
305 | desc->bHubContrCurrent = 0; | 305 | desc->bHubContrCurrent = 0; |
306 | 306 | ||
307 | /* workaround bogus struct definition */ | 307 | /* workaround bogus struct definition */ |
308 | desc->DeviceRemovable[0] = 0x02; /* port 1 */ | 308 | desc->u.hs.DeviceRemovable[0] = 0x02; /* port 1 */ |
309 | desc->DeviceRemovable[1] = 0xff; | 309 | desc->u.hs.DeviceRemovable[1] = 0xff; |
310 | } | 310 | } |
311 | break; | 311 | break; |
312 | case GetHubStatus: | 312 | case GetHubStatus: |
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index bc8badd16897..25cb8b0003b1 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <linux/io.h> | 33 | #include <linux/io.h> |
34 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
35 | #include <linux/dma-mapping.h> | 35 | #include <linux/dma-mapping.h> |
36 | #include <linux/pm_runtime.h> | ||
37 | #include <linux/err.h> | ||
36 | 38 | ||
37 | #include "musb_core.h" | 39 | #include "musb_core.h" |
38 | #include "omap2430.h" | 40 | #include "omap2430.h" |
@@ -40,7 +42,6 @@ | |||
40 | struct omap2430_glue { | 42 | struct omap2430_glue { |
41 | struct device *dev; | 43 | struct device *dev; |
42 | struct platform_device *musb; | 44 | struct platform_device *musb; |
43 | struct clk *clk; | ||
44 | }; | 45 | }; |
45 | #define glue_to_musb(g) platform_get_drvdata(g->musb) | 46 | #define glue_to_musb(g) platform_get_drvdata(g->musb) |
46 | 47 | ||
@@ -216,20 +217,12 @@ static inline void omap2430_low_level_exit(struct musb *musb) | |||
216 | l = musb_readl(musb->mregs, OTG_FORCESTDBY); | 217 | l = musb_readl(musb->mregs, OTG_FORCESTDBY); |
217 | l |= ENABLEFORCE; /* enable MSTANDBY */ | 218 | l |= ENABLEFORCE; /* enable MSTANDBY */ |
218 | musb_writel(musb->mregs, OTG_FORCESTDBY, l); | 219 | musb_writel(musb->mregs, OTG_FORCESTDBY, l); |
219 | |||
220 | l = musb_readl(musb->mregs, OTG_SYSCONFIG); | ||
221 | l |= ENABLEWAKEUP; /* enable wakeup */ | ||
222 | musb_writel(musb->mregs, OTG_SYSCONFIG, l); | ||
223 | } | 220 | } |
224 | 221 | ||
225 | static inline void omap2430_low_level_init(struct musb *musb) | 222 | static inline void omap2430_low_level_init(struct musb *musb) |
226 | { | 223 | { |
227 | u32 l; | 224 | u32 l; |
228 | 225 | ||
229 | l = musb_readl(musb->mregs, OTG_SYSCONFIG); | ||
230 | l &= ~ENABLEWAKEUP; /* disable wakeup */ | ||
231 | musb_writel(musb->mregs, OTG_SYSCONFIG, l); | ||
232 | |||
233 | l = musb_readl(musb->mregs, OTG_FORCESTDBY); | 226 | l = musb_readl(musb->mregs, OTG_FORCESTDBY); |
234 | l &= ~ENABLEFORCE; /* disable MSTANDBY */ | 227 | l &= ~ENABLEFORCE; /* disable MSTANDBY */ |
235 | musb_writel(musb->mregs, OTG_FORCESTDBY, l); | 228 | musb_writel(musb->mregs, OTG_FORCESTDBY, l); |
@@ -251,31 +244,39 @@ static int musb_otg_notifications(struct notifier_block *nb, | |||
251 | if (is_otg_enabled(musb)) { | 244 | if (is_otg_enabled(musb)) { |
252 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | 245 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC |
253 | if (musb->gadget_driver) { | 246 | if (musb->gadget_driver) { |
247 | pm_runtime_get_sync(musb->controller); | ||
254 | otg_init(musb->xceiv); | 248 | otg_init(musb->xceiv); |
255 | 249 | omap2430_musb_set_vbus(musb, 1); | |
256 | if (data->interface_type == | ||
257 | MUSB_INTERFACE_UTMI) | ||
258 | omap2430_musb_set_vbus(musb, 1); | ||
259 | |||
260 | } | 250 | } |
261 | #endif | 251 | #endif |
262 | } else { | 252 | } else { |
253 | pm_runtime_get_sync(musb->controller); | ||
263 | otg_init(musb->xceiv); | 254 | otg_init(musb->xceiv); |
264 | if (data->interface_type == | 255 | omap2430_musb_set_vbus(musb, 1); |
265 | MUSB_INTERFACE_UTMI) | ||
266 | omap2430_musb_set_vbus(musb, 1); | ||
267 | } | 256 | } |
268 | break; | 257 | break; |
269 | 258 | ||
270 | case USB_EVENT_VBUS: | 259 | case USB_EVENT_VBUS: |
271 | DBG(4, "VBUS Connect\n"); | 260 | DBG(4, "VBUS Connect\n"); |
272 | 261 | ||
262 | if (musb->gadget_driver) | ||
263 | pm_runtime_get_sync(musb->controller); | ||
264 | |||
273 | otg_init(musb->xceiv); | 265 | otg_init(musb->xceiv); |
274 | break; | 266 | break; |
275 | 267 | ||
276 | case USB_EVENT_NONE: | 268 | case USB_EVENT_NONE: |
277 | DBG(4, "VBUS Disconnect\n"); | 269 | DBG(4, "VBUS Disconnect\n"); |
278 | 270 | ||
271 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
272 | if (is_otg_enabled(musb)) | ||
273 | if (musb->gadget_driver) | ||
274 | #endif | ||
275 | { | ||
276 | pm_runtime_mark_last_busy(musb->controller); | ||
277 | pm_runtime_put_autosuspend(musb->controller); | ||
278 | } | ||
279 | |||
279 | if (data->interface_type == MUSB_INTERFACE_UTMI) { | 280 | if (data->interface_type == MUSB_INTERFACE_UTMI) { |
280 | if (musb->xceiv->set_vbus) | 281 | if (musb->xceiv->set_vbus) |
281 | otg_set_vbus(musb->xceiv, 0); | 282 | otg_set_vbus(musb->xceiv, 0); |
@@ -307,22 +308,11 @@ static int omap2430_musb_init(struct musb *musb) | |||
307 | return -ENODEV; | 308 | return -ENODEV; |
308 | } | 309 | } |
309 | 310 | ||
310 | omap2430_low_level_init(musb); | 311 | status = pm_runtime_get_sync(dev); |
311 | 312 | if (status < 0) { | |
312 | l = musb_readl(musb->mregs, OTG_SYSCONFIG); | 313 | dev_err(dev, "pm_runtime_get_sync FAILED"); |
313 | l &= ~ENABLEWAKEUP; /* disable wakeup */ | 314 | goto err1; |
314 | l &= ~NOSTDBY; /* remove possible nostdby */ | 315 | } |
315 | l |= SMARTSTDBY; /* enable smart standby */ | ||
316 | l &= ~AUTOIDLE; /* disable auto idle */ | ||
317 | l &= ~NOIDLE; /* remove possible noidle */ | ||
318 | l |= SMARTIDLE; /* enable smart idle */ | ||
319 | /* | ||
320 | * MUSB AUTOIDLE don't work in 3430. | ||
321 | * Workaround by Richard Woodruff/TI | ||
322 | */ | ||
323 | if (!cpu_is_omap3430()) | ||
324 | l |= AUTOIDLE; /* enable auto idle */ | ||
325 | musb_writel(musb->mregs, OTG_SYSCONFIG, l); | ||
326 | 316 | ||
327 | l = musb_readl(musb->mregs, OTG_INTERFSEL); | 317 | l = musb_readl(musb->mregs, OTG_INTERFSEL); |
328 | 318 | ||
@@ -350,14 +340,58 @@ static int omap2430_musb_init(struct musb *musb) | |||
350 | if (status) | 340 | if (status) |
351 | DBG(1, "notification register failed\n"); | 341 | DBG(1, "notification register failed\n"); |
352 | 342 | ||
353 | /* check whether cable is already connected */ | ||
354 | if (musb->xceiv->state ==OTG_STATE_B_IDLE) | ||
355 | musb_otg_notifications(&musb->nb, 1, | ||
356 | musb->xceiv->gadget); | ||
357 | |||
358 | setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); | 343 | setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); |
359 | 344 | ||
360 | return 0; | 345 | return 0; |
346 | |||
347 | err1: | ||
348 | pm_runtime_disable(dev); | ||
349 | return status; | ||
350 | } | ||
351 | |||
352 | static void omap2430_musb_enable(struct musb *musb) | ||
353 | { | ||
354 | u8 devctl; | ||
355 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); | ||
356 | struct device *dev = musb->controller; | ||
357 | struct musb_hdrc_platform_data *pdata = dev->platform_data; | ||
358 | struct omap_musb_board_data *data = pdata->board_data; | ||
359 | |||
360 | switch (musb->xceiv->last_event) { | ||
361 | |||
362 | case USB_EVENT_ID: | ||
363 | otg_init(musb->xceiv); | ||
364 | if (data->interface_type == MUSB_INTERFACE_UTMI) { | ||
365 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
366 | /* start the session */ | ||
367 | devctl |= MUSB_DEVCTL_SESSION; | ||
368 | musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); | ||
369 | while (musb_readb(musb->mregs, MUSB_DEVCTL) & | ||
370 | MUSB_DEVCTL_BDEVICE) { | ||
371 | cpu_relax(); | ||
372 | |||
373 | if (time_after(jiffies, timeout)) { | ||
374 | dev_err(musb->controller, | ||
375 | "configured as A device timeout"); | ||
376 | break; | ||
377 | } | ||
378 | } | ||
379 | } | ||
380 | break; | ||
381 | |||
382 | case USB_EVENT_VBUS: | ||
383 | otg_init(musb->xceiv); | ||
384 | break; | ||
385 | |||
386 | default: | ||
387 | break; | ||
388 | } | ||
389 | } | ||
390 | |||
391 | static void omap2430_musb_disable(struct musb *musb) | ||
392 | { | ||
393 | if (musb->xceiv->last_event) | ||
394 | otg_shutdown(musb->xceiv); | ||
361 | } | 395 | } |
362 | 396 | ||
363 | static int omap2430_musb_exit(struct musb *musb) | 397 | static int omap2430_musb_exit(struct musb *musb) |
@@ -378,6 +412,9 @@ static const struct musb_platform_ops omap2430_ops = { | |||
378 | .try_idle = omap2430_musb_try_idle, | 412 | .try_idle = omap2430_musb_try_idle, |
379 | 413 | ||
380 | .set_vbus = omap2430_musb_set_vbus, | 414 | .set_vbus = omap2430_musb_set_vbus, |
415 | |||
416 | .enable = omap2430_musb_enable, | ||
417 | .disable = omap2430_musb_disable, | ||
381 | }; | 418 | }; |
382 | 419 | ||
383 | static u64 omap2430_dmamask = DMA_BIT_MASK(32); | 420 | static u64 omap2430_dmamask = DMA_BIT_MASK(32); |
@@ -387,8 +424,6 @@ static int __init omap2430_probe(struct platform_device *pdev) | |||
387 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | 424 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; |
388 | struct platform_device *musb; | 425 | struct platform_device *musb; |
389 | struct omap2430_glue *glue; | 426 | struct omap2430_glue *glue; |
390 | struct clk *clk; | ||
391 | |||
392 | int ret = -ENOMEM; | 427 | int ret = -ENOMEM; |
393 | 428 | ||
394 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); | 429 | glue = kzalloc(sizeof(*glue), GFP_KERNEL); |
@@ -403,26 +438,12 @@ static int __init omap2430_probe(struct platform_device *pdev) | |||
403 | goto err1; | 438 | goto err1; |
404 | } | 439 | } |
405 | 440 | ||
406 | clk = clk_get(&pdev->dev, "ick"); | ||
407 | if (IS_ERR(clk)) { | ||
408 | dev_err(&pdev->dev, "failed to get clock\n"); | ||
409 | ret = PTR_ERR(clk); | ||
410 | goto err2; | ||
411 | } | ||
412 | |||
413 | ret = clk_enable(clk); | ||
414 | if (ret) { | ||
415 | dev_err(&pdev->dev, "failed to enable clock\n"); | ||
416 | goto err3; | ||
417 | } | ||
418 | |||
419 | musb->dev.parent = &pdev->dev; | 441 | musb->dev.parent = &pdev->dev; |
420 | musb->dev.dma_mask = &omap2430_dmamask; | 442 | musb->dev.dma_mask = &omap2430_dmamask; |
421 | musb->dev.coherent_dma_mask = omap2430_dmamask; | 443 | musb->dev.coherent_dma_mask = omap2430_dmamask; |
422 | 444 | ||
423 | glue->dev = &pdev->dev; | 445 | glue->dev = &pdev->dev; |
424 | glue->musb = musb; | 446 | glue->musb = musb; |
425 | glue->clk = clk; | ||
426 | 447 | ||
427 | pdata->platform_ops = &omap2430_ops; | 448 | pdata->platform_ops = &omap2430_ops; |
428 | 449 | ||
@@ -432,28 +453,24 @@ static int __init omap2430_probe(struct platform_device *pdev) | |||
432 | pdev->num_resources); | 453 | pdev->num_resources); |
433 | if (ret) { | 454 | if (ret) { |
434 | dev_err(&pdev->dev, "failed to add resources\n"); | 455 | dev_err(&pdev->dev, "failed to add resources\n"); |
435 | goto err4; | 456 | goto err2; |
436 | } | 457 | } |
437 | 458 | ||
438 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); | 459 | ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); |
439 | if (ret) { | 460 | if (ret) { |
440 | dev_err(&pdev->dev, "failed to add platform_data\n"); | 461 | dev_err(&pdev->dev, "failed to add platform_data\n"); |
441 | goto err4; | 462 | goto err2; |
442 | } | 463 | } |
443 | 464 | ||
444 | ret = platform_device_add(musb); | 465 | ret = platform_device_add(musb); |
445 | if (ret) { | 466 | if (ret) { |
446 | dev_err(&pdev->dev, "failed to register musb device\n"); | 467 | dev_err(&pdev->dev, "failed to register musb device\n"); |
447 | goto err4; | 468 | goto err2; |
448 | } | 469 | } |
449 | 470 | ||
450 | return 0; | 471 | pm_runtime_enable(&pdev->dev); |
451 | |||
452 | err4: | ||
453 | clk_disable(clk); | ||
454 | 472 | ||
455 | err3: | 473 | return 0; |
456 | clk_put(clk); | ||
457 | 474 | ||
458 | err2: | 475 | err2: |
459 | platform_device_put(musb); | 476 | platform_device_put(musb); |
@@ -471,61 +488,40 @@ static int __exit omap2430_remove(struct platform_device *pdev) | |||
471 | 488 | ||
472 | platform_device_del(glue->musb); | 489 | platform_device_del(glue->musb); |
473 | platform_device_put(glue->musb); | 490 | platform_device_put(glue->musb); |
474 | clk_disable(glue->clk); | 491 | pm_runtime_put(&pdev->dev); |
475 | clk_put(glue->clk); | 492 | pm_runtime_disable(&pdev->dev); |
476 | kfree(glue); | 493 | kfree(glue); |
477 | 494 | ||
478 | return 0; | 495 | return 0; |
479 | } | 496 | } |
480 | 497 | ||
481 | #ifdef CONFIG_PM | 498 | #ifdef CONFIG_PM |
482 | static void omap2430_save_context(struct musb *musb) | ||
483 | { | ||
484 | musb->context.otg_sysconfig = musb_readl(musb->mregs, OTG_SYSCONFIG); | ||
485 | musb->context.otg_forcestandby = musb_readl(musb->mregs, OTG_FORCESTDBY); | ||
486 | } | ||
487 | 499 | ||
488 | static void omap2430_restore_context(struct musb *musb) | 500 | static int omap2430_runtime_suspend(struct device *dev) |
489 | { | ||
490 | musb_writel(musb->mregs, OTG_SYSCONFIG, musb->context.otg_sysconfig); | ||
491 | musb_writel(musb->mregs, OTG_FORCESTDBY, musb->context.otg_forcestandby); | ||
492 | } | ||
493 | |||
494 | static int omap2430_suspend(struct device *dev) | ||
495 | { | 501 | { |
496 | struct omap2430_glue *glue = dev_get_drvdata(dev); | 502 | struct omap2430_glue *glue = dev_get_drvdata(dev); |
497 | struct musb *musb = glue_to_musb(glue); | 503 | struct musb *musb = glue_to_musb(glue); |
498 | 504 | ||
499 | omap2430_low_level_exit(musb); | 505 | omap2430_low_level_exit(musb); |
500 | otg_set_suspend(musb->xceiv, 1); | 506 | otg_set_suspend(musb->xceiv, 1); |
501 | omap2430_save_context(musb); | ||
502 | clk_disable(glue->clk); | ||
503 | 507 | ||
504 | return 0; | 508 | return 0; |
505 | } | 509 | } |
506 | 510 | ||
507 | static int omap2430_resume(struct device *dev) | 511 | static int omap2430_runtime_resume(struct device *dev) |
508 | { | 512 | { |
509 | struct omap2430_glue *glue = dev_get_drvdata(dev); | 513 | struct omap2430_glue *glue = dev_get_drvdata(dev); |
510 | struct musb *musb = glue_to_musb(glue); | 514 | struct musb *musb = glue_to_musb(glue); |
511 | int ret; | ||
512 | |||
513 | ret = clk_enable(glue->clk); | ||
514 | if (ret) { | ||
515 | dev_err(dev, "faled to enable clock\n"); | ||
516 | return ret; | ||
517 | } | ||
518 | 515 | ||
519 | omap2430_low_level_init(musb); | 516 | omap2430_low_level_init(musb); |
520 | omap2430_restore_context(musb); | ||
521 | otg_set_suspend(musb->xceiv, 0); | 517 | otg_set_suspend(musb->xceiv, 0); |
522 | 518 | ||
523 | return 0; | 519 | return 0; |
524 | } | 520 | } |
525 | 521 | ||
526 | static struct dev_pm_ops omap2430_pm_ops = { | 522 | static struct dev_pm_ops omap2430_pm_ops = { |
527 | .suspend = omap2430_suspend, | 523 | .runtime_suspend = omap2430_runtime_suspend, |
528 | .resume = omap2430_resume, | 524 | .runtime_resume = omap2430_runtime_resume, |
529 | }; | 525 | }; |
530 | 526 | ||
531 | #define DEV_PM_OPS (&omap2430_pm_ops) | 527 | #define DEV_PM_OPS (&omap2430_pm_ops) |
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c index c061a88f2b0f..99cb541e4ef0 100644 --- a/drivers/usb/musb/tusb6010_omap.c +++ b/drivers/usb/musb/tusb6010_omap.c | |||
@@ -680,7 +680,7 @@ dma_controller_create(struct musb *musb, void __iomem *base) | |||
680 | 680 | ||
681 | tusb_dma = kzalloc(sizeof(struct tusb_omap_dma), GFP_KERNEL); | 681 | tusb_dma = kzalloc(sizeof(struct tusb_omap_dma), GFP_KERNEL); |
682 | if (!tusb_dma) | 682 | if (!tusb_dma) |
683 | goto cleanup; | 683 | goto out; |
684 | 684 | ||
685 | tusb_dma->musb = musb; | 685 | tusb_dma->musb = musb; |
686 | tusb_dma->tbase = musb->ctrl_base; | 686 | tusb_dma->tbase = musb->ctrl_base; |
@@ -721,6 +721,6 @@ dma_controller_create(struct musb *musb, void __iomem *base) | |||
721 | 721 | ||
722 | cleanup: | 722 | cleanup: |
723 | dma_controller_destroy(&tusb_dma->controller); | 723 | dma_controller_destroy(&tusb_dma->controller); |
724 | 724 | out: | |
725 | return NULL; | 725 | return NULL; |
726 | } | 726 | } |