aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/dma/fsl-edma.c189
1 files changed, 96 insertions, 93 deletions
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index 58c6fc7e902e..6fb2e902b459 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -118,17 +118,17 @@
118 BIT(DMA_SLAVE_BUSWIDTH_8_BYTES) 118 BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)
119 119
120struct fsl_edma_hw_tcd { 120struct fsl_edma_hw_tcd {
121 u32 saddr; 121 __le32 saddr;
122 u16 soff; 122 __le16 soff;
123 u16 attr; 123 __le16 attr;
124 u32 nbytes; 124 __le32 nbytes;
125 u32 slast; 125 __le32 slast;
126 u32 daddr; 126 __le32 daddr;
127 u16 doff; 127 __le16 doff;
128 u16 citer; 128 __le16 citer;
129 u32 dlast_sga; 129 __le32 dlast_sga;
130 u16 csr; 130 __le16 csr;
131 u16 biter; 131 __le16 biter;
132}; 132};
133 133
134struct fsl_edma_sw_tcd { 134struct fsl_edma_sw_tcd {
@@ -175,18 +175,12 @@ struct fsl_edma_engine {
175}; 175};
176 176
177/* 177/*
178 * R/W functions for big- or little-endian registers 178 * R/W functions for big- or little-endian registers:
179 * the eDMA controller's endian is independent of the CPU core's endian. 179 * The eDMA controller's endian is independent of the CPU core's endian.
180 * For the big-endian IP module, the offset for 8-bit or 16-bit registers
181 * should also be swapped opposite to that in little-endian IP.
180 */ 182 */
181 183
182static u16 edma_readw(struct fsl_edma_engine *edma, void __iomem *addr)
183{
184 if (edma->big_endian)
185 return ioread16be(addr);
186 else
187 return ioread16(addr);
188}
189
190static u32 edma_readl(struct fsl_edma_engine *edma, void __iomem *addr) 184static u32 edma_readl(struct fsl_edma_engine *edma, void __iomem *addr)
191{ 185{
192 if (edma->big_endian) 186 if (edma->big_endian)
@@ -197,13 +191,18 @@ static u32 edma_readl(struct fsl_edma_engine *edma, void __iomem *addr)
197 191
198static void edma_writeb(struct fsl_edma_engine *edma, u8 val, void __iomem *addr) 192static void edma_writeb(struct fsl_edma_engine *edma, u8 val, void __iomem *addr)
199{ 193{
200 iowrite8(val, addr); 194 /* swap the reg offset for these in big-endian mode */
195 if (edma->big_endian)
196 iowrite8(val, (void __iomem *)((unsigned long)addr ^ 0x3));
197 else
198 iowrite8(val, addr);
201} 199}
202 200
203static void edma_writew(struct fsl_edma_engine *edma, u16 val, void __iomem *addr) 201static void edma_writew(struct fsl_edma_engine *edma, u16 val, void __iomem *addr)
204{ 202{
203 /* swap the reg offset for these in big-endian mode */
205 if (edma->big_endian) 204 if (edma->big_endian)
206 iowrite16be(val, addr); 205 iowrite16be(val, (void __iomem *)((unsigned long)addr ^ 0x2));
207 else 206 else
208 iowrite16(val, addr); 207 iowrite16(val, addr);
209} 208}
@@ -254,13 +253,12 @@ static void fsl_edma_chan_mux(struct fsl_edma_chan *fsl_chan,
254 chans_per_mux = fsl_chan->edma->n_chans / DMAMUX_NR; 253 chans_per_mux = fsl_chan->edma->n_chans / DMAMUX_NR;
255 ch_off = fsl_chan->vchan.chan.chan_id % chans_per_mux; 254 ch_off = fsl_chan->vchan.chan.chan_id % chans_per_mux;
256 muxaddr = fsl_chan->edma->muxbase[ch / chans_per_mux]; 255 muxaddr = fsl_chan->edma->muxbase[ch / chans_per_mux];
256 slot = EDMAMUX_CHCFG_SOURCE(slot);
257 257
258 if (enable) 258 if (enable)
259 edma_writeb(fsl_chan->edma, 259 iowrite8(EDMAMUX_CHCFG_ENBL | slot, muxaddr + ch_off);
260 EDMAMUX_CHCFG_ENBL | EDMAMUX_CHCFG_SOURCE(slot),
261 muxaddr + ch_off);
262 else 260 else
263 edma_writeb(fsl_chan->edma, EDMAMUX_CHCFG_DIS, muxaddr + ch_off); 261 iowrite8(EDMAMUX_CHCFG_DIS, muxaddr + ch_off);
264} 262}
265 263
266static unsigned int fsl_edma_get_tcd_attr(enum dma_slave_buswidth addr_width) 264static unsigned int fsl_edma_get_tcd_attr(enum dma_slave_buswidth addr_width)
@@ -286,9 +284,8 @@ static void fsl_edma_free_desc(struct virt_dma_desc *vdesc)
286 284
287 fsl_desc = to_fsl_edma_desc(vdesc); 285 fsl_desc = to_fsl_edma_desc(vdesc);
288 for (i = 0; i < fsl_desc->n_tcds; i++) 286 for (i = 0; i < fsl_desc->n_tcds; i++)
289 dma_pool_free(fsl_desc->echan->tcd_pool, 287 dma_pool_free(fsl_desc->echan->tcd_pool, fsl_desc->tcd[i].vtcd,
290 fsl_desc->tcd[i].vtcd, 288 fsl_desc->tcd[i].ptcd);
291 fsl_desc->tcd[i].ptcd);
292 kfree(fsl_desc); 289 kfree(fsl_desc);
293} 290}
294 291
@@ -363,8 +360,8 @@ static size_t fsl_edma_desc_residue(struct fsl_edma_chan *fsl_chan,
363 360
364 /* calculate the total size in this desc */ 361 /* calculate the total size in this desc */
365 for (len = i = 0; i < fsl_chan->edesc->n_tcds; i++) 362 for (len = i = 0; i < fsl_chan->edesc->n_tcds; i++)
366 len += edma_readl(fsl_chan->edma, &(edesc->tcd[i].vtcd->nbytes)) 363 len += le32_to_cpu(edesc->tcd[i].vtcd->nbytes)
367 * edma_readw(fsl_chan->edma, &(edesc->tcd[i].vtcd->biter)); 364 * le16_to_cpu(edesc->tcd[i].vtcd->biter);
368 365
369 if (!in_progress) 366 if (!in_progress)
370 return len; 367 return len;
@@ -376,14 +373,12 @@ static size_t fsl_edma_desc_residue(struct fsl_edma_chan *fsl_chan,
376 373
377 /* figure out the finished and calculate the residue */ 374 /* figure out the finished and calculate the residue */
378 for (i = 0; i < fsl_chan->edesc->n_tcds; i++) { 375 for (i = 0; i < fsl_chan->edesc->n_tcds; i++) {
379 size = edma_readl(fsl_chan->edma, &(edesc->tcd[i].vtcd->nbytes)) 376 size = le32_to_cpu(edesc->tcd[i].vtcd->nbytes)
380 * edma_readw(fsl_chan->edma, &(edesc->tcd[i].vtcd->biter)); 377 * le16_to_cpu(edesc->tcd[i].vtcd->biter);
381 if (dir == DMA_MEM_TO_DEV) 378 if (dir == DMA_MEM_TO_DEV)
382 dma_addr = edma_readl(fsl_chan->edma, 379 dma_addr = le32_to_cpu(edesc->tcd[i].vtcd->saddr);
383 &(edesc->tcd[i].vtcd->saddr));
384 else 380 else
385 dma_addr = edma_readl(fsl_chan->edma, 381 dma_addr = le32_to_cpu(edesc->tcd[i].vtcd->daddr);
386 &(edesc->tcd[i].vtcd->daddr));
387 382
388 len -= size; 383 len -= size;
389 if (cur_addr >= dma_addr && cur_addr < dma_addr + size) { 384 if (cur_addr >= dma_addr && cur_addr < dma_addr + size) {
@@ -424,55 +419,67 @@ static enum dma_status fsl_edma_tx_status(struct dma_chan *chan,
424 return fsl_chan->status; 419 return fsl_chan->status;
425} 420}
426 421
427static void fsl_edma_set_tcd_params(struct fsl_edma_chan *fsl_chan, 422static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
428 u32 src, u32 dst, u16 attr, u16 soff, u32 nbytes, 423 struct fsl_edma_hw_tcd *tcd)
429 u32 slast, u16 citer, u16 biter, u32 doff, u32 dlast_sga,
430 u16 csr)
431{ 424{
425 struct fsl_edma_engine *edma = fsl_chan->edma;
432 void __iomem *addr = fsl_chan->edma->membase; 426 void __iomem *addr = fsl_chan->edma->membase;
433 u32 ch = fsl_chan->vchan.chan.chan_id; 427 u32 ch = fsl_chan->vchan.chan.chan_id;
434 428
435 /* 429 /*
436 * TCD parameters have been swapped in fill_tcd_params(), 430 * TCD parameters are stored in struct fsl_edma_hw_tcd in little
437 * so just write them to registers in the cpu endian here 431 * endian format. However, we need to load the TCD registers in
432 * big- or little-endian obeying the eDMA engine model endian.
438 */ 433 */
439 writew(0, addr + EDMA_TCD_CSR(ch)); 434 edma_writew(edma, 0, addr + EDMA_TCD_CSR(ch));
440 writel(src, addr + EDMA_TCD_SADDR(ch)); 435 edma_writel(edma, le32_to_cpu(tcd->saddr), addr + EDMA_TCD_SADDR(ch));
441 writel(dst, addr + EDMA_TCD_DADDR(ch)); 436 edma_writel(edma, le32_to_cpu(tcd->daddr), addr + EDMA_TCD_DADDR(ch));
442 writew(attr, addr + EDMA_TCD_ATTR(ch)); 437
443 writew(soff, addr + EDMA_TCD_SOFF(ch)); 438 edma_writew(edma, le16_to_cpu(tcd->attr), addr + EDMA_TCD_ATTR(ch));
444 writel(nbytes, addr + EDMA_TCD_NBYTES(ch)); 439 edma_writew(edma, le16_to_cpu(tcd->soff), addr + EDMA_TCD_SOFF(ch));
445 writel(slast, addr + EDMA_TCD_SLAST(ch)); 440
446 writew(citer, addr + EDMA_TCD_CITER(ch)); 441 edma_writel(edma, le32_to_cpu(tcd->nbytes), addr + EDMA_TCD_NBYTES(ch));
447 writew(biter, addr + EDMA_TCD_BITER(ch)); 442 edma_writel(edma, le32_to_cpu(tcd->slast), addr + EDMA_TCD_SLAST(ch));
448 writew(doff, addr + EDMA_TCD_DOFF(ch)); 443
449 writel(dlast_sga, addr + EDMA_TCD_DLAST_SGA(ch)); 444 edma_writew(edma, le16_to_cpu(tcd->citer), addr + EDMA_TCD_CITER(ch));
450 writew(csr, addr + EDMA_TCD_CSR(ch)); 445 edma_writew(edma, le16_to_cpu(tcd->biter), addr + EDMA_TCD_BITER(ch));
451} 446 edma_writew(edma, le16_to_cpu(tcd->doff), addr + EDMA_TCD_DOFF(ch));
452 447
453static void fill_tcd_params(struct fsl_edma_engine *edma, 448 edma_writel(edma, le32_to_cpu(tcd->dlast_sga), addr + EDMA_TCD_DLAST_SGA(ch));
454 struct fsl_edma_hw_tcd *tcd, u32 src, u32 dst, 449
455 u16 attr, u16 soff, u32 nbytes, u32 slast, u16 citer, 450 edma_writew(edma, le16_to_cpu(tcd->csr), addr + EDMA_TCD_CSR(ch));
456 u16 biter, u16 doff, u32 dlast_sga, bool major_int, 451}
457 bool disable_req, bool enable_sg) 452
453static inline
454void fsl_edma_fill_tcd(struct fsl_edma_hw_tcd *tcd, u32 src, u32 dst,
455 u16 attr, u16 soff, u32 nbytes, u32 slast, u16 citer,
456 u16 biter, u16 doff, u32 dlast_sga, bool major_int,
457 bool disable_req, bool enable_sg)
458{ 458{
459 u16 csr = 0; 459 u16 csr = 0;
460 460
461 /* 461 /*
462 * eDMA hardware SGs require the TCD parameters stored in memory 462 * eDMA hardware SGs require the TCDs to be stored in little
463 * the same endian as the eDMA module so that they can be loaded 463 * endian format irrespective of the register endian model.
464 * automatically by the engine 464 * So we put the value in little endian in memory, waiting
465 * for fsl_edma_set_tcd_regs doing the swap.
465 */ 466 */
466 edma_writel(edma, src, &(tcd->saddr)); 467 tcd->saddr = cpu_to_le32(src);
467 edma_writel(edma, dst, &(tcd->daddr)); 468 tcd->daddr = cpu_to_le32(dst);
468 edma_writew(edma, attr, &(tcd->attr)); 469
469 edma_writew(edma, EDMA_TCD_SOFF_SOFF(soff), &(tcd->soff)); 470 tcd->attr = cpu_to_le16(attr);
470 edma_writel(edma, EDMA_TCD_NBYTES_NBYTES(nbytes), &(tcd->nbytes)); 471
471 edma_writel(edma, EDMA_TCD_SLAST_SLAST(slast), &(tcd->slast)); 472 tcd->soff = cpu_to_le16(EDMA_TCD_SOFF_SOFF(soff));
472 edma_writew(edma, EDMA_TCD_CITER_CITER(citer), &(tcd->citer)); 473
473 edma_writew(edma, EDMA_TCD_DOFF_DOFF(doff), &(tcd->doff)); 474 tcd->nbytes = cpu_to_le32(EDMA_TCD_NBYTES_NBYTES(nbytes));
474 edma_writel(edma, EDMA_TCD_DLAST_SGA_DLAST_SGA(dlast_sga), &(tcd->dlast_sga)); 475 tcd->slast = cpu_to_le32(EDMA_TCD_SLAST_SLAST(slast));
475 edma_writew(edma, EDMA_TCD_BITER_BITER(biter), &(tcd->biter)); 476
477 tcd->citer = cpu_to_le16(EDMA_TCD_CITER_CITER(citer));
478 tcd->doff = cpu_to_le16(EDMA_TCD_DOFF_DOFF(doff));
479
480 tcd->dlast_sga = cpu_to_le32(EDMA_TCD_DLAST_SGA_DLAST_SGA(dlast_sga));
481
482 tcd->biter = cpu_to_le16(EDMA_TCD_BITER_BITER(biter));
476 if (major_int) 483 if (major_int)
477 csr |= EDMA_TCD_CSR_INT_MAJOR; 484 csr |= EDMA_TCD_CSR_INT_MAJOR;
478 485
@@ -482,7 +489,7 @@ static void fill_tcd_params(struct fsl_edma_engine *edma,
482 if (enable_sg) 489 if (enable_sg)
483 csr |= EDMA_TCD_CSR_E_SG; 490 csr |= EDMA_TCD_CSR_E_SG;
484 491
485 edma_writew(edma, csr, &(tcd->csr)); 492 tcd->csr = cpu_to_le16(csr);
486} 493}
487 494
488static struct fsl_edma_desc *fsl_edma_alloc_desc(struct fsl_edma_chan *fsl_chan, 495static struct fsl_edma_desc *fsl_edma_alloc_desc(struct fsl_edma_chan *fsl_chan,
@@ -558,9 +565,9 @@ static struct dma_async_tx_descriptor *fsl_edma_prep_dma_cyclic(
558 doff = fsl_chan->fsc.addr_width; 565 doff = fsl_chan->fsc.addr_width;
559 } 566 }
560 567
561 fill_tcd_params(fsl_chan->edma, fsl_desc->tcd[i].vtcd, src_addr, 568 fsl_edma_fill_tcd(fsl_desc->tcd[i].vtcd, src_addr, dst_addr,
562 dst_addr, fsl_chan->fsc.attr, soff, nbytes, 0, 569 fsl_chan->fsc.attr, soff, nbytes, 0, iter,
563 iter, iter, doff, last_sg, true, false, true); 570 iter, doff, last_sg, true, false, true);
564 dma_buf_next += period_len; 571 dma_buf_next += period_len;
565 } 572 }
566 573
@@ -607,16 +614,16 @@ static struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg(
607 iter = sg_dma_len(sg) / nbytes; 614 iter = sg_dma_len(sg) / nbytes;
608 if (i < sg_len - 1) { 615 if (i < sg_len - 1) {
609 last_sg = fsl_desc->tcd[(i + 1)].ptcd; 616 last_sg = fsl_desc->tcd[(i + 1)].ptcd;
610 fill_tcd_params(fsl_chan->edma, fsl_desc->tcd[i].vtcd, 617 fsl_edma_fill_tcd(fsl_desc->tcd[i].vtcd, src_addr,
611 src_addr, dst_addr, fsl_chan->fsc.attr, 618 dst_addr, fsl_chan->fsc.attr, soff,
612 soff, nbytes, 0, iter, iter, doff, last_sg, 619 nbytes, 0, iter, iter, doff, last_sg,
613 false, false, true); 620 false, false, true);
614 } else { 621 } else {
615 last_sg = 0; 622 last_sg = 0;
616 fill_tcd_params(fsl_chan->edma, fsl_desc->tcd[i].vtcd, 623 fsl_edma_fill_tcd(fsl_desc->tcd[i].vtcd, src_addr,
617 src_addr, dst_addr, fsl_chan->fsc.attr, 624 dst_addr, fsl_chan->fsc.attr, soff,
618 soff, nbytes, 0, iter, iter, doff, last_sg, 625 nbytes, 0, iter, iter, doff, last_sg,
619 true, true, false); 626 true, true, false);
620 } 627 }
621 } 628 }
622 629
@@ -625,17 +632,13 @@ static struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg(
625 632
626static void fsl_edma_xfer_desc(struct fsl_edma_chan *fsl_chan) 633static void fsl_edma_xfer_desc(struct fsl_edma_chan *fsl_chan)
627{ 634{
628 struct fsl_edma_hw_tcd *tcd;
629 struct virt_dma_desc *vdesc; 635 struct virt_dma_desc *vdesc;
630 636
631 vdesc = vchan_next_desc(&fsl_chan->vchan); 637 vdesc = vchan_next_desc(&fsl_chan->vchan);
632 if (!vdesc) 638 if (!vdesc)
633 return; 639 return;
634 fsl_chan->edesc = to_fsl_edma_desc(vdesc); 640 fsl_chan->edesc = to_fsl_edma_desc(vdesc);
635 tcd = fsl_chan->edesc->tcd[0].vtcd; 641 fsl_edma_set_tcd_regs(fsl_chan, fsl_chan->edesc->tcd[0].vtcd);
636 fsl_edma_set_tcd_params(fsl_chan, tcd->saddr, tcd->daddr, tcd->attr,
637 tcd->soff, tcd->nbytes, tcd->slast, tcd->citer,
638 tcd->biter, tcd->doff, tcd->dlast_sga, tcd->csr);
639 fsl_edma_enable_request(fsl_chan); 642 fsl_edma_enable_request(fsl_chan);
640 fsl_chan->status = DMA_IN_PROGRESS; 643 fsl_chan->status = DMA_IN_PROGRESS;
641} 644}