aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorTomasz Figa <tomasz.figa@gmail.com>2013-08-11 13:59:15 -0400
committerVinod Koul <vinod.koul@intel.com>2013-09-02 02:19:56 -0400
commitba6785ffc85bcf967b0646f4e8b9b13fdbad3254 (patch)
treef34a53c16eba8d9ab5094ba4247977d041b144a7 /drivers/dma
parentd86ccea79485fcc637d3a69fdf6ebe90094da307 (diff)
dmaengine: PL08x: Rework LLI handling to be less fragile
Currently memory allocated for LLIs is casted to an array of structs, which is fragile and also limits the driver to a single, predefined LLI layout, while there are some variants of PL08x, which have more fields in LLI (namely PL080S with its extra CCTL2). This patch makes LLIs a sequence of 32-bit words, which is just filled with appropriate values in appropriate order and padded with required amount of dummy words (currently zero, but PL080S will make better use of this). Suggested-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/amba-pl08x.c147
1 files changed, 82 insertions, 65 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 2538e05de5bf..d3399c2c090f 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -108,19 +108,6 @@ struct vendor_data {
108 bool nomadik; 108 bool nomadik;
109}; 109};
110 110
111/*
112 * PL08X private data structures
113 * An LLI struct - see PL08x TRM. Note that next uses bit[0] as a bus bit,
114 * start & end do not - their bus bit info is in cctl. Also note that these
115 * are fixed 32-bit quantities.
116 */
117struct pl08x_lli {
118 u32 src;
119 u32 dst;
120 u32 lli;
121 u32 cctl;
122};
123
124/** 111/**
125 * struct pl08x_bus_data - information of source or destination 112 * struct pl08x_bus_data - information of source or destination
126 * busses for a transfer 113 * busses for a transfer
@@ -181,7 +168,7 @@ struct pl08x_txd {
181 struct virt_dma_desc vd; 168 struct virt_dma_desc vd;
182 struct list_head dsg_list; 169 struct list_head dsg_list;
183 dma_addr_t llis_bus; 170 dma_addr_t llis_bus;
184 struct pl08x_lli *llis_va; 171 u32 *llis_va;
185 /* Default cctl value for LLIs */ 172 /* Default cctl value for LLIs */
186 u32 cctl; 173 u32 cctl;
187 /* 174 /*
@@ -265,17 +252,27 @@ struct pl08x_driver_data {
265 struct dma_pool *pool; 252 struct dma_pool *pool;
266 u8 lli_buses; 253 u8 lli_buses;
267 u8 mem_buses; 254 u8 mem_buses;
255 u8 lli_words;
268}; 256};
269 257
270/* 258/*
271 * PL08X specific defines 259 * PL08X specific defines
272 */ 260 */
273 261
274/* Size (bytes) of each LLI buffer allocated for one transfer */ 262/* The order of words in an LLI. */
275# define PL08X_LLI_TSFR_SIZE 0x2000 263#define PL080_LLI_SRC 0
264#define PL080_LLI_DST 1
265#define PL080_LLI_LLI 2
266#define PL080_LLI_CCTL 3
267
268/* Total words in an LLI. */
269#define PL080_LLI_WORDS 4
276 270
277/* Maximum times we call dma_pool_alloc on this pool without freeing */ 271/*
278#define MAX_NUM_TSFR_LLIS (PL08X_LLI_TSFR_SIZE/sizeof(struct pl08x_lli)) 272 * Number of LLIs in each LLI buffer allocated for one transfer
273 * (maximum times we call dma_pool_alloc on this pool without freeing)
274 */
275#define MAX_NUM_TSFR_LLIS 512
279#define PL08X_ALIGN 8 276#define PL08X_ALIGN 8
280 277
281static inline struct pl08x_dma_chan *to_pl08x_chan(struct dma_chan *chan) 278static inline struct pl08x_dma_chan *to_pl08x_chan(struct dma_chan *chan)
@@ -340,6 +337,23 @@ static int pl08x_phy_channel_busy(struct pl08x_phy_chan *ch)
340 return val & PL080_CONFIG_ACTIVE; 337 return val & PL080_CONFIG_ACTIVE;
341} 338}
342 339
340static void pl08x_write_lli(struct pl08x_driver_data *pl08x,
341 struct pl08x_phy_chan *phychan, const u32 *lli, u32 ccfg)
342{
343 dev_vdbg(&pl08x->adev->dev,
344 "WRITE channel %d: csrc=0x%08x, cdst=0x%08x, "
345 "clli=0x%08x, cctl=0x%08x, ccfg=0x%08x\n",
346 phychan->id, lli[PL080_LLI_SRC], lli[PL080_LLI_DST],
347 lli[PL080_LLI_LLI], lli[PL080_LLI_CCTL], ccfg);
348
349 writel_relaxed(lli[PL080_LLI_SRC], phychan->base + PL080_CH_SRC_ADDR);
350 writel_relaxed(lli[PL080_LLI_DST], phychan->base + PL080_CH_DST_ADDR);
351 writel_relaxed(lli[PL080_LLI_LLI], phychan->base + PL080_CH_LLI);
352 writel_relaxed(lli[PL080_LLI_CCTL], phychan->base + PL080_CH_CONTROL);
353
354 writel(ccfg, phychan->reg_config);
355}
356
343/* 357/*
344 * Set the initial DMA register values i.e. those for the first LLI 358 * Set the initial DMA register values i.e. those for the first LLI
345 * The next LLI pointer and the configuration interrupt bit have 359 * The next LLI pointer and the configuration interrupt bit have
@@ -352,7 +366,6 @@ static void pl08x_start_next_txd(struct pl08x_dma_chan *plchan)
352 struct pl08x_phy_chan *phychan = plchan->phychan; 366 struct pl08x_phy_chan *phychan = plchan->phychan;
353 struct virt_dma_desc *vd = vchan_next_desc(&plchan->vc); 367 struct virt_dma_desc *vd = vchan_next_desc(&plchan->vc);
354 struct pl08x_txd *txd = to_pl08x_txd(&vd->tx); 368 struct pl08x_txd *txd = to_pl08x_txd(&vd->tx);
355 struct pl08x_lli *lli;
356 u32 val; 369 u32 val;
357 370
358 list_del(&txd->vd.node); 371 list_del(&txd->vd.node);
@@ -363,19 +376,7 @@ static void pl08x_start_next_txd(struct pl08x_dma_chan *plchan)
363 while (pl08x_phy_channel_busy(phychan)) 376 while (pl08x_phy_channel_busy(phychan))
364 cpu_relax(); 377 cpu_relax();
365 378
366 lli = &txd->llis_va[0]; 379 pl08x_write_lli(pl08x, phychan, &txd->llis_va[0], txd->ccfg);
367
368 dev_vdbg(&pl08x->adev->dev,
369 "WRITE channel %d: csrc=0x%08x, cdst=0x%08x, "
370 "clli=0x%08x, cctl=0x%08x, ccfg=0x%08x\n",
371 phychan->id, lli->src, lli->dst, lli->lli, lli->cctl,
372 txd->ccfg);
373
374 writel(lli->src, phychan->base + PL080_CH_SRC_ADDR);
375 writel(lli->dst, phychan->base + PL080_CH_DST_ADDR);
376 writel(lli->lli, phychan->base + PL080_CH_LLI);
377 writel(lli->cctl, phychan->base + PL080_CH_CONTROL);
378 writel(txd->ccfg, phychan->reg_config);
379 380
380 /* Enable the DMA channel */ 381 /* Enable the DMA channel */
381 /* Do not access config register until channel shows as disabled */ 382 /* Do not access config register until channel shows as disabled */
@@ -471,12 +472,13 @@ static inline u32 get_bytes_in_cctl(u32 cctl)
471/* The channel should be paused when calling this */ 472/* The channel should be paused when calling this */
472static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan) 473static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
473{ 474{
474 struct pl08x_lli *llis_va; 475 struct pl08x_driver_data *pl08x = plchan->host;
476 const u32 *llis_va, *llis_va_limit;
475 struct pl08x_phy_chan *ch; 477 struct pl08x_phy_chan *ch;
476 dma_addr_t llis_bus; 478 dma_addr_t llis_bus;
477 struct pl08x_txd *txd; 479 struct pl08x_txd *txd;
480 u32 llis_max_words;
478 size_t bytes; 481 size_t bytes;
479 int index;
480 u32 clli; 482 u32 clli;
481 483
482 ch = plchan->phychan; 484 ch = plchan->phychan;
@@ -500,22 +502,25 @@ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
500 llis_va = txd->llis_va; 502 llis_va = txd->llis_va;
501 llis_bus = txd->llis_bus; 503 llis_bus = txd->llis_bus;
502 504
505 llis_max_words = pl08x->lli_words * MAX_NUM_TSFR_LLIS;
503 BUG_ON(clli < llis_bus || clli >= llis_bus + 506 BUG_ON(clli < llis_bus || clli >= llis_bus +
504 sizeof(struct pl08x_lli) * MAX_NUM_TSFR_LLIS); 507 sizeof(u32) * llis_max_words);
505 508
506 /* 509 /*
507 * Locate the next LLI - as this is an array, 510 * Locate the next LLI - as this is an array,
508 * it's simple maths to find. 511 * it's simple maths to find.
509 */ 512 */
510 index = (clli - llis_bus) / sizeof(struct pl08x_lli); 513 llis_va += (clli - llis_bus) / sizeof(u32);
511 514
512 for (; index < MAX_NUM_TSFR_LLIS; index++) { 515 llis_va_limit = llis_va + llis_max_words;
513 bytes += get_bytes_in_cctl(llis_va[index].cctl); 516
517 for (; llis_va < llis_va_limit; llis_va += pl08x->lli_words) {
518 bytes += get_bytes_in_cctl(llis_va[PL080_LLI_CCTL]);
514 519
515 /* 520 /*
516 * A LLI pointer of 0 terminates the LLI list 521 * A LLI pointer of 0 terminates the LLI list
517 */ 522 */
518 if (!llis_va[index].lli) 523 if (!llis_va[PL080_LLI_LLI])
519 break; 524 break;
520 } 525 }
521 526
@@ -771,20 +776,24 @@ static void pl08x_choose_master_bus(struct pl08x_lli_build_data *bd,
771/* 776/*
772 * Fills in one LLI for a certain transfer descriptor and advance the counter 777 * Fills in one LLI for a certain transfer descriptor and advance the counter
773 */ 778 */
774static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd, 779static void pl08x_fill_lli_for_desc(struct pl08x_driver_data *pl08x,
775 int num_llis, int len, u32 cctl) 780 struct pl08x_lli_build_data *bd,
781 int num_llis, int len, u32 cctl)
776{ 782{
777 struct pl08x_lli *llis_va = bd->txd->llis_va; 783 u32 offset = num_llis * pl08x->lli_words;
784 u32 *llis_va = bd->txd->llis_va + offset;
778 dma_addr_t llis_bus = bd->txd->llis_bus; 785 dma_addr_t llis_bus = bd->txd->llis_bus;
779 786
780 BUG_ON(num_llis >= MAX_NUM_TSFR_LLIS); 787 BUG_ON(num_llis >= MAX_NUM_TSFR_LLIS);
781 788
782 llis_va[num_llis].cctl = cctl; 789 /* Advance the offset to next LLI. */
783 llis_va[num_llis].src = bd->srcbus.addr; 790 offset += pl08x->lli_words;
784 llis_va[num_llis].dst = bd->dstbus.addr; 791
785 llis_va[num_llis].lli = llis_bus + (num_llis + 1) * 792 llis_va[PL080_LLI_SRC] = bd->srcbus.addr;
786 sizeof(struct pl08x_lli); 793 llis_va[PL080_LLI_DST] = bd->dstbus.addr;
787 llis_va[num_llis].lli |= bd->lli_bus; 794 llis_va[PL080_LLI_LLI] = (llis_bus + sizeof(u32) * offset);
795 llis_va[PL080_LLI_LLI] |= bd->lli_bus;
796 llis_va[PL080_LLI_CCTL] = cctl;
788 797
789 if (cctl & PL080_CONTROL_SRC_INCR) 798 if (cctl & PL080_CONTROL_SRC_INCR)
790 bd->srcbus.addr += len; 799 bd->srcbus.addr += len;
@@ -796,11 +805,12 @@ static void pl08x_fill_lli_for_desc(struct pl08x_lli_build_data *bd,
796 bd->remainder -= len; 805 bd->remainder -= len;
797} 806}
798 807
799static inline void prep_byte_width_lli(struct pl08x_lli_build_data *bd, 808static inline void prep_byte_width_lli(struct pl08x_driver_data *pl08x,
800 u32 *cctl, u32 len, int num_llis, size_t *total_bytes) 809 struct pl08x_lli_build_data *bd, u32 *cctl, u32 len,
810 int num_llis, size_t *total_bytes)
801{ 811{
802 *cctl = pl08x_cctl_bits(*cctl, 1, 1, len); 812 *cctl = pl08x_cctl_bits(*cctl, 1, 1, len);
803 pl08x_fill_lli_for_desc(bd, num_llis, len, *cctl); 813 pl08x_fill_lli_for_desc(pl08x, bd, num_llis, len, *cctl);
804 (*total_bytes) += len; 814 (*total_bytes) += len;
805} 815}
806 816
@@ -817,7 +827,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
817 int num_llis = 0; 827 int num_llis = 0;
818 u32 cctl, early_bytes = 0; 828 u32 cctl, early_bytes = 0;
819 size_t max_bytes_per_lli, total_bytes; 829 size_t max_bytes_per_lli, total_bytes;
820 struct pl08x_lli *llis_va; 830 u32 *llis_va, *last_lli;
821 struct pl08x_sg *dsg; 831 struct pl08x_sg *dsg;
822 832
823 txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT, &txd->llis_bus); 833 txd->llis_va = dma_pool_alloc(pl08x->pool, GFP_NOWAIT, &txd->llis_bus);
@@ -904,7 +914,8 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
904 914
905 cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth, 915 cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
906 bd.dstbus.buswidth, 0); 916 bd.dstbus.buswidth, 0);
907 pl08x_fill_lli_for_desc(&bd, num_llis++, 0, cctl); 917 pl08x_fill_lli_for_desc(pl08x, &bd, num_llis++,
918 0, cctl);
908 break; 919 break;
909 } 920 }
910 921
@@ -926,8 +937,8 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
926 dev_vdbg(&pl08x->adev->dev, 937 dev_vdbg(&pl08x->adev->dev,
927 "%s byte width LLIs (remain 0x%08x)\n", 938 "%s byte width LLIs (remain 0x%08x)\n",
928 __func__, bd.remainder); 939 __func__, bd.remainder);
929 prep_byte_width_lli(&bd, &cctl, early_bytes, num_llis++, 940 prep_byte_width_lli(pl08x, &bd, &cctl, early_bytes,
930 &total_bytes); 941 num_llis++, &total_bytes);
931 } 942 }
932 943
933 if (bd.remainder) { 944 if (bd.remainder) {
@@ -983,7 +994,7 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
983 994
984 cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth, 995 cctl = pl08x_cctl_bits(cctl, bd.srcbus.buswidth,
985 bd.dstbus.buswidth, tsize); 996 bd.dstbus.buswidth, tsize);
986 pl08x_fill_lli_for_desc(&bd, num_llis++, 997 pl08x_fill_lli_for_desc(pl08x, &bd, num_llis++,
987 lli_len, cctl); 998 lli_len, cctl);
988 total_bytes += lli_len; 999 total_bytes += lli_len;
989 } 1000 }
@@ -995,8 +1006,8 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
995 dev_vdbg(&pl08x->adev->dev, 1006 dev_vdbg(&pl08x->adev->dev,
996 "%s align with boundary, send odd bytes (remain %zu)\n", 1007 "%s align with boundary, send odd bytes (remain %zu)\n",
997 __func__, bd.remainder); 1008 __func__, bd.remainder);
998 prep_byte_width_lli(&bd, &cctl, bd.remainder, 1009 prep_byte_width_lli(pl08x, &bd, &cctl,
999 num_llis++, &total_bytes); 1010 bd.remainder, num_llis++, &total_bytes);
1000 } 1011 }
1001 } 1012 }
1002 1013
@@ -1010,16 +1021,17 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
1010 if (num_llis >= MAX_NUM_TSFR_LLIS) { 1021 if (num_llis >= MAX_NUM_TSFR_LLIS) {
1011 dev_err(&pl08x->adev->dev, 1022 dev_err(&pl08x->adev->dev,
1012 "%s need to increase MAX_NUM_TSFR_LLIS from 0x%08x\n", 1023 "%s need to increase MAX_NUM_TSFR_LLIS from 0x%08x\n",
1013 __func__, (u32) MAX_NUM_TSFR_LLIS); 1024 __func__, MAX_NUM_TSFR_LLIS);
1014 return 0; 1025 return 0;
1015 } 1026 }
1016 } 1027 }
1017 1028
1018 llis_va = txd->llis_va; 1029 llis_va = txd->llis_va;
1030 last_lli = llis_va + (num_llis - 1) * pl08x->lli_words;
1019 /* The final LLI terminates the LLI. */ 1031 /* The final LLI terminates the LLI. */
1020 llis_va[num_llis - 1].lli = 0; 1032 last_lli[PL080_LLI_LLI] = 0;
1021 /* The final LLI element shall also fire an interrupt. */ 1033 /* The final LLI element shall also fire an interrupt. */
1022 llis_va[num_llis - 1].cctl |= PL080_CONTROL_TC_IRQ_EN; 1034 last_lli[PL080_LLI_CCTL] |= PL080_CONTROL_TC_IRQ_EN;
1023 1035
1024#ifdef VERBOSE_DEBUG 1036#ifdef VERBOSE_DEBUG
1025 { 1037 {
@@ -1031,9 +1043,10 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
1031 for (i = 0; i < num_llis; i++) { 1043 for (i = 0; i < num_llis; i++) {
1032 dev_vdbg(&pl08x->adev->dev, 1044 dev_vdbg(&pl08x->adev->dev,
1033 "%3d @%p: 0x%08x 0x%08x 0x%08x 0x%08x\n", 1045 "%3d @%p: 0x%08x 0x%08x 0x%08x 0x%08x\n",
1034 i, &llis_va[i], llis_va[i].src, 1046 i, llis_va, llis_va[PL080_LLI_SRC],
1035 llis_va[i].dst, llis_va[i].lli, llis_va[i].cctl 1047 llis_va[PL080_LLI_DST], llis_va[PL080_LLI_LLI],
1036 ); 1048 llis_va[PL080_LLI_CCTL]);
1049 llis_va += pl08x->lli_words;
1037 } 1050 }
1038 } 1051 }
1039#endif 1052#endif
@@ -1853,6 +1866,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
1853{ 1866{
1854 struct pl08x_driver_data *pl08x; 1867 struct pl08x_driver_data *pl08x;
1855 const struct vendor_data *vd = id->data; 1868 const struct vendor_data *vd = id->data;
1869 u32 tsfr_size;
1856 int ret = 0; 1870 int ret = 0;
1857 int i; 1871 int i;
1858 1872
@@ -1909,9 +1923,12 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
1909 pl08x->mem_buses = pl08x->pd->mem_buses; 1923 pl08x->mem_buses = pl08x->pd->mem_buses;
1910 } 1924 }
1911 1925
1926 pl08x->lli_words = PL080_LLI_WORDS;
1927 tsfr_size = MAX_NUM_TSFR_LLIS * pl08x->lli_words * sizeof(u32);
1928
1912 /* A DMA memory pool for LLIs, align on 1-byte boundary */ 1929 /* A DMA memory pool for LLIs, align on 1-byte boundary */
1913 pl08x->pool = dma_pool_create(DRIVER_NAME, &pl08x->adev->dev, 1930 pl08x->pool = dma_pool_create(DRIVER_NAME, &pl08x->adev->dev,
1914 PL08X_LLI_TSFR_SIZE, PL08X_ALIGN, 0); 1931 tsfr_size, PL08X_ALIGN, 0);
1915 if (!pl08x->pool) { 1932 if (!pl08x->pool) {
1916 ret = -ENOMEM; 1933 ret = -ENOMEM;
1917 goto out_no_lli_pool; 1934 goto out_no_lli_pool;