/** Turn of DMA channel configured by EnableDma(). @param Channel DMA Channel to configure @param SuccesMask Bits in DMA4_CSR register indicate EFI_SUCCESS @param ErrorMask Bits in DMA4_CSR register indicate EFI_DEVICE_ERROR @retval EFI_SUCCESS DMA hardware disabled @retval EFI_INVALID_PARAMETER Channel is not valid @retval EFI_DEVICE_ERROR The system hardware could not map the requested information. **/ EFI_STATUS EFIAPI DisableDmaChannel ( IN UINTN Channel, IN UINT32 SuccessMask, IN UINT32 ErrorMask ) { EFI_STATUS Status = EFI_SUCCESS; UINT32 Reg; if (Channel > DMA4_MAX_CHANNEL) { return EFI_INVALID_PARAMETER; } do { Reg = MmioRead32 (DMA4_CSR(Channel)); if ((Reg & ErrorMask) != 0) { Status = EFI_DEVICE_ERROR; DEBUG ((EFI_D_ERROR, "DMA Error (%d) %x\n", Channel, Reg)); break; } } while ((Reg & SuccessMask) != SuccessMask); // Disable all status bits and clear them MmioWrite32 (DMA4_CICR (Channel), 0); MmioWrite32 (DMA4_CSR (Channel), DMA4_CSR_RESET); MmioAnd32 (DMA4_CCR(0), ~(DMA4_CCR_ENABLE | DMA4_CCR_RD_ACTIVE | DMA4_CCR_WR_ACTIVE)); return Status; }
/** * ti_sdma_deactivate_channel - deactivates a channel * @ch: the channel to deactivate * * * * LOCKING: * DMA registers protected by internal mutex * * RETURNS: * EH_HANDLED or EH_NOT_HANDLED */ int ti_sdma_deactivate_channel(unsigned int ch) { struct ti_sdma_softc *sc = ti_sdma_sc; unsigned int j; unsigned int addr; /* Sanity check */ if (sc == NULL) return (ENOMEM); TI_SDMA_LOCK(sc); /* First check if the channel is currently active */ if ((sc->sc_active_channels & (1 << ch)) == 0) { TI_SDMA_UNLOCK(sc); return (EBUSY); } /* Mark the channel as inactive */ sc->sc_active_channels &= ~(1 << ch); /* Disable all DMA interrupts for the channel. */ ti_sdma_write_4(sc, DMA4_CICR(ch), 0); /* Make sure the DMA transfer is stopped. */ ti_sdma_write_4(sc, DMA4_CCR(ch), 0); /* Clear the CSR register and IRQ status register */ ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK); for (j = 0; j < NUM_DMA_IRQS; j++) { ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch)); } /* Clear all the channel registers, this should abort any transaction */ for (addr = DMA4_CCR(ch); addr <= DMA4_COLOR(ch); addr += 4) ti_sdma_write_4(sc, addr, 0x00000000); TI_SDMA_UNLOCK(sc); return 0; }
/** * ti_sdma_disable_channel_irq - enables IRQ's on the given channel * @ch: the channel to enable IRQ's on * @flags: bitmask of interrupt types to enable * * Flags can be a bitmask of the following options: * DMA_IRQ_FLAG_DROP * DMA_IRQ_FLAG_HALF_FRAME_COMPL * DMA_IRQ_FLAG_FRAME_COMPL * DMA_IRQ_FLAG_START_LAST_FRAME * DMA_IRQ_FLAG_BLOCK_COMPL * DMA_IRQ_FLAG_ENDOF_PKT * DMA_IRQ_FLAG_DRAIN * * * LOCKING: * DMA registers protected by internal mutex * * RETURNS: * EH_HANDLED or EH_NOT_HANDLED */ int ti_sdma_enable_channel_irq(unsigned int ch, uint32_t flags) { struct ti_sdma_softc *sc = ti_sdma_sc; uint32_t irq_enable; /* Sanity check */ if (sc == NULL) return (ENOMEM); TI_SDMA_LOCK(sc); if ((sc->sc_active_channels & (1 << ch)) == 0) { TI_SDMA_UNLOCK(sc); return (EINVAL); } /* Always enable the error interrupts if we have interrupts enabled */ flags |= DMA4_CICR_TRANS_ERR_IE | DMA4_CICR_SECURE_ERR_IE | DMA4_CICR_SUPERVISOR_ERR_IE | DMA4_CICR_MISALIGNED_ADRS_ERR_IE; sc->sc_channel[ch].reg_cicr = flags; /* Write the values to the register */ ti_sdma_write_4(sc, DMA4_CICR(ch), flags); /* Enable the channel interrupt enable */ irq_enable = ti_sdma_read_4(sc, DMA4_IRQENABLE_L(0)); irq_enable |= (1 << ch); ti_sdma_write_4(sc, DMA4_IRQENABLE_L(0), irq_enable); /* Indicate the registers need to be rewritten on the next transaction */ sc->sc_channel[ch].need_reg_write = 1; TI_SDMA_UNLOCK(sc); return (0); }
/** * ti_sdma_disable_channel_irq - disables IRQ's on the given channel * @ch: the channel to disable IRQ's on * * Disable interupt generation for the given channel. * * LOCKING: * DMA registers protected by internal mutex * * RETURNS: * EH_HANDLED or EH_NOT_HANDLED */ int ti_sdma_disable_channel_irq(unsigned int ch) { struct ti_sdma_softc *sc = ti_sdma_sc; uint32_t irq_enable; unsigned int j; /* Sanity check */ if (sc == NULL) return (ENOMEM); TI_SDMA_LOCK(sc); if ((sc->sc_active_channels & (1 << ch)) == 0) { TI_SDMA_UNLOCK(sc); return (EINVAL); } /* Disable all the individual error conditions */ sc->sc_channel[ch].reg_cicr = 0x0000; ti_sdma_write_4(sc, DMA4_CICR(ch), 0x0000); /* Disable the channel interrupt enable */ for (j = 0; j < NUM_DMA_IRQS; j++) { irq_enable = ti_sdma_read_4(sc, DMA4_IRQENABLE_L(j)); irq_enable &= ~(1 << ch); ti_sdma_write_4(sc, DMA4_IRQENABLE_L(j), irq_enable); } /* Indicate the registers need to be rewritten on the next transaction */ sc->sc_channel[ch].need_reg_write = 1; TI_SDMA_UNLOCK(sc); return (0); }
/** * ti_sdma_stop_xfer - stops any currently active transfers * @ch: the channel number to set the endianess of * * This function call is effectively a NOP if no transaction is in progress. * * LOCKING: * DMA registers protected by internal mutex * * RETURNS: * EH_HANDLED or EH_NOT_HANDLED */ int ti_sdma_stop_xfer(unsigned int ch) { struct ti_sdma_softc *sc = ti_sdma_sc; unsigned int j; /* Sanity check */ if (sc == NULL) return (ENOMEM); TI_SDMA_LOCK(sc); if ((sc->sc_active_channels & (1 << ch)) == 0) { TI_SDMA_UNLOCK(sc); return (EINVAL); } /* Disable all DMA interrupts for the channel. */ ti_sdma_write_4(sc, DMA4_CICR(ch), 0); /* Make sure the DMA transfer is stopped. */ ti_sdma_write_4(sc, DMA4_CCR(ch), 0); /* Clear the CSR register and IRQ status register */ ti_sdma_write_4(sc, DMA4_CSR(ch), DMA4_CSR_CLEAR_MASK); for (j = 0; j < NUM_DMA_IRQS; j++) { ti_sdma_write_4(sc, DMA4_IRQSTATUS_L(j), (1 << ch)); } /* Configuration registers need to be re-written on the next xfer */ sc->sc_channel[ch].need_reg_write = 1; TI_SDMA_UNLOCK(sc); return (0); }
/** Configure OMAP DMA Channel @param Channel DMA Channel to configure @param Dma4 Pointer to structure used to initialize DMA registers for the Channel @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. @retval EFI_INVALID_PARAMETER Channel is not valid @retval EFI_DEVICE_ERROR The system hardware could not map the requested information. **/ EFI_STATUS EFIAPI EnableDmaChannel ( IN UINTN Channel, IN OMAP_DMA4 *DMA4 ) { UINT32 RegVal; if (Channel > DMA4_MAX_CHANNEL) { return EFI_INVALID_PARAMETER; } /* 1) Configure the transfer parameters in the logical DMA registers */ /*-------------------------------------------------------------------*/ /* a) Set the data type CSDP[1:0], the Read/Write Port access type CSDP[8:7]/[15:14], the Source/dest endianism CSDP[21]/CSDP[19], write mode CSDP[17:16], source/dest packed or nonpacked CSDP[6]/CSDP[13] */ // Read CSDP RegVal = MmioRead32 (DMA4_CSDP (Channel)); // Build reg RegVal = ((RegVal & ~ 0x3) | DMA4->DataType ); RegVal = ((RegVal & ~(0x3 << 7)) | (DMA4->ReadPortAccessType << 7)); RegVal = ((RegVal & ~(0x3 << 14)) | (DMA4->WritePortAccessType << 14)); RegVal = ((RegVal & ~(0x1 << 21)) | (DMA4->SourceEndiansim << 21)); RegVal = ((RegVal & ~(0x1 << 19)) | (DMA4->DestinationEndianism << 19)); RegVal = ((RegVal & ~(0x3 << 16)) | (DMA4->WriteMode << 16)); RegVal = ((RegVal & ~(0x1 << 6)) | (DMA4->SourcePacked << 6)); RegVal = ((RegVal & ~(0x1 << 13)) | (DMA4->DestinationPacked << 13)); // Write CSDP MmioWrite32 (DMA4_CSDP (Channel), RegVal); /* b) Set the number of element per frame CEN[23:0]*/ MmioWrite32 (DMA4_CEN (Channel), DMA4->NumberOfElementPerFrame); /* c) Set the number of frame per block CFN[15:0]*/ MmioWrite32 (DMA4_CFN (Channel), DMA4->NumberOfFramePerTransferBlock); /* d) Set the Source/dest start address index CSSA[31:0]/CDSA[31:0]*/ MmioWrite32 (DMA4_CSSA (Channel), DMA4->SourceStartAddress); MmioWrite32 (DMA4_CDSA (Channel), DMA4->DestinationStartAddress); /* e) Set the Read Port addressing mode CCR[13:12], the Write Port addressing mode CCR[15:14], read/write priority CCR[6]/CCR[26] I changed LCH CCR[20:19]=00 and CCR[4:0]=00000 to LCH CCR[20:19]= DMA4->WriteRequestNumber and CCR[4:0]=DMA4->ReadRequestNumber */ // Read CCR RegVal = MmioRead32 (DMA4_CCR (Channel)); // Build reg RegVal = ((RegVal & ~0x1f) | DMA4->ReadRequestNumber); RegVal = ((RegVal & ~(BIT20 | BIT19)) | DMA4->WriteRequestNumber << 19); RegVal = ((RegVal & ~(0x3 << 12)) | (DMA4->ReadPortAccessMode << 12)); RegVal = ((RegVal & ~(0x3 << 14)) | (DMA4->WritePortAccessMode << 14)); RegVal = ((RegVal & ~(0x1 << 6)) | (DMA4->ReadPriority << 6)); RegVal = ((RegVal & ~(0x1 << 26)) | (DMA4->WritePriority << 26)); // Write CCR MmioWrite32 (DMA4_CCR (Channel), RegVal); /* f)- Set the source element index CSEI[15:0]*/ MmioWrite32 (DMA4_CSEI (Channel), DMA4->SourceElementIndex); /* - Set the source frame index CSFI[15:0]*/ MmioWrite32 (DMA4_CSFI (Channel), DMA4->SourceFrameIndex); /* - Set the destination element index CDEI[15:0]*/ MmioWrite32 (DMA4_CDEI (Channel), DMA4->DestinationElementIndex); /* - Set the destination frame index CDFI[31:0]*/ MmioWrite32 (DMA4_CDFI (Channel), DMA4->DestinationFrameIndex); MmioWrite32 (DMA4_CDFI (Channel), DMA4->DestinationFrameIndex); // Enable all the status bits since we are polling MmioWrite32 (DMA4_CICR (Channel), DMA4_CICR_ENABLE_ALL); MmioWrite32 (DMA4_CSR (Channel), DMA4_CSR_RESET); /* 2) Start the DMA transfer by Setting the enable bit CCR[7]=1 */ /*--------------------------------------------------------------*/ //write enable bit MmioOr32 (DMA4_CCR(Channel), DMA4_CCR_ENABLE); //Launch transfer return EFI_SUCCESS; }