.. | .. |
---|
405 | 405 | */ |
---|
406 | 406 | BUSY, |
---|
407 | 407 | /* |
---|
| 408 | + * Pause was called while descriptor was BUSY. Due to hardware |
---|
| 409 | + * limitations, only termination is possible for descriptors |
---|
| 410 | + * that have been paused. |
---|
| 411 | + */ |
---|
| 412 | + PAUSED, |
---|
| 413 | + /* |
---|
408 | 414 | * Sitting on the channel work_list but xfer done |
---|
409 | 415 | * by PL330 core |
---|
410 | 416 | */ |
---|
.. | .. |
---|
541 | 547 | /* For cyclic capability */ |
---|
542 | 548 | bool cyclic; |
---|
543 | 549 | size_t num_periods; |
---|
544 | | -#ifdef CONFIG_NO_GKI |
---|
545 | | - /* interlace size */ |
---|
546 | | - unsigned int src_interlace_size; |
---|
547 | | - unsigned int dst_interlace_size; |
---|
548 | | -#endif |
---|
| 550 | + |
---|
| 551 | + /* interleaved size */ |
---|
| 552 | + struct data_chunk sgl; |
---|
549 | 553 | }; |
---|
550 | 554 | |
---|
551 | 555 | struct _xfer_spec { |
---|
.. | .. |
---|
1073 | 1077 | return true; |
---|
1074 | 1078 | } |
---|
1075 | 1079 | |
---|
1076 | | -static bool _start(struct pl330_thread *thrd) |
---|
| 1080 | +static bool pl330_start_thread(struct pl330_thread *thrd) |
---|
1077 | 1081 | { |
---|
1078 | 1082 | switch (_state(thrd)) { |
---|
1079 | 1083 | case PL330_STATE_FAULT_COMPLETING: |
---|
.. | .. |
---|
1204 | 1208 | const struct _xfer_spec *pxs, int cyc, |
---|
1205 | 1209 | enum pl330_cond cond) |
---|
1206 | 1210 | { |
---|
1207 | | - int off = 0; |
---|
| 1211 | + int off = 0, i = 0, burstn = 1; |
---|
1208 | 1212 | |
---|
1209 | 1213 | /* |
---|
1210 | 1214 | * do FLUSHP at beginning to clear any stale dma requests before the |
---|
.. | .. |
---|
1212 | 1216 | */ |
---|
1213 | 1217 | if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)) |
---|
1214 | 1218 | off += _emit_FLUSHP(dry_run, &buf[off], pxs->desc->peri); |
---|
| 1219 | + |
---|
| 1220 | + if (pxs->desc->sgl.size) { |
---|
| 1221 | + WARN_ON(BYTE_MOD_BURST_LEN(pxs->desc->sgl.size, pxs->ccr)); |
---|
| 1222 | + burstn = BYTE_TO_BURST(pxs->desc->sgl.size, pxs->ccr); |
---|
| 1223 | + } |
---|
| 1224 | + |
---|
1215 | 1225 | while (cyc--) { |
---|
1216 | | - off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); |
---|
1217 | | - off += _emit_load(dry_run, &buf[off], cond, pxs->desc->rqtype, |
---|
1218 | | - pxs->desc->peri); |
---|
1219 | | - off += _emit_store(dry_run, &buf[off], cond, pxs->desc->rqtype, |
---|
1220 | | - pxs->desc->peri); |
---|
1221 | | -#ifdef CONFIG_NO_GKI |
---|
| 1226 | + for (i = 0; i < burstn; i++) { |
---|
| 1227 | + off += _emit_WFP(dry_run, &buf[off], cond, pxs->desc->peri); |
---|
| 1228 | + off += _emit_load(dry_run, &buf[off], cond, pxs->desc->rqtype, |
---|
| 1229 | + pxs->desc->peri); |
---|
| 1230 | + off += _emit_store(dry_run, &buf[off], cond, pxs->desc->rqtype, |
---|
| 1231 | + pxs->desc->peri); |
---|
| 1232 | + } |
---|
| 1233 | + |
---|
1222 | 1234 | switch (pxs->desc->rqtype) { |
---|
1223 | 1235 | case DMA_DEV_TO_MEM: |
---|
1224 | | - |
---|
1225 | | - if (pxs->desc->dst_interlace_size) |
---|
| 1236 | + if (pxs->desc->sgl.dst_icg) |
---|
1226 | 1237 | off += _emit_ADDH(dry_run, &buf[off], DST, |
---|
1227 | | - pxs->desc->dst_interlace_size); |
---|
| 1238 | + pxs->desc->sgl.dst_icg); |
---|
1228 | 1239 | break; |
---|
1229 | 1240 | case DMA_MEM_TO_DEV: |
---|
1230 | | - if (pxs->desc->src_interlace_size) |
---|
| 1241 | + if (pxs->desc->sgl.src_icg) |
---|
1231 | 1242 | off += _emit_ADDH(dry_run, &buf[off], SRC, |
---|
1232 | | - pxs->desc->src_interlace_size); |
---|
| 1243 | + pxs->desc->sgl.src_icg); |
---|
1233 | 1244 | break; |
---|
1234 | 1245 | default: |
---|
1235 | 1246 | WARN_ON(1); |
---|
1236 | 1247 | break; |
---|
1237 | 1248 | } |
---|
1238 | | -#endif |
---|
1239 | 1249 | } |
---|
1240 | 1250 | |
---|
1241 | 1251 | return off; |
---|
.. | .. |
---|
1450 | 1460 | off += _emit_LPEND(dry_run, &buf[off], &lpend); |
---|
1451 | 1461 | } |
---|
1452 | 1462 | |
---|
1453 | | -#ifdef CONFIG_NO_GKI |
---|
1454 | | - if (!pxs->desc->src_interlace_size && |
---|
1455 | | - !pxs->desc->dst_interlace_size) { |
---|
| 1463 | + if (!pxs->desc->sgl.src_icg && !pxs->desc->sgl.dst_icg) { |
---|
1456 | 1464 | num_dregs = BYTE_MOD_BURST_LEN(x->bytes, pxs->ccr); |
---|
1457 | 1465 | |
---|
1458 | 1466 | if (num_dregs) { |
---|
.. | .. |
---|
1460 | 1468 | off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr); |
---|
1461 | 1469 | } |
---|
1462 | 1470 | } |
---|
1463 | | -#else |
---|
1464 | | - num_dregs = BYTE_MOD_BURST_LEN(x->bytes, pxs->ccr); |
---|
1465 | | - |
---|
1466 | | - if (num_dregs) { |
---|
1467 | | - off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs); |
---|
1468 | | - off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr); |
---|
1469 | | - } |
---|
1470 | | -#endif |
---|
1471 | 1471 | |
---|
1472 | 1472 | off += _emit_SEV(dry_run, &buf[off], ev); |
---|
1473 | 1473 | |
---|
.. | .. |
---|
1535 | 1535 | BRST_SIZE(ccr); |
---|
1536 | 1536 | int off = 0; |
---|
1537 | 1537 | |
---|
1538 | | -#ifdef CONFIG_NO_GKI |
---|
1539 | | - if (pxs->desc->rqtype == DMA_DEV_TO_MEM) |
---|
1540 | | - bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) + |
---|
1541 | | - pxs->desc->dst_interlace_size); |
---|
1542 | | - else if (pxs->desc->rqtype == DMA_MEM_TO_DEV) |
---|
1543 | | - bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) + |
---|
1544 | | - pxs->desc->src_interlace_size); |
---|
1545 | | -#endif |
---|
| 1538 | + if (pxs->desc->sgl.size) |
---|
| 1539 | + bursts = x->bytes / pxs->desc->sgl.size; |
---|
| 1540 | + |
---|
1546 | 1541 | while (bursts) { |
---|
1547 | 1542 | c = bursts; |
---|
1548 | 1543 | off += _loop(pl330, dry_run, &buf[off], &c, pxs); |
---|
1549 | 1544 | bursts -= c; |
---|
1550 | 1545 | } |
---|
1551 | | -#ifdef CONFIG_NO_GKI |
---|
1552 | | - if (!pxs->desc->src_interlace_size && |
---|
1553 | | - !pxs->desc->dst_interlace_size) |
---|
| 1546 | + |
---|
| 1547 | + if (!pxs->desc->sgl.src_icg && !pxs->desc->sgl.dst_icg) |
---|
1554 | 1548 | off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs); |
---|
1555 | | -#else |
---|
1556 | | - off += _dregs(pl330, dry_run, &buf[off], pxs, num_dregs); |
---|
1557 | | -#endif |
---|
| 1549 | + |
---|
1558 | 1550 | return off; |
---|
1559 | 1551 | } |
---|
1560 | 1552 | |
---|
.. | .. |
---|
1585 | 1577 | unsigned long bursts = BYTE_TO_BURST(x->bytes, ccr); |
---|
1586 | 1578 | int off = 0; |
---|
1587 | 1579 | |
---|
1588 | | -#ifdef CONFIG_NO_GKI |
---|
1589 | | - if (pxs->desc->rqtype == DMA_DEV_TO_MEM) |
---|
1590 | | - bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) |
---|
1591 | | - + pxs->desc->dst_interlace_size); |
---|
1592 | | - else if (pxs->desc->rqtype == DMA_MEM_TO_DEV) |
---|
1593 | | - bursts = x->bytes / (BRST_SIZE(ccr) * BRST_LEN(ccr) |
---|
1594 | | - + pxs->desc->src_interlace_size); |
---|
1595 | | -#endif |
---|
| 1580 | + if (pxs->desc->sgl.size) |
---|
| 1581 | + bursts = x->bytes / pxs->desc->sgl.size; |
---|
| 1582 | + |
---|
1596 | 1583 | /* Setup Loop(s) */ |
---|
1597 | 1584 | off += _loop_cyclic(pl330, dry_run, &buf[off], bursts, pxs, ev); |
---|
1598 | 1585 | |
---|
.. | .. |
---|
1907 | 1894 | thrd->req[active].desc = NULL; |
---|
1908 | 1895 | thrd->req_running = -1; |
---|
1909 | 1896 | /* Get going again ASAP */ |
---|
1910 | | - _start(thrd); |
---|
| 1897 | + pl330_start_thread(thrd); |
---|
1911 | 1898 | } |
---|
1912 | 1899 | |
---|
1913 | 1900 | /* For now, just make a list of callbacks to be done */ |
---|
.. | .. |
---|
2248 | 2235 | list_for_each_entry(desc, &pch->work_list, node) { |
---|
2249 | 2236 | |
---|
2250 | 2237 | /* If already submitted */ |
---|
2251 | | - if (desc->status == BUSY) |
---|
| 2238 | + if (desc->status == BUSY || desc->status == PAUSED) |
---|
2252 | 2239 | continue; |
---|
2253 | 2240 | |
---|
2254 | 2241 | ret = pl330_submit_req(pch->thread, desc); |
---|
.. | .. |
---|
2309 | 2296 | } else { |
---|
2310 | 2297 | /* Make sure the PL330 Channel thread is active */ |
---|
2311 | 2298 | spin_lock(&pch->thread->dmac->lock); |
---|
2312 | | - _start(pch->thread); |
---|
| 2299 | + pl330_start_thread(pch->thread); |
---|
2313 | 2300 | spin_unlock(&pch->thread->dmac->lock); |
---|
2314 | 2301 | } |
---|
2315 | 2302 | |
---|
.. | .. |
---|
2454 | 2441 | pch->fifo_addr = slave_config->dst_addr; |
---|
2455 | 2442 | if (slave_config->dst_addr_width) |
---|
2456 | 2443 | pch->burst_sz = __ffs(slave_config->dst_addr_width); |
---|
2457 | | -#ifdef CONFIG_NO_GKI |
---|
2458 | | - if (slave_config->src_interlace_size) |
---|
2459 | | - pch->slave_config.src_interlace_size = slave_config->src_interlace_size; |
---|
2460 | | -#endif |
---|
2461 | 2444 | pch->burst_len = fixup_burst_len(slave_config->dst_maxburst, |
---|
2462 | 2445 | pch->dmac->quirks); |
---|
2463 | 2446 | } else if (direction == DMA_DEV_TO_MEM) { |
---|
.. | .. |
---|
2465 | 2448 | pch->fifo_addr = slave_config->src_addr; |
---|
2466 | 2449 | if (slave_config->src_addr_width) |
---|
2467 | 2450 | pch->burst_sz = __ffs(slave_config->src_addr_width); |
---|
2468 | | -#ifdef CONFIG_NO_GKI |
---|
2469 | | - if (slave_config->dst_interlace_size) |
---|
2470 | | - pch->slave_config.dst_interlace_size = slave_config->dst_interlace_size; |
---|
2471 | | -#endif |
---|
2472 | 2451 | pch->burst_len = fixup_burst_len(slave_config->src_maxburst, |
---|
2473 | 2452 | pch->dmac->quirks); |
---|
2474 | 2453 | } |
---|
.. | .. |
---|
2541 | 2520 | { |
---|
2542 | 2521 | struct dma_pl330_chan *pch = to_pchan(chan); |
---|
2543 | 2522 | struct pl330_dmac *pl330 = pch->dmac; |
---|
| 2523 | + struct dma_pl330_desc *desc; |
---|
2544 | 2524 | unsigned long flags; |
---|
2545 | 2525 | |
---|
2546 | 2526 | pm_runtime_get_sync(pl330->ddma.dev); |
---|
.. | .. |
---|
2550 | 2530 | _stop(pch->thread); |
---|
2551 | 2531 | spin_unlock(&pl330->lock); |
---|
2552 | 2532 | |
---|
| 2533 | + list_for_each_entry(desc, &pch->work_list, node) { |
---|
| 2534 | + if (desc->status == BUSY) |
---|
| 2535 | + desc->status = PAUSED; |
---|
| 2536 | + } |
---|
2553 | 2537 | spin_unlock_irqrestore(&pch->lock, flags); |
---|
2554 | 2538 | pm_runtime_mark_last_busy(pl330->ddma.dev); |
---|
2555 | 2539 | pm_runtime_put_autosuspend(pl330->ddma.dev); |
---|
.. | .. |
---|
2639 | 2623 | else if (running && desc == running) |
---|
2640 | 2624 | transferred = |
---|
2641 | 2625 | pl330_get_current_xferred_count(pch, desc); |
---|
2642 | | - else if (desc->status == BUSY) |
---|
| 2626 | + else if (desc->status == BUSY || desc->status == PAUSED) |
---|
2643 | 2627 | /* |
---|
2644 | 2628 | * Busy but not running means either just enqueued, |
---|
2645 | 2629 | * or finished and not yet marked done |
---|
.. | .. |
---|
2655 | 2639 | switch (desc->status) { |
---|
2656 | 2640 | case DONE: |
---|
2657 | 2641 | ret = DMA_COMPLETE; |
---|
| 2642 | + break; |
---|
| 2643 | + case PAUSED: |
---|
| 2644 | + ret = DMA_PAUSED; |
---|
2658 | 2645 | break; |
---|
2659 | 2646 | case PREP: |
---|
2660 | 2647 | case BUSY: |
---|
.. | .. |
---|
2821 | 2808 | desc->cyclic = false; |
---|
2822 | 2809 | desc->num_periods = 1; |
---|
2823 | 2810 | |
---|
| 2811 | + desc->sgl.size = 0; |
---|
| 2812 | + desc->sgl.src_icg = 0; |
---|
| 2813 | + desc->sgl.dst_icg = 0; |
---|
| 2814 | + |
---|
2824 | 2815 | dma_async_tx_descriptor_init(&desc->txd, &pch->chan); |
---|
2825 | 2816 | |
---|
2826 | 2817 | return desc; |
---|
.. | .. |
---|
2936 | 2927 | desc->cyclic = true; |
---|
2937 | 2928 | desc->num_periods = len / period_len; |
---|
2938 | 2929 | desc->txd.flags = flags; |
---|
| 2930 | + |
---|
| 2931 | + return &desc->txd; |
---|
| 2932 | +} |
---|
| 2933 | + |
---|
| 2934 | +static struct dma_async_tx_descriptor *pl330_prep_interleaved_dma( |
---|
| 2935 | + struct dma_chan *chan, struct dma_interleaved_template *xt, |
---|
| 2936 | + unsigned long flags) |
---|
| 2937 | +{ |
---|
| 2938 | + struct dma_pl330_desc *desc = NULL; |
---|
| 2939 | + struct dma_pl330_chan *pch = to_pchan(chan); |
---|
| 2940 | + dma_addr_t dst = 0, src = 0; |
---|
| 2941 | + size_t size, src_icg, dst_icg, period_bytes, buffer_bytes, full_buffer_bytes; |
---|
| 2942 | + size_t nump = 0, numf = 0; |
---|
| 2943 | + |
---|
| 2944 | + if (!xt->numf || !xt->sgl[0].size || xt->frame_size != 1) |
---|
| 2945 | + return NULL; |
---|
| 2946 | + |
---|
2939 | 2947 | #ifdef CONFIG_NO_GKI |
---|
2940 | | - desc->src_interlace_size = pch->slave_config.src_interlace_size; |
---|
2941 | | - desc->dst_interlace_size = pch->slave_config.dst_interlace_size; |
---|
| 2948 | + nump = xt->nump; |
---|
2942 | 2949 | #endif |
---|
| 2950 | + numf = xt->numf; |
---|
| 2951 | + size = xt->sgl[0].size; |
---|
| 2952 | + period_bytes = size * nump; |
---|
| 2953 | + buffer_bytes = size * numf; |
---|
| 2954 | + |
---|
| 2955 | + if (flags & DMA_PREP_REPEAT && (!nump || (numf % nump))) |
---|
| 2956 | + return NULL; |
---|
| 2957 | + |
---|
| 2958 | + src_icg = dmaengine_get_src_icg(xt, &xt->sgl[0]); |
---|
| 2959 | + dst_icg = dmaengine_get_dst_icg(xt, &xt->sgl[0]); |
---|
| 2960 | + |
---|
| 2961 | + pl330_config_write(chan, &pch->slave_config, xt->dir); |
---|
| 2962 | + |
---|
| 2963 | + if (!pl330_prep_slave_fifo(pch, xt->dir)) |
---|
| 2964 | + return NULL; |
---|
| 2965 | + |
---|
| 2966 | + desc = pl330_get_desc(pch); |
---|
| 2967 | + if (!desc) { |
---|
| 2968 | + dev_err(chan->device->dev, "Failed to get desc\n"); |
---|
| 2969 | + return NULL; |
---|
| 2970 | + } |
---|
| 2971 | + |
---|
| 2972 | + if (xt->dir == DMA_MEM_TO_DEV) { |
---|
| 2973 | + desc->rqcfg.src_inc = 1; |
---|
| 2974 | + desc->rqcfg.dst_inc = 0; |
---|
| 2975 | + src = xt->src_start; |
---|
| 2976 | + dst = pch->fifo_dma; |
---|
| 2977 | + full_buffer_bytes = (size + src_icg) * numf; |
---|
| 2978 | + } else { |
---|
| 2979 | + desc->rqcfg.src_inc = 0; |
---|
| 2980 | + desc->rqcfg.dst_inc = 1; |
---|
| 2981 | + src = pch->fifo_dma; |
---|
| 2982 | + dst = xt->dst_start; |
---|
| 2983 | + full_buffer_bytes = (size + dst_icg) * numf; |
---|
| 2984 | + } |
---|
| 2985 | + |
---|
| 2986 | + desc->rqtype = xt->dir; |
---|
| 2987 | + desc->rqcfg.brst_size = pch->burst_sz; |
---|
| 2988 | + desc->rqcfg.brst_len = pch->burst_len; |
---|
| 2989 | + desc->bytes_requested = full_buffer_bytes; |
---|
| 2990 | + desc->sgl.size = size; |
---|
| 2991 | + desc->sgl.src_icg = src_icg; |
---|
| 2992 | + desc->sgl.dst_icg = dst_icg; |
---|
| 2993 | + desc->txd.flags = flags; |
---|
| 2994 | + |
---|
| 2995 | + if (flags & DMA_PREP_REPEAT) { |
---|
| 2996 | + desc->cyclic = true; |
---|
| 2997 | + desc->num_periods = numf / nump; |
---|
| 2998 | + fill_px(&desc->px, dst, src, period_bytes); |
---|
| 2999 | + } else { |
---|
| 3000 | + fill_px(&desc->px, dst, src, buffer_bytes); |
---|
| 3001 | + } |
---|
| 3002 | + |
---|
| 3003 | + dev_dbg(chan->device->dev, "size: %zu, src_icg: %zu, dst_icg: %zu, nump: %zu, numf: %zu\n", |
---|
| 3004 | + size, src_icg, dst_icg, nump, numf); |
---|
| 3005 | + |
---|
2943 | 3006 | return &desc->txd; |
---|
2944 | 3007 | } |
---|
2945 | 3008 | |
---|
.. | .. |
---|
3072 | 3135 | desc->rqcfg.brst_len = pch->burst_len; |
---|
3073 | 3136 | desc->rqtype = direction; |
---|
3074 | 3137 | desc->bytes_requested = sg_dma_len(sg); |
---|
3075 | | -#ifdef CONFIG_NO_GKI |
---|
3076 | | - desc->src_interlace_size = pch->slave_config.src_interlace_size; |
---|
3077 | | - desc->dst_interlace_size = pch->slave_config.dst_interlace_size; |
---|
3078 | | -#endif |
---|
3079 | 3138 | } |
---|
3080 | 3139 | |
---|
3081 | 3140 | /* Return the last desc in the chain */ |
---|
.. | .. |
---|
3311 | 3370 | dma_cap_set(DMA_SLAVE, pd->cap_mask); |
---|
3312 | 3371 | dma_cap_set(DMA_CYCLIC, pd->cap_mask); |
---|
3313 | 3372 | dma_cap_set(DMA_PRIVATE, pd->cap_mask); |
---|
| 3373 | + dma_cap_set(DMA_INTERLEAVE, pd->cap_mask); |
---|
| 3374 | + dma_cap_set(DMA_REPEAT, pd->cap_mask); |
---|
| 3375 | + dma_cap_set(DMA_LOAD_EOT, pd->cap_mask); |
---|
3314 | 3376 | } |
---|
3315 | 3377 | |
---|
3316 | 3378 | pd->device_alloc_chan_resources = pl330_alloc_chan_resources; |
---|
3317 | 3379 | pd->device_free_chan_resources = pl330_free_chan_resources; |
---|
3318 | 3380 | pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy; |
---|
3319 | 3381 | pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic; |
---|
| 3382 | + pd->device_prep_interleaved_dma = pl330_prep_interleaved_dma; |
---|
3320 | 3383 | pd->device_tx_status = pl330_tx_status; |
---|
3321 | 3384 | pd->device_prep_slave_sg = pl330_prep_slave_sg; |
---|
3322 | 3385 | pd->device_config = pl330_config; |
---|