Lines Matching refs:tdc
177 static inline void tdma_ch_write(struct tegra_adma_chan *tdc, u32 reg, u32 val) in tdma_ch_write() argument
179 writel(val, tdc->chan_addr + reg); in tdma_ch_write()
182 static inline u32 tdma_ch_read(struct tegra_adma_chan *tdc, u32 reg) in tdma_ch_read() argument
184 return readl(tdc->chan_addr + reg); in tdma_ch_read()
198 static inline struct device *tdc2dev(struct tegra_adma_chan *tdc) in tdc2dev() argument
200 return tdc->tdma->dev; in tdc2dev()
211 struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc); in tegra_adma_slave_config() local
213 memcpy(&tdc->sconfig, sconfig, sizeof(*sconfig)); in tegra_adma_slave_config()
244 static int tegra_adma_request_alloc(struct tegra_adma_chan *tdc, in tegra_adma_request_alloc() argument
247 struct tegra_adma *tdma = tdc->tdma; in tegra_adma_request_alloc()
248 unsigned int sreq_index = tdc->sreq_index; in tegra_adma_request_alloc()
250 if (tdc->sreq_reserved) in tegra_adma_request_alloc()
251 return tdc->sreq_dir == direction ? 0 : -EINVAL; in tegra_adma_request_alloc()
275 dma_chan_name(&tdc->vc.chan)); in tegra_adma_request_alloc()
279 tdc->sreq_dir = direction; in tegra_adma_request_alloc()
280 tdc->sreq_reserved = true; in tegra_adma_request_alloc()
285 static void tegra_adma_request_free(struct tegra_adma_chan *tdc) in tegra_adma_request_free() argument
287 struct tegra_adma *tdma = tdc->tdma; in tegra_adma_request_free()
289 if (!tdc->sreq_reserved) in tegra_adma_request_free()
292 switch (tdc->sreq_dir) { in tegra_adma_request_free()
294 clear_bit(tdc->sreq_index, &tdma->tx_requests_reserved); in tegra_adma_request_free()
298 clear_bit(tdc->sreq_index, &tdma->rx_requests_reserved); in tegra_adma_request_free()
303 dma_chan_name(&tdc->vc.chan)); in tegra_adma_request_free()
307 tdc->sreq_reserved = false; in tegra_adma_request_free()
310 static u32 tegra_adma_irq_status(struct tegra_adma_chan *tdc) in tegra_adma_irq_status() argument
312 u32 status = tdma_ch_read(tdc, ADMA_CH_INT_STATUS); in tegra_adma_irq_status()
317 static u32 tegra_adma_irq_clear(struct tegra_adma_chan *tdc) in tegra_adma_irq_clear() argument
319 u32 status = tegra_adma_irq_status(tdc); in tegra_adma_irq_clear()
322 tdma_ch_write(tdc, ADMA_CH_INT_CLEAR, status); in tegra_adma_irq_clear()
327 static void tegra_adma_stop(struct tegra_adma_chan *tdc) in tegra_adma_stop() argument
332 tdma_ch_write(tdc, ADMA_CH_CMD, 0); in tegra_adma_stop()
335 tegra_adma_irq_clear(tdc); in tegra_adma_stop()
337 if (readx_poll_timeout_atomic(readl, tdc->chan_addr + ADMA_CH_STATUS, in tegra_adma_stop()
340 dev_err(tdc2dev(tdc), "unable to stop DMA channel\n"); in tegra_adma_stop()
344 kfree(tdc->desc); in tegra_adma_stop()
345 tdc->desc = NULL; in tegra_adma_stop()
348 static void tegra_adma_start(struct tegra_adma_chan *tdc) in tegra_adma_start() argument
350 struct virt_dma_desc *vd = vchan_next_desc(&tdc->vc); in tegra_adma_start()
362 dev_warn(tdc2dev(tdc), "unable to start DMA, no descriptor\n"); in tegra_adma_start()
368 tdc->tx_buf_pos = 0; in tegra_adma_start()
369 tdc->tx_buf_count = 0; in tegra_adma_start()
370 tdma_ch_write(tdc, ADMA_CH_TC, ch_regs->tc); in tegra_adma_start()
371 tdma_ch_write(tdc, ADMA_CH_CTRL, ch_regs->ctrl); in tegra_adma_start()
372 tdma_ch_write(tdc, ADMA_CH_LOWER_SRC_ADDR, ch_regs->src_addr); in tegra_adma_start()
373 tdma_ch_write(tdc, ADMA_CH_LOWER_TRG_ADDR, ch_regs->trg_addr); in tegra_adma_start()
374 tdma_ch_write(tdc, ADMA_CH_FIFO_CTRL, ch_regs->fifo_ctrl); in tegra_adma_start()
375 tdma_ch_write(tdc, ADMA_CH_CONFIG, ch_regs->config); in tegra_adma_start()
378 tdma_ch_write(tdc, ADMA_CH_CMD, 1); in tegra_adma_start()
380 tdc->desc = desc; in tegra_adma_start()
383 static unsigned int tegra_adma_get_residue(struct tegra_adma_chan *tdc) in tegra_adma_get_residue() argument
385 struct tegra_adma_desc *desc = tdc->desc; in tegra_adma_get_residue()
387 unsigned int pos = tdma_ch_read(tdc, ADMA_CH_XFER_STATUS); in tegra_adma_get_residue()
393 if (pos < tdc->tx_buf_pos) in tegra_adma_get_residue()
394 tdc->tx_buf_count += pos + (max - tdc->tx_buf_pos); in tegra_adma_get_residue()
396 tdc->tx_buf_count += pos - tdc->tx_buf_pos; in tegra_adma_get_residue()
398 periods_remaining = tdc->tx_buf_count % desc->num_periods; in tegra_adma_get_residue()
399 tdc->tx_buf_pos = pos; in tegra_adma_get_residue()
406 struct tegra_adma_chan *tdc = dev_id; in tegra_adma_isr() local
409 spin_lock(&tdc->vc.lock); in tegra_adma_isr()
411 status = tegra_adma_irq_clear(tdc); in tegra_adma_isr()
412 if (status == 0 || !tdc->desc) { in tegra_adma_isr()
413 spin_unlock(&tdc->vc.lock); in tegra_adma_isr()
417 vchan_cyclic_callback(&tdc->desc->vd); in tegra_adma_isr()
419 spin_unlock(&tdc->vc.lock); in tegra_adma_isr()
426 struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc); in tegra_adma_issue_pending() local
429 spin_lock_irqsave(&tdc->vc.lock, flags); in tegra_adma_issue_pending()
431 if (vchan_issue_pending(&tdc->vc)) { in tegra_adma_issue_pending()
432 if (!tdc->desc) in tegra_adma_issue_pending()
433 tegra_adma_start(tdc); in tegra_adma_issue_pending()
436 spin_unlock_irqrestore(&tdc->vc.lock, flags); in tegra_adma_issue_pending()
439 static bool tegra_adma_is_paused(struct tegra_adma_chan *tdc) in tegra_adma_is_paused() argument
443 csts = tdma_ch_read(tdc, ADMA_CH_STATUS); in tegra_adma_is_paused()
451 struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc); in tegra_adma_pause() local
452 struct tegra_adma_desc *desc = tdc->desc; in tegra_adma_pause()
456 ch_regs->ctrl = tdma_ch_read(tdc, ADMA_CH_CTRL); in tegra_adma_pause()
458 tdma_ch_write(tdc, ADMA_CH_CTRL, ch_regs->ctrl); in tegra_adma_pause()
460 while (dcnt-- && !tegra_adma_is_paused(tdc)) in tegra_adma_pause()
464 dev_err(tdc2dev(tdc), "unable to pause DMA channel\n"); in tegra_adma_pause()
473 struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc); in tegra_adma_resume() local
474 struct tegra_adma_desc *desc = tdc->desc; in tegra_adma_resume()
477 ch_regs->ctrl = tdma_ch_read(tdc, ADMA_CH_CTRL); in tegra_adma_resume()
479 tdma_ch_write(tdc, ADMA_CH_CTRL, ch_regs->ctrl); in tegra_adma_resume()
486 struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc); in tegra_adma_terminate_all() local
490 spin_lock_irqsave(&tdc->vc.lock, flags); in tegra_adma_terminate_all()
492 if (tdc->desc) in tegra_adma_terminate_all()
493 tegra_adma_stop(tdc); in tegra_adma_terminate_all()
495 tegra_adma_request_free(tdc); in tegra_adma_terminate_all()
496 vchan_get_all_descriptors(&tdc->vc, &head); in tegra_adma_terminate_all()
497 spin_unlock_irqrestore(&tdc->vc.lock, flags); in tegra_adma_terminate_all()
498 vchan_dma_desc_free_list(&tdc->vc, &head); in tegra_adma_terminate_all()
507 struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc); in tegra_adma_tx_status() local
518 spin_lock_irqsave(&tdc->vc.lock, flags); in tegra_adma_tx_status()
520 vd = vchan_find_desc(&tdc->vc, cookie); in tegra_adma_tx_status()
524 } else if (tdc->desc && tdc->desc->vd.tx.cookie == cookie) { in tegra_adma_tx_status()
525 residual = tegra_adma_get_residue(tdc); in tegra_adma_tx_status()
530 spin_unlock_irqrestore(&tdc->vc.lock, flags); in tegra_adma_tx_status()
553 static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc, in tegra_adma_set_xfer_params() argument
559 const struct tegra_adma_chip_data *cdata = tdc->tdma->cdata; in tegra_adma_set_xfer_params()
569 burst_size = tdc->sconfig.dst_maxburst; in tegra_adma_set_xfer_params()
571 ch_regs->ctrl = ADMA_CH_REG_FIELD_VAL(tdc->sreq_index, in tegra_adma_set_xfer_params()
580 burst_size = tdc->sconfig.src_maxburst; in tegra_adma_set_xfer_params()
582 ch_regs->ctrl = ADMA_CH_REG_FIELD_VAL(tdc->sreq_index, in tegra_adma_set_xfer_params()
589 dev_err(tdc2dev(tdc), "DMA direction is not supported\n"); in tegra_adma_set_xfer_params()
612 if (tdc->sreq_index > cdata->sreq_index_offset) in tegra_adma_set_xfer_params()
623 return tegra_adma_request_alloc(tdc, direction); in tegra_adma_set_xfer_params()
631 struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc); in tegra_adma_prep_dma_cyclic() local
635 dev_err(tdc2dev(tdc), "invalid buffer/period len\n"); in tegra_adma_prep_dma_cyclic()
640 dev_err(tdc2dev(tdc), "buf_len not a multiple of period_len\n"); in tegra_adma_prep_dma_cyclic()
645 dev_err(tdc2dev(tdc), "invalid buffer alignment\n"); in tegra_adma_prep_dma_cyclic()
657 if (tegra_adma_set_xfer_params(tdc, desc, buf_addr, direction)) { in tegra_adma_prep_dma_cyclic()
662 return vchan_tx_prep(&tdc->vc, &desc->vd, flags); in tegra_adma_prep_dma_cyclic()
667 struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc); in tegra_adma_alloc_chan_resources() local
670 ret = request_irq(tdc->irq, tegra_adma_isr, 0, dma_chan_name(dc), tdc); in tegra_adma_alloc_chan_resources()
672 dev_err(tdc2dev(tdc), "failed to get interrupt for %s\n", in tegra_adma_alloc_chan_resources()
677 ret = pm_runtime_resume_and_get(tdc2dev(tdc)); in tegra_adma_alloc_chan_resources()
679 free_irq(tdc->irq, tdc); in tegra_adma_alloc_chan_resources()
683 dma_cookie_init(&tdc->vc.chan); in tegra_adma_alloc_chan_resources()
690 struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc); in tegra_adma_free_chan_resources() local
693 vchan_free_chan_resources(&tdc->vc); in tegra_adma_free_chan_resources()
694 tasklet_kill(&tdc->vc.task); in tegra_adma_free_chan_resources()
695 free_irq(tdc->irq, tdc); in tegra_adma_free_chan_resources()
696 pm_runtime_put(tdc2dev(tdc)); in tegra_adma_free_chan_resources()
698 tdc->sreq_index = 0; in tegra_adma_free_chan_resources()
699 tdc->sreq_dir = DMA_TRANS_NONE; in tegra_adma_free_chan_resources()
706 struct tegra_adma_chan *tdc; in tegra_dma_of_xlate() local
724 tdc = to_tegra_adma_chan(chan); in tegra_dma_of_xlate()
725 tdc->sreq_index = sreq_index; in tegra_dma_of_xlate()
734 struct tegra_adma_chan *tdc; in tegra_adma_runtime_suspend() local
742 tdc = &tdma->channels[i]; in tegra_adma_runtime_suspend()
743 ch_reg = &tdc->ch_regs; in tegra_adma_runtime_suspend()
744 ch_reg->cmd = tdma_ch_read(tdc, ADMA_CH_CMD); in tegra_adma_runtime_suspend()
748 ch_reg->tc = tdma_ch_read(tdc, ADMA_CH_TC); in tegra_adma_runtime_suspend()
749 ch_reg->src_addr = tdma_ch_read(tdc, ADMA_CH_LOWER_SRC_ADDR); in tegra_adma_runtime_suspend()
750 ch_reg->trg_addr = tdma_ch_read(tdc, ADMA_CH_LOWER_TRG_ADDR); in tegra_adma_runtime_suspend()
751 ch_reg->ctrl = tdma_ch_read(tdc, ADMA_CH_CTRL); in tegra_adma_runtime_suspend()
752 ch_reg->fifo_ctrl = tdma_ch_read(tdc, ADMA_CH_FIFO_CTRL); in tegra_adma_runtime_suspend()
753 ch_reg->config = tdma_ch_read(tdc, ADMA_CH_CONFIG); in tegra_adma_runtime_suspend()
766 struct tegra_adma_chan *tdc; in tegra_adma_runtime_resume() local
780 tdc = &tdma->channels[i]; in tegra_adma_runtime_resume()
781 ch_reg = &tdc->ch_regs; in tegra_adma_runtime_resume()
785 tdma_ch_write(tdc, ADMA_CH_TC, ch_reg->tc); in tegra_adma_runtime_resume()
786 tdma_ch_write(tdc, ADMA_CH_LOWER_SRC_ADDR, ch_reg->src_addr); in tegra_adma_runtime_resume()
787 tdma_ch_write(tdc, ADMA_CH_LOWER_TRG_ADDR, ch_reg->trg_addr); in tegra_adma_runtime_resume()
788 tdma_ch_write(tdc, ADMA_CH_CTRL, ch_reg->ctrl); in tegra_adma_runtime_resume()
789 tdma_ch_write(tdc, ADMA_CH_FIFO_CTRL, ch_reg->fifo_ctrl); in tegra_adma_runtime_resume()
790 tdma_ch_write(tdc, ADMA_CH_CONFIG, ch_reg->config); in tegra_adma_runtime_resume()
791 tdma_ch_write(tdc, ADMA_CH_CMD, ch_reg->cmd); in tegra_adma_runtime_resume()
871 struct tegra_adma_chan *tdc = &tdma->channels[i]; in tegra_adma_probe() local
873 tdc->chan_addr = tdma->base_addr + cdata->ch_base_offset in tegra_adma_probe()
876 tdc->irq = of_irq_get(pdev->dev.of_node, i); in tegra_adma_probe()
877 if (tdc->irq <= 0) { in tegra_adma_probe()
878 ret = tdc->irq ?: -ENXIO; in tegra_adma_probe()
882 vchan_init(&tdc->vc, &tdma->dma_dev); in tegra_adma_probe()
883 tdc->vc.desc_free = tegra_adma_desc_free; in tegra_adma_probe()
884 tdc->tdma = tdma; in tegra_adma_probe()