Skip to content

Commit 9c691cc

Browse files
Peter Ujfalusigregkh
authored andcommitted
usb: musb: tusb6010_omap: Convert to DMAengine API
With the port_window support in DMAengine and the sDMA driver we can convert the driver to DMAengine. Signed-off-by: Peter Ujfalusi <[email protected]> Tested-by: Tony Lindgren <[email protected]> Signed-off-by: Bin Liu <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 868772d commit 9c691cc

File tree

1 file changed

+80
-121
lines changed

1 file changed

+80
-121
lines changed

drivers/usb/musb/tusb6010_omap.c

Lines changed: 80 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include <linux/platform_device.h>
1616
#include <linux/dma-mapping.h>
1717
#include <linux/slab.h>
18-
#include <linux/omap-dma.h>
18+
#include <linux/dmaengine.h>
1919

2020
#include "musb_core.h"
2121
#include "tusb6010.h"
@@ -24,17 +24,9 @@
2424

2525
#define MAX_DMAREQ 5 /* REVISIT: Really 6, but req5 not OK */
2626

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-
3427
struct tusb_dma_data {
35-
int ch;
3628
s8 dmareq;
37-
s8 sync_dev;
29+
struct dma_chan *chan;
3830
};
3931

4032
struct tusb_omap_dma_ch {
@@ -105,7 +97,7 @@ static inline void tusb_omap_free_shared_dmareq(struct tusb_omap_dma_ch *chdat)
10597
* See also musb_dma_completion in plat_uds.c and musb_g_[tx|rx]() in
10698
* musb_gadget.c.
10799
*/
108-
static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
100+
static void tusb_omap_dma_cb(void *data)
109101
{
110102
struct dma_channel *channel = (struct dma_channel *)data;
111103
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
@@ -116,18 +108,11 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
116108
void __iomem *ep_conf = hw_ep->conf;
117109
void __iomem *mbase = musb->mregs;
118110
unsigned long remaining, flags, pio;
119-
int ch;
120111

121112
spin_lock_irqsave(&musb->lock, flags);
122113

123-
ch = chdat->dma_data->ch;
124-
125-
if (ch_status != OMAP_DMA_BLOCK_IRQ)
126-
printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
127-
128-
dev_dbg(musb->controller, "ep%i %s dma callback ch: %i status: %x\n",
129-
chdat->epnum, chdat->tx ? "tx" : "rx",
130-
ch, ch_status);
114+
dev_dbg(musb->controller, "ep%i %s dma callback\n",
115+
chdat->epnum, chdat->tx ? "tx" : "rx");
131116

132117
if (chdat->tx)
133118
remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
@@ -138,8 +123,8 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
138123

139124
/* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
140125
if (unlikely(remaining > chdat->transfer_len)) {
141-
dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 0x%08lx\n",
142-
chdat->tx ? "tx" : "rx", ch, remaining);
126+
dev_dbg(musb->controller, "Corrupt %s XFR_SIZE: 0x%08lx\n",
127+
chdat->tx ? "tx" : "rx", remaining);
143128
remaining = 0;
144129
}
145130

@@ -206,13 +191,16 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
206191
struct musb_hw_ep *hw_ep = chdat->hw_ep;
207192
void __iomem *mbase = musb->mregs;
208193
void __iomem *ep_conf = hw_ep->conf;
209-
dma_addr_t fifo = hw_ep->fifo_sync;
210-
struct omap_dma_channel_params dma_params;
194+
dma_addr_t fifo_addr = hw_ep->fifo_sync;
211195
u32 dma_remaining;
212-
int src_burst, dst_burst;
213196
u16 csr;
214197
u32 psize;
215198
struct tusb_dma_data *dma_data;
199+
struct dma_async_tx_descriptor *dma_desc;
200+
struct dma_slave_config dma_cfg;
201+
enum dma_transfer_direction dma_dir;
202+
u32 port_window;
203+
int ret;
216204

217205
if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
218206
return false;
@@ -238,10 +226,8 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
238226

239227
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
240228
if (dma_remaining) {
241-
dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
242-
chdat->tx ? "tx" : "rx",
243-
chdat->dma_data ? chdat->dma_data->ch : -1,
244-
dma_remaining);
229+
dev_dbg(musb->controller, "Busy %s dma, not using: %08x\n",
230+
chdat->tx ? "tx" : "rx", dma_remaining);
245231
return false;
246232
}
247233

@@ -258,7 +244,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
258244
dev_dbg(musb->controller, "could not get dma for ep%i\n", chdat->epnum);
259245
return false;
260246
}
261-
if (dma_data->ch < 0) {
247+
if (dma_data->dmareq < 0) {
262248
/* REVISIT: This should get blocked earlier, happens
263249
* with MSC ErrorRecoveryTest
264250
*/
@@ -267,88 +253,75 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
267253
}
268254
}
269255

