diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-16 13:05:06 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-12-16 13:05:06 -0500 |
commit | 36facadd9ea98f8415d0dbb63e0763b7ee9d3911 (patch) | |
tree | 99dea00b332ed852f2b0a4923b581dd723f03634 /drivers/usb/gadget/ci13xxx_udc.c | |
parent | 2faa83e2a519abea1055d156ce1b42b8fa57e87b (diff) | |
parent | 0b83ae960cd7d4a5ee02786ecf41ab45688999bf (diff) |
Merge branch 'usb-next' into musb-merge
* usb-next: (132 commits)
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
usb: gadget: f_ncm.c added
usb: gadget: u_ether: prepare for NCM
usb: pch_udc: Fix setup transfers with data out
usb: pch_udc: Fix compile error, warnings and checkpatch warnings
usb: add ab8500 usb transceiver driver
USB: gadget: Implement runtime PM for MSM bus glue driver
USB: gadget: Implement runtime PM for ci13xxx gadget
USB: gadget: Add USB controller driver for MSM SoC
USB: gadget: Introduce ci13xxx_udc_driver struct
USB: gadget: Initialize ci13xxx gadget device's coherent DMA mask
USB: gadget: Fix "scheduling while atomic" bugs in ci13xxx_udc
USB: gadget: Separate out PCI bus code from ci13xxx_udc
...
Diffstat (limited to 'drivers/usb/gadget/ci13xxx_udc.c')
-rw-r--r-- | drivers/usb/gadget/ci13xxx_udc.c | 384 |
1 files changed, 165 insertions, 219 deletions
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 98b36fc88c77..f200e472e476 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c | |||
@@ -22,7 +22,6 @@ | |||
22 | * - ENDPT: endpoint operations (Gadget API) | 22 | * - ENDPT: endpoint operations (Gadget API) |
23 | * - GADGET: gadget operations (Gadget API) | 23 | * - GADGET: gadget operations (Gadget API) |
24 | * - BUS: bus glue code, bus abstraction layer | 24 | * - BUS: bus glue code, bus abstraction layer |
25 | * - PCI: PCI core interface and PCI resources (interrupts, memory...) | ||
26 | * | 25 | * |
27 | * Compile Options | 26 | * Compile Options |
28 | * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities | 27 | * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities |
@@ -60,11 +59,11 @@ | |||
60 | #include <linux/io.h> | 59 | #include <linux/io.h> |
61 | #include <linux/irq.h> | 60 | #include <linux/irq.h> |
62 | #include <linux/kernel.h> | 61 | #include <linux/kernel.h> |
63 | #include <linux/module.h> | ||
64 | #include <linux/pci.h> | ||
65 | #include <linux/slab.h> | 62 | #include <linux/slab.h> |
63 | #include <linux/pm_runtime.h> | ||
66 | #include <linux/usb/ch9.h> | 64 | #include <linux/usb/ch9.h> |
67 | #include <linux/usb/gadget.h> | 65 | #include <linux/usb/gadget.h> |
66 | #include <linux/usb/otg.h> | ||
68 | 67 | ||
69 | #include "ci13xxx_udc.h" | 68 | #include "ci13xxx_udc.h" |
70 | 69 | ||
@@ -75,9 +74,6 @@ | |||
75 | /* ctrl register bank access */ | 74 | /* ctrl register bank access */ |
76 | static DEFINE_SPINLOCK(udc_lock); | 75 | static DEFINE_SPINLOCK(udc_lock); |
77 | 76 | ||
78 | /* driver name */ | ||
79 | #define UDC_DRIVER_NAME "ci13xxx_udc" | ||
80 | |||
81 | /* control endpoint description */ | 77 | /* control endpoint description */ |
82 | static const struct usb_endpoint_descriptor | 78 | static const struct usb_endpoint_descriptor |
83 | ctrl_endpt_desc = { | 79 | ctrl_endpt_desc = { |
@@ -132,6 +128,9 @@ static struct { | |||
132 | size_t size; /* bank size */ | 128 | size_t size; /* bank size */ |
133 | } hw_bank; | 129 | } hw_bank; |
134 | 130 | ||
131 | /* MSM specific */ | ||
132 | #define ABS_AHBBURST (0x0090UL) | ||
133 | #define ABS_AHBMODE (0x0098UL) | ||
135 | /* UDC register map */ | 134 | /* UDC register map */ |
136 | #define ABS_CAPLENGTH (0x100UL) | 135 | #define ABS_CAPLENGTH (0x100UL) |
137 | #define ABS_HCCPARAMS (0x108UL) | 136 | #define ABS_HCCPARAMS (0x108UL) |
@@ -248,13 +247,7 @@ static u32 hw_ctest_and_write(u32 addr, u32 mask, u32 data) | |||
248 | return (reg & mask) >> ffs_nr(mask); | 247 | return (reg & mask) >> ffs_nr(mask); |
249 | } | 248 | } |
250 | 249 | ||
251 | /** | 250 | static int hw_device_init(void __iomem *base) |
252 | * hw_device_reset: resets chip (execute without interruption) | ||
253 | * @base: register base address | ||
254 | * | ||
255 | * This function returns an error code | ||
256 | */ | ||
257 | static int hw_device_reset(void __iomem *base) | ||
258 | { | 251 | { |
259 | u32 reg; | 252 | u32 reg; |
260 | 253 | ||
@@ -271,6 +264,28 @@ static int hw_device_reset(void __iomem *base) | |||
271 | hw_bank.size += CAP_LAST; | 264 | hw_bank.size += CAP_LAST; |
272 | hw_bank.size /= sizeof(u32); | 265 | hw_bank.size /= sizeof(u32); |
273 | 266 | ||
267 | reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN); | ||
268 | if (reg == 0 || reg > ENDPT_MAX) | ||
269 | return -ENODEV; | ||
270 | |||
271 | hw_ep_max = reg; /* cache hw ENDPT_MAX */ | ||
272 | |||
273 | /* setup lock mode ? */ | ||
274 | |||
275 | /* ENDPTSETUPSTAT is '0' by default */ | ||
276 | |||
277 | /* HCSPARAMS.bf.ppc SHOULD BE zero for device */ | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | /** | ||
282 | * hw_device_reset: resets chip (execute without interruption) | ||
283 | * @base: register base address | ||
284 | * | ||
285 | * This function returns an error code | ||
286 | */ | ||
287 | static int hw_device_reset(struct ci13xxx *udc) | ||
288 | { | ||
274 | /* should flush & stop before reset */ | 289 | /* should flush & stop before reset */ |
275 | hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); | 290 | hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); |
276 | hw_cwrite(CAP_USBCMD, USBCMD_RS, 0); | 291 | hw_cwrite(CAP_USBCMD, USBCMD_RS, 0); |
@@ -279,6 +294,14 @@ static int hw_device_reset(void __iomem *base) | |||
279 | while (hw_cread(CAP_USBCMD, USBCMD_RST)) | 294 | while (hw_cread(CAP_USBCMD, USBCMD_RST)) |
280 | udelay(10); /* not RTOS friendly */ | 295 | udelay(10); /* not RTOS friendly */ |
281 | 296 | ||
297 | |||
298 | if (udc->udc_driver->notify_event) | ||
299 | udc->udc_driver->notify_event(udc, | ||
300 | CI13XXX_CONTROLLER_RESET_EVENT); | ||
301 | |||
302 | if (udc->udc_driver->flags && CI13XXX_DISABLE_STREAMING) | ||
303 | hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS); | ||
304 | |||
282 | /* USBMODE should be configured step by step */ | 305 | /* USBMODE should be configured step by step */ |
283 | hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE); | 306 | hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE); |
284 | hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE); | 307 | hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE); |
@@ -290,18 +313,6 @@ static int hw_device_reset(void __iomem *base) | |||
290 | return -ENODEV; | 313 | return -ENODEV; |
291 | } | 314 | } |
292 | 315 | ||
293 | reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN); | ||
294 | if (reg == 0 || reg > ENDPT_MAX) | ||
295 | return -ENODEV; | ||
296 | |||
297 | hw_ep_max = reg; /* cache hw ENDPT_MAX */ | ||
298 | |||
299 | /* setup lock mode ? */ | ||
300 | |||
301 | /* ENDPTSETUPSTAT is '0' by default */ | ||
302 | |||
303 | /* HCSPARAMS.bf.ppc SHOULD BE zero for device */ | ||
304 | |||
305 | return 0; | 316 | return 0; |
306 | } | 317 | } |
307 | 318 | ||
@@ -1557,8 +1568,6 @@ __acquires(mEp->lock) | |||
1557 | * Caller must hold lock | 1568 | * Caller must hold lock |
1558 | */ | 1569 | */ |
1559 | static int _gadget_stop_activity(struct usb_gadget *gadget) | 1570 | static int _gadget_stop_activity(struct usb_gadget *gadget) |
1560 | __releases(udc->lock) | ||
1561 | __acquires(udc->lock) | ||
1562 | { | 1571 | { |
1563 | struct usb_ep *ep; | 1572 | struct usb_ep *ep; |
1564 | struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); | 1573 | struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); |
@@ -1570,8 +1579,6 @@ __acquires(udc->lock) | |||
1570 | if (gadget == NULL) | 1579 | if (gadget == NULL) |
1571 | return -EINVAL; | 1580 | return -EINVAL; |
1572 | 1581 | ||
1573 | spin_unlock(udc->lock); | ||
1574 | |||
1575 | /* flush all endpoints */ | 1582 | /* flush all endpoints */ |
1576 | gadget_for_each_ep(ep, gadget) { | 1583 | gadget_for_each_ep(ep, gadget) { |
1577 | usb_ep_fifo_flush(ep); | 1584 | usb_ep_fifo_flush(ep); |
@@ -1591,8 +1598,6 @@ __acquires(udc->lock) | |||
1591 | mEp->status = NULL; | 1598 | mEp->status = NULL; |
1592 | } | 1599 | } |
1593 | 1600 | ||
1594 | spin_lock(udc->lock); | ||
1595 | |||
1596 | return 0; | 1601 | return 0; |
1597 | } | 1602 | } |
1598 | 1603 | ||
@@ -1621,6 +1626,7 @@ __acquires(udc->lock) | |||
1621 | 1626 | ||
1622 | dbg_event(0xFF, "BUS RST", 0); | 1627 | dbg_event(0xFF, "BUS RST", 0); |
1623 | 1628 | ||
1629 | spin_unlock(udc->lock); | ||
1624 | retval = _gadget_stop_activity(&udc->gadget); | 1630 | retval = _gadget_stop_activity(&udc->gadget); |
1625 | if (retval) | 1631 | if (retval) |
1626 | goto done; | 1632 | goto done; |
@@ -1629,10 +1635,9 @@ __acquires(udc->lock) | |||
1629 | if (retval) | 1635 | if (retval) |
1630 | goto done; | 1636 | goto done; |
1631 | 1637 | ||
1632 | spin_unlock(udc->lock); | ||
1633 | retval = usb_ep_enable(&mEp->ep, &ctrl_endpt_desc); | 1638 | retval = usb_ep_enable(&mEp->ep, &ctrl_endpt_desc); |
1634 | if (!retval) { | 1639 | if (!retval) { |
1635 | mEp->status = usb_ep_alloc_request(&mEp->ep, GFP_KERNEL); | 1640 | mEp->status = usb_ep_alloc_request(&mEp->ep, GFP_ATOMIC); |
1636 | if (mEp->status == NULL) { | 1641 | if (mEp->status == NULL) { |
1637 | usb_ep_disable(&mEp->ep); | 1642 | usb_ep_disable(&mEp->ep); |
1638 | retval = -ENOMEM; | 1643 | retval = -ENOMEM; |
@@ -2061,7 +2066,6 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) | |||
2061 | { | 2066 | { |
2062 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | 2067 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); |
2063 | struct ci13xxx_req *mReq = NULL; | 2068 | struct ci13xxx_req *mReq = NULL; |
2064 | unsigned long flags; | ||
2065 | 2069 | ||
2066 | trace("%p, %i", ep, gfp_flags); | 2070 | trace("%p, %i", ep, gfp_flags); |
2067 | 2071 | ||
@@ -2070,8 +2074,6 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) | |||
2070 | return NULL; | 2074 | return NULL; |
2071 | } | 2075 | } |
2072 | 2076 | ||
2073 | spin_lock_irqsave(mEp->lock, flags); | ||
2074 | |||
2075 | mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags); | 2077 | mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags); |
2076 | if (mReq != NULL) { | 2078 | if (mReq != NULL) { |
2077 | INIT_LIST_HEAD(&mReq->queue); | 2079 | INIT_LIST_HEAD(&mReq->queue); |
@@ -2086,8 +2088,6 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) | |||
2086 | 2088 | ||
2087 | dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL); | 2089 | dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL); |
2088 | 2090 | ||
2089 | spin_unlock_irqrestore(mEp->lock, flags); | ||
2090 | |||
2091 | return (mReq == NULL) ? NULL : &mReq->req; | 2091 | return (mReq == NULL) ? NULL : &mReq->req; |
2092 | } | 2092 | } |
2093 | 2093 | ||
@@ -2332,12 +2332,47 @@ static const struct usb_ep_ops usb_ep_ops = { | |||
2332 | /****************************************************************************** | 2332 | /****************************************************************************** |
2333 | * GADGET block | 2333 | * GADGET block |
2334 | *****************************************************************************/ | 2334 | *****************************************************************************/ |
2335 | static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) | ||
2336 | { | ||
2337 | struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget); | ||
2338 | unsigned long flags; | ||
2339 | int gadget_ready = 0; | ||
2340 | |||
2341 | if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS)) | ||
2342 | return -EOPNOTSUPP; | ||
2343 | |||
2344 | spin_lock_irqsave(udc->lock, flags); | ||
2345 | udc->vbus_active = is_active; | ||
2346 | if (udc->driver) | ||
2347 | gadget_ready = 1; | ||
2348 | spin_unlock_irqrestore(udc->lock, flags); | ||
2349 | |||
2350 | if (gadget_ready) { | ||
2351 | if (is_active) { | ||
2352 | pm_runtime_get_sync(&_gadget->dev); | ||
2353 | hw_device_reset(udc); | ||
2354 | hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma); | ||
2355 | } else { | ||
2356 | hw_device_state(0); | ||
2357 | if (udc->udc_driver->notify_event) | ||
2358 | udc->udc_driver->notify_event(udc, | ||
2359 | CI13XXX_CONTROLLER_STOPPED_EVENT); | ||
2360 | _gadget_stop_activity(&udc->gadget); | ||
2361 | pm_runtime_put_sync(&_gadget->dev); | ||
2362 | } | ||
2363 | } | ||
2364 | |||
2365 | return 0; | ||
2366 | } | ||
2367 | |||
2335 | /** | 2368 | /** |
2336 | * Device operations part of the API to the USB controller hardware, | 2369 | * Device operations part of the API to the USB controller hardware, |
2337 | * which don't involve endpoints (or i/o) | 2370 | * which don't involve endpoints (or i/o) |
2338 | * Check "usb_gadget.h" for details | 2371 | * Check "usb_gadget.h" for details |
2339 | */ | 2372 | */ |
2340 | static const struct usb_gadget_ops usb_gadget_ops; | 2373 | static const struct usb_gadget_ops usb_gadget_ops = { |
2374 | .vbus_session = ci13xxx_vbus_session, | ||
2375 | }; | ||
2341 | 2376 | ||
2342 | /** | 2377 | /** |
2343 | * usb_gadget_probe_driver: register a gadget driver | 2378 | * usb_gadget_probe_driver: register a gadget driver |
@@ -2390,7 +2425,6 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, | |||
2390 | info("hw_ep_max = %d", hw_ep_max); | 2425 | info("hw_ep_max = %d", hw_ep_max); |
2391 | 2426 | ||
2392 | udc->driver = driver; | 2427 | udc->driver = driver; |
2393 | udc->gadget.ops = NULL; | ||
2394 | udc->gadget.dev.driver = NULL; | 2428 | udc->gadget.dev.driver = NULL; |
2395 | 2429 | ||
2396 | retval = 0; | 2430 | retval = 0; |
@@ -2410,9 +2444,11 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, | |||
2410 | /* this allocation cannot be random */ | 2444 | /* this allocation cannot be random */ |
2411 | for (k = RX; k <= TX; k++) { | 2445 | for (k = RX; k <= TX; k++) { |
2412 | INIT_LIST_HEAD(&mEp->qh[k].queue); | 2446 | INIT_LIST_HEAD(&mEp->qh[k].queue); |
2447 | spin_unlock_irqrestore(udc->lock, flags); | ||
2413 | mEp->qh[k].ptr = dma_pool_alloc(udc->qh_pool, | 2448 | mEp->qh[k].ptr = dma_pool_alloc(udc->qh_pool, |
2414 | GFP_KERNEL, | 2449 | GFP_KERNEL, |
2415 | &mEp->qh[k].dma); | 2450 | &mEp->qh[k].dma); |
2451 | spin_lock_irqsave(udc->lock, flags); | ||
2416 | if (mEp->qh[k].ptr == NULL) | 2452 | if (mEp->qh[k].ptr == NULL) |
2417 | retval = -ENOMEM; | 2453 | retval = -ENOMEM; |
2418 | else | 2454 | else |
@@ -2429,7 +2465,6 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, | |||
2429 | 2465 | ||
2430 | /* bind gadget */ | 2466 | /* bind gadget */ |
2431 | driver->driver.bus = NULL; | 2467 | driver->driver.bus = NULL; |
2432 | udc->gadget.ops = &usb_gadget_ops; | ||
2433 | udc->gadget.dev.driver = &driver->driver; | 2468 | udc->gadget.dev.driver = &driver->driver; |
2434 | 2469 | ||
2435 | spin_unlock_irqrestore(udc->lock, flags); | 2470 | spin_unlock_irqrestore(udc->lock, flags); |
@@ -2437,12 +2472,24 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, | |||
2437 | spin_lock_irqsave(udc->lock, flags); | 2472 | spin_lock_irqsave(udc->lock, flags); |
2438 | 2473 | ||
2439 | if (retval) { | 2474 | if (retval) { |
2440 | udc->gadget.ops = NULL; | ||
2441 | udc->gadget.dev.driver = NULL; | 2475 | udc->gadget.dev.driver = NULL; |
2442 | goto done; | 2476 | goto done; |
2443 | } | 2477 | } |
2444 | 2478 | ||
2479 | pm_runtime_get_sync(&udc->gadget.dev); | ||
2480 | if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) { | ||
2481 | if (udc->vbus_active) { | ||
2482 | if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) | ||
2483 | hw_device_reset(udc); | ||
2484 | } else { | ||
2485 | pm_runtime_put_sync(&udc->gadget.dev); | ||
2486 | goto done; | ||
2487 | } | ||
2488 | } | ||
2489 | |||
2445 | retval = hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma); | 2490 | retval = hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma); |
2491 | if (retval) | ||
2492 | pm_runtime_put_sync(&udc->gadget.dev); | ||
2446 | 2493 | ||
2447 | done: | 2494 | done: |
2448 | spin_unlock_irqrestore(udc->lock, flags); | 2495 | spin_unlock_irqrestore(udc->lock, flags); |
@@ -2475,19 +2522,22 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | |||
2475 | 2522 | ||
2476 | spin_lock_irqsave(udc->lock, flags); | 2523 | spin_lock_irqsave(udc->lock, flags); |
2477 | 2524 | ||
2478 | hw_device_state(0); | 2525 | if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) || |
2479 | 2526 | udc->vbus_active) { | |
2480 | /* unbind gadget */ | 2527 | hw_device_state(0); |
2481 | if (udc->gadget.ops != NULL) { | 2528 | if (udc->udc_driver->notify_event) |
2529 | udc->udc_driver->notify_event(udc, | ||
2530 | CI13XXX_CONTROLLER_STOPPED_EVENT); | ||
2482 | _gadget_stop_activity(&udc->gadget); | 2531 | _gadget_stop_activity(&udc->gadget); |
2532 | pm_runtime_put(&udc->gadget.dev); | ||
2533 | } | ||
2483 | 2534 | ||
2484 | spin_unlock_irqrestore(udc->lock, flags); | 2535 | /* unbind gadget */ |
2485 | driver->unbind(&udc->gadget); /* MAY SLEEP */ | 2536 | spin_unlock_irqrestore(udc->lock, flags); |
2486 | spin_lock_irqsave(udc->lock, flags); | 2537 | driver->unbind(&udc->gadget); /* MAY SLEEP */ |
2538 | spin_lock_irqsave(udc->lock, flags); | ||
2487 | 2539 | ||
2488 | udc->gadget.ops = NULL; | 2540 | udc->gadget.dev.driver = NULL; |
2489 | udc->gadget.dev.driver = NULL; | ||
2490 | } | ||
2491 | 2541 | ||
2492 | /* free resources */ | 2542 | /* free resources */ |
2493 | for (i = 0; i < hw_ep_max; i++) { | 2543 | for (i = 0; i < hw_ep_max; i++) { |
@@ -2544,6 +2594,14 @@ static irqreturn_t udc_irq(void) | |||
2544 | } | 2594 | } |
2545 | 2595 | ||
2546 | spin_lock(udc->lock); | 2596 | spin_lock(udc->lock); |
2597 | |||
2598 | if (udc->udc_driver->flags & CI13XXX_REGS_SHARED) { | ||
2599 | if (hw_cread(CAP_USBMODE, USBMODE_CM) != | ||
2600 | USBMODE_CM_DEVICE) { | ||
2601 | spin_unlock(udc->lock); | ||
2602 | return IRQ_NONE; | ||
2603 | } | ||
2604 | } | ||
2547 | intr = hw_test_and_clear_intr_active(); | 2605 | intr = hw_test_and_clear_intr_active(); |
2548 | if (intr) { | 2606 | if (intr) { |
2549 | isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr; | 2607 | isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr; |
@@ -2602,14 +2660,16 @@ static void udc_release(struct device *dev) | |||
2602 | * No interrupts active, the IRQ has not been requested yet | 2660 | * No interrupts active, the IRQ has not been requested yet |
2603 | * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask | 2661 | * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask |
2604 | */ | 2662 | */ |
2605 | static int udc_probe(struct device *dev, void __iomem *regs, const char *name) | 2663 | static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev, |
2664 | void __iomem *regs) | ||
2606 | { | 2665 | { |
2607 | struct ci13xxx *udc; | 2666 | struct ci13xxx *udc; |
2608 | int retval = 0; | 2667 | int retval = 0; |
2609 | 2668 | ||
2610 | trace("%p, %p, %p", dev, regs, name); | 2669 | trace("%p, %p, %p", dev, regs, name); |
2611 | 2670 | ||
2612 | if (dev == NULL || regs == NULL || name == NULL) | 2671 | if (dev == NULL || regs == NULL || driver == NULL || |
2672 | driver->name == NULL) | ||
2613 | return -EINVAL; | 2673 | return -EINVAL; |
2614 | 2674 | ||
2615 | udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL); | 2675 | udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL); |
@@ -2617,42 +2677,77 @@ static int udc_probe(struct device *dev, void __iomem *regs, const char *name) | |||
2617 | return -ENOMEM; | 2677 | return -ENOMEM; |
2618 | 2678 | ||
2619 | udc->lock = &udc_lock; | 2679 | udc->lock = &udc_lock; |
2680 | udc->regs = regs; | ||
2681 | udc->udc_driver = driver; | ||
2620 | 2682 | ||
2621 | retval = hw_device_reset(regs); | 2683 | udc->gadget.ops = &usb_gadget_ops; |
2622 | if (retval) | ||
2623 | goto done; | ||
2624 | |||
2625 | udc->gadget.ops = NULL; | ||
2626 | udc->gadget.speed = USB_SPEED_UNKNOWN; | 2684 | udc->gadget.speed = USB_SPEED_UNKNOWN; |
2627 | udc->gadget.is_dualspeed = 1; | 2685 | udc->gadget.is_dualspeed = 1; |
2628 | udc->gadget.is_otg = 0; | 2686 | udc->gadget.is_otg = 0; |
2629 | udc->gadget.name = name; | 2687 | udc->gadget.name = driver->name; |
2630 | 2688 | ||
2631 | INIT_LIST_HEAD(&udc->gadget.ep_list); | 2689 | INIT_LIST_HEAD(&udc->gadget.ep_list); |
2632 | udc->gadget.ep0 = NULL; | 2690 | udc->gadget.ep0 = NULL; |
2633 | 2691 | ||
2634 | dev_set_name(&udc->gadget.dev, "gadget"); | 2692 | dev_set_name(&udc->gadget.dev, "gadget"); |
2635 | udc->gadget.dev.dma_mask = dev->dma_mask; | 2693 | udc->gadget.dev.dma_mask = dev->dma_mask; |
2694 | udc->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask; | ||
2636 | udc->gadget.dev.parent = dev; | 2695 | udc->gadget.dev.parent = dev; |
2637 | udc->gadget.dev.release = udc_release; | 2696 | udc->gadget.dev.release = udc_release; |
2638 | 2697 | ||
2698 | retval = hw_device_init(regs); | ||
2699 | if (retval < 0) | ||
2700 | goto free_udc; | ||
2701 | |||
2702 | udc->transceiver = otg_get_transceiver(); | ||
2703 | |||
2704 | if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) { | ||
2705 | if (udc->transceiver == NULL) { | ||
2706 | retval = -ENODEV; | ||
2707 | goto free_udc; | ||
2708 | } | ||
2709 | } | ||
2710 | |||
2711 | if (!(udc->udc_driver->flags & CI13XXX_REGS_SHARED)) { | ||
2712 | retval = hw_device_reset(udc); | ||
2713 | if (retval) | ||
2714 | goto put_transceiver; | ||
2715 | } | ||
2716 | |||
2639 | retval = device_register(&udc->gadget.dev); | 2717 | retval = device_register(&udc->gadget.dev); |
2640 | if (retval) | 2718 | if (retval) { |
2641 | goto done; | 2719 | put_device(&udc->gadget.dev); |
2720 | goto put_transceiver; | ||
2721 | } | ||
2642 | 2722 | ||
2643 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES | 2723 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES |
2644 | retval = dbg_create_files(&udc->gadget.dev); | 2724 | retval = dbg_create_files(&udc->gadget.dev); |
2645 | #endif | 2725 | #endif |
2646 | if (retval) { | 2726 | if (retval) |
2647 | device_unregister(&udc->gadget.dev); | 2727 | goto unreg_device; |
2648 | goto done; | 2728 | |
2729 | if (udc->transceiver) { | ||
2730 | retval = otg_set_peripheral(udc->transceiver, &udc->gadget); | ||
2731 | if (retval) | ||
2732 | goto remove_dbg; | ||
2649 | } | 2733 | } |
2734 | pm_runtime_no_callbacks(&udc->gadget.dev); | ||
2735 | pm_runtime_enable(&udc->gadget.dev); | ||
2650 | 2736 | ||
2651 | _udc = udc; | 2737 | _udc = udc; |
2652 | return retval; | 2738 | return retval; |
2653 | 2739 | ||
2654 | done: | ||
2655 | err("error = %i", retval); | 2740 | err("error = %i", retval); |
2741 | remove_dbg: | ||
2742 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES | ||
2743 | dbg_remove_files(&udc->gadget.dev); | ||
2744 | #endif | ||
2745 | unreg_device: | ||
2746 | device_unregister(&udc->gadget.dev); | ||
2747 | put_transceiver: | ||
2748 | if (udc->transceiver) | ||
2749 | otg_put_transceiver(udc->transceiver); | ||
2750 | free_udc: | ||
2656 | kfree(udc); | 2751 | kfree(udc); |
2657 | _udc = NULL; | 2752 | _udc = NULL; |
2658 | return retval; | 2753 | return retval; |
@@ -2672,6 +2767,10 @@ static void udc_remove(void) | |||
2672 | return; | 2767 | return; |
2673 | } | 2768 | } |
2674 | 2769 | ||
2770 | if (udc->transceiver) { | ||
2771 | otg_set_peripheral(udc->transceiver, &udc->gadget); | ||
2772 | otg_put_transceiver(udc->transceiver); | ||
2773 | } | ||
2675 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES | 2774 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES |
2676 | dbg_remove_files(&udc->gadget.dev); | 2775 | dbg_remove_files(&udc->gadget.dev); |
2677 | #endif | 2776 | #endif |
@@ -2680,156 +2779,3 @@ static void udc_remove(void) | |||
2680 | kfree(udc); | 2779 | kfree(udc); |
2681 | _udc = NULL; | 2780 | _udc = NULL; |
2682 | } | 2781 | } |
2683 | |||
2684 | /****************************************************************************** | ||
2685 | * PCI block | ||
2686 | *****************************************************************************/ | ||
2687 | /** | ||
2688 | * ci13xxx_pci_irq: interrut handler | ||
2689 | * @irq: irq number | ||
2690 | * @pdev: USB Device Controller interrupt source | ||
2691 | * | ||
2692 | * This function returns IRQ_HANDLED if the IRQ has been handled | ||
2693 | * This is an ISR don't trace, use attribute interface instead | ||
2694 | */ | ||
2695 | static irqreturn_t ci13xxx_pci_irq(int irq, void *pdev) | ||
2696 | { | ||
2697 | if (irq == 0) { | ||
2698 | dev_err(&((struct pci_dev *)pdev)->dev, "Invalid IRQ0 usage!"); | ||
2699 | return IRQ_HANDLED; | ||
2700 | } | ||
2701 | return udc_irq(); | ||
2702 | } | ||
2703 | |||
2704 | /** | ||
2705 | * ci13xxx_pci_probe: PCI probe | ||
2706 | * @pdev: USB device controller being probed | ||
2707 | * @id: PCI hotplug ID connecting controller to UDC framework | ||
2708 | * | ||
2709 | * This function returns an error code | ||
2710 | * Allocates basic PCI resources for this USB device controller, and then | ||
2711 | * invokes the udc_probe() method to start the UDC associated with it | ||
2712 | */ | ||
2713 | static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, | ||
2714 | const struct pci_device_id *id) | ||
2715 | { | ||
2716 | void __iomem *regs = NULL; | ||
2717 | int retval = 0; | ||
2718 | |||
2719 | if (id == NULL) | ||
2720 | return -EINVAL; | ||
2721 | |||
2722 | retval = pci_enable_device(pdev); | ||
2723 | if (retval) | ||
2724 | goto done; | ||
2725 | |||
2726 | if (!pdev->irq) { | ||
2727 | dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!"); | ||
2728 | retval = -ENODEV; | ||
2729 | goto disable_device; | ||
2730 | } | ||
2731 | |||
2732 | retval = pci_request_regions(pdev, UDC_DRIVER_NAME); | ||
2733 | if (retval) | ||
2734 | goto disable_device; | ||
2735 | |||
2736 | /* BAR 0 holds all the registers */ | ||
2737 | regs = pci_iomap(pdev, 0, 0); | ||
2738 | if (!regs) { | ||
2739 | dev_err(&pdev->dev, "Error mapping memory!"); | ||
2740 | retval = -EFAULT; | ||
2741 | goto release_regions; | ||
2742 | } | ||
2743 | pci_set_drvdata(pdev, (__force void *)regs); | ||
2744 | |||
2745 | pci_set_master(pdev); | ||
2746 | pci_try_set_mwi(pdev); | ||
2747 | |||
2748 | retval = udc_probe(&pdev->dev, regs, UDC_DRIVER_NAME); | ||
2749 | if (retval) | ||
2750 | goto iounmap; | ||
2751 | |||
2752 | /* our device does not have MSI capability */ | ||
2753 | |||
2754 | retval = request_irq(pdev->irq, ci13xxx_pci_irq, IRQF_SHARED, | ||
2755 | UDC_DRIVER_NAME, pdev); | ||
2756 | if (retval) | ||
2757 | goto gadget_remove; | ||
2758 | |||
2759 | return 0; | ||
2760 | |||
2761 | gadget_remove: | ||
2762 | udc_remove(); | ||
2763 | iounmap: | ||
2764 | pci_iounmap(pdev, regs); | ||
2765 | release_regions: | ||
2766 | pci_release_regions(pdev); | ||
2767 | disable_device: | ||
2768 | pci_disable_device(pdev); | ||
2769 | done: | ||
2770 | return retval; | ||
2771 | } | ||
2772 | |||
2773 | /** | ||
2774 | * ci13xxx_pci_remove: PCI remove | ||
2775 | * @pdev: USB Device Controller being removed | ||
2776 | * | ||
2777 | * Reverses the effect of ci13xxx_pci_probe(), | ||
2778 | * first invoking the udc_remove() and then releases | ||
2779 | * all PCI resources allocated for this USB device controller | ||
2780 | */ | ||
2781 | static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev) | ||
2782 | { | ||
2783 | free_irq(pdev->irq, pdev); | ||
2784 | udc_remove(); | ||
2785 | pci_iounmap(pdev, (__force void __iomem *)pci_get_drvdata(pdev)); | ||
2786 | pci_release_regions(pdev); | ||
2787 | pci_disable_device(pdev); | ||
2788 | } | ||
2789 | |||
2790 | /** | ||
2791 | * PCI device table | ||
2792 | * PCI device structure | ||
2793 | * | ||
2794 | * Check "pci.h" for details | ||
2795 | */ | ||
2796 | static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = { | ||
2797 | { PCI_DEVICE(0x153F, 0x1004) }, | ||
2798 | { PCI_DEVICE(0x153F, 0x1006) }, | ||
2799 | { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ } | ||
2800 | }; | ||
2801 | MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table); | ||
2802 | |||
2803 | static struct pci_driver ci13xxx_pci_driver = { | ||
2804 | .name = UDC_DRIVER_NAME, | ||
2805 | .id_table = ci13xxx_pci_id_table, | ||
2806 | .probe = ci13xxx_pci_probe, | ||
2807 | .remove = __devexit_p(ci13xxx_pci_remove), | ||
2808 | }; | ||
2809 | |||
2810 | /** | ||
2811 | * ci13xxx_pci_init: module init | ||
2812 | * | ||
2813 | * Driver load | ||
2814 | */ | ||
2815 | static int __init ci13xxx_pci_init(void) | ||
2816 | { | ||
2817 | return pci_register_driver(&ci13xxx_pci_driver); | ||
2818 | } | ||
2819 | module_init(ci13xxx_pci_init); | ||
2820 | |||
2821 | /** | ||
2822 | * ci13xxx_pci_exit: module exit | ||
2823 | * | ||
2824 | * Driver unload | ||
2825 | */ | ||
2826 | static void __exit ci13xxx_pci_exit(void) | ||
2827 | { | ||
2828 | pci_unregister_driver(&ci13xxx_pci_driver); | ||
2829 | } | ||
2830 | module_exit(ci13xxx_pci_exit); | ||
2831 | |||
2832 | MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>"); | ||
2833 | MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller"); | ||
2834 | MODULE_LICENSE("GPL"); | ||
2835 | MODULE_VERSION("June 2008"); | ||