diff options
Diffstat (limited to 'drivers/usb/renesas_usbhs/mod_gadget.c')
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_gadget.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 89d2b16fbb10..31d28dc78aa3 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
@@ -160,6 +160,71 @@ static void usbhsg_queue_done(struct usbhs_pkt *pkt) | |||
160 | usbhsg_queue_pop(uep, ureq, 0); | 160 | usbhsg_queue_pop(uep, ureq, 0); |
161 | } | 161 | } |
162 | 162 | ||
163 | static int usbhsg_dma_map(struct device *dev, | ||
164 | struct usbhs_pkt *pkt, | ||
165 | enum dma_data_direction dir) | ||
166 | { | ||
167 | struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); | ||
168 | struct usb_request *req = &ureq->req; | ||
169 | |||
170 | if (pkt->dma != DMA_ADDR_INVALID) { | ||
171 | dev_err(dev, "dma is already mapped\n"); | ||
172 | return -EIO; | ||
173 | } | ||
174 | |||
175 | if (req->dma == DMA_ADDR_INVALID) { | ||
176 | pkt->dma = dma_map_single(dev, pkt->buf, pkt->length, dir); | ||
177 | } else { | ||
178 | dma_sync_single_for_device(dev, req->dma, req->length, dir); | ||
179 | pkt->dma = req->dma; | ||
180 | } | ||
181 | |||
182 | if (dma_mapping_error(dev, pkt->dma)) { | ||
183 | dev_err(dev, "dma mapping error %x\n", pkt->dma); | ||
184 | return -EIO; | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static int usbhsg_dma_unmap(struct device *dev, | ||
191 | struct usbhs_pkt *pkt, | ||
192 | enum dma_data_direction dir) | ||
193 | { | ||
194 | struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt); | ||
195 | struct usb_request *req = &ureq->req; | ||
196 | |||
197 | if (pkt->dma == DMA_ADDR_INVALID) { | ||
198 | dev_err(dev, "dma is not mapped\n"); | ||
199 | return -EIO; | ||
200 | } | ||
201 | |||
202 | if (req->dma == DMA_ADDR_INVALID) | ||
203 | dma_unmap_single(dev, pkt->dma, pkt->length, dir); | ||
204 | else | ||
205 | dma_sync_single_for_cpu(dev, req->dma, req->length, dir); | ||
206 | |||
207 | pkt->dma = DMA_ADDR_INVALID; | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int usbhsg_dma_map_ctrl(struct usbhs_pkt *pkt, int map) | ||
213 | { | ||
214 | struct usbhs_pipe *pipe = pkt->pipe; | ||
215 | struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe); | ||
216 | struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); | ||
217 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | ||
218 | enum dma_data_direction dir; | ||
219 | |||
220 | dir = usbhs_pipe_is_dir_in(pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
221 | |||
222 | if (map) | ||
223 | return usbhsg_dma_map(dev, pkt, dir); | ||
224 | else | ||
225 | return usbhsg_dma_unmap(dev, pkt, dir); | ||
226 | } | ||
227 | |||
163 | /* | 228 | /* |
164 | * USB_TYPE_STANDARD / clear feature functions | 229 | * USB_TYPE_STANDARD / clear feature functions |
165 | */ | 230 | */ |
@@ -434,6 +499,8 @@ static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, | |||
434 | 499 | ||
435 | usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq)); | 500 | usbhs_pkt_init(usbhsg_ureq_to_pkt(ureq)); |
436 | 501 | ||
502 | ureq->req.dma = DMA_ADDR_INVALID; | ||
503 | |||
437 | return &ureq->req; | 504 | return &ureq->req; |
438 | } | 505 | } |
439 | 506 | ||
@@ -569,7 +636,8 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | |||
569 | * pipe initialize and enable DCP | 636 | * pipe initialize and enable DCP |
570 | */ | 637 | */ |
571 | usbhs_pipe_init(priv, | 638 | usbhs_pipe_init(priv, |
572 | usbhsg_queue_done); | 639 | usbhsg_queue_done, |
640 | usbhsg_dma_map_ctrl); | ||
573 | usbhs_fifo_init(priv); | 641 | usbhs_fifo_init(priv); |
574 | usbhsg_uep_init(gpriv); | 642 | usbhsg_uep_init(gpriv); |
575 | 643 | ||