I'm attempting to get a momeory-memory SGDMA desgin working, and I'm having some problems with clearing the interrupt from the SGDMA. The system is roughly as follows:
Arria V SoC with two banks of DDR3, one for the HPS, one for attched to the FPGA.
SGDMA IP core reading from FPGA DDR3 (avl_0 slave port on UniPHY DDR3 controller) and writing to HPS DDR3 (f2h_sdram0_data a slave port on the multi-master DDR controller in the HPS)
Linux image running on HPS with custom driver for the SGDMA to provide access to FPGA attached DDR3 to userspace Linux software.
Built using Quartus 15.1 on windows 7 64-bit
My problem is that I can perform a single DMA transfer (with multiple descriptors in the chain) just fine, but when attemptiing a second transfer the interrupt never arrives and the driver stalls waiting for it. On a read() request my driver performs the following actions:
Builds a descriptor chain in the dedicated onchip memory attached to the sgdma descriptor ports.
reads the SGDMA status register to confirm it is not BUSY
Clears any previous completion bits in the status register by writing 1 to the DESCRIPTOR_COMPLETED and CHAIN_COMPLETED bits.
sets the next_descriptor_pointer register to point at the start of the descriptor chain.
sets the IE_CHAIN_COMPLETED, IE_GLOBAL and RUN bits in the control register.
waits for the interrupt to arrive
checks the status register to ensure DESCRIPTOR_COMPLETED and CHAIN_COMPLETED bits are set and BUSY is not set.
clears the status register by writing 1 to the DESCRIPTOR_COMPLETED and CHAIN_COMPLETED bits.
clears the IRQ by writing 1 to CLEAR_INTERRUPT.
clears the RUN bit in the control register
The first read works fine (interrupt arrives correctly etc). The second read hangs at step 6. I suspect that I am not clearing the interrupt from the SGDMA correctly. I'm happy that the Linux driver side of the code (registering interrupts etc) is ok as if I perform a software reset after each transfer (write 1 to SW_RESET bit twice after step 10 above) everything works correctly for multiple transfers. What am I doing wrong? What should I be doing to clear the interrupt from the SGDMA? Thanks Phil