@@ -50,6 +50,83 @@ static irqreturn_t fsl_edma_tx_handler(int irq, void *dev_id)
5050 return IRQ_HANDLED ;
5151}
5252
53+ static void fsl_edma3_err_check (struct fsl_edma_chan * fsl_chan )
54+ {
55+ unsigned int ch_err ;
56+ u32 val ;
57+
58+ scoped_guard (spinlock , & fsl_chan -> vchan .lock ) {
59+ ch_err = edma_readl_chreg (fsl_chan , ch_es );
60+ if (!(ch_err & EDMA_V3_CH_ERR ))
61+ return ;
62+
63+ edma_writel_chreg (fsl_chan , EDMA_V3_CH_ERR , ch_es );
64+ val = edma_readl_chreg (fsl_chan , ch_csr );
65+ val &= ~EDMA_V3_CH_CSR_ERQ ;
66+ edma_writel_chreg (fsl_chan , val , ch_csr );
67+ }
68+
69+ /* Ignore this interrupt since channel has been disabled already */
70+ if (!fsl_chan -> edesc )
71+ return ;
72+
73+ if (ch_err & EDMA_V3_CH_ERR_DBE )
74+ dev_err (& fsl_chan -> pdev -> dev , "Destination Bus Error interrupt.\n" );
75+
76+ if (ch_err & EDMA_V3_CH_ERR_SBE )
77+ dev_err (& fsl_chan -> pdev -> dev , "Source Bus Error interrupt.\n" );
78+
79+ if (ch_err & EDMA_V3_CH_ERR_SGE )
80+ dev_err (& fsl_chan -> pdev -> dev , "Scatter/Gather Configuration Error interrupt.\n" );
81+
82+ if (ch_err & EDMA_V3_CH_ERR_NCE )
83+ dev_err (& fsl_chan -> pdev -> dev , "NBYTES/CITER Configuration Error interrupt.\n" );
84+
85+ if (ch_err & EDMA_V3_CH_ERR_DOE )
86+ dev_err (& fsl_chan -> pdev -> dev , "Destination Offset Error interrupt.\n" );
87+
88+ if (ch_err & EDMA_V3_CH_ERR_DAE )
89+ dev_err (& fsl_chan -> pdev -> dev , "Destination Address Error interrupt.\n" );
90+
91+ if (ch_err & EDMA_V3_CH_ERR_SOE )
92+ dev_err (& fsl_chan -> pdev -> dev , "Source Offset Error interrupt.\n" );
93+
94+ if (ch_err & EDMA_V3_CH_ERR_SAE )
95+ dev_err (& fsl_chan -> pdev -> dev , "Source Address Error interrupt.\n" );
96+
97+ if (ch_err & EDMA_V3_CH_ERR_ECX )
98+ dev_err (& fsl_chan -> pdev -> dev , "Transfer Canceled interrupt.\n" );
99+
100+ if (ch_err & EDMA_V3_CH_ERR_UCE )
101+ dev_err (& fsl_chan -> pdev -> dev , "Uncorrectable TCD error during channel execution interrupt.\n" );
102+
103+ fsl_chan -> status = DMA_ERROR ;
104+ }
105+
106+ static irqreturn_t fsl_edma3_err_handler_per_chan (int irq , void * dev_id )
107+ {
108+ struct fsl_edma_chan * fsl_chan = dev_id ;
109+
110+ fsl_edma3_err_check (fsl_chan );
111+
112+ return IRQ_HANDLED ;
113+ }
114+
115+ static irqreturn_t fsl_edma3_err_handler_shared (int irq , void * dev_id )
116+ {
117+ struct fsl_edma_engine * fsl_edma = dev_id ;
118+ unsigned int ch ;
119+
120+ for (ch = 0 ; ch < fsl_edma -> n_chans ; ch ++ ) {
121+ if (fsl_edma -> chan_masked & BIT (ch ))
122+ continue ;
123+
124+ fsl_edma3_err_check (& fsl_edma -> chans [ch ]);
125+ }
126+
127+ return IRQ_HANDLED ;
128+ }
129+
53130static irqreturn_t fsl_edma3_tx_handler (int irq , void * dev_id )
54131{
55132 struct fsl_edma_chan * fsl_chan = dev_id ;
@@ -309,7 +386,8 @@ fsl_edma_irq_init(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma
309386
310387static int fsl_edma3_irq_init (struct platform_device * pdev , struct fsl_edma_engine * fsl_edma )
311388{
312- int i ;
389+ char * errirq_name ;
390+ int i , ret ;
313391
314392 for (i = 0 ; i < fsl_edma -> n_chans ; i ++ ) {
315393
@@ -324,6 +402,27 @@ static int fsl_edma3_irq_init(struct platform_device *pdev, struct fsl_edma_engi
324402 return - EINVAL ;
325403
326404 fsl_chan -> irq_handler = fsl_edma3_tx_handler ;
405+
406+ if (!(fsl_edma -> drvdata -> flags & FSL_EDMA_DRV_ERRIRQ_SHARE )) {
407+ fsl_chan -> errirq = fsl_chan -> txirq ;
408+ fsl_chan -> errirq_handler = fsl_edma3_err_handler_per_chan ;
409+ }
410+ }
411+
412+ /* All channel err use one irq number */
413+ if (fsl_edma -> drvdata -> flags & FSL_EDMA_DRV_ERRIRQ_SHARE ) {
414+ /* last one is error irq */
415+ fsl_edma -> errirq = platform_get_irq_optional (pdev , fsl_edma -> n_chans );
416+ if (fsl_edma -> errirq < 0 )
417+ return 0 ; /* dts miss err irq, treat as no err irq case */
418+
419+ errirq_name = devm_kasprintf (& pdev -> dev , GFP_KERNEL , "%s-err" ,
420+ dev_name (& pdev -> dev ));
421+
422+ ret = devm_request_irq (& pdev -> dev , fsl_edma -> errirq , fsl_edma3_err_handler_shared ,
423+ 0 , errirq_name , fsl_edma );
424+ if (ret )
425+ return dev_err_probe (& pdev -> dev , ret , "Can't register eDMA err IRQ.\n" );
327426 }
328427
329428 return 0 ;
@@ -464,7 +563,8 @@ static struct fsl_edma_drvdata imx7ulp_data = {
464563};
465564
466565static struct fsl_edma_drvdata imx8qm_data = {
467- .flags = FSL_EDMA_DRV_HAS_PD | FSL_EDMA_DRV_EDMA3 | FSL_EDMA_DRV_MEM_REMOTE ,
566+ .flags = FSL_EDMA_DRV_HAS_PD | FSL_EDMA_DRV_EDMA3 | FSL_EDMA_DRV_MEM_REMOTE
567+ | FSL_EDMA_DRV_ERRIRQ_SHARE ,
468568 .chreg_space_sz = 0x10000 ,
469569 .chreg_off = 0x10000 ,
470570 .setup_irq = fsl_edma3_irq_init ,
@@ -481,14 +581,15 @@ static struct fsl_edma_drvdata imx8ulp_data = {
481581};
482582
483583static struct fsl_edma_drvdata imx93_data3 = {
484- .flags = FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA3 ,
584+ .flags = FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA3 | FSL_EDMA_DRV_ERRIRQ_SHARE ,
485585 .chreg_space_sz = 0x10000 ,
486586 .chreg_off = 0x10000 ,
487587 .setup_irq = fsl_edma3_irq_init ,
488588};
489589
490590static struct fsl_edma_drvdata imx93_data4 = {
491- .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA4 ,
591+ .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA4
592+ | FSL_EDMA_DRV_ERRIRQ_SHARE ,
492593 .chreg_space_sz = 0x8000 ,
493594 .chreg_off = 0x10000 ,
494595 .mux_off = 0x10000 + offsetof(struct fsl_edma3_ch_reg , ch_mux ),
@@ -498,7 +599,7 @@ static struct fsl_edma_drvdata imx93_data4 = {
498599
499600static struct fsl_edma_drvdata imx95_data5 = {
500601 .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA4 |
501- FSL_EDMA_DRV_TCD64 ,
602+ FSL_EDMA_DRV_TCD64 | FSL_EDMA_DRV_ERRIRQ_SHARE ,
502603 .chreg_space_sz = 0x8000 ,
503604 .chreg_off = 0x10000 ,
504605 .mux_off = 0x200 ,
@@ -700,6 +801,9 @@ static int fsl_edma_probe(struct platform_device *pdev)
700801 snprintf (fsl_chan -> chan_name , sizeof (fsl_chan -> chan_name ), "%s-CH%02d" ,
701802 dev_name (& pdev -> dev ), i );
702803
804+ snprintf (fsl_chan -> errirq_name , sizeof (fsl_chan -> errirq_name ),
805+ "%s-CH%02d-err" , dev_name (& pdev -> dev ), i );
806+
703807 fsl_chan -> edma = fsl_edma ;
704808 fsl_chan -> pm_state = RUNNING ;
705809 fsl_chan -> srcid = 0 ;
0 commit comments