aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/renesas_usbhs
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-03-01 12:20:28 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-03-01 12:20:28 -0500
commitf9b0f5170918695891f42645737682ccb452ee13 (patch)
tree75eaab0ff54f8aadaa6375df140cc9d685f78d95 /drivers/usb/renesas_usbhs
parent8062d94a545457a83d5291bd62c3bfd14200bba0 (diff)
parent6440093f5eae9842feb06e40d41c3bd569b6b461 (diff)
Merge tag 'gadget-for-v3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
USB: Gadget: changes for 3.4 This merge is rather big. Here's what it contains: For am5536udc we have just simple coding style fixes. Nothing that has any potential to cause any issues going forward. With mv_udc, there's only one single change removing an unneeded NULL check. at91_udc also only saw a single change this merge window, and that's only removing a duplicated header. The Renesas controller has a few more involved changes. Support for SUDMAC was added, there's now a special handling of IRQ resources for when the IRQ line is shared between Renesas controller and SUDMAC, we also had a bug fix where Renesas controller would sleep in atomic context while doing DMA transfers from a tasklet. There were also a set of minor cleanups. The FSL UDC also had a scheduling in atomic context bug fix, but that's all. Thanks to Sebastian, the dummy_hcd now works better than ever with support for scatterlists and streams. Sebastian also added SuperSpeed descriptors to the serial gadgets. The highlight on this merge is the addition of a generic API for mapping and unmapping usb_requests. This will avoid code duplication on all UDC controllers and also kills all the defines for DMA_ADDR_INVALID which UDC controllers sprinkled around. A few of the UDC controllers were already converted to use this new API. Conflicts: drivers/usb/dwc3/gadget.c
Diffstat (limited to 'drivers/usb/renesas_usbhs')
-rw-r--r--drivers/usb/renesas_usbhs/common.c11
-rw-r--r--drivers/usb/renesas_usbhs/common.h1
-rw-r--r--drivers/usb/renesas_usbhs/fifo.c29
-rw-r--r--drivers/usb/renesas_usbhs/fifo.h3
-rw-r--r--drivers/usb/renesas_usbhs/mod.c2
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c79
6 files changed, 46 insertions, 79 deletions
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index e9a5b1d2615e..a165490bae48 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -413,8 +413,7 @@ static int usbhs_probe(struct platform_device *pdev)
413 struct renesas_usbhs_platform_info *info = pdev->dev.platform_data; 413 struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
414 struct renesas_usbhs_driver_callback *dfunc; 414 struct renesas_usbhs_driver_callback *dfunc;
415 struct usbhs_priv *priv; 415 struct usbhs_priv *priv;
416 struct resource *res; 416 struct resource *res, *irq_res;
417 unsigned int irq;
418 int ret; 417 int ret;
419 418
420 /* check platform information */ 419 /* check platform information */
@@ -426,8 +425,8 @@ static int usbhs_probe(struct platform_device *pdev)
426 425
427 /* platform data */ 426 /* platform data */
428 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 427 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
429 irq = platform_get_irq(pdev, 0); 428 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
430 if (!res || (int)irq <= 0) { 429 if (!res || !irq_res) {
431 dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n"); 430 dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n");
432 return -ENODEV; 431 return -ENODEV;
433 } 432 }
@@ -476,7 +475,9 @@ static int usbhs_probe(struct platform_device *pdev)
476 /* 475 /*
477 * priv settings 476 * priv settings
478 */ 477 */
479 priv->irq = irq; 478 priv->irq = irq_res->start;
479 if (irq_res->flags & IORESOURCE_IRQ_SHAREABLE)
480 priv->irqflags = IRQF_SHARED;
480 priv->pdev = pdev; 481 priv->pdev = pdev;
481 INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug); 482 INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug);
482 spin_lock_init(usbhs_priv_to_lock(priv)); 483 spin_lock_init(usbhs_priv_to_lock(priv));
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h
index d79b3e27db95..3f3ccd358753 100644
--- a/drivers/usb/renesas_usbhs/common.h
+++ b/drivers/usb/renesas_usbhs/common.h
@@ -242,6 +242,7 @@ struct usbhs_priv {
242 242
243 void __iomem *base; 243 void __iomem *base;
244 unsigned int irq; 244 unsigned int irq;
245 unsigned long irqflags;
245 246
246 struct renesas_usbhs_platform_callback pfunc; 247 struct renesas_usbhs_platform_callback pfunc;
247 struct renesas_usbhs_driver_param dparam; 248 struct renesas_usbhs_driver_param dparam;
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 72339bd6fcab..3648c82a17fe 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -23,6 +23,7 @@
23#define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo)) 23#define usbhsf_get_cfifo(p) (&((p)->fifo_info.cfifo))
24#define usbhsf_get_d0fifo(p) (&((p)->fifo_info.d0fifo)) 24#define usbhsf_get_d0fifo(p) (&((p)->fifo_info.d0fifo))
25#define usbhsf_get_d1fifo(p) (&((p)->fifo_info.d1fifo)) 25#define usbhsf_get_d1fifo(p) (&((p)->fifo_info.d1fifo))
26#define usbhsf_is_cfifo(p, f) (usbhsf_get_cfifo(p) == f)
26 27
27#define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */ 28#define usbhsf_fifo_is_busy(f) ((f)->pipe) /* see usbhs_pipe_select_fifo */
28 29
@@ -75,8 +76,7 @@ void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt,
75 pipe->handler = &usbhsf_null_handler; 76 pipe->handler = &usbhsf_null_handler;
76 } 77 }
77 78
78 list_del_init(&pkt->node); 79 list_move_tail(&pkt->node, &pipe->list);
79 list_add_tail(&pkt->node, &pipe->list);
80 80
81 /* 81 /*
82 * each pkt must hold own handler. 82 * each pkt must hold own handler.
@@ -106,7 +106,7 @@ static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe)
106 if (list_empty(&pipe->list)) 106 if (list_empty(&pipe->list))
107 return NULL; 107 return NULL;
108 108
109 return list_entry(pipe->list.next, struct usbhs_pkt, node); 109 return list_first_entry(&pipe->list, struct usbhs_pkt, node);
110} 110}
111 111
112struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) 112struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt)
@@ -305,7 +305,10 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe,
305 } 305 }
306 306
307 /* "base" will be used below */ 307 /* "base" will be used below */
308 usbhs_write(priv, fifo->sel, base | MBW_32); 308 if (usbhs_get_dparam(priv, has_sudmac) && !usbhsf_is_cfifo(priv, fifo))
309 usbhs_write(priv, fifo->sel, base);
310 else
311 usbhs_write(priv, fifo->sel, base | MBW_32);
309 312
310 /* check ISEL and CURPIPE value */ 313 /* check ISEL and CURPIPE value */
311 while (timeout--) { 314 while (timeout--) {
@@ -762,9 +765,9 @@ static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
762} 765}
763 766
764static void usbhsf_dma_complete(void *arg); 767static void usbhsf_dma_complete(void *arg);
765static void usbhsf_dma_prepare_tasklet(unsigned long data) 768static void xfer_work(struct work_struct *work)
766{ 769{
767 struct usbhs_pkt *pkt = (struct usbhs_pkt *)data; 770 struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work);
768 struct usbhs_pipe *pipe = pkt->pipe; 771 struct usbhs_pipe *pipe = pkt->pipe;
769 struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe); 772 struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe);
770 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); 773 struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
@@ -844,11 +847,8 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
844 847
845 pkt->trans = len; 848 pkt->trans = len;
846 849
847 tasklet_init(&fifo->tasklet, 850 INIT_WORK(&pkt->work, xfer_work);
848 usbhsf_dma_prepare_tasklet, 851 schedule_work(&pkt->work);
849 (unsigned long)pkt);
850
851 tasklet_schedule(&fifo->tasklet);
852 852
853 return 0; 853 return 0;
854 854
@@ -938,11 +938,8 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)
938 938
939 pkt->trans = len; 939 pkt->trans = len;
940 940
941 tasklet_init(&fifo->tasklet, 941 INIT_WORK(&pkt->work, xfer_work);
942 usbhsf_dma_prepare_tasklet, 942 schedule_work(&pkt->work);
943 (unsigned long)pkt);
944
945 tasklet_schedule(&fifo->tasklet);
946 943
947 return 0; 944 return 0;
948 945
diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h
index f68609c0f489..c31731a843d1 100644
--- a/drivers/usb/renesas_usbhs/fifo.h
+++ b/drivers/usb/renesas_usbhs/fifo.h
@@ -19,6 +19,7 @@
19 19
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/sh_dma.h> 21#include <linux/sh_dma.h>
22#include <linux/workqueue.h>
22#include <asm/dma.h> 23#include <asm/dma.h>
23#include "pipe.h" 24#include "pipe.h"
24 25
@@ -31,7 +32,6 @@ struct usbhs_fifo {
31 u32 ctr; /* xFIFOCTR */ 32 u32 ctr; /* xFIFOCTR */
32 33
33 struct usbhs_pipe *pipe; 34 struct usbhs_pipe *pipe;
34 struct tasklet_struct tasklet;
35 35
36 struct dma_chan *tx_chan; 36 struct dma_chan *tx_chan;
37 struct dma_chan *rx_chan; 37 struct dma_chan *rx_chan;
@@ -53,6 +53,7 @@ struct usbhs_pkt {
53 struct usbhs_pkt_handle *handler; 53 struct usbhs_pkt_handle *handler;
54 void (*done)(struct usbhs_priv *priv, 54 void (*done)(struct usbhs_priv *priv,
55 struct usbhs_pkt *pkt); 55 struct usbhs_pkt *pkt);
56 struct work_struct work;
56 dma_addr_t dma; 57 dma_addr_t dma;
57 void *buf; 58 void *buf;
58 int length; 59 int length;
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c
index 1b97fb12694b..0871e816df45 100644
--- a/drivers/usb/renesas_usbhs/mod.c
+++ b/drivers/usb/renesas_usbhs/mod.c
@@ -152,7 +152,7 @@ int usbhs_mod_probe(struct usbhs_priv *priv)
152 152
153 /* irq settings */ 153 /* irq settings */
154 ret = request_irq(priv->irq, usbhs_interrupt, 154 ret = request_irq(priv->irq, usbhs_interrupt,
155 0, dev_name(dev), priv); 155 priv->irqflags, dev_name(dev), priv);
156 if (ret) { 156 if (ret) {
157 dev_err(dev, "irq request err\n"); 157 dev_err(dev, "irq request err\n");
158 goto mod_init_gadget_err; 158 goto mod_init_gadget_err;
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 7542aa94a462..00bd2a5e0362 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -165,69 +165,32 @@ static void usbhsg_queue_push(struct usbhsg_uep *uep,
165/* 165/*
166 * dma map/unmap 166 * dma map/unmap
167 */ 167 */
168static int usbhsg_dma_map(struct device *dev, 168static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
169 struct usbhs_pkt *pkt,
170 enum dma_data_direction dir)
171{
172 struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
173 struct usb_request *req = &ureq->req;
174
175 if (pkt->dma != DMA_ADDR_INVALID) {
176 dev_err(dev, "dma is already mapped\n");
177 return -EIO;
178 }
179
180 if (req->dma == DMA_ADDR_INVALID) {
181 pkt->dma = dma_map_single(dev, pkt->buf, pkt->length, dir);
182 } else {
183 dma_sync_single_for_device(dev, req->dma, req->length, dir);
184 pkt->dma = req->dma;
185 }
186
187 if (dma_mapping_error(dev, pkt->dma)) {
188 dev_err(dev, "dma mapping error %llx\n", (u64)pkt->dma);
189 return -EIO;
190 }
191
192 return 0;
193}
194
195static int usbhsg_dma_unmap(struct device *dev,
196 struct usbhs_pkt *pkt,
197 enum dma_data_direction dir)
198{ 169{
199 struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); 170 struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);
200 struct usb_request *req = &ureq->req; 171 struct usb_request *req = &ureq->req;
201
202 if (pkt->dma == DMA_ADDR_INVALID) {
203 dev_err(dev, "dma is not mapped\n");
204 return -EIO;
205 }
206
207 if (req->dma == DMA_ADDR_INVALID)
208 dma_unmap_single(dev, pkt->dma, pkt->length, dir);
209 else
210 dma_sync_single_for_cpu(dev, req->dma, req->length, dir);
211
212 pkt->dma = DMA_ADDR_INVALID;
213
214 return 0;
215}
216
217static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
218{
219 struct usbhs_pipe *pipe = pkt->pipe; 172 struct usbhs_pipe *pipe = pkt->pipe;
220 struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); 173 struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe);
221 struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); 174 struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
222 struct device *dev = usbhsg_gpriv_to_dev(gpriv);
223 enum dma_data_direction dir; 175 enum dma_data_direction dir;
176 int ret = 0;
224 177
225 dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; 178 dir = usbhs_pipe_is_dir_host(pipe);
226 179
227 if (map) 180 if (map) {
228 return usbhsg_dma_map(dev, pkt, dir); 181 /* it can not use scatter/gather */
229 else 182 WARN_ON(req->num_sgs);
230 return usbhsg_dma_unmap(dev, pkt, dir); 183
184 ret = usb_gadget_map_request(&gpriv->gadget, req, dir);
185 if (ret < 0)
186 return ret;
187
188 pkt->dma = req->dma;
189 } else {
190 usb_gadget_unmap_request(&gpriv->gadget, req, dir);
191 }
192
193 return ret;
231} 194}
232 195
233/* 196/*
@@ -657,8 +620,6 @@ static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep,
657 620
658 usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq)); 621 usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq));
659 622
660 ureq->req.dma = DMA_ADDR_INVALID;
661
662 return &ureq->req; 623 return &ureq->req;
663} 624}
664 625
@@ -941,6 +902,11 @@ static int usbhsg_stop(struct usbhs_priv *priv)
941 return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); 902 return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);
942} 903}
943 904
905static void usbhs_mod_gadget_release(struct device *pdev)
906{
907 /* do nothing */
908}
909
944int usbhs_mod_gadget_probe(struct usbhs_priv *priv) 910int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
945{ 911{
946 struct usbhsg_gpriv *gpriv; 912 struct usbhsg_gpriv *gpriv;
@@ -989,6 +955,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
989 */ 955 */
990 dev_set_name(&gpriv->gadget.dev, "gadget"); 956 dev_set_name(&gpriv->gadget.dev, "gadget");
991 gpriv->gadget.dev.parent = dev; 957 gpriv->gadget.dev.parent = dev;
958 gpriv->gadget.dev.release = usbhs_mod_gadget_release;
992 gpriv->gadget.name = "renesas_usbhs_udc"; 959 gpriv->gadget.name = "renesas_usbhs_udc";
993 gpriv->gadget.ops = &usbhsg_gadget_ops; 960 gpriv->gadget.ops = &usbhsg_gadget_ops;
994 gpriv->gadget.max_speed = USB_SPEED_HIGH; 961 gpriv->gadget.max_speed = USB_SPEED_HIGH;