Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

dmaengine: fsl-edma: add support for S32G based platforms

S32G2/S32G3 includes two system eDMA instances based on v3 version, each of
them integrated with two DMAMUX blocks.

Another particularity of these SoCs is that the interrupts are shared
between channels as follows:
- DMA Channels 0-15 share the 'tx-0-15' interrupt
- DMA Channels 16-31 share the 'tx-16-31' interrupt
- all channels share the 'err' interrupt

Signed-off-by: Larisa Grigore <larisa.grigore@oss.nxp.com>
Co-developed-by: Ciprian Marian Costea <ciprianmarian.costea@nxp.com>
Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/r/20241219102415.1208328-5-larisa.grigore@oss.nxp.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Larisa Grigore and committed by
Vinod Koul
2500243e 57eeb0a5

+111 -1
+3
drivers/dma/fsl-edma-common.h
··· 68 68 #define EDMA_V3_CH_CSR_EEI BIT(2) 69 69 #define EDMA_V3_CH_CSR_DONE BIT(30) 70 70 #define EDMA_V3_CH_CSR_ACTIVE BIT(31) 71 + #define EDMA_V3_CH_ES_ERR BIT(31) 72 + #define EDMA_V3_MP_ES_VLD BIT(31) 71 73 72 74 enum fsl_edma_pm_state { 73 75 RUNNING = 0, ··· 242 240 const struct fsl_edma_drvdata *drvdata; 243 241 u32 n_chans; 244 242 int txirq; 243 + int txirq_16_31; 245 244 int errirq; 246 245 bool big_endian; 247 246 struct edma_regs regs;
+108 -1
drivers/dma/fsl-edma-main.c
··· 3 3 * drivers/dma/fsl-edma.c 4 4 * 5 5 * Copyright 2013-2014 Freescale Semiconductor, Inc. 6 + * Copyright 2024 NXP 6 7 * 7 8 * Driver for the Freescale eDMA engine with flexible channel multiplexing 8 9 * capability for DMA request sources. The eDMA block can be found on some 9 - * Vybrid and Layerscape SoCs. 10 + * Vybrid, Layerscape and S32G SoCs. 10 11 */ 11 12 12 13 #include <dt-bindings/dma/fsl-edma.h> ··· 71 70 struct fsl_edma_chan *fsl_chan = devi_id; 72 71 73 72 return fsl_edma_tx_handler(irq, fsl_chan->edma); 73 + } 74 + 75 + static irqreturn_t fsl_edma3_or_tx_handler(int irq, void *dev_id, 76 + u8 start, u8 end) 77 + { 78 + struct fsl_edma_engine *fsl_edma = dev_id; 79 + struct fsl_edma_chan *chan; 80 + int i; 81 + 82 + end = min(end, fsl_edma->n_chans); 83 + 84 + for (i = start; i < end; i++) { 85 + chan = &fsl_edma->chans[i]; 86 + 87 + fsl_edma3_tx_handler(irq, chan); 88 + } 89 + 90 + return IRQ_HANDLED; 91 + } 92 + 93 + static irqreturn_t fsl_edma3_tx_0_15_handler(int irq, void *dev_id) 94 + { 95 + return fsl_edma3_or_tx_handler(irq, dev_id, 0, 16); 96 + } 97 + 98 + static irqreturn_t fsl_edma3_tx_16_31_handler(int irq, void *dev_id) 99 + { 100 + return fsl_edma3_or_tx_handler(irq, dev_id, 16, 32); 101 + } 102 + 103 + static irqreturn_t fsl_edma3_or_err_handler(int irq, void *dev_id) 104 + { 105 + struct fsl_edma_engine *fsl_edma = dev_id; 106 + struct edma_regs *regs = &fsl_edma->regs; 107 + unsigned int err, ch, ch_es; 108 + struct fsl_edma_chan *chan; 109 + 110 + err = edma_readl(fsl_edma, regs->es); 111 + if (!(err & EDMA_V3_MP_ES_VLD)) 112 + return IRQ_NONE; 113 + 114 + for (ch = 0; ch < fsl_edma->n_chans; ch++) { 115 + chan = &fsl_edma->chans[ch]; 116 + 117 + ch_es = edma_readl_chreg(chan, ch_es); 118 + if (!(ch_es & EDMA_V3_CH_ES_ERR)) 119 + continue; 120 + 121 + edma_writel_chreg(chan, EDMA_V3_CH_ES_ERR, ch_es); 122 + fsl_edma_disable_request(chan); 123 + fsl_edma->chans[ch].status = DMA_ERROR; 124 + } 125 + 126 + return IRQ_HANDLED; 74 127 } 75 128 76 129 static irqreturn_t fsl_edma_err_handler(int irq, void *dev_id) ··· 329 274 return 0; 330 275 } 331 276 277 + static int fsl_edma3_or_irq_init(struct platform_device *pdev, 278 + struct fsl_edma_engine *fsl_edma) 279 + { 280 + int ret; 281 + 282 + fsl_edma->txirq = platform_get_irq_byname(pdev, "tx-0-15"); 283 + if (fsl_edma->txirq < 0) 284 + return fsl_edma->txirq; 285 + 286 + fsl_edma->txirq_16_31 = platform_get_irq_byname(pdev, "tx-16-31"); 287 + if (fsl_edma->txirq_16_31 < 0) 288 + return fsl_edma->txirq_16_31; 289 + 290 + fsl_edma->errirq = platform_get_irq_byname(pdev, "err"); 291 + if (fsl_edma->errirq < 0) 292 + return fsl_edma->errirq; 293 + 294 + ret = devm_request_irq(&pdev->dev, fsl_edma->txirq, 295 + fsl_edma3_tx_0_15_handler, 0, "eDMA tx0_15", 296 + fsl_edma); 297 + if (ret) 298 + return dev_err_probe(&pdev->dev, ret, 299 + "Can't register eDMA tx0_15 IRQ.\n"); 300 + 301 + if (fsl_edma->n_chans > 16) { 302 + ret = devm_request_irq(&pdev->dev, fsl_edma->txirq_16_31, 303 + fsl_edma3_tx_16_31_handler, 0, 304 + "eDMA tx16_31", fsl_edma); 305 + if (ret) 306 + return dev_err_probe(&pdev->dev, ret, 307 + "Can't register eDMA tx16_31 IRQ.\n"); 308 + } 309 + 310 + ret = devm_request_irq(&pdev->dev, fsl_edma->errirq, 311 + fsl_edma3_or_err_handler, 0, "eDMA err", 312 + fsl_edma); 313 + if (ret) 314 + return dev_err_probe(&pdev->dev, ret, 315 + "Can't register eDMA err IRQ.\n"); 316 + 317 + return 0; 318 + } 319 + 332 320 static int 333 321 fsl_edma2_irq_init(struct platform_device *pdev, 334 322 struct fsl_edma_engine *fsl_edma) ··· 502 404 .setup_irq = fsl_edma3_irq_init, 503 405 }; 504 406 407 + static const struct fsl_edma_drvdata s32g2_data = { 408 + .dmamuxs = DMAMUX_NR, 409 + .chreg_space_sz = EDMA_TCD, 410 + .chreg_off = 0x4000, 411 + .flags = FSL_EDMA_DRV_EDMA3 | FSL_EDMA_DRV_MUX_SWAP, 412 + .setup_irq = fsl_edma3_or_irq_init, 413 + }; 414 + 505 415 static const struct of_device_id fsl_edma_dt_ids[] = { 506 416 { .compatible = "fsl,vf610-edma", .data = &vf610_data}, 507 417 { .compatible = "fsl,ls1028a-edma", .data = &ls1028a_data}, ··· 519 413 { .compatible = "fsl,imx93-edma3", .data = &imx93_data3}, 520 414 { .compatible = "fsl,imx93-edma4", .data = &imx93_data4}, 521 415 { .compatible = "fsl,imx95-edma5", .data = &imx95_data5}, 416 + { .compatible = "nxp,s32g2-edma", .data = &s32g2_data}, 522 417 { /* sentinel */ } 523 418 }; 524 419 MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);