From: Rander Wang rander.wang@intel.com
On cnl, all the dma share the same interrupt pin, so all the dma controller need to be checked in interrupt function. And also refine dma probe
Signed-off-by: Rander Wang rander.wang@linux.intel.com --- src/drivers/dw-dma.c | 61 +++++++++++++++++++++----------------- src/platform/cannonlake/platform.c | 5 ++++ 2 files changed, 39 insertions(+), 27 deletions(-)
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index 15d608c..a06087e 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -1029,7 +1029,6 @@ static int dw_dma_probe(struct dma *dma) }
#else - /* this will probably be called at the end of every period copied */ static void dw_dma_irq_handler(void *data) { @@ -1047,14 +1046,7 @@ static void dw_dma_irq_handler(void *data)
status_intr = dw_read(dma, DW_INTR_STATUS); if (!status_intr) { -#ifdef CONFIG_CANNONLAKE - dma++; - status_intr = dw_read(dma, DW_INTR_STATUS); - if (!status_intr) - trace_dma_error("eI0"); -#else trace_dma_error("eI0"); -#endif }
tracev_dma("DIr"); @@ -1144,37 +1136,52 @@ static void dw_dma_irq_handler(void *data) } }
+/*All the dma share the same interrupt on CNL, so check each dma*/ +/*controller when interrupt coming, then do the work */ +static void dw_dma_irq_cnl(void *data) +{ + struct dma *dma; + uint32_t status_intr; + + /*check interrupt status of DMA controller 0*/ + dma = dma_get(DMA_GP_LP_DMAC0); + status_intr = dw_read(dma, DW_INTR_STATUS); + if (status_intr) + dw_dma_irq_handler(dma); + + /*check interrupt status of DMA controller 1*/ + dma = dma_get(DMA_GP_LP_DMAC1); + status_intr = dw_read(dma, DW_INTR_STATUS); + if (status_intr) + dw_dma_irq_handler(dma); +} + static int dw_dma_probe(struct dma *dma) { struct dma_pdata *dw_pdata; - struct dma *dmac = dma; int i; -#ifdef CONFIG_CANNONLAKE - int j; - - for (j = 0; j < MAX_GPDMA_COUNT; j++) -#endif - { - /* allocate private data */ - dw_pdata = rzalloc(RZONE_SYS, RFLAGS_NONE, sizeof(*dw_pdata)); - dma_set_drvdata(dmac, dw_pdata);
- spinlock_init(&dmac->lock); + /* allocate private data */ + dw_pdata = rzalloc(RZONE_SYS, RFLAGS_NONE, sizeof(*dw_pdata)); + dma_set_drvdata(dma, dw_pdata);
- dw_dma_setup(dmac); + spinlock_init(&dma->lock);
- /* init work */ - for (i = 0; i < DW_MAX_CHAN; i++) { - dw_pdata->chan[i].dma = dmac; - dw_pdata->chan[i].channel = i; - dw_pdata->chan[i].status = COMP_STATE_INIT; - } + dw_dma_setup(dma);
- dmac++; + /* init work */ + for (i = 0; i < DW_MAX_CHAN; i++) { + dw_pdata->chan[i].dma = dma; + dw_pdata->chan[i].channel = i; + dw_pdata->chan[i].status = COMP_STATE_INIT; }
/* register our IRQ handler */ +#ifdef CONFIG_CANNONLAKE + interrupt_register(dma_irq(dma), dw_dma_irq_cnl, dma); +#else interrupt_register(dma_irq(dma), dw_dma_irq_handler, dma); +#endif interrupt_enable(dma_irq(dma));
return 0; diff --git a/src/platform/cannonlake/platform.c b/src/platform/cannonlake/platform.c index beb6582..1a9b88a 100644 --- a/src/platform/cannonlake/platform.c +++ b/src/platform/cannonlake/platform.c @@ -253,6 +253,11 @@ int platform_init(struct reef *reef) return -ENODEV; dma_probe(dmac);
+ dmac = dma_get(DMA_GP_LP_DMAC1); + if (!dmac) + return -ENODEV; + dma_probe(dmac); + dmac = dma_get(DMA_HOST_OUT_DMAC); if (!dmac) return -ENODEV;