diff options
| author | Vishal Annapurve <vannapurve@nvidia.com> | 2016-05-11 08:28:30 -0400 |
|---|---|---|
| committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2016-09-12 04:14:01 -0400 |
| commit | d42541ff01ceeef37bc305649647d2c7e59ebeae (patch) | |
| tree | b16e95cdef7b798e1e7d4fcf7e9d450742d3558b | |
| parent | 3fe30f1c8a6a6eeff026733e50fd7e139c1a0d52 (diff) | |
t186: gpcdma: Support servicing irq when enabled
This change makes sure that DMA channel irq is enabled
after software setup of DMA controller is completed.
Bug 1762362
Change-Id: I7e2373ee03f5643b25621311c63fbfbd557f2bce
Signed-off-by: Vishal Annapurve <vannapurve@nvidia.com>
Reviewed-on: http://git-master/r/1208405
(cherry picked from commit e8c8773915141aba1b493e4e72182c9f671a1d09)
Reviewed-on: http://git-master/r/1213731
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
| -rw-r--r-- | drivers/dma/tegra186-gpc-dma.c | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c index c95c6782f..4d2c464d3 100644 --- a/drivers/dma/tegra186-gpc-dma.c +++ b/drivers/dma/tegra186-gpc-dma.c | |||
| @@ -664,25 +664,33 @@ static void tegra_dma_chan_decode_error(struct tegra_dma_channel *tdc, unsigned | |||
| 664 | { | 664 | { |
| 665 | switch(TEGRA_GPCDMA_CHAN_ERR_TYPE(err_status)) { | 665 | switch(TEGRA_GPCDMA_CHAN_ERR_TYPE(err_status)) { |
| 666 | case TEGRA_DMA_BM_FIFO_FULL_ERR: | 666 | case TEGRA_DMA_BM_FIFO_FULL_ERR: |
| 667 | dev_info(tdc2dev(tdc), "bm fifo full\n"); | 667 | dev_err(tdc->tdma->dev, |
| 668 | "GPCDMA CH%d bm fifo full\n", tdc->id); | ||
| 668 | break; | 669 | break; |
| 669 | case TEGRA_DMA_PERIPH_FIFO_FULL_ERR: | 670 | case TEGRA_DMA_PERIPH_FIFO_FULL_ERR: |
| 670 | dev_info(tdc2dev(tdc), "peripheral fifo full\n"); | 671 | dev_err(tdc->tdma->dev, |
| 672 | "GPCDMA CH%d peripheral fifo full\n", tdc->id); | ||
| 671 | break; | 673 | break; |
| 672 | case TEGRA_DMA_PERIPH_ID_ERR: | 674 | case TEGRA_DMA_PERIPH_ID_ERR: |
| 673 | dev_info(tdc2dev(tdc), "illegal peripheral id\n"); | 675 | dev_err(tdc->tdma->dev, |
| 676 | "GPCDMA CH%d illegal peripheral id\n", tdc->id); | ||
| 674 | break; | 677 | break; |
| 675 | case TEGRA_DMA_STREAM_ID_ERR: | 678 | case TEGRA_DMA_STREAM_ID_ERR: |
| 676 | dev_info(tdc2dev(tdc), "illegal stream id\n"); | 679 | dev_err(tdc->tdma->dev, |
| 680 | "GPCDMA CH%d illegal stream id\n", tdc->id); | ||
| 677 | break; | 681 | break; |
| 678 | case TEGRA_DMA_MC_SLAVE_ERR: | 682 | case TEGRA_DMA_MC_SLAVE_ERR: |
| 679 | dev_info(tdc2dev(tdc), "mc slave error\n"); | 683 | dev_err(tdc->tdma->dev, |
| 684 | "GPCDMA CH%d mc slave error\n", tdc->id); | ||
| 680 | break; | 685 | break; |
| 681 | case TEGRA_DMA_MMIO_SLAVE_ERR: | 686 | case TEGRA_DMA_MMIO_SLAVE_ERR: |
| 682 | dev_info(tdc2dev(tdc), "mmio slave error\n"); | 687 | dev_err(tdc->tdma->dev, |
| 688 | "GPCDMA CH%d mmio slave error\n", tdc->id); | ||
| 683 | break; | 689 | break; |
| 684 | default: | 690 | default: |
| 685 | dev_info(tdc2dev(tdc), "security violation %x\n", err_status); | 691 | dev_err(tdc->tdma->dev, |
| 692 | "GPCDMA CH%d security violation %x\n", tdc->id, | ||
| 693 | err_status); | ||
| 686 | } | 694 | } |
| 687 | } | 695 | } |
| 688 | 696 | ||
| @@ -700,20 +708,26 @@ static irqreturn_t tegra_dma_isr(int irq, void *dev_id) | |||
| 700 | 708 | ||
| 701 | if (err_status) { | 709 | if (err_status) { |
| 702 | tegra_dma_chan_decode_error(tdc, err_status); | 710 | tegra_dma_chan_decode_error(tdc, err_status); |
| 711 | tegra_dma_dump_chan_regs(tdc); | ||
| 703 | tdc_write(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS, 0xFFFFFFFF); | 712 | tdc_write(tdc, TEGRA_GPCDMA_CHAN_ERR_STATUS, 0xFFFFFFFF); |
| 704 | } | 713 | } |
| 705 | 714 | ||
| 706 | if (status & TEGRA_GPCDMA_STATUS_ISE_EOC) { | 715 | if (status & TEGRA_GPCDMA_STATUS_ISE_EOC) { |
| 707 | tdc_write(tdc, TEGRA_GPCDMA_CHAN_STATUS, TEGRA_GPCDMA_STATUS_ISE_EOC); | 716 | tdc_write(tdc, TEGRA_GPCDMA_CHAN_STATUS, TEGRA_GPCDMA_STATUS_ISE_EOC); |
| 708 | tdc->isr_handler(tdc, false); | 717 | if (tdc->isr_handler) |
| 718 | tdc->isr_handler(tdc, false); | ||
| 719 | else { | ||
| 720 | dev_err(tdc->tdma->dev, | ||
| 721 | "GPCDMA CH%d: status %lx ISR handler absent!\n", | ||
| 722 | tdc->id, status); | ||
| 723 | tegra_dma_dump_chan_regs(tdc); | ||
| 724 | } | ||
| 709 | tasklet_schedule(&tdc->tasklet); | 725 | tasklet_schedule(&tdc->tasklet); |
| 710 | spin_unlock_irqrestore(&tdc->lock, flags); | 726 | spin_unlock_irqrestore(&tdc->lock, flags); |
| 711 | return IRQ_HANDLED; | 727 | return IRQ_HANDLED; |
| 712 | } | 728 | } |
| 713 | 729 | ||
| 714 | spin_unlock_irqrestore(&tdc->lock, flags); | 730 | spin_unlock_irqrestore(&tdc->lock, flags); |
| 715 | dev_info(tdc2dev(tdc), | ||
| 716 | "Interrupt already served status 0x%08lx\n", status); | ||
| 717 | return IRQ_NONE; | 731 | return IRQ_NONE; |
| 718 | } | 732 | } |
| 719 | 733 | ||
| @@ -1764,15 +1778,6 @@ static int tegra_dma_probe(struct platform_device *pdev) | |||
| 1764 | } | 1778 | } |
| 1765 | tdc->irq = res->start; | 1779 | tdc->irq = res->start; |
| 1766 | snprintf(tdc->name, sizeof(tdc->name), "gpcdma.%d", i); | 1780 | snprintf(tdc->name, sizeof(tdc->name), "gpcdma.%d", i); |
| 1767 | ret = devm_request_irq(&pdev->dev, tdc->irq, | ||
| 1768 | tegra_dma_isr, 0, tdc->name, tdc); | ||
| 1769 | if (ret) { | ||
| 1770 | dev_err(&pdev->dev, | ||
| 1771 | "request_irq failed with err %d channel %d\n", | ||
| 1772 | i, ret); | ||
| 1773 | goto err_irq; | ||
| 1774 | } | ||
| 1775 | |||
| 1776 | 1781 | ||
| 1777 | tdc->dma_chan.device = &tdma->dma_dev; | 1782 | tdc->dma_chan.device = &tdma->dma_dev; |
| 1778 | dma_cookie_init(&tdc->dma_chan); | 1783 | dma_cookie_init(&tdc->dma_chan); |
| @@ -1825,6 +1830,20 @@ static int tegra_dma_probe(struct platform_device *pdev) | |||
| 1825 | tdma->dma_dev.device_tx_status = tegra_dma_tx_status; | 1830 | tdma->dma_dev.device_tx_status = tegra_dma_tx_status; |
| 1826 | tdma->dma_dev.device_issue_pending = tegra_dma_issue_pending; | 1831 | tdma->dma_dev.device_issue_pending = tegra_dma_issue_pending; |
| 1827 | 1832 | ||
| 1833 | /* Register DMA channel interrupt handlers after everything is setup */ | ||
| 1834 | for (i = 0; i < cdata->nr_channels; i++) { | ||
| 1835 | struct tegra_dma_channel *tdc = &tdma->channels[i]; | ||
| 1836 | |||
| 1837 | ret = devm_request_irq(&pdev->dev, tdc->irq, | ||
| 1838 | tegra_dma_isr, 0, tdc->name, tdc); | ||
| 1839 | if (ret) { | ||
| 1840 | dev_err(&pdev->dev, | ||
| 1841 | "request_irq failed with err %d channel %d\n", | ||
| 1842 | i, ret); | ||
| 1843 | goto err_irq; | ||
| 1844 | } | ||
| 1845 | } | ||
| 1846 | |||
| 1828 | ret = dma_async_device_register(&tdma->dma_dev); | 1847 | ret = dma_async_device_register(&tdma->dma_dev); |
| 1829 | if (ret < 0) { | 1848 | if (ret < 0) { |
| 1830 | dev_err(&pdev->dev, | 1849 | dev_err(&pdev->dev, |