270-
omap_set_dma_callback(dma_data->ch, tusb_omap_dma_cb, channel);
271-
272256
chdat->packet_sz = packet_sz;
273257
chdat->len = len;
274258
channel->actual_len = 0;
275259
chdat->dma_addr = dma_addr;
276260
channel->status = MUSB_DMA_STATUS_BUSY;
277261

278262
/* Since we're recycling dma areas, we need to clean or invalidate */
279-
if (chdat->tx)
263+
if (chdat->tx) {
264+
dma_dir = DMA_MEM_TO_DEV;
280265
dma_map_single(dev, phys_to_virt(dma_addr), len,
281266
DMA_TO_DEVICE);
282-
else
267+
} else {
268+
dma_dir = DMA_DEV_TO_MEM;
283269
dma_map_single(dev, phys_to_virt(dma_addr), len,
284270
DMA_FROM_DEVICE);
271+
}
272+
273+
memset(&dma_cfg, 0, sizeof(dma_cfg));
285274

286275
/* Use 16-bit transfer if dma_addr is not 32-bit aligned */
287276
if ((dma_addr & 0x3) == 0) {
288-
dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
289-
dma_params.elem_count = 8; /* Elements in frame */
277+
dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
278+
dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
279+
port_window = 8;
290280
} else {
291-
dma_params.data_type = OMAP_DMA_DATA_TYPE_S16;
292-
dma_params.elem_count = 16; /* Elements in frame */
293-
fifo = hw_ep->fifo_async;
294-
}
281+
dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
282+
dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
283+
port_window = 16;
295284

296-
dma_params.frame_count = chdat->transfer_len / 32; /* Burst sz frame */
285+
fifo_addr = hw_ep->fifo_async;
286+
}
297287

298-
dev_dbg(musb->controller, "ep%i %s dma ch%i dma: %pad len: %u(%u) packet_sz: %i(%i)\n",
299-
chdat->epnum, chdat->tx ? "tx" : "rx",
300-
dma_data->ch, &dma_addr, chdat->transfer_len, len,
301-
chdat->transfer_packet_sz, packet_sz);
288+
dev_dbg(musb->controller,
289+
"ep%i %s dma: %pad len: %u(%u) packet_sz: %i(%i)\n",
290+
chdat->epnum, chdat->tx ? "tx" : "rx", &dma_addr,
291+
chdat->transfer_len, len, chdat->transfer_packet_sz, packet_sz);
292+
293+
dma_cfg.src_addr = fifo_addr;
294+
dma_cfg.dst_addr = fifo_addr;
295+
dma_cfg.src_port_window_size = port_window;
296+
dma_cfg.src_maxburst = port_window;
297+
dma_cfg.dst_port_window_size = port_window;
298+
dma_cfg.dst_maxburst = port_window;
299+
300+
ret = dmaengine_slave_config(dma_data->chan, &dma_cfg);
301+
if (ret) {
302+
dev_err(musb->controller, "DMA slave config failed: %d\n", ret);
303+
return false;
304+
}
302305

303-
/*
304-
* Prepare omap DMA for transfer
305-
*/
306-
if (chdat->tx) {
307-
dma_params.src_amode = OMAP_DMA_AMODE_POST_INC;
308-
dma_params.src_start = (unsigned long)dma_addr;
309-
dma_params.src_ei = 0;
310-
dma_params.src_fi = 0;
311-
312-
dma_params.dst_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
313-
dma_params.dst_start = (unsigned long)fifo;
314-
dma_params.dst_ei = 1;
315-
dma_params.dst_fi = -31; /* Loop 32 byte window */
316-
317-
dma_params.trigger = dma_data->sync_dev;
318-
dma_params.sync_mode = OMAP_DMA_SYNC_FRAME;
319-
dma_params.src_or_dst_synch = 0; /* Dest sync */
320-
321-
src_burst = OMAP_DMA_DATA_BURST_16; /* 16x32 read */
322-
dst_burst = OMAP_DMA_DATA_BURST_8; /* 8x32 write */
323-
} else {
324-
dma_params.src_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
325-
dma_params.src_start = (unsigned long)fifo;
326-
dma_params.src_ei = 1;
327-
dma_params.src_fi = -31; /* Loop 32 byte window */
328-
329-
dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
330-
dma_params.dst_start = (unsigned long)dma_addr;
331-
dma_params.dst_ei = 0;
332-
dma_params.dst_fi = 0;
333-
334-
dma_params.trigger = dma_data->sync_dev;
335-
dma_params.sync_mode = OMAP_DMA_SYNC_FRAME;
336-
dma_params.src_or_dst_synch = 1; /* Source sync */
337-
338-
src_burst = OMAP_DMA_DATA_BURST_8; /* 8x32 read */
339-
dst_burst = OMAP_DMA_DATA_BURST_16; /* 16x32 write */
306+
dma_desc = dmaengine_prep_slave_single(dma_data->chan, dma_addr,
307+
chdat->transfer_len, dma_dir,
308+
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
309+
if (!dma_desc) {
310+
dev_err(musb->controller, "DMA prep_slave_single failed\n");
311+
return false;
340312
}
341313

342-
dev_dbg(musb->controller, "ep%i %s using %i-bit %s dma from 0x%08lx to 0x%08lx\n",
314+
dma_desc->callback = tusb_omap_dma_cb;
315+
dma_desc->callback_param = channel;
316+
dmaengine_submit(dma_desc);
317+
318+
dev_dbg(musb->controller,
319+
"ep%i %s using %i-bit %s dma from %pad to %pad\n",
343320
chdat->epnum, chdat->tx ? "tx" : "rx",
344-
(dma_params.data_type == OMAP_DMA_DATA_TYPE_S32) ? 32 : 16,
321+
dma_cfg.src_addr_width * 8,
345322
((dma_addr & 0x3) == 0) ? "sync" : "async",
346-
dma_params.src_start, dma_params.dst_start);
347-
348-
omap_set_dma_params(dma_data->ch, &dma_params);
349-
omap_set_dma_src_burst_mode(dma_data->ch, src_burst);
350-
omap_set_dma_dest_burst_mode(dma_data->ch, dst_burst);
351-
omap_set_dma_write_mode(dma_data->ch, OMAP_DMA_WRITE_LAST_NON_POSTED);
323+
(dma_dir == DMA_MEM_TO_DEV) ? &dma_addr : &fifo_addr,
324+
(dma_dir == DMA_MEM_TO_DEV) ? &fifo_addr : &dma_addr);
352325

353326
/*
354327
* Prepare MUSB for DMA transfer
@@ -368,10 +341,8 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
368341
csr | MUSB_RXCSR_P_WZC_BITS);
369342
}
370343

371-
/*
372-
* Start DMA transfer
373-
*/
374-
omap_start_dma(dma_data->ch);
344+
/* Start DMA transfer */
345+
dma_async_issue_pending(dma_data->chan);
375346

376347
if (chdat->tx) {
377348
/* Send transfer_packet_sz packets at a time */
@@ -401,7 +372,7 @@ static int tusb_omap_dma_abort(struct dma_channel *channel)
401372
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
402373

403374
if (chdat->dma_data)
404-
omap_stop_dma(chdat->dma_data->ch);
375+
dmaengine_terminate_all(chdat->dma_data->chan);
405376

406377
channel->status = MUSB_DMA_STATUS_FREE;
407378

@@ -511,11 +482,11 @@ tusb_omap_dma_allocate(struct dma_controller *c,
511482

512483
dma_data = chdat->dma_data;
513484

514-
dev_dbg(musb->controller, "ep%i %s dma: %s dma%i dmareq%i sync%i\n",
485+
dev_dbg(musb->controller, "ep%i %s dma: %s dmareq%i\n",
515486
chdat->epnum,
516487
chdat->tx ? "tx" : "rx",
517488
tusb_dma->multichannel ? "shared" : "dedicated",
518-
dma_data->ch, dma_data->dmareq, dma_data->sync_dev);
489+
dma_data->dmareq);
519490

520491
return channel;
521492

@@ -533,12 +504,11 @@ static void tusb_omap_dma_release(struct dma_channel *channel)
533504
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
534505
struct musb *musb = chdat->musb;
535506

536-
dev_dbg(musb->controller, "ep%i ch%i\n", chdat->epnum,
537-
chdat->dma_data->ch);
507+
dev_dbg(musb->controller, "Release for ep%i\n", chdat->epnum);
538508

539509
channel->status = MUSB_DMA_STATUS_UNKNOWN;
540510

541-
omap_stop_dma(chdat->dma_data->ch);
511+
dmaengine_terminate_sync(chdat->dma_data->chan);
542512
tusb_omap_dma_free_dmareq(chdat);
543513

544514
channel = NULL;
@@ -558,8 +528,8 @@ void tusb_dma_controller_destroy(struct dma_controller *c)
558528
}
559529

560530
/* Free up the DMA channels */
561-
if (tusb_dma && tusb_dma->dma_pool[i].ch >= 0)
562-
omap_free_dma(tusb_dma->dma_pool[i].ch);
531+
if (tusb_dma && tusb_dma->dma_pool[i].chan)
532+
dma_release_channel(tusb_dma->dma_pool[i].chan);
563533
}
564534

565535
kfree(tusb_dma);
@@ -568,16 +538,9 @@ EXPORT_SYMBOL_GPL(tusb_dma_controller_destroy);
568538

569539
static int tusb_omap_allocate_dma_pool(struct tusb_omap_dma *tusb_dma)
570540
{
541+
struct musb *musb = tusb_dma->controller.musb;
571542
int i;
572543
int ret = 0;
573-
const int sync_dev[6] = {
574-
OMAP24XX_DMA_EXT_DMAREQ0,
575-
OMAP24XX_DMA_EXT_DMAREQ1,
576-
OMAP242X_DMA_EXT_DMAREQ2,
577-
OMAP242X_DMA_EXT_DMAREQ3,
578-
OMAP242X_DMA_EXT_DMAREQ4,
579-
OMAP242X_DMA_EXT_DMAREQ5,
580-
};
581544

582545
for (i = 0; i < MAX_DMAREQ; i++) {
583546
struct tusb_dma_data *dma_data = &tusb_dma->dma_pool[i];
@@ -591,22 +554,18 @@ static int tusb_omap_allocate_dma_pool(struct tusb_omap_dma *tusb_dma)
591554
char ch_name[8];
592555

593556
sprintf(ch_name, "dmareq%d", i);
594-
dma_data->sync_dev = sync_dev[i];
595-
dma_data->ch = -1;
596-
/* callback data is ngoing to be set later */
597-
ret = omap_request_dma(dma_data->sync_dev, ch_name,
598-
tusb_omap_dma_cb, NULL, &dma_data->ch);
599-
if (ret != 0) {
600-
dev_err(tusb_dma->controller.musb->controller,
557+
dma_data->chan = dma_request_chan(musb->controller,
558+
ch_name);
559+
if (IS_ERR(dma_data->chan)) {
560+
dev_err(musb->controller,
601561
"Failed to request %s\n", ch_name);
562+
ret = PTR_ERR(dma_data->chan);
602563
goto dma_error;
603564
}
604565

605566
dma_data->dmareq = i;
606567
} else {
607568
dma_data->dmareq = -1;
608-
dma_data->sync_dev = -1;
609-
dma_data->ch = -1;
610569
}
611570
}
612571

@@ -616,8 +575,8 @@ static int tusb_omap_allocate_dma_pool(struct tusb_omap_dma *tusb_dma)
616575
for (; i >= 0; i--) {
617576
struct tusb_dma_data *dma_data = &tusb_dma->dma_pool[i];
618577

619-
if (dma_data->ch >= 0)
620-
omap_free_dma(dma_data->ch);
578+
if (dma_data->dmareq >= 0)
579+
dma_release_channel(dma_data->chan);
621580
}
622581

623582
return ret;

0 commit comments

Comments
 (0)