From 338edabcd879320f0f86cc701161b95277be6b5d Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Fri, 18 May 2012 14:33:46 +0530 Subject: usb: s3c-hsotg: Use devm_* functions in s3c-hsotg.c file devm_* functions are used to replace kzalloc, request_mem_region, ioremap and request_irq functions in probe call. With the usage of devm_* functions explicit freeing and unmapping is not required. Signed-off-by: Sachin Kamat Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 51 +++++++++--------------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) (limited to 'drivers/usb/gadget/s3c-hsotg.c') diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index f4abb0ed9872..d37585105bb4 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -136,7 +136,6 @@ struct s3c_hsotg_ep { * @driver: USB gadget driver * @plat: The platform specific configuration data. * @regs: The memory area mapped for accessing registers. - * @regs_res: The resource that was allocated when claiming register space. * @irq: The IRQ number we are using * @supplies: Definition of USB power supplies * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos. @@ -158,7 +157,6 @@ struct s3c_hsotg { struct s3c_hsotg_plat *plat; void __iomem *regs; - struct resource *regs_res; int irq; struct clk *clk; @@ -3477,7 +3475,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) return -EINVAL; } - hsotg = kzalloc(sizeof(struct s3c_hsotg), GFP_KERNEL); + hsotg = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsotg), GFP_KERNEL); if (!hsotg) { dev_err(dev, "cannot get memory\n"); return -ENOMEM; @@ -3489,46 +3487,33 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) hsotg->clk = clk_get(&pdev->dev, "otg"); if (IS_ERR(hsotg->clk)) { dev_err(dev, "cannot get otg clock\n"); - ret = PTR_ERR(hsotg->clk); - goto err_mem; + return PTR_ERR(hsotg->clk); } platform_set_drvdata(pdev, hsotg); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "cannot find register resource 0\n"); - ret = -EINVAL; - goto err_clk; - } - - hsotg->regs_res = request_mem_region(res->start, resource_size(res), - dev_name(dev)); - if (!hsotg->regs_res) { - dev_err(dev, "cannot reserve registers\n"); - ret = -ENOENT; - goto err_clk; - } - hsotg->regs = ioremap(res->start, resource_size(res)); + hsotg->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hsotg->regs) { dev_err(dev, "cannot map registers\n"); ret = -ENXIO; - goto err_regs_res; + goto err_clk; } ret = platform_get_irq(pdev, 0); if (ret < 0) { dev_err(dev, "cannot find IRQ\n"); - goto err_regs; + goto err_clk; } hsotg->irq = ret; - ret = request_irq(ret, s3c_hsotg_irq, 0, dev_name(dev), hsotg); + ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0, + dev_name(dev), hsotg); if (ret < 0) { dev_err(dev, "cannot claim IRQ\n"); - goto err_regs; + goto err_clk; } dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq); @@ -3558,7 +3543,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) hsotg->supplies); if (ret) { dev_err(dev, "failed to request supplies: %d\n", ret); - goto err_irq; + goto err_clk; } ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), @@ -3642,19 +3627,11 @@ err_ep_mem: err_supplies: s3c_hsotg_phy_disable(hsotg); regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); -err_irq: - free_irq(hsotg->irq, hsotg); -err_regs: - iounmap(hsotg->regs); - -err_regs_res: - release_resource(hsotg->regs_res); - kfree(hsotg->regs_res); + err_clk: clk_disable_unprepare(hsotg->clk); clk_put(hsotg->clk); -err_mem: - kfree(hsotg); + return ret; } @@ -3675,12 +3652,6 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev) usb_gadget_unregister_driver(hsotg->driver); } - free_irq(hsotg->irq, hsotg); - iounmap(hsotg->regs); - - release_resource(hsotg->regs_res); - kfree(hsotg->regs_res); - s3c_hsotg_phy_disable(hsotg); regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); -- cgit v1.2.2 From 22258f4906aa87e0c0debcad22cb292453e2ebfb Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Thu, 14 Jun 2012 10:02:24 +0200 Subject: usb: hsotg: samsung: Replace endpoint specific locks with a global lock The endpoint specific locks are replaced with a global lock. This is crucial for running s3c-hsotg driver on a SMP SoC. Signed-off-by: Lukasz Majewski Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 54 ++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 26 deletions(-) (limited to 'drivers/usb/gadget/s3c-hsotg.c') diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index d37585105bb4..b10791282f15 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -112,7 +112,6 @@ struct s3c_hsotg_ep { struct s3c_hsotg_req *req; struct dentry *debugfs; - spinlock_t lock; unsigned long total_data; unsigned int size_loaded; @@ -156,6 +155,8 @@ struct s3c_hsotg { struct usb_gadget_driver *driver; struct s3c_hsotg_plat *plat; + spinlock_t lock; + void __iomem *regs; int irq; struct clk *clk; @@ -901,6 +902,8 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, ep->name, req, req->length, req->buf, req->no_interrupt, req->zero, req->short_not_ok); + spin_lock_irqsave(&hs->lock, irqflags); + /* initialise status of the request */ INIT_LIST_HEAD(&hs_req->queue); req->actual = 0; @@ -913,15 +916,13 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, return ret; } - spin_lock_irqsave(&hs_ep->lock, irqflags); - first = list_empty(&hs_ep->queue); list_add_tail(&hs_req->queue, &hs_ep->queue); if (first) s3c_hsotg_start_req(hs, hs_ep, hs_req, false); - spin_unlock_irqrestore(&hs_ep->lock, irqflags); + spin_unlock_irqrestore(&hs->lock, irqflags); return 0; } @@ -1381,9 +1382,9 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, */ if (hs_req->req.complete) { - spin_unlock(&hs_ep->lock); + spin_unlock(&hsotg->lock); hs_req->req.complete(&hs_ep->ep, &hs_req->req); - spin_lock(&hs_ep->lock); + spin_lock(&hsotg->lock); } /* @@ -1418,9 +1419,9 @@ static void s3c_hsotg_complete_request_lock(struct s3c_hsotg *hsotg, { unsigned long flags; - spin_lock_irqsave(&hs_ep->lock, flags); + spin_lock_irqsave(&hsotg->lock, flags); s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result); - spin_unlock_irqrestore(&hs_ep->lock, flags); + spin_unlock_irqrestore(&hsotg->lock, flags); } /** @@ -1442,6 +1443,8 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) int max_req; int read_ptr; + spin_lock(&hsotg->lock); + if (!hs_req) { u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx)); int ptr; @@ -1454,11 +1457,10 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) for (ptr = 0; ptr < size; ptr += 4) (void)readl(fifo); + spin_unlock(&hsotg->lock); return; } - spin_lock(&hs_ep->lock); - to_read = size; read_ptr = hs_req->req.actual; max_req = hs_req->req.length - read_ptr; @@ -1486,7 +1488,7 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) */ readsl(fifo, hs_req->req.buf + read_ptr, to_read); - spin_unlock(&hs_ep->lock); + spin_unlock(&hsotg->lock); } /** @@ -2123,7 +2125,7 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, struct s3c_hsotg_req *req, *treq; unsigned long flags; - spin_lock_irqsave(&ep->lock, flags); + spin_lock_irqsave(&hsotg->lock, flags); list_for_each_entry_safe(req, treq, &ep->queue, queue) { /* @@ -2138,7 +2140,7 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, result); } - spin_unlock_irqrestore(&ep->lock, flags); + spin_unlock_irqrestore(&hsotg->lock, flags); } #define call_gadget(_hs, _entry) \ @@ -2602,7 +2604,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n", __func__, epctrl, epctrl_reg); - spin_lock_irqsave(&hs_ep->lock, flags); + spin_lock_irqsave(&hsotg->lock, flags); epctrl &= ~(DxEPCTL_EPType_MASK | DxEPCTL_MPS_MASK); epctrl |= DxEPCTL_MPS(mps); @@ -2681,7 +2683,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1); out: - spin_unlock_irqrestore(&hs_ep->lock, flags); + spin_unlock_irqrestore(&hsotg->lock, flags); return ret; } @@ -2711,7 +2713,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) /* terminate all requests with shutdown */ kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false); - spin_lock_irqsave(&hs_ep->lock, flags); + spin_lock_irqsave(&hsotg->lock, flags); ctrl = readl(hsotg->regs + epctrl_reg); ctrl &= ~DxEPCTL_EPEna; @@ -2724,7 +2726,7 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) /* disable endpoint interrupts */ s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0); - spin_unlock_irqrestore(&hs_ep->lock, flags); + spin_unlock_irqrestore(&hsotg->lock, flags); return 0; } @@ -2759,15 +2761,15 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) dev_info(hs->dev, "ep_dequeue(%p,%p)\n", ep, req); - spin_lock_irqsave(&hs_ep->lock, flags); + spin_lock_irqsave(&hs->lock, flags); if (!on_list(hs_ep, hs_req)) { - spin_unlock_irqrestore(&hs_ep->lock, flags); + spin_unlock_irqrestore(&hs->lock, flags); return -EINVAL; } s3c_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET); - spin_unlock_irqrestore(&hs_ep->lock, flags); + spin_unlock_irqrestore(&hs->lock, flags); return 0; } @@ -2789,7 +2791,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value); - spin_lock_irqsave(&hs_ep->lock, irqflags); + spin_lock_irqsave(&hs->lock, irqflags); /* write both IN and OUT control registers */ @@ -2825,7 +2827,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) writel(epctl, hs->regs + epreg); - spin_unlock_irqrestore(&hs_ep->lock, irqflags); + spin_unlock_irqrestore(&hs->lock, irqflags); return 0; } @@ -3061,8 +3063,6 @@ static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg, INIT_LIST_HEAD(&hs_ep->queue); INIT_LIST_HEAD(&hs_ep->ep.ep_list); - spin_lock_init(&hs_ep->lock); - /* add to the list of endpoints known by the gadget driver */ if (epnum) list_add_tail(&hs_ep->ep.ep_list, &hsotg->gadget.ep_list); @@ -3340,7 +3340,7 @@ static int ep_show(struct seq_file *seq, void *v) seq_printf(seq, "request list (%p,%p):\n", ep->queue.next, ep->queue.prev); - spin_lock_irqsave(&ep->lock, flags); + spin_lock_irqsave(&hsotg->lock, flags); list_for_each_entry(req, &ep->queue, queue) { if (--show_limit < 0) { @@ -3355,7 +3355,7 @@ static int ep_show(struct seq_file *seq, void *v) req->req.actual, req->req.status); } - spin_unlock_irqrestore(&ep->lock, flags); + spin_unlock_irqrestore(&hsotg->lock, flags); return 0; } @@ -3507,6 +3507,8 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) goto err_clk; } + spin_lock_init(&hsotg->lock); + hsotg->irq = ret; ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0, -- cgit v1.2.2 From 2b19a52cc8a31ede990323d46a7faeeeba76bb8f Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Thu, 14 Jun 2012 10:02:25 +0200 Subject: usb: hsotg: samsung: Protect the udc_stop routine with spinlock Signed-off-by: Lukasz Majewski Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/usb/gadget/s3c-hsotg.c') diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index b10791282f15..ee1fe2b8b07f 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2988,6 +2988,7 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { struct s3c_hsotg *hsotg = to_hsotg(gadget); + unsigned long flags = 0; int ep; if (!hsotg) @@ -3000,6 +3001,8 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, for (ep = 0; ep < hsotg->num_of_eps; ep++) s3c_hsotg_ep_disable(&hsotg->eps[ep].ep); + spin_lock_irqsave(&hsotg->lock, flags); + s3c_hsotg_phy_disable(hsotg); regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); @@ -3007,6 +3010,8 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, hsotg->gadget.speed = USB_SPEED_UNKNOWN; hsotg->gadget.dev.driver = NULL; + spin_unlock_irqrestore(&hsotg->lock, flags); + dev_info(hsotg->dev, "unregistered gadget driver '%s'\n", driver->driver.name); -- cgit v1.2.2 From 5ad1d3160973c588db806072968d7a2a93cb2a80 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Thu, 14 Jun 2012 10:02:26 +0200 Subject: usb: hsotg: samsung: smp Provide *_lock functions abstraction layer for SMP SoCs For SMP processors the spin_lock_irqsave is _only_ able to disable interrupt on a core on which it is executed. Therefore there may be a situation when other cores raise s3c-hsotg IRQ. Then there are several places where critical sections can be overwritten. To protect the above thread, a spin_lock in the interrupt handler has been added. Due to coherent memory view (especially L1 cache) the spin lock variable control access to IRQ handler only for one CPU core. In this way serialization to access this driver is provided and hence several spin_lock_* routines could be removed from IRQ handler's related functions. The complete_request_lock function has been removed since all its calls are performed from interrupt (spin lock protected) context. Signed-off-by: Lukasz Majewski Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 97 +++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 49 deletions(-) (limited to 'drivers/usb/gadget/s3c-hsotg.c') diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index ee1fe2b8b07f..d208c46341d7 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -895,15 +895,12 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, struct s3c_hsotg_req *hs_req = our_req(req); struct s3c_hsotg_ep *hs_ep = our_ep(ep); struct s3c_hsotg *hs = hs_ep->parent; - unsigned long irqflags; bool first; dev_dbg(hs->dev, "%s: req %p: %d@%p, noi=%d, zero=%d, snok=%d\n", ep->name, req, req->length, req->buf, req->no_interrupt, req->zero, req->short_not_ok); - spin_lock_irqsave(&hs->lock, irqflags); - /* initialise status of the request */ INIT_LIST_HEAD(&hs_req->queue); req->actual = 0; @@ -922,11 +919,24 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, if (first) s3c_hsotg_start_req(hs, hs_ep, hs_req, false); - spin_unlock_irqrestore(&hs->lock, irqflags); - return 0; } +static int s3c_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req, + gfp_t gfp_flags) +{ + struct s3c_hsotg_ep *hs_ep = our_ep(ep); + struct s3c_hsotg *hs = hs_ep->parent; + unsigned long flags = 0; + int ret = 0; + + spin_lock_irqsave(&hs->lock, flags); + ret = s3c_hsotg_ep_queue(ep, req, gfp_flags); + spin_unlock_irqrestore(&hs->lock, flags); + + return ret; +} + static void s3c_hsotg_ep_free_request(struct usb_ep *ep, struct usb_request *req) { @@ -1402,28 +1412,6 @@ static void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, } } -/** - * s3c_hsotg_complete_request_lock - complete a request given to us (locked) - * @hsotg: The device state. - * @hs_ep: The endpoint the request was on. - * @hs_req: The request to complete. - * @result: The result code (0 => Ok, otherwise errno) - * - * See s3c_hsotg_complete_request(), but called with the endpoint's - * lock held. - */ -static void s3c_hsotg_complete_request_lock(struct s3c_hsotg *hsotg, - struct s3c_hsotg_ep *hs_ep, - struct s3c_hsotg_req *hs_req, - int result) -{ - unsigned long flags; - - spin_lock_irqsave(&hsotg->lock, flags); - s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result); - spin_unlock_irqrestore(&hsotg->lock, flags); -} - /** * s3c_hsotg_rx_data - receive data from the FIFO for an endpoint * @hsotg: The device state. @@ -1443,7 +1431,6 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) int max_req; int read_ptr; - spin_lock(&hsotg->lock); if (!hs_req) { u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx)); @@ -1457,7 +1444,6 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) for (ptr = 0; ptr < size; ptr += 4) (void)readl(fifo); - spin_unlock(&hsotg->lock); return; } @@ -1487,8 +1473,6 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) * alignment of the data. */ readsl(fifo, hs_req->req.buf + read_ptr, to_read); - - spin_unlock(&hsotg->lock); } /** @@ -1609,7 +1593,7 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, s3c_hsotg_send_zlp(hsotg, hs_req); } - s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, result); + s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result); } /** @@ -1864,7 +1848,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, /* Finish ZLP handling for IN EP0 transactions */ if (hsotg->eps[0].sent_zlp) { dev_dbg(hsotg->dev, "zlp packet received\n"); - s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0); + s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); return; } @@ -1915,7 +1899,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__); s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true); } else - s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0); + s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0); } /** @@ -2123,9 +2107,6 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, int result, bool force) { struct s3c_hsotg_req *req, *treq; - unsigned long flags; - - spin_lock_irqsave(&hsotg->lock, flags); list_for_each_entry_safe(req, treq, &ep->queue, queue) { /* @@ -2139,14 +2120,15 @@ static void kill_all_requests(struct s3c_hsotg *hsotg, s3c_hsotg_complete_request(hsotg, ep, req, result); } - - spin_unlock_irqrestore(&hsotg->lock, flags); } #define call_gadget(_hs, _entry) \ if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN && \ - (_hs)->driver && (_hs)->driver->_entry) \ - (_hs)->driver->_entry(&(_hs)->gadget); + (_hs)->driver && (_hs)->driver->_entry) { \ + spin_unlock(&_hs->lock); \ + (_hs)->driver->_entry(&(_hs)->gadget); \ + spin_lock(&_hs->lock); \ + } /** * s3c_hsotg_disconnect - disconnect service @@ -2388,6 +2370,7 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw) u32 gintsts; u32 gintmsk; + spin_lock(&hsotg->lock); irq_retry: gintsts = readl(hsotg->regs + GINTSTS); gintmsk = readl(hsotg->regs + GINTMSK); @@ -2557,6 +2540,8 @@ irq_retry: if (gintsts & IRQ_RETRY_MASK && --retry_count > 0) goto irq_retry; + spin_unlock(&hsotg->lock); + return IRQ_HANDLED; } @@ -2710,10 +2695,10 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep) epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); + spin_lock_irqsave(&hsotg->lock, flags); /* terminate all requests with shutdown */ kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false); - spin_lock_irqsave(&hsotg->lock, flags); ctrl = readl(hsotg->regs + epctrl_reg); ctrl &= ~DxEPCTL_EPEna; @@ -2784,15 +2769,12 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) struct s3c_hsotg_ep *hs_ep = our_ep(ep); struct s3c_hsotg *hs = hs_ep->parent; int index = hs_ep->index; - unsigned long irqflags; u32 epreg; u32 epctl; u32 xfertype; dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value); - spin_lock_irqsave(&hs->lock, irqflags); - /* write both IN and OUT control registers */ epreg = DIEPCTL(index); @@ -2827,19 +2809,36 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) writel(epctl, hs->regs + epreg); - spin_unlock_irqrestore(&hs->lock, irqflags); - return 0; } +/** + * s3c_hsotg_ep_sethalt_lock - set halt on a given endpoint with lock held + * @ep: The endpoint to set halt. + * @value: Set or unset the halt. + */ +static int s3c_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value) +{ + struct s3c_hsotg_ep *hs_ep = our_ep(ep); + struct s3c_hsotg *hs = hs_ep->parent; + unsigned long flags = 0; + int ret = 0; + + spin_lock_irqsave(&hs->lock, flags); + ret = s3c_hsotg_ep_sethalt(ep, value); + spin_unlock_irqrestore(&hs->lock, flags); + + return ret; +} + static struct usb_ep_ops s3c_hsotg_ep_ops = { .enable = s3c_hsotg_ep_enable, .disable = s3c_hsotg_ep_disable, .alloc_request = s3c_hsotg_ep_alloc_request, .free_request = s3c_hsotg_ep_free_request, - .queue = s3c_hsotg_ep_queue, + .queue = s3c_hsotg_ep_queue_lock, .dequeue = s3c_hsotg_ep_dequeue, - .set_halt = s3c_hsotg_ep_sethalt, + .set_halt = s3c_hsotg_ep_sethalt_lock, /* note, don't believe we have any call for the fifo routines */ }; -- cgit v1.2.2 From a188b6897e3dca82dd6f5beceabf1fc62b9786d9 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Fri, 22 Jun 2012 09:29:56 +0200 Subject: usb: gadget: hsotg: pullup method implementation for s3c-hsotg UDC driver This commit adds pullup method implementation for UDC s3c-hsotg driver. It is needed for e.g. CCG - Configurable Composite Gadget, when user space configuration change request device disconnection from USB bus (done via calling usb_gadget_connect/disconnect, which calls UDC's pullup method). Implementation of pullup method has caused removal of phy_enable and core_init methods from udc_start to pullup. Signed-off-by: Lukasz Majewski Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'drivers/usb/gadget/s3c-hsotg.c') diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index d208c46341d7..75a28e6d3761 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2963,9 +2963,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget, goto err; } - s3c_hsotg_phy_enable(hsotg); - - s3c_hsotg_core_init(hsotg); hsotg->last_rst = jiffies; dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name); return 0; @@ -3028,10 +3025,40 @@ static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget) return s3c_hsotg_read_frameno(to_hsotg(gadget)); } +/** + * s3c_hsotg_pullup - connect/disconnect the USB PHY + * @gadget: The usb gadget state + * @is_on: Current state of the USB PHY + * + * Connect/Disconnect the USB PHY pullup + */ +static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on) +{ + struct s3c_hsotg *hsotg = to_hsotg(gadget); + unsigned long flags = 0; + + dev_dbg(hsotg->dev, "%s: is_in: %d\n", __func__, is_on); + + spin_lock_irqsave(&hsotg->lock, flags); + if (is_on) { + s3c_hsotg_phy_enable(hsotg); + s3c_hsotg_core_init(hsotg); + } else { + s3c_hsotg_disconnect(hsotg); + s3c_hsotg_phy_disable(hsotg); + } + + hsotg->gadget.speed = USB_SPEED_UNKNOWN; + spin_unlock_irqrestore(&hsotg->lock, flags); + + return 0; +} + static struct usb_gadget_ops s3c_hsotg_gadget_ops = { .get_frame = s3c_hsotg_gadget_getframe, .udc_start = s3c_hsotg_udc_start, .udc_stop = s3c_hsotg_udc_stop, + .pullup = s3c_hsotg_pullup, }; /** -- cgit v1.2.2 From 7d7b22928b900bcb0f8885a95846e5125a757e76 Mon Sep 17 00:00:00 2001 From: Alexandre Pereira da Silva Date: Tue, 26 Jun 2012 11:27:10 -0300 Subject: usb: gadget: s3c-hsotg: Propagate devicetree to gadget drivers Fill dev.of_node of gadget drivers, so they can use devicetree Signed-off-by: Alexandre Pereira da Silva Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb/gadget/s3c-hsotg.c') diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 75a28e6d3761..b13e0bb5f5b8 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2953,6 +2953,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget, driver->driver.bus = NULL; hsotg->driver = driver; hsotg->gadget.dev.driver = &driver->driver; + hsotg->gadget.dev.of_node = hsotg->dev->of_node; hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask; hsotg->gadget.speed = USB_SPEED_UNKNOWN; -- cgit v1.2.2