/* * Some of the SoCs feature two DMAC modules. In such a case, the channels are * distributed equally among them.
*/ #ifdef SH_DMAC_BASE1 #define SH_DMAC_NR_MD_CH (CONFIG_NR_ONCHIP_DMA_CHANNELS / 2) #else #define SH_DMAC_NR_MD_CH CONFIG_NR_ONCHIP_DMA_CHANNELS #endif
#define SH_DMAC_CH_SZ 0x10
/* * Define the default configuration for dual address memory-memory transfer. * The 0x400 value represents auto-request, external->external.
*/ #define RS_DUAL (DM_INC | SM_INC | RS_AUTO | TS_INDEX2VAL(XMIT_SZ_32BIT))
staticunsignedlong dma_find_base(unsignedint chan)
{ unsignedlong base = SH_DMAC_BASE0;
#ifdef SH_DMAC_BASE1 if (chan >= SH_DMAC_NR_MD_CH)
base = SH_DMAC_BASE1; #endif
return base;
}
staticunsignedlong dma_base_addr(unsignedint chan)
{ unsignedlong base = dma_find_base(chan);
chan = (chan % SH_DMAC_NR_MD_CH) * SH_DMAC_CH_SZ;
/* DMAOR is placed inside the channel register space. Step over it. */ if (chan >= DMAOR)
base += SH_DMAC_CH_SZ;
/* * We determine the correct shift size based off of the CHCR transmit size * for the given channel. Since we know that it will take: * * info->count >> ts_shift[transmit_size] * * iterations to complete the transfer.
*/ staticunsignedint ts_shift[] = TS_SHIFT;
/* * The transfer end interrupt must read the chcr register to end the * hardware interrupt active condition. * Besides that it needs to waken any waiting process, which should handle * setting up the next transfer.
*/ static irqreturn_t dma_tei(int irq, void *dev_id)
{ struct dma_channel *chan = dev_id;
u32 chcr;
staticint sh_dmac_xfer_dma(struct dma_channel *chan)
{ /* * If we haven't pre-configured the channel with special flags, use * the defaults.
*/ if (unlikely(!(chan->flags & DMA_CONFIGURED)))
sh_dmac_configure_channel(chan, 0);
sh_dmac_disable_dma(chan);
/* * Single-address mode usage note! * * It's important that we don't accidentally write any value to SAR/DAR * (this includes 0) that hasn't been directly specified by the user if * we're in single-address mode. * * In this case, only one address can be defined, anything else will * result in a DMA address error interrupt (at least on the SH-4), * which will subsequently halt the transfer. * * Channel 2 on the Dreamcast is a special case, as this is used for * cascading to the PVR2 DMAC. In this case, we still need to write * SAR and DAR, regardless of value, in order for cascading to work.
*/ if (chan->sar || (mach_is_dreamcast() &&
chan->chan == PVR2_CASCADE_CHAN))
__raw_writel(chan->sar, (dma_base_addr(chan->chan) + SAR)); if (chan->dar || (mach_is_dreamcast() &&
chan->chan == PVR2_CASCADE_CHAN))
__raw_writel(chan->dar, (dma_base_addr(chan->chan) + DAR));
/* Try to clear the error flags first, incase they are set */
dmaor &= ~(DMAOR_NMIF | DMAOR_AE);
dmaor_write_reg(no, dmaor);
dmaor |= DMAOR_INIT;
dmaor_write_reg(no, dmaor);
/* See if we got an error again */ if ((dmaor_read_reg(no) & (DMAOR_AE | DMAOR_NMIF))) {
printk(KERN_ERR "dma-sh: Can't initialize DMAOR.\n"); return -EINVAL;
}
staticint __init sh_dmac_init(void)
{ struct dma_info *info = &sh_dmac_info; int i, rc;
/* * Initialize DMAE, for parts that support it.
*/
rc = dmae_irq_init(); if (unlikely(rc != 0)) return rc;
/* * Initialize DMAOR, and clean up any error flags that may have * been set.
*/ for (i = 0; i < NR_DMAOR; i++) {
rc = dmaor_reset(i); if (unlikely(rc != 0)) return rc;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.