static int dma_stm32_stop(struct device *dev, u32_t id) { struct dma_stm32_device *ddata = dev->driver_data; struct dma_stm32_stream *stream = &ddata->stream[id]; u32_t scr, sfcr, irqstatus; int ret; /* Disable all IRQs */ scr = dma_stm32_read(ddata, DMA_STM32_SCR(id)); scr &= ~DMA_STM32_SCR_IRQ_MASK; dma_stm32_write(ddata, DMA_STM32_SCR(id), scr); sfcr = dma_stm32_read(ddata, DMA_STM32_SFCR(id)); sfcr &= ~DMA_STM32_SFCR_FEIE; dma_stm32_write(ddata, DMA_STM32_SFCR(id), sfcr); /* Disable stream */ ret = dma_stm32_disable_stream(ddata, id); if (ret) return ret; /* Clear remanent IRQs from previous transfers */ irqstatus = dma_stm32_irq_status(ddata, id); if (irqstatus) { dma_stm32_irq_clear(ddata, id, irqstatus); } /* Finally, flag stream as free */ stream->busy = false; return 0; }
static void dma_stm32_irq_clear(struct dma_stm32_device *ddata, u32_t id, u32_t irqs) { irqs = irqs << (((id & 2) << 3) | ((id & 1) * 6)); if (id & 4) { dma_stm32_write(ddata, DMA_STM32_HIFCR, irqs); } else { dma_stm32_write(ddata, DMA_STM32_LIFCR, irqs); } }
static int dma_stm32_disable_stream(struct dma_stm32_device *ddata, u32_t id) { u32_t config; int count = 0; int ret = 0; for (;;) { config = dma_stm32_read(ddata, DMA_STM32_SCR(id)); /* Stream already disabled */ if (!(config & DMA_STM32_SCR_EN)) { return 0; } /* Try to disable stream */ dma_stm32_write(ddata, DMA_STM32_SCR(id), config &= ~DMA_STM32_SCR_EN); /* After trying for 5 seconds, give up */ k_sleep(K_SECONDS(5)); if (count++ > (5 * 1000) / 50) { SYS_LOG_ERR("DMA error: Stream in use\n"); return -EBUSY; } } return ret; }
static int dma_stm32_start(struct device *dev, u32_t id) { struct dma_stm32_device *ddata = dev->driver_data; struct dma_stm32_stream_reg *regs = &ddata->stream[id].regs; u32_t irqstatus; int ret; ret = dma_stm32_disable_stream(ddata, id); if (ret) { return ret; } dma_stm32_write(ddata, DMA_STM32_SCR(id), regs->scr); dma_stm32_write(ddata, DMA_STM32_SPAR(id), regs->spar); dma_stm32_write(ddata, DMA_STM32_SM0AR(id), regs->sm0ar); dma_stm32_write(ddata, DMA_STM32_SFCR(id), regs->sfcr); dma_stm32_write(ddata, DMA_STM32_SM1AR(id), regs->sm1ar); dma_stm32_write(ddata, DMA_STM32_SNDTR(id), regs->sndtr); /* Clear remanent IRQs from previous transfers */ irqstatus = dma_stm32_irq_status(ddata, id); if (irqstatus) { dma_stm32_irq_clear(ddata, id, irqstatus); } dma_stm32_dump_reg(ddata, id); /* Push the start button */ dma_stm32_write(ddata, DMA_STM32_SCR(id), regs->scr | DMA_STM32_SCR_EN); return 0; }