diff options
Diffstat (limited to 'drivers/usb/gadget/pxa27x_udc.c')
| -rw-r--r-- | drivers/usb/gadget/pxa27x_udc.c | 316 |
1 files changed, 158 insertions, 158 deletions
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index adda1208a1e..cdf4d678be9 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -8,21 +8,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/errno.h> +#include <linux/err.h> #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/list.h> @@ -31,14 +22,14 @@ #include <linux/clk.h> #include <linux/irq.h> #include <linux/gpio.h> - -#include <asm/byteorder.h> -#include <mach/hardware.h> +#include <linux/slab.h> +#include <linux/prefetch.h> +#include <linux/byteorder/generic.h> +#include <linux/platform_data/pxa2xx_udc.h> #include <linux/usb.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> -#include <mach/udc.h> #include "pxa27x_udc.h" @@ -601,7 +592,7 @@ static void inc_ep_stats_reqs(struct pxa_ep *ep, int is_in) /** * inc_ep_stats_bytes - Update ep stats counts * @ep: physical endpoint - * @count: bytes transfered on endpoint + * @count: bytes transferred on endpoint * @is_in: ep direction (USB_DIR_IN or 0) */ static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in) @@ -618,7 +609,7 @@ static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in) * * Find the physical pxa27x ep, and setup its UDCCR */ -static __init void pxa_ep_setup(struct pxa_ep *ep) +static void pxa_ep_setup(struct pxa_ep *ep) { u32 new_udccr; @@ -640,7 +631,7 @@ static __init void pxa_ep_setup(struct pxa_ep *ep) * * Setup all pxa physical endpoints, except ep0 */ -static __init void pxa_eps_setup(struct pxa_udc *dev) +static void pxa_eps_setup(struct pxa_udc *dev) { unsigned int i; @@ -742,13 +733,17 @@ static void ep_del_request(struct pxa_ep *ep, struct pxa27x_request *req) * @ep: pxa physical endpoint * @req: pxa request * @status: usb request status sent to gadget API + * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held * - * Context: ep->lock held + * Context: ep->lock held if flags not NULL, else ep->lock released * * Retire a pxa27x usb request. Endpoint must be locked. */ -static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status) +static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status, + unsigned long *pflags) { + unsigned long flags; + ep_del_request(ep, req); if (likely(req->req.status == -EINPROGRESS)) req->req.status = status; @@ -760,38 +755,48 @@ static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status) &req->req, status, req->req.actual, req->req.length); + if (pflags) + spin_unlock_irqrestore(&ep->lock, *pflags); + local_irq_save(flags); req->req.complete(&req->udc_usb_ep->usb_ep, &req->req); + local_irq_restore(flags); + if (pflags) + spin_lock_irqsave(&ep->lock, *pflags); } /** * ep_end_out_req - Ends endpoint OUT request * @ep: physical endpoint * @req: pxa request + * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held * - * Context: ep->lock held + * Context: ep->lock held or released (see req_done()) * * Ends endpoint OUT request (completes usb request). */ -static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req) +static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req, + unsigned long *pflags) { inc_ep_stats_reqs(ep, !USB_DIR_IN); - req_done(ep, req, 0); + req_done(ep, req, 0, pflags); } /** * ep0_end_out_req - Ends control endpoint OUT request (ends data stage) * @ep: physical endpoint * @req: pxa request + * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held * - * Context: ep->lock held + * Context: ep->lock held or released (see req_done()) * * Ends control endpoint OUT request (completes usb request), and puts * control endpoint into idle state */ -static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req) +static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req, + unsigned long *pflags) { set_ep0state(ep->dev, OUT_STATUS_STAGE); - ep_end_out_req(ep, req); + ep_end_out_req(ep, req, pflags); ep0_idle(ep->dev); } @@ -799,31 +804,35 @@ static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req) * ep_end_in_req - Ends endpoint IN request * @ep: physical endpoint * @req: pxa request + * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held * - * Context: ep->lock held + * Context: ep->lock held or released (see req_done()) * * Ends endpoint IN request (completes usb request). */ -static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req) +static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req, + unsigned long *pflags) { inc_ep_stats_reqs(ep, USB_DIR_IN); - req_done(ep, req, 0); + req_done(ep, req, 0, pflags); } /** * ep0_end_in_req - Ends control endpoint IN request (ends data stage) * @ep: physical endpoint * @req: pxa request + * @pflags: flags of previous spinlock_irq_save() or NULL if no lock held * - * Context: ep->lock held + * Context: ep->lock held or released (see req_done()) * * Ends control endpoint IN request (completes usb request), and puts * control endpoint into status state */ -static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req) +static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req, + unsigned long *pflags) { set_ep0state(ep->dev, IN_STATUS_STAGE); - ep_end_in_req(ep, req); + ep_end_in_req(ep, req, pflags); } /** @@ -831,19 +840,22 @@ static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req) * @ep: pxa endpoint * @status: usb request status * - * Context: ep->lock held + * Context: ep->lock released * * Dequeues all requests on an endpoint. As a side effect, interrupts will be * disabled on that endpoint (because no more requests). */ static void nuke(struct pxa_ep *ep, int status) { - struct pxa27x_request *req; + struct pxa27x_request *req; + unsigned long flags; + spin_lock_irqsave(&ep->lock, flags); while (!list_empty(&ep->queue)) { req = list_entry(ep->queue.next, struct pxa27x_request, queue); - req_done(ep, req, status); + req_done(ep, req, status, &flags); } + spin_unlock_irqrestore(&ep->lock, flags); } /** @@ -855,7 +867,7 @@ static void nuke(struct pxa_ep *ep, int status) * If there is less space in request than bytes received in OUT endpoint, * bytes are left in the OUT endpoint. * - * Returns how many bytes were actually transfered + * Returns how many bytes were actually transferred */ static int read_packet(struct pxa_ep *ep, struct pxa27x_request *req) { @@ -892,7 +904,7 @@ static int read_packet(struct pxa_ep *ep, struct pxa27x_request *req) * endpoint. If there are no bytes to transfer, doesn't write anything * to physical endpoint. * - * Returns how many bytes were actually transfered. + * Returns how many bytes were actually transferred. */ static int write_packet(struct pxa_ep *ep, struct pxa27x_request *req, unsigned int max) @@ -969,7 +981,7 @@ static int read_fifo(struct pxa_ep *ep, struct pxa27x_request *req) * caller guarantees at least one packet buffer is ready (or a zlp). * Doesn't complete the request, that's the caller's job * - * Returns 1 if request fully transfered, 0 if partial transfer + * Returns 1 if request fully transferred, 0 if partial transfer */ static int write_fifo(struct pxa_ep *ep, struct pxa27x_request *req) { @@ -1072,7 +1084,7 @@ static int read_ep0_fifo(struct pxa_ep *ep, struct pxa27x_request *req) * Sends a request (or a part of the request) to the control endpoint (ep0 in). * If the request doesn't fit, the remaining part will be sent from irq. * The request is considered fully written only if either : - * - last write transfered all remaining bytes, but fifo was not fully filled + * - last write transferred all remaining bytes, but fifo was not fully filled * - last write was a 0 length write * * Returns 1 if request fully written, 0 if request only partially sent @@ -1123,6 +1135,7 @@ static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int rc = 0; int is_first_req; unsigned length; + int recursion_detected; req = container_of(_req, struct pxa27x_request, req); udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep); @@ -1152,6 +1165,7 @@ static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req, return -EMSGSIZE; spin_lock_irqsave(&ep->lock, flags); + recursion_detected = ep->in_handle_ep; is_first_req = list_empty(&ep->queue); ep_dbg(ep, "queue req %p(first=%s), len %d buf %p\n", @@ -1161,12 +1175,12 @@ static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req, if (!ep->enabled) { _req->status = -ESHUTDOWN; rc = -ESHUTDOWN; - goto out; + goto out_locked; } if (req->in_use) { ep_err(ep, "refusing to queue req %p (already queued)\n", req); - goto out; + goto out_locked; } length = _req->length; @@ -1174,12 +1188,13 @@ static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req, _req->actual = 0; ep_add_request(ep, req); + spin_unlock_irqrestore(&ep->lock, flags); if (is_ep0(ep)) { switch (dev->ep0state) { case WAIT_ACK_SET_CONF_INTERF: if (length == 0) { - ep_end_in_req(ep, req); + ep_end_in_req(ep, req, NULL); } else { ep_err(ep, "got a request of %d bytes while" "in state WAIT_ACK_SET_CONF_INTERF\n", @@ -1192,12 +1207,12 @@ static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req, case IN_DATA_STAGE: if (!ep_is_full(ep)) if (write_ep0_fifo(ep, req)) - ep0_end_in_req(ep, req); + ep0_end_in_req(ep, req, NULL); break; case OUT_DATA_STAGE: if ((length == 0) || !epout_has_pkt(ep)) if (read_ep0_fifo(ep, req)) - ep0_end_out_req(ep, req); + ep0_end_out_req(ep, req, NULL); break; default: ep_err(ep, "odd state %s to send me a request\n", @@ -1207,12 +1222,15 @@ static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req, break; } } else { - handle_ep(ep); + if (!recursion_detected) + handle_ep(ep); } out: - spin_unlock_irqrestore(&ep->lock, flags); return rc; +out_locked: + spin_unlock_irqrestore(&ep->lock, flags); + goto out; } /** @@ -1242,13 +1260,14 @@ static int pxa_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) /* make sure it's actually queued on this endpoint */ list_for_each_entry(req, &ep->queue, queue) { if (&req->req == _req) { - req_done(ep, req, -ECONNRESET); rc = 0; break; } } spin_unlock_irqrestore(&ep->lock, flags); + if (!rc) + req_done(ep, req, -ECONNRESET, NULL); return rc; } @@ -1365,8 +1384,6 @@ static void pxa_ep_fifo_flush(struct usb_ep *_ep) } spin_unlock_irqrestore(&ep->lock, flags); - - return; } /** @@ -1411,7 +1428,7 @@ static int pxa_ep_enable(struct usb_ep *_ep, return -EINVAL; } - if (ep->fifo_size < le16_to_cpu(desc->wMaxPacketSize)) { + if (ep->fifo_size < usb_endpoint_maxp(desc)) { ep_err(ep, "bad maxpacket\n"); return -ERANGE; } @@ -1445,7 +1462,6 @@ static int pxa_ep_disable(struct usb_ep *_ep) { struct pxa_ep *ep; struct udc_usb_ep *udc_usb_ep; - unsigned long flags; if (!_ep) return -EINVAL; @@ -1455,10 +1471,8 @@ static int pxa_ep_disable(struct usb_ep *_ep) if (!ep || is_ep0(ep) || !list_empty(&ep->queue)) return -EINVAL; - spin_lock_irqsave(&ep->lock, flags); ep->enabled = 0; nuke(ep, -ESHUTDOWN); - spin_unlock_irqrestore(&ep->lock, flags); pxa_ep_fifo_flush(_ep); udc_usb_ep->pxa_ep = NULL; @@ -1524,7 +1538,7 @@ static int pxa_udc_get_frame(struct usb_gadget *_gadget) * pxa_udc_wakeup - Force udc device out of suspend * @_gadget: usb gadget * - * Returns 0 if successfull, error code otherwise + * Returns 0 if successful, error code otherwise */ static int pxa_udc_wakeup(struct usb_gadget *_gadget) { @@ -1558,7 +1572,7 @@ static int should_enable_udc(struct pxa_udc *udc) int put_on; put_on = ((udc->pullup_on) && (udc->driver)); - put_on &= ((udc->vbus_sensed) || (!udc->transceiver)); + put_on &= ((udc->vbus_sensed) || (IS_ERR_OR_NULL(udc->transceiver))); return put_on; } @@ -1579,7 +1593,7 @@ static int should_disable_udc(struct pxa_udc *udc) int put_off; put_off = ((!udc->pullup_on) || (!udc->driver)); - put_off |= ((!udc->vbus_sensed) && (udc->transceiver)); + put_off |= ((!udc->vbus_sensed) && (!IS_ERR_OR_NULL(udc->transceiver))); return put_off; } @@ -1650,17 +1664,24 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) struct pxa_udc *udc; udc = to_gadget_udc(_gadget); - if (udc->transceiver) - return otg_set_power(udc->transceiver, mA); + if (!IS_ERR_OR_NULL(udc->transceiver)) + return usb_phy_set_power(udc->transceiver, mA); return -EOPNOTSUPP; } +static int pxa27x_udc_start(struct usb_gadget *g, + struct usb_gadget_driver *driver); +static int pxa27x_udc_stop(struct usb_gadget *g, + struct usb_gadget_driver *driver); + static const struct usb_gadget_ops pxa_udc_ops = { .get_frame = pxa_udc_get_frame, .wakeup = pxa_udc_wakeup, .pullup = pxa_udc_pullup, .vbus_session = pxa_udc_vbus_session, .vbus_draw = pxa_udc_vbus_draw, + .udc_start = pxa27x_udc_start, + .udc_stop = pxa27x_udc_stop, }; /** @@ -1695,7 +1716,7 @@ static void udc_disable(struct pxa_udc *udc) * Initializes gadget endpoint list, endpoints locks. No action is taken * on the hardware. */ -static __init void udc_init_data(struct pxa_udc *dev) +static void udc_init_data(struct pxa_udc *dev) { int i; struct pxa_ep *ep; @@ -1716,9 +1737,12 @@ static __init void udc_init_data(struct pxa_udc *dev) } /* USB endpoints init */ - for (i = 1; i < NR_USB_ENDPOINTS; i++) + for (i = 1; i < NR_USB_ENDPOINTS; i++) { list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list, &dev->gadget.ep_list); + usb_ep_set_maxpacket_limit(&dev->udc_usb_ep[i].usb_ep, + dev->udc_usb_ep[i].usb_ep.maxpacket); + } } /** @@ -1766,8 +1790,9 @@ static void udc_enable(struct pxa_udc *udc) } /** - * usb_gadget_register_driver - Register gadget driver + * pxa27x_start - Register gadget driver * @driver: gadget driver + * @bind: bind function * * When a driver is successfully registered, it will receive control requests * including set_configuration(), which enables non-control requests. Then @@ -1779,43 +1804,22 @@ static void udc_enable(struct pxa_udc *udc) * * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise */ -int usb_gadget_register_driver(struct usb_gadget_driver *driver) +static int pxa27x_udc_start(struct usb_gadget *g, + struct usb_gadget_driver *driver) { - struct pxa_udc *udc = the_controller; + struct pxa_udc *udc = to_pxa(g); int retval; - if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind - || !driver->disconnect || !driver->setup) - return -EINVAL; - if (!udc) - return -ENODEV; - if (udc->driver) - return -EBUSY; - /* first hook up the driver ... */ udc->driver = driver; - udc->gadget.dev.driver = &driver->driver; dplus_pullup(udc, 1); - retval = device_add(&udc->gadget.dev); - if (retval) { - dev_err(udc->dev, "device_add error %d\n", retval); - goto add_fail; - } - retval = driver->bind(&udc->gadget); - if (retval) { - dev_err(udc->dev, "bind to driver %s --> error %d\n", - driver->driver.name, retval); - goto bind_fail; - } - dev_dbg(udc->dev, "registered gadget driver '%s'\n", - driver->driver.name); - - if (udc->transceiver) { - retval = otg_set_peripheral(udc->transceiver, &udc->gadget); + if (!IS_ERR_OR_NULL(udc->transceiver)) { + retval = otg_set_peripheral(udc->transceiver->otg, + &udc->gadget); if (retval) { dev_err(udc->dev, "can't bind to transceiver\n"); - goto transceiver_fail; + goto fail; } } @@ -1823,18 +1827,10 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) udc_enable(udc); return 0; -transceiver_fail: - if (driver->unbind) - driver->unbind(&udc->gadget); -bind_fail: - device_del(&udc->gadget.dev); -add_fail: +fail: udc->driver = NULL; - udc->gadget.dev.driver = NULL; return retval; } -EXPORT_SYMBOL(usb_gadget_register_driver); - /** * stop_activity - Stops udc endpoints @@ -1855,42 +1851,29 @@ static void stop_activity(struct pxa_udc *udc, struct usb_gadget_driver *driver) for (i = 0; i < NR_USB_ENDPOINTS; i++) pxa_ep_disable(&udc->udc_usb_ep[i].usb_ep); - - if (driver) - driver->disconnect(&udc->gadget); } /** - * usb_gadget_unregister_driver - Unregister the gadget driver + * pxa27x_udc_stop - Unregister the gadget driver * @driver: gadget driver * * Returns 0 if no error, -ENODEV, -EINVAL otherwise */ -int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) +static int pxa27x_udc_stop(struct usb_gadget *g, + struct usb_gadget_driver *driver) { - struct pxa_udc *udc = the_controller; - - if (!udc) - return -ENODEV; - if (!driver || driver != udc->driver || !driver->unbind) - return -EINVAL; + struct pxa_udc *udc = to_pxa(g); stop_activity(udc, driver); udc_disable(udc); dplus_pullup(udc, 0); - driver->unbind(&udc->gadget); udc->driver = NULL; - device_del(&udc->gadget.dev); - dev_info(udc->dev, "unregistered gadget driver '%s'\n", - driver->driver.name); - - if (udc->transceiver) - return otg_set_peripheral(udc->transceiver, NULL); + if (!IS_ERR_OR_NULL(udc->transceiver)) + return otg_set_peripheral(udc->transceiver->otg, NULL); return 0; } -EXPORT_SYMBOL(usb_gadget_unregister_driver); /** * handle_ep0_ctrl_req - handle control endpoint control request @@ -1907,8 +1890,10 @@ static void handle_ep0_ctrl_req(struct pxa_udc *udc, } u; int i; int have_extrabytes = 0; + unsigned long flags; nuke(ep, -EPROTO); + spin_lock_irqsave(&ep->lock, flags); /* * In the PXA320 manual, in the section about Back-to-Back setup @@ -1947,10 +1932,13 @@ static void handle_ep0_ctrl_req(struct pxa_udc *udc, /* Tell UDC to enter Data Stage */ ep_write_UDCCSR(ep, UDCCSR0_SA | UDCCSR0_OPC); + spin_unlock_irqrestore(&ep->lock, flags); i = udc->driver->setup(&udc->gadget, &u.r); + spin_lock_irqsave(&ep->lock, flags); if (i < 0) goto stall; out: + spin_unlock_irqrestore(&ep->lock, flags); return; stall: ep_dbg(ep, "protocol STALL, udccsr0=%03x err %d\n", @@ -2055,13 +2043,13 @@ static void handle_ep0(struct pxa_udc *udc, int fifo_irq, int opc_irq) if (req && !ep_is_full(ep)) completed = write_ep0_fifo(ep, req); if (completed) - ep0_end_in_req(ep, req); + ep0_end_in_req(ep, req, NULL); break; case OUT_DATA_STAGE: /* SET_DESCRIPTOR */ if (epout_has_pkt(ep) && req) completed = read_ep0_fifo(ep, req); if (completed) - ep0_end_out_req(ep, req); + ep0_end_out_req(ep, req, NULL); break; case STALL: ep_write_UDCCSR(ep, UDCCSR0_FST); @@ -2091,7 +2079,7 @@ static void handle_ep0(struct pxa_udc *udc, int fifo_irq, int opc_irq) * Tries to transfer all pending request data into the endpoint and/or * transfer all pending data in the endpoint into usb requests. * - * Is always called when in_interrupt() or with ep->lock held. + * Is always called when in_interrupt() and with ep->lock released. */ static void handle_ep(struct pxa_ep *ep) { @@ -2100,10 +2088,17 @@ static void handle_ep(struct pxa_ep *ep) u32 udccsr; int is_in = ep->dir_in; int loop = 0; + unsigned long flags; + + spin_lock_irqsave(&ep->lock, flags); + if (ep->in_handle_ep) + goto recursion_detected; + ep->in_handle_ep = 1; do { completed = 0; udccsr = udc_ep_readl(ep, UDCCSR); + if (likely(!list_empty(&ep->queue))) req = list_entry(ep->queue.next, struct pxa27x_request, queue); @@ -2122,15 +2117,22 @@ static void handle_ep(struct pxa_ep *ep) if (unlikely(is_in)) { if (likely(!ep_is_full(ep))) completed = write_fifo(ep, req); - if (completed) - ep_end_in_req(ep, req); } else { if (likely(epout_has_pkt(ep))) completed = read_fifo(ep, req); - if (completed) - ep_end_out_req(ep, req); + } + + if (completed) { + if (is_in) + ep_end_in_req(ep, req, &flags); + else + ep_end_out_req(ep, req, &flags); } } while (completed); + + ep->in_handle_ep = 0; +recursion_detected: + spin_unlock_irqrestore(&ep->lock, flags); } /** @@ -2218,9 +2220,13 @@ static void irq_handle_data(int irq, struct pxa_udc *udc) continue; udc_writel(udc, UDCISR0, UDCISR_INT(i, UDCISR_INT_MASK)); - ep = &udc->pxa_ep[i]; - ep->stats.irqs++; - handle_ep(ep); + + WARN_ON(i >= ARRAY_SIZE(udc->pxa_ep)); + if (i < ARRAY_SIZE(udc->pxa_ep)) { + ep = &udc->pxa_ep[i]; + ep->stats.irqs++; + handle_ep(ep); + } } for (i = 16; udcisr1 != 0 && i < 24; udcisr1 >>= 2, i++) { @@ -2228,9 +2234,12 @@ static void irq_handle_data(int irq, struct pxa_udc *udc) if (!(udcisr1 & UDCISR_INT_MASK)) continue; - ep = &udc->pxa_ep[i]; - ep->stats.irqs++; - handle_ep(ep); + WARN_ON(i >= ARRAY_SIZE(udc->pxa_ep)); + if (i < ARRAY_SIZE(udc->pxa_ep)) { + ep = &udc->pxa_ep[i]; + ep->stats.irqs++; + handle_ep(ep); + } } } @@ -2402,7 +2411,7 @@ static struct pxa_udc memory = { * Perform basic init : allocates udc clock, creates sysfs files, requests * irq. */ -static int __init pxa_udc_probe(struct platform_device *pdev) +static int pxa_udc_probe(struct platform_device *pdev) { struct resource *regs; struct pxa_udc *udc = &memory; @@ -2416,8 +2425,8 @@ static int __init pxa_udc_probe(struct platform_device *pdev) return udc->irq; udc->dev = &pdev->dev; - udc->mach = pdev->dev.platform_data; - udc->transceiver = otg_get_transceiver(); + udc->mach = dev_get_platdata(&pdev->dev); + udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); gpio = udc->mach->gpio_pullup; if (gpio_is_valid(gpio)) { @@ -2439,15 +2448,12 @@ static int __init pxa_udc_probe(struct platform_device *pdev) } retval = -ENOMEM; - udc->regs = ioremap(regs->start, regs->end - regs->start + 1); + udc->regs = ioremap(regs->start, resource_size(regs)); if (!udc->regs) { dev_err(&pdev->dev, "Unable to map UDC I/O memory\n"); goto err_map; } - device_initialize(&udc->gadget.dev); - udc->gadget.dev.parent = &pdev->dev; - udc->gadget.dev.dma_mask = NULL; udc->vbus_sensed = 0; the_controller = udc; @@ -2460,12 +2466,20 @@ static int __init pxa_udc_probe(struct platform_device *pdev) IRQF_SHARED, driver_name, udc); if (retval != 0) { dev_err(udc->dev, "%s: can't get irq %i, err %d\n", - driver_name, IRQ_USB, retval); + driver_name, udc->irq, retval); goto err_irq; } + retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget); + if (retval) + goto err_add_udc; + pxa_init_debugfs(udc); + return 0; + +err_add_udc: + free_irq(udc->irq, udc); err_irq: iounmap(udc->regs); err_map: @@ -2479,21 +2493,21 @@ err_clk: * pxa_udc_remove - removes the udc device driver * @_dev: platform device */ -static int __exit pxa_udc_remove(struct platform_device *_dev) +static int pxa_udc_remove(struct platform_device *_dev) { struct pxa_udc *udc = platform_get_drvdata(_dev); int gpio = udc->mach->gpio_pullup; + usb_del_gadget_udc(&udc->gadget); usb_gadget_unregister_driver(udc->driver); free_irq(udc->irq, udc); pxa_cleanup_debugfs(udc); if (gpio_is_valid(gpio)) gpio_free(gpio); - otg_put_transceiver(udc->transceiver); + usb_put_phy(udc->transceiver); udc->transceiver = NULL; - platform_set_drvdata(_dev, NULL); the_controller = NULL; clk_put(udc->clk); iounmap(udc->regs); @@ -2509,7 +2523,7 @@ static void pxa_udc_shutdown(struct platform_device *_dev) udc_disable(udc); } -#ifdef CONFIG_CPU_PXA27x +#ifdef CONFIG_PXA27x extern void pxa27x_clear_otgph(void); #else #define pxa27x_clear_otgph() do {} while (0) @@ -2596,7 +2610,8 @@ static struct platform_driver udc_driver = { .name = "pxa27x-udc", .owner = THIS_MODULE, }, - .remove = __exit_p(pxa_udc_remove), + .probe = pxa_udc_probe, + .remove = pxa_udc_remove, .shutdown = pxa_udc_shutdown, #ifdef CONFIG_PM .suspend = pxa_udc_suspend, @@ -2604,22 +2619,7 @@ static struct platform_driver udc_driver = { #endif }; -static int __init udc_init(void) -{ - if (!cpu_is_pxa27x() && !cpu_is_pxa3xx()) - return -ENODEV; - - printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION); - return platform_driver_probe(&udc_driver, pxa_udc_probe); -} -module_init(udc_init); - - -static void __exit udc_exit(void) -{ - platform_driver_unregister(&udc_driver); -} -module_exit(udc_exit); +module_platform_driver(udc_driver); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR("Robert Jarzmik"); |
