int stmp3xxx_arch_dma_is_interrupt(int channel) { int dmabus = channel / 16; int r = 0; switch (dmabus) { case STMP3XXX_BUS_APBH: r = HW_APBH_CTRL1_RD() & (1 << (channel % 16)); break; case STMP3XXX_BUS_APBX: r = HW_APBX_CTRL1_RD() & (1 << (channel % 16)); break; } return r; }
int gpmi_run_dma(apbh_dma_t * theDma, unsigned chipSelect, uint16_t waitMask, uint32_t timeout) { uint32_t physicalCommandAddress; reg32_t r32ChipDmaNumber = (NAND0_APBH_CH); //+chipSelect); reg32_t r32ChannelMask = (0x1 << r32ChipDmaNumber); bool bDmaIsRunning; int rtStatus = SUCCESS; // Save off the chip that we're watching in the DMA completion structure. g_gpmi.dmaInfo.u16CurrentChip = chipSelect; // We're using DMA channel 0 for all DMAs. g_gpmi.dmaInfo.dmaChannel = 0; // Set the criteria for finishing this DMA. g_gpmi.dmaInfo.u16DmaWaitMask = waitMask; // Clear the status word used to check the criteria for finishing this DMA. g_gpmi.dmaInfo.u16DmaWaitStatus = kNandGpmiDmaWaitMask_Nothing; // Alert me if a DMA chain is currently running!! // Note that this checks the SEMA.PHORE register field for the DMA. bDmaIsRunning = gpmi_is_dma_active(chipSelect); if (bDmaIsRunning) { rtStatus = ERROR_DDI_NAND_GPMI_DMA_BUSY; goto _standardExit; } // At this point, there should be no DMA running. // Sanity-test to make sure the DMA channel IRQ is deasserted. // (Note that the optimizing compiler will probably combine the // body of this section with the previous section.) if ( 0 != (HW_APBH_CTRL1_RD() & (r32ChannelMask << BP_APBH_CTRL1_CH0_CMDCMPLT_IRQ)) ) { rtStatus = ERROR_DDI_NAND_GPMI_DMA_BUSY; goto _standardExit; } // Get the physical address of the DMA chain. physicalCommandAddress = (uint32_t)nand_virtual_to_physical(theDma); // Flush the data cache. We don't need to invalidate since the hardware is only reading // the DMA chain, not writing to it. If the caller set the length to 0, then they don't // want us to flush the cache, probably because they just flushed the entire cache already. // if (dmaCommandLength > 0) // { // hw_core_clean_DCache_MVA_BySize((uint32_t)pDmaCmd, dmaCommandLength); // } // Initialize DMA by setting up NextCMD field HW_APBH_CHn_NXTCMDAR_WR(r32ChipDmaNumber, (reg32_t)physicalCommandAddress); // Start DMA by incrementing the semaphore. BW_APBH_CHn_SEMA_INCREMENT_SEMA(r32ChipDmaNumber, 1); // Record the time that I started the transaction // Used in the NAND_HAL_Dma_Status function below and the ddi_gpmi_wait_for_dma // function above to determine timeouts. g_gpmi.dmaInfo.uStartDMATime = time_get_microseconds(); rtStatus = gpmi_wait_for_dma(timeout, chipSelect); _standardExit: return rtStatus; }