void dma_resume_channel(int channel)
{
    /* Resume - must reinit to where it left off (so the docs say) */
    unsigned long control = DMAC_CH_CONTROL(channel);
    if ((control & 0x7ff) == 0)
        return; /* empty */

    DMAC_INT_TC_CLEAR = (1<<channel);
    DMAC_INT_ERR_CLEAR = (1<<channel);
    DMAC_CH_SRC_ADDR(channel) = DMAC_CH_SRC_ADDR(channel);
    DMAC_CH_DST_ADDR(channel) = DMAC_CH_DST_ADDR(channel);
    DMAC_CH_LLI(channel) = DMAC_CH_LLI(channel);
    DMAC_CH_CONTROL(channel) = control;
    bitset32(&DMAC_CH_CONFIGURATION(channel), (1<<0));
}
Exemple #2
0
void dma_enable_channel(int channel, void *src, void *dst, int peri,
                        int flow_controller, bool src_inc, bool dst_inc,
                        size_t size, int nwords, void (*callback)(void))
{
    dma_callback[channel] = callback;

    /* Clear any pending interrupts leftover from previous operation */
    DMAC_INT_TC_CLEAR  = (1<<channel);
    DMAC_INT_ERR_CLEAR = (1<<channel);

    DMAC_CH_SRC_ADDR(channel) = (int)src;
    DMAC_CH_DST_ADDR(channel) = (int)dst;

    /* When LLI is 0 channel is disabled upon transfer completion */
    DMAC_CH_LLI(channel) = 0;

    /*  Channel Control Register */
    DMAC_CH_CONTROL(channel) =
         ((1<<31)                 /* LLI triggers terminal count interrupt */
     /* | (1<<30) */              /* cacheable  = 1,  non = 0 */
     /* | (1<<29) */              /* bufferable = 1,  non = 0 */
     /* | (1<<28) */              /* privileged = 1, user = 0 */
        | (dst_inc? (1<<27): 0)   /* specify address increment */
        | (src_inc? (1<<26): 0)   /* specify address increment */
       /* [25:24] */              /* undefined  */
        | (2<<21)                 /* dst width = word, 32bit */
        | (2<<18)                 /* src width = word, 32bit */
       /* OF uses transfers of 4 * 32 bits words on memory, i2sin, i2sout */
       /* OF uses transfers of 8 * 32 bits words on SD */
        | (nwords<<15)            /* dst size  */
        | (nwords<<12)            /* src size  */
        | ((size & 0x7ff)<<0));   /* transfer size */

    /*  Channel Config Register  */
    DMAC_CH_CONFIGURATION(channel) =
       /* [31:19] */              /* Read undefined. Write as zero  */
       /* (0<<18) */              /* Halt Bit    */
       /* (0<<17) */              /* Active Bit  */
       /* (0<<16) */              /* Lock Bit    */
          (1<<15)                 /* terminal count interrupt mask */
        | (1<<14)                 /* interrupt error mask */
        | (flow_controller<<11)   /* flow controller is peripheral or SDMAC */
       /* we set the same peripheral as source and destination because we
        * always use memory-to-peripheral or peripheral-to-memory transfers */
        | (peri<<6)               /* dst peripheral */
        | (peri<<1)               /* src peripheral */
        | (1<<0);                 /* enable channel */
}