Lines Matching +full:compute +full:- +full:cb

1 // SPDX-License-Identifier: GPL-2.0
8 #include <linux/dma-mapping.h>
19 #include "virt-dma.h"
95 /* mc->vc.lock must be held by caller */
101 vd = vchan_next_desc(&mc->vc); in milbeaut_hdmac_next_desc()
103 mc->md = NULL; in milbeaut_hdmac_next_desc()
107 list_del(&vd->node); in milbeaut_hdmac_next_desc()
109 mc->md = to_milbeaut_hdmac_desc(vd); in milbeaut_hdmac_next_desc()
111 return mc->md; in milbeaut_hdmac_next_desc()
114 /* mc->vc.lock must be held by caller */
119 u32 cb, ca, src_addr, dest_addr, len; in milbeaut_chan_start() local
122 sg = &md->sgl[md->sg_cur]; in milbeaut_chan_start()
125 cb = MLB_HDMAC_CI | MLB_HDMAC_EI; in milbeaut_chan_start()
126 if (md->dir == DMA_MEM_TO_DEV) { in milbeaut_chan_start()
127 cb |= MLB_HDMAC_FD; in milbeaut_chan_start()
128 width = mc->cfg.dst_addr_width; in milbeaut_chan_start()
129 burst = mc->cfg.dst_maxburst; in milbeaut_chan_start()
131 dest_addr = mc->cfg.dst_addr; in milbeaut_chan_start()
133 cb |= MLB_HDMAC_FS; in milbeaut_chan_start()
134 width = mc->cfg.src_addr_width; in milbeaut_chan_start()
135 burst = mc->cfg.src_maxburst; in milbeaut_chan_start()
136 src_addr = mc->cfg.src_addr; in milbeaut_chan_start()
139 cb |= FIELD_PREP(MLB_HDMAC_TW, (width >> 1)); in milbeaut_chan_start()
140 cb |= FIELD_PREP(MLB_HDMAC_MS, 2); in milbeaut_chan_start()
142 writel_relaxed(MLB_HDMAC_DE, mc->mdev->reg_base + MLB_HDMAC_DMACR); in milbeaut_chan_start()
143 writel_relaxed(src_addr, mc->reg_ch_base + MLB_HDMAC_DMACSA); in milbeaut_chan_start()
144 writel_relaxed(dest_addr, mc->reg_ch_base + MLB_HDMAC_DMACDA); in milbeaut_chan_start()
145 writel_relaxed(cb, mc->reg_ch_base + MLB_HDMAC_DMACB); in milbeaut_chan_start()
147 ca = FIELD_PREP(MLB_HDMAC_IS, mc->slave_id); in milbeaut_chan_start()
155 ca |= FIELD_PREP(MLB_HDMAC_TC, (len / burst - 1)); in milbeaut_chan_start()
156 writel_relaxed(ca, mc->reg_ch_base + MLB_HDMAC_DMACA); in milbeaut_chan_start()
158 writel_relaxed(ca, mc->reg_ch_base + MLB_HDMAC_DMACA); in milbeaut_chan_start()
161 /* mc->vc.lock must be held by caller */
177 spin_lock(&mc->vc.lock); in milbeaut_hdmac_interrupt()
180 val = readl_relaxed(mc->reg_ch_base + MLB_HDMAC_DMACB); in milbeaut_hdmac_interrupt()
182 writel_relaxed(val, mc->reg_ch_base + MLB_HDMAC_DMACB); in milbeaut_hdmac_interrupt()
185 writel_relaxed(val, mc->reg_ch_base + MLB_HDMAC_DMACB); in milbeaut_hdmac_interrupt()
187 md = mc->md; in milbeaut_hdmac_interrupt()
191 md->sg_cur++; in milbeaut_hdmac_interrupt()
193 if (md->sg_cur >= md->sg_len) { in milbeaut_hdmac_interrupt()
194 vchan_cookie_complete(&md->vd); in milbeaut_hdmac_interrupt()
203 spin_unlock(&mc->vc.lock); in milbeaut_hdmac_interrupt()
218 spin_lock(&mc->vc.lock); in milbeaut_hdmac_chan_config()
219 mc->cfg = *cfg; in milbeaut_hdmac_chan_config()
220 spin_unlock(&mc->vc.lock); in milbeaut_hdmac_chan_config()
231 spin_lock(&mc->vc.lock); in milbeaut_hdmac_chan_pause()
232 val = readl_relaxed(mc->reg_ch_base + MLB_HDMAC_DMACA); in milbeaut_hdmac_chan_pause()
234 writel_relaxed(val, mc->reg_ch_base + MLB_HDMAC_DMACA); in milbeaut_hdmac_chan_pause()
235 spin_unlock(&mc->vc.lock); in milbeaut_hdmac_chan_pause()
246 spin_lock(&mc->vc.lock); in milbeaut_hdmac_chan_resume()
247 val = readl_relaxed(mc->reg_ch_base + MLB_HDMAC_DMACA); in milbeaut_hdmac_chan_resume()
249 writel_relaxed(val, mc->reg_ch_base + MLB_HDMAC_DMACA); in milbeaut_hdmac_chan_resume()
250 spin_unlock(&mc->vc.lock); in milbeaut_hdmac_chan_resume()
272 md->sgl = kcalloc(sg_len, sizeof(*sgl), GFP_NOWAIT); in milbeaut_hdmac_prep_slave_sg()
273 if (!md->sgl) { in milbeaut_hdmac_prep_slave_sg()
279 md->sgl[i] = sgl[i]; in milbeaut_hdmac_prep_slave_sg()
281 md->sg_len = sg_len; in milbeaut_hdmac_prep_slave_sg()
282 md->dir = direction; in milbeaut_hdmac_prep_slave_sg()
284 return vchan_tx_prep(vc, &md->vd, flags); in milbeaut_hdmac_prep_slave_sg()
296 spin_lock_irqsave(&vc->lock, flags); in milbeaut_hdmac_terminate_all()
298 val = readl_relaxed(mc->reg_ch_base + MLB_HDMAC_DMACA); in milbeaut_hdmac_terminate_all()
300 writel_relaxed(val, mc->reg_ch_base + MLB_HDMAC_DMACA); in milbeaut_hdmac_terminate_all()
302 if (mc->md) { in milbeaut_hdmac_terminate_all()
303 vchan_terminate_vdesc(&mc->md->vd); in milbeaut_hdmac_terminate_all()
304 mc->md = NULL; in milbeaut_hdmac_terminate_all()
309 spin_unlock_irqrestore(&vc->lock, flags); in milbeaut_hdmac_terminate_all()
334 /* Return immediately if we do not need to compute the residue. */ in milbeaut_hdmac_tx_status()
340 spin_lock_irqsave(&vc->lock, flags); in milbeaut_hdmac_tx_status()
344 /* residue from the on-flight chunk */ in milbeaut_hdmac_tx_status()
345 if (mc->md && mc->md->vd.tx.cookie == cookie) { in milbeaut_hdmac_tx_status()
349 md = mc->md; in milbeaut_hdmac_tx_status()
350 sg = &md->sgl[md->sg_cur]; in milbeaut_hdmac_tx_status()
352 if (md->dir == DMA_DEV_TO_MEM) in milbeaut_hdmac_tx_status()
353 done = readl_relaxed(mc->reg_ch_base in milbeaut_hdmac_tx_status()
356 done = readl_relaxed(mc->reg_ch_base in milbeaut_hdmac_tx_status()
358 done -= sg_dma_address(sg); in milbeaut_hdmac_tx_status()
360 txstate->residue = -done; in milbeaut_hdmac_tx_status()
371 for (i = md->sg_cur; i < md->sg_len; i++) in milbeaut_hdmac_tx_status()
372 txstate->residue += sg_dma_len(&md->sgl[i]); in milbeaut_hdmac_tx_status()
375 spin_unlock_irqrestore(&vc->lock, flags); in milbeaut_hdmac_tx_status()
386 spin_lock_irqsave(&vc->lock, flags); in milbeaut_hdmac_issue_pending()
388 if (vchan_issue_pending(vc) && !mc->md) in milbeaut_hdmac_issue_pending()
391 spin_unlock_irqrestore(&vc->lock, flags); in milbeaut_hdmac_issue_pending()
398 kfree(md->sgl); in milbeaut_hdmac_desc_free()
405 struct milbeaut_hdmac_device *mdev = of_dma->of_dma_data; in milbeaut_hdmac_xlate()
410 if (dma_spec->args_count != 1) in milbeaut_hdmac_xlate()
413 chan = dma_get_any_slave_channel(&mdev->ddev); in milbeaut_hdmac_xlate()
419 mc->slave_id = dma_spec->args[0]; in milbeaut_hdmac_xlate()
428 struct device *dev = &pdev->dev; in milbeaut_hdmac_chan_init()
429 struct milbeaut_hdmac_chan *mc = &mdev->channels[chan_id]; in milbeaut_hdmac_chan_init()
437 irq_name = devm_kasprintf(dev, GFP_KERNEL, "milbeaut-hdmac-%d", in milbeaut_hdmac_chan_init()
440 return -ENOMEM; in milbeaut_hdmac_chan_init()
447 mc->mdev = mdev; in milbeaut_hdmac_chan_init()
448 mc->reg_ch_base = mdev->reg_base + MLB_HDMAC_CH_STRIDE * (chan_id + 1); in milbeaut_hdmac_chan_init()
449 mc->vc.desc_free = milbeaut_hdmac_desc_free; in milbeaut_hdmac_chan_init()
450 vchan_init(&mc->vc, &mdev->ddev); in milbeaut_hdmac_chan_init()
457 struct device *dev = &pdev->dev; in milbeaut_hdmac_probe()
473 return -ENOMEM; in milbeaut_hdmac_probe()
475 mdev->reg_base = devm_platform_ioremap_resource(pdev, 0); in milbeaut_hdmac_probe()
476 if (IS_ERR(mdev->reg_base)) in milbeaut_hdmac_probe()
477 return PTR_ERR(mdev->reg_base); in milbeaut_hdmac_probe()
479 mdev->clk = devm_clk_get(dev, NULL); in milbeaut_hdmac_probe()
480 if (IS_ERR(mdev->clk)) { in milbeaut_hdmac_probe()
482 return PTR_ERR(mdev->clk); in milbeaut_hdmac_probe()
485 ret = clk_prepare_enable(mdev->clk); in milbeaut_hdmac_probe()
489 ddev = &mdev->ddev; in milbeaut_hdmac_probe()
490 ddev->dev = dev; in milbeaut_hdmac_probe()
491 dma_cap_set(DMA_SLAVE, ddev->cap_mask); in milbeaut_hdmac_probe()
492 dma_cap_set(DMA_PRIVATE, ddev->cap_mask); in milbeaut_hdmac_probe()
493 ddev->src_addr_widths = MLB_HDMAC_BUSWIDTHS; in milbeaut_hdmac_probe()
494 ddev->dst_addr_widths = MLB_HDMAC_BUSWIDTHS; in milbeaut_hdmac_probe()
495 ddev->directions = BIT(DMA_MEM_TO_DEV) | BIT(DMA_DEV_TO_MEM); in milbeaut_hdmac_probe()
496 ddev->device_free_chan_resources = milbeaut_hdmac_free_chan_resources; in milbeaut_hdmac_probe()
497 ddev->device_config = milbeaut_hdmac_chan_config; in milbeaut_hdmac_probe()
498 ddev->device_pause = milbeaut_hdmac_chan_pause; in milbeaut_hdmac_probe()
499 ddev->device_resume = milbeaut_hdmac_chan_resume; in milbeaut_hdmac_probe()
500 ddev->device_prep_slave_sg = milbeaut_hdmac_prep_slave_sg; in milbeaut_hdmac_probe()
501 ddev->device_terminate_all = milbeaut_hdmac_terminate_all; in milbeaut_hdmac_probe()
502 ddev->device_synchronize = milbeaut_hdmac_synchronize; in milbeaut_hdmac_probe()
503 ddev->device_tx_status = milbeaut_hdmac_tx_status; in milbeaut_hdmac_probe()
504 ddev->device_issue_pending = milbeaut_hdmac_issue_pending; in milbeaut_hdmac_probe()
505 INIT_LIST_HEAD(&ddev->channels); in milbeaut_hdmac_probe()
517 ret = of_dma_controller_register(dev->of_node, in milbeaut_hdmac_probe()
529 clk_disable_unprepare(mdev->clk); in milbeaut_hdmac_probe()
542 * ->device_free_chan_resources() hook. However, each channel might in milbeaut_hdmac_remove()
543 * be still holding one descriptor that was on-flight at that moment. in milbeaut_hdmac_remove()
547 list_for_each_entry(chan, &mdev->ddev.channels, device_node) { in milbeaut_hdmac_remove()
554 of_dma_controller_free(pdev->dev.of_node); in milbeaut_hdmac_remove()
555 dma_async_device_unregister(&mdev->ddev); in milbeaut_hdmac_remove()
556 clk_disable_unprepare(mdev->clk); in milbeaut_hdmac_remove()
562 { .compatible = "socionext,milbeaut-m10v-hdmac" },
571 .name = "milbeaut-m10v-hdmac",