]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/usb/musb/tusb6010_omap.c
usb: musb: tusb6010_omap: Create new struct for DMA data/parameters
[mirror_ubuntu-bionic-kernel.git] / drivers / usb / musb / tusb6010_omap.c
CommitLineData
550a7375
FB
1/*
2 * TUSB6010 USB 2.0 OTG Dual Role controller OMAP DMA interface
3 *
4 * Copyright (C) 2006 Nokia Corporation
5 * Tony Lindgren <tony@atomide.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/module.h>
12#include <linux/kernel.h>
13#include <linux/errno.h>
550a7375
FB
14#include <linux/usb.h>
15#include <linux/platform_device.h>
16#include <linux/dma-mapping.h>
5a0e3ad6 17#include <linux/slab.h>
45c3eb7d 18#include <linux/omap-dma.h>
550a7375
FB
19
20#include "musb_core.h"
240a16e2 21#include "tusb6010.h"
550a7375
FB
22
23#define to_chdat(c) ((struct tusb_omap_dma_ch *)(c)->private_data)
24
25#define MAX_DMAREQ 5 /* REVISIT: Really 6, but req5 not OK */
26
d5e7c864
LV
27#define OMAP24XX_DMA_EXT_DMAREQ0 2
28#define OMAP24XX_DMA_EXT_DMAREQ1 3
29#define OMAP242X_DMA_EXT_DMAREQ2 14
30#define OMAP242X_DMA_EXT_DMAREQ3 15
31#define OMAP242X_DMA_EXT_DMAREQ4 16
32#define OMAP242X_DMA_EXT_DMAREQ5 64
33
1df9d9ec
PU
34struct tusb_dma_data {
35 int ch;
36 s8 dmareq;
37 s8 sync_dev;
38};
39
550a7375
FB
40struct tusb_omap_dma_ch {
41 struct musb *musb;
42 void __iomem *tbase;
43 unsigned long phys_offset;
44 int epnum;
45 u8 tx;
46 struct musb_hw_ep *hw_ep;
47
1df9d9ec 48 struct tusb_dma_data dma_data;
550a7375
FB
49
50 struct tusb_omap_dma *tusb_dma;
51
1d0f11b3 52 dma_addr_t dma_addr;
550a7375
FB
53
54 u32 len;
55 u16 packet_sz;
56 u16 transfer_packet_sz;
57 u32 transfer_len;
58 u32 completed_len;
59};
60
61struct tusb_omap_dma {
62 struct dma_controller controller;
550a7375
FB
63 void __iomem *tbase;
64
1df9d9ec 65 struct tusb_dma_data dma_data;
550a7375
FB
66 unsigned multichannel:1;
67};
68
550a7375
FB
69/*
70 * Allocate dmareq0 to the current channel unless it's already taken
71 */
72static inline int tusb_omap_use_shared_dmareq(struct tusb_omap_dma_ch *chdat)
73{
74 u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
75
76 if (reg != 0) {
74c6f3a4 77 dev_dbg(chdat->musb->controller, "ep%i dmareq0 is busy for ep%i\n",
550a7375
FB
78 chdat->epnum, reg & 0xf);
79 return -EAGAIN;
80 }
81
82 if (chdat->tx)
83 reg = (1 << 4) | chdat->epnum;
84 else
85 reg = chdat->epnum;
86
87 musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
88
89 return 0;
90}
91
92static inline void tusb_omap_free_shared_dmareq(struct tusb_omap_dma_ch *chdat)
93{
94 u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
95
96 if ((reg & 0xf) != chdat->epnum) {
97 printk(KERN_ERR "ep%i trying to release dmareq0 for ep%i\n",
98 chdat->epnum, reg & 0xf);
99 return;
100 }
101 musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, 0);
102}
103
104/*
105 * See also musb_dma_completion in plat_uds.c and musb_g_[tx|rx]() in
106 * musb_gadget.c.
107 */
108static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
109{
110 struct dma_channel *channel = (struct dma_channel *)data;
111 struct tusb_omap_dma_ch *chdat = to_chdat(channel);
112 struct tusb_omap_dma *tusb_dma = chdat->tusb_dma;
113 struct musb *musb = chdat->musb;
1d0f11b3 114 struct device *dev = musb->controller;
550a7375
FB
115 struct musb_hw_ep *hw_ep = chdat->hw_ep;
116 void __iomem *ep_conf = hw_ep->conf;
117 void __iomem *mbase = musb->mregs;
118 unsigned long remaining, flags, pio;
119 int ch;
120
121 spin_lock_irqsave(&musb->lock, flags);
122
123 if (tusb_dma->multichannel)
1df9d9ec 124 ch = chdat->dma_data.ch;
550a7375 125 else
1df9d9ec 126 ch = tusb_dma->dma_data.ch;
550a7375
FB
127
128 if (ch_status != OMAP_DMA_BLOCK_IRQ)
129 printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
130
5c8a86e1 131 dev_dbg(musb->controller, "ep%i %s dma callback ch: %i status: %x\n",
550a7375
FB
132 chdat->epnum, chdat->tx ? "tx" : "rx",
133 ch, ch_status);
134
135 if (chdat->tx)
136 remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
137 else
138 remaining = musb_readl(ep_conf, TUSB_EP_RX_OFFSET);
139
140 remaining = TUSB_EP_CONFIG_XFR_SIZE(remaining);
141
142 /* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
143 if (unlikely(remaining > chdat->transfer_len)) {
5c8a86e1 144 dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 0x%08lx\n",
1df9d9ec 145 chdat->tx ? "tx" : "rx", ch, remaining);
550a7375
FB
146 remaining = 0;
147 }
148
149 channel->actual_len = chdat->transfer_len - remaining;
150 pio = chdat->len - channel->actual_len;
151
5c8a86e1 152 dev_dbg(musb->controller, "DMA remaining %lu/%u\n", remaining, chdat->transfer_len);
550a7375
FB
153
154 /* Transfer remaining 1 - 31 bytes */
155 if (pio > 0 && pio < 32) {
156 u8 *buf;
157
5c8a86e1 158 dev_dbg(musb->controller, "Using PIO for remaining %lu bytes\n", pio);
550a7375
FB
159 buf = phys_to_virt((u32)chdat->dma_addr) + chdat->transfer_len;
160 if (chdat->tx) {
1d0f11b3
TL
161 dma_unmap_single(dev, chdat->dma_addr,
162 chdat->transfer_len,
163 DMA_TO_DEVICE);
550a7375
FB
164 musb_write_fifo(hw_ep, pio, buf);
165 } else {
1d0f11b3
TL
166 dma_unmap_single(dev, chdat->dma_addr,
167 chdat->transfer_len,
168 DMA_FROM_DEVICE);
550a7375 169 musb_read_fifo(hw_ep, pio, buf);
550a7375
FB
170 }
171 channel->actual_len += pio;
172 }
173
174 if (!tusb_dma->multichannel)
175 tusb_omap_free_shared_dmareq(chdat);
176
177 channel->status = MUSB_DMA_STATUS_FREE;
178
179 /* Handle only RX callbacks here. TX callbacks must be handled based
180 * on the TUSB DMA status interrupt.
181 * REVISIT: Use both TUSB DMA status interrupt and OMAP DMA callback
182 * interrupt for RX and TX.
183 */
184 if (!chdat->tx)
185 musb_dma_completion(musb, chdat->epnum, chdat->tx);
186
187 /* We must terminate short tx transfers manually by setting TXPKTRDY.
188 * REVISIT: This same problem may occur with other MUSB dma as well.
189 * Easy to test with g_ether by pinging the MUSB board with ping -s54.
190 */
191 if ((chdat->transfer_len < chdat->packet_sz)
192 || (chdat->transfer_len % chdat->packet_sz != 0)) {
193 u16 csr;
194
195 if (chdat->tx) {
5c8a86e1 196 dev_dbg(musb->controller, "terminating short tx packet\n");
550a7375
FB
197 musb_ep_select(mbase, chdat->epnum);
198 csr = musb_readw(hw_ep->regs, MUSB_TXCSR);
199 csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY
200 | MUSB_TXCSR_P_WZC_BITS;
201 musb_writew(hw_ep->regs, MUSB_TXCSR, csr);
202 }
203 }
204
205 spin_unlock_irqrestore(&musb->lock, flags);
206}
207
208static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
209 u8 rndis_mode, dma_addr_t dma_addr, u32 len)
210{
211 struct tusb_omap_dma_ch *chdat = to_chdat(channel);
212 struct tusb_omap_dma *tusb_dma = chdat->tusb_dma;
213 struct musb *musb = chdat->musb;
1d0f11b3 214 struct device *dev = musb->controller;
550a7375
FB
215 struct musb_hw_ep *hw_ep = chdat->hw_ep;
216 void __iomem *mbase = musb->mregs;
217 void __iomem *ep_conf = hw_ep->conf;
218 dma_addr_t fifo = hw_ep->fifo_sync;
219 struct omap_dma_channel_params dma_params;
220 u32 dma_remaining;
221 int src_burst, dst_burst;
222 u16 csr;
6df2b42f 223 u32 psize;
1df9d9ec 224 struct tusb_dma_data *dma_data;
550a7375
FB
225
226 if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
227 return false;
228
229 /*
230 * HW issue #10: Async dma will eventually corrupt the XFR_SIZE
231 * register which will cause missed DMA interrupt. We could try to
232 * use a timer for the callback, but it is unsafe as the XFR_SIZE
233 * register is corrupt, and we won't know if the DMA worked.
234 */
235 if (dma_addr & 0x2)
236 return false;
237
238 /*
239 * Because of HW issue #10, it seems like mixing sync DMA and async
240 * PIO access can confuse the DMA. Make sure XFR_SIZE is reset before
241 * using the channel for DMA.
242 */
243 if (chdat->tx)
244 dma_remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
245 else
246 dma_remaining = musb_readl(ep_conf, TUSB_EP_RX_OFFSET);
247
248 dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
249 if (dma_remaining) {
5c8a86e1 250 dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
1df9d9ec 251 chdat->tx ? "tx" : "rx", chdat->dma_data.ch,
550a7375
FB
252 dma_remaining);
253 return false;
254 }
255
256 chdat->transfer_len = len & ~0x1f;
257
258 if (len < packet_sz)
259 chdat->transfer_packet_sz = chdat->transfer_len;
260 else
261 chdat->transfer_packet_sz = packet_sz;
262
263 if (tusb_dma->multichannel) {
1df9d9ec 264 dma_data = &chdat->dma_data;
550a7375 265 } else {
1df9d9ec
PU
266 dma_data = &tusb_dma->dma_data;
267
550a7375 268 if (tusb_omap_use_shared_dmareq(chdat) != 0) {
5c8a86e1 269 dev_dbg(musb->controller, "could not get dma for ep%i\n", chdat->epnum);
550a7375
FB
270 return false;
271 }
1df9d9ec 272 if (dma_data->ch < 0) {
550a7375
FB
273 /* REVISIT: This should get blocked earlier, happens
274 * with MSC ErrorRecoveryTest
275 */
276 WARN_ON(1);
277 return false;
278 }
279
1df9d9ec 280 omap_set_dma_callback(dma_data->ch, tusb_omap_dma_cb, channel);
550a7375
FB
281 }
282
283 chdat->packet_sz = packet_sz;
284 chdat->len = len;
285 channel->actual_len = 0;
1d0f11b3 286 chdat->dma_addr = dma_addr;
550a7375
FB
287 channel->status = MUSB_DMA_STATUS_BUSY;
288
289 /* Since we're recycling dma areas, we need to clean or invalidate */
290 if (chdat->tx)
1d0f11b3
TL
291 dma_map_single(dev, phys_to_virt(dma_addr), len,
292 DMA_TO_DEVICE);
550a7375 293 else
1d0f11b3
TL
294 dma_map_single(dev, phys_to_virt(dma_addr), len,
295 DMA_FROM_DEVICE);
550a7375
FB
296
297 /* Use 16-bit transfer if dma_addr is not 32-bit aligned */
298 if ((dma_addr & 0x3) == 0) {
299 dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
300 dma_params.elem_count = 8; /* Elements in frame */
301 } else {
302 dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
303 dma_params.elem_count = 16; /* Elements in frame */
304 fifo = hw_ep->fifo_async;
305 }
306
307 dma_params.frame_count = chdat->transfer_len / 32; /* Burst sz frame */
308
3ec08ddf 309 dev_dbg(musb->controller, "ep%i %s dma ch%i dma: %pad len: %u(%u) packet_sz: %i(%i)\n",
550a7375 310 chdat->epnum, chdat->tx ? "tx" : "rx",
1df9d9ec 311 dma_data->ch, &dma_addr, chdat->transfer_len, len,
550a7375
FB
312 chdat->transfer_packet_sz, packet_sz);
313
314 /*
315 * Prepare omap DMA for transfer
316 */
317 if (chdat->tx) {
318 dma_params.src_amode = OMAP_DMA_AMODE_POST_INC;
319 dma_params.src_start = (unsigned long)dma_addr;
320 dma_params.src_ei = 0;
321 dma_params.src_fi = 0;
322
323 dma_params.dst_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
324 dma_params.dst_start = (unsigned long)fifo;
325 dma_params.dst_ei = 1;
326 dma_params.dst_fi = -31; /* Loop 32 byte window */
327
1df9d9ec 328 dma_params.trigger = dma_data->sync_dev;
550a7375
FB
329 dma_params.sync_mode = OMAP_DMA_SYNC_FRAME;
330 dma_params.src_or_dst_synch = 0; /* Dest sync */
331
332 src_burst = OMAP_DMA_DATA_BURST_16; /* 16x32 read */
333 dst_burst = OMAP_DMA_DATA_BURST_8; /* 8x32 write */
334 } else {
335 dma_params.src_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
336 dma_params.src_start = (unsigned long)fifo;
337 dma_params.src_ei = 1;
338 dma_params.src_fi = -31; /* Loop 32 byte window */
339
340 dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
341 dma_params.dst_start = (unsigned long)dma_addr;
342 dma_params.dst_ei = 0;
343 dma_params.dst_fi = 0;
344
1df9d9ec 345 dma_params.trigger = dma_data->sync_dev;
550a7375
FB
346 dma_params.sync_mode = OMAP_DMA_SYNC_FRAME;
347 dma_params.src_or_dst_synch = 1; /* Source sync */
348
349 src_burst = OMAP_DMA_DATA_BURST_8; /* 8x32 read */
350 dst_burst = OMAP_DMA_DATA_BURST_16; /* 16x32 write */
351 }
352
5c8a86e1 353 dev_dbg(musb->controller, "ep%i %s using %i-bit %s dma from 0x%08lx to 0x%08lx\n",
550a7375
FB
354 chdat->epnum, chdat->tx ? "tx" : "rx",
355 (dma_params.data_type == OMAP_DMA_DATA_TYPE_S32) ? 32 : 16,
356 ((dma_addr & 0x3) == 0) ? "sync" : "async",
357 dma_params.src_start, dma_params.dst_start);
358
1df9d9ec
PU
359 omap_set_dma_params(dma_data->ch, &dma_params);
360 omap_set_dma_src_burst_mode(dma_data->ch, src_burst);
361 omap_set_dma_dest_burst_mode(dma_data->ch, dst_burst);
362 omap_set_dma_write_mode(dma_data->ch, OMAP_DMA_WRITE_LAST_NON_POSTED);
550a7375
FB
363
364 /*
365 * Prepare MUSB for DMA transfer
366 */
3565b787 367 musb_ep_select(mbase, chdat->epnum);
550a7375 368 if (chdat->tx) {
550a7375
FB
369 csr = musb_readw(hw_ep->regs, MUSB_TXCSR);
370 csr |= (MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB
371 | MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE);
372 csr &= ~MUSB_TXCSR_P_UNDERRUN;
373 musb_writew(hw_ep->regs, MUSB_TXCSR, csr);
374 } else {
550a7375
FB
375 csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
376 csr |= MUSB_RXCSR_DMAENAB;
377 csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAMODE);
378 musb_writew(hw_ep->regs, MUSB_RXCSR,
379 csr | MUSB_RXCSR_P_WZC_BITS);
380 }
381
382 /*
383 * Start DMA transfer
384 */
1df9d9ec 385 omap_start_dma(dma_data->ch);
550a7375
FB
386
387 if (chdat->tx) {
388 /* Send transfer_packet_sz packets at a time */
6df2b42f
PU
389 psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET);
390 psize &= ~0x7ff;
391 psize |= chdat->transfer_packet_sz;
392 musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize);
550a7375
FB
393
394 musb_writel(ep_conf, TUSB_EP_TX_OFFSET,
395 TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
396 } else {
397 /* Receive transfer_packet_sz packets at a time */
6df2b42f
PU
398 psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET);
399 psize &= ~(0x7ff << 16);
400 psize |= (chdat->transfer_packet_sz << 16);
401 musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize);
550a7375
FB
402
403 musb_writel(ep_conf, TUSB_EP_RX_OFFSET,
404 TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
405 }
406
407 return true;
408}
409
410static int tusb_omap_dma_abort(struct dma_channel *channel)
411{
412 struct tusb_omap_dma_ch *chdat = to_chdat(channel);
413 struct tusb_omap_dma *tusb_dma = chdat->tusb_dma;
1df9d9ec 414 struct tusb_dma_data *dma_data = &tusb_dma->dma_data;
550a7375
FB
415
416 if (!tusb_dma->multichannel) {
1df9d9ec
PU
417 if (dma_data->ch >= 0) {
418 omap_stop_dma(dma_data->ch);
419 omap_free_dma(dma_data->ch);
420 dma_data->ch = -1;
550a7375
FB
421 }
422
1df9d9ec
PU
423 dma_data->dmareq = -1;
424 dma_data->sync_dev = -1;
550a7375
FB
425 }
426
427 channel->status = MUSB_DMA_STATUS_FREE;
428
429 return 0;
430}
431
432static inline int tusb_omap_dma_allocate_dmareq(struct tusb_omap_dma_ch *chdat)
433{
434 u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
435 int i, dmareq_nr = -1;
436
437 const int sync_dev[6] = {
438 OMAP24XX_DMA_EXT_DMAREQ0,
439 OMAP24XX_DMA_EXT_DMAREQ1,
440 OMAP242X_DMA_EXT_DMAREQ2,
441 OMAP242X_DMA_EXT_DMAREQ3,
442 OMAP242X_DMA_EXT_DMAREQ4,
443 OMAP242X_DMA_EXT_DMAREQ5,
444 };
445
446 for (i = 0; i < MAX_DMAREQ; i++) {
447 int cur = (reg & (0xf << (i * 5))) >> (i * 5);
448 if (cur == 0) {
449 dmareq_nr = i;
450 break;
451 }
452 }
453
454 if (dmareq_nr == -1)
455 return -EAGAIN;
456
457 reg |= (chdat->epnum << (dmareq_nr * 5));
458 if (chdat->tx)
459 reg |= ((1 << 4) << (dmareq_nr * 5));
460 musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
461
1df9d9ec
PU
462 chdat->dma_data.dmareq = dmareq_nr;
463 chdat->dma_data.sync_dev = sync_dev[chdat->dma_data.dmareq];
550a7375
FB
464
465 return 0;
466}
467
468static inline void tusb_omap_dma_free_dmareq(struct tusb_omap_dma_ch *chdat)
469{
470 u32 reg;
471
1df9d9ec 472 if (!chdat || chdat->dma_data.dmareq < 0)
550a7375
FB
473 return;
474
475 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
1df9d9ec 476 reg &= ~(0x1f << (chdat->dma_data.dmareq * 5));
550a7375
FB
477 musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
478
1df9d9ec
PU
479 chdat->dma_data.dmareq = -1;
480 chdat->dma_data.sync_dev = -1;
550a7375
FB
481}
482
483static struct dma_channel *dma_channel_pool[MAX_DMAREQ];
484
485static struct dma_channel *
486tusb_omap_dma_allocate(struct dma_controller *c,
487 struct musb_hw_ep *hw_ep,
488 u8 tx)
489{
490 int ret, i;
491 const char *dev_name;
1df9d9ec 492 void *cb_data;
550a7375
FB
493 struct tusb_omap_dma *tusb_dma;
494 struct musb *musb;
495 void __iomem *tbase;
496 struct dma_channel *channel = NULL;
497 struct tusb_omap_dma_ch *chdat = NULL;
1df9d9ec 498 struct tusb_dma_data *dma_data = NULL;
550a7375
FB
499 u32 reg;
500
501 tusb_dma = container_of(c, struct tusb_omap_dma, controller);
a96ca0d2 502 musb = tusb_dma->controller.musb;
550a7375
FB
503 tbase = musb->ctrl_base;
504
505 reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
506 if (tx)
507 reg &= ~(1 << hw_ep->epnum);
508 else
509 reg &= ~(1 << (hw_ep->epnum + 15));
510 musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
511
512 /* REVISIT: Why does dmareq5 not work? */
513 if (hw_ep->epnum == 0) {
5c8a86e1 514 dev_dbg(musb->controller, "Not allowing DMA for ep0 %s\n", tx ? "tx" : "rx");
550a7375
FB
515 return NULL;
516 }
517
518 for (i = 0; i < MAX_DMAREQ; i++) {
519 struct dma_channel *ch = dma_channel_pool[i];
520 if (ch->status == MUSB_DMA_STATUS_UNKNOWN) {
521 ch->status = MUSB_DMA_STATUS_FREE;
522 channel = ch;
523 chdat = ch->private_data;
524 break;
525 }
526 }
527
528 if (!channel)
529 return NULL;
530
a96ca0d2 531 chdat->musb = tusb_dma->controller.musb;
550a7375
FB
532 chdat->tbase = tusb_dma->tbase;
533 chdat->hw_ep = hw_ep;
534 chdat->epnum = hw_ep->epnum;
550a7375
FB
535 chdat->completed_len = 0;
536 chdat->tusb_dma = tusb_dma;
1df9d9ec
PU
537 if (tx)
538 chdat->tx = 1;
539 else
540 chdat->tx = 0;
550a7375
FB
541
542 channel->max_len = 0x7fffffff;
543 channel->desired_mode = 0;
544 channel->actual_len = 0;
545
546 if (tusb_dma->multichannel) {
1df9d9ec 547 dma_data = &chdat->dma_data;
550a7375
FB
548 ret = tusb_omap_dma_allocate_dmareq(chdat);
549 if (ret != 0)
550 goto free_dmareq;
551
1df9d9ec
PU
552 if (chdat->tx)
553 dev_name = "TUSB transmit";
554 else
555 dev_name = "TUSB receive";
556 cb_data = channel;
557 } else if (tusb_dma->dma_data.ch == -1) {
558 dma_data = &tusb_dma->dma_data;
559 dma_data->dmareq = 0;
560 dma_data->sync_dev = OMAP24XX_DMA_EXT_DMAREQ0;
561
562 dev_name = "TUSB shared";
550a7375 563 /* Callback data gets set later in the shared dmareq case */
1df9d9ec
PU
564 cb_data = NULL;
565
566 chdat->dma_data.dmareq = -1;
567 chdat->dma_data.ch = -1;
568 chdat->dma_data.sync_dev = -1;
569 }
570
571 if (dma_data) {
572 ret = omap_request_dma(dma_data->sync_dev, dev_name,
573 tusb_omap_dma_cb, cb_data,
574 &dma_data->ch);
550a7375
FB
575 if (ret != 0)
576 goto free_dmareq;
1df9d9ec
PU
577 } else {
578 /* Already allocated shared, single DMA channel. */
579 dma_data = &tusb_dma->dma_data;
550a7375
FB
580 }
581
5c8a86e1 582 dev_dbg(musb->controller, "ep%i %s dma: %s dma%i dmareq%i sync%i\n",
550a7375
FB
583 chdat->epnum,
584 chdat->tx ? "tx" : "rx",
1df9d9ec
PU
585 chdat->dma_data.ch >= 0 ? "dedicated" : "shared",
586 dma_data->ch, dma_data->dmareq, dma_data->sync_dev);
550a7375
FB
587
588 return channel;
589
590free_dmareq:
591 tusb_omap_dma_free_dmareq(chdat);
592
5c8a86e1 593 dev_dbg(musb->controller, "ep%i: Could not get a DMA channel\n", chdat->epnum);
550a7375
FB
594 channel->status = MUSB_DMA_STATUS_UNKNOWN;
595
596 return NULL;
597}
598
599static void tusb_omap_dma_release(struct dma_channel *channel)
600{
601 struct tusb_omap_dma_ch *chdat = to_chdat(channel);
602 struct musb *musb = chdat->musb;
603 void __iomem *tbase = musb->ctrl_base;
604 u32 reg;
605
1df9d9ec
PU
606 dev_dbg(musb->controller, "ep%i ch%i\n", chdat->epnum,
607 chdat->dma_data.ch);
550a7375
FB
608
609 reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
610 if (chdat->tx)
611 reg |= (1 << chdat->epnum);
612 else
613 reg |= (1 << (chdat->epnum + 15));
614 musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
615
616 reg = musb_readl(tbase, TUSB_DMA_INT_CLEAR);
617 if (chdat->tx)
618 reg |= (1 << chdat->epnum);
619 else
620 reg |= (1 << (chdat->epnum + 15));
621 musb_writel(tbase, TUSB_DMA_INT_CLEAR, reg);
622
623 channel->status = MUSB_DMA_STATUS_UNKNOWN;
624
1df9d9ec
PU
625 if (chdat->dma_data.ch >= 0) {
626 omap_stop_dma(chdat->dma_data.ch);
627 omap_free_dma(chdat->dma_data.ch);
628 chdat->dma_data.ch = -1;
550a7375
FB
629 }
630
1df9d9ec 631 if (chdat->dma_data.dmareq >= 0)
550a7375
FB
632 tusb_omap_dma_free_dmareq(chdat);
633
634 channel = NULL;
635}
636
7f6283ed 637void tusb_dma_controller_destroy(struct dma_controller *c)
550a7375
FB
638{
639 struct tusb_omap_dma *tusb_dma;
640 int i;
641
642 tusb_dma = container_of(c, struct tusb_omap_dma, controller);
643 for (i = 0; i < MAX_DMAREQ; i++) {
644 struct dma_channel *ch = dma_channel_pool[i];
645 if (ch) {
646 kfree(ch->private_data);
647 kfree(ch);
648 }
649 }
650
1df9d9ec
PU
651 if (tusb_dma && !tusb_dma->multichannel && tusb_dma->dma_data.ch >= 0)
652 omap_free_dma(tusb_dma->dma_data.ch);
550a7375
FB
653
654 kfree(tusb_dma);
655}
7f6283ed 656EXPORT_SYMBOL_GPL(tusb_dma_controller_destroy);
550a7375 657
7f6283ed
TL
658struct dma_controller *
659tusb_dma_controller_create(struct musb *musb, void __iomem *base)
550a7375
FB
660{
661 void __iomem *tbase = musb->ctrl_base;
662 struct tusb_omap_dma *tusb_dma;
663 int i;
664
665 /* REVISIT: Get dmareq lines used from board-*.c */
666
667 musb_writel(musb->ctrl_base, TUSB_DMA_INT_MASK, 0x7fffffff);
668 musb_writel(musb->ctrl_base, TUSB_DMA_EP_MAP, 0);
669
670 musb_writel(tbase, TUSB_DMA_REQ_CONF,
671 TUSB_DMA_REQ_CONF_BURST_SIZE(2)
672 | TUSB_DMA_REQ_CONF_DMA_REQ_EN(0x3f)
673 | TUSB_DMA_REQ_CONF_DMA_REQ_ASSER(2));
674
675 tusb_dma = kzalloc(sizeof(struct tusb_omap_dma), GFP_KERNEL);
676 if (!tusb_dma)
c88ba39c 677 goto out;
550a7375 678
a96ca0d2 679 tusb_dma->controller.musb = musb;
550a7375
FB
680 tusb_dma->tbase = musb->ctrl_base;
681
1df9d9ec
PU
682 tusb_dma->dma_data.ch = -1;
683 tusb_dma->dma_data.dmareq = -1;
684 tusb_dma->dma_data.sync_dev = -1;
550a7375 685
550a7375
FB
686 tusb_dma->controller.channel_alloc = tusb_omap_dma_allocate;
687 tusb_dma->controller.channel_release = tusb_omap_dma_release;
688 tusb_dma->controller.channel_program = tusb_omap_dma_program;
689 tusb_dma->controller.channel_abort = tusb_omap_dma_abort;
690
7751b6fb 691 if (musb->tusb_revision >= TUSB_REV_30)
550a7375
FB
692 tusb_dma->multichannel = 1;
693
694 for (i = 0; i < MAX_DMAREQ; i++) {
695 struct dma_channel *ch;
696 struct tusb_omap_dma_ch *chdat;
697
698 ch = kzalloc(sizeof(struct dma_channel), GFP_KERNEL);
699 if (!ch)
700 goto cleanup;
701
702 dma_channel_pool[i] = ch;
703
704 chdat = kzalloc(sizeof(struct tusb_omap_dma_ch), GFP_KERNEL);
705 if (!chdat)
706 goto cleanup;
707
708 ch->status = MUSB_DMA_STATUS_UNKNOWN;
709 ch->private_data = chdat;
710 }
711
712 return &tusb_dma->controller;
713
714cleanup:
7f6283ed 715 musb_dma_controller_destroy(&tusb_dma->controller);
c88ba39c 716out:
550a7375
FB
717 return NULL;
718}
7f6283ed 719EXPORT_SYMBOL_GPL(tusb_dma_controller_create);