/* linux/arch/arm/plat-s3c64xx/dma.c * * Copyright 2009 Openmoko, Inc. * Copyright 2009 Simtec Electronics * Ben Dooks * http://armlinux.simtec.co.uk/ * * S3C64XX DMA core * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* dma channel state information */ struct s3c64xx_dmac { struct device dev; struct clk *clk; void __iomem *regs; struct s3c2410_dma_chan *channels; enum dma_ch chanbase; }; /* pool to provide LLI buffers */ static struct dma_pool *dma_pool; /* Debug configuration and code */ static unsigned char debug_show_buffs = 0; static void dbg_showchan(struct s3c2410_dma_chan *chan) { pr_debug("DMA%d: %08x->%08x L %08x C %08x,%08x S %08x\n", chan->number, readl(chan->regs + PL080_CH_SRC_ADDR), readl(chan->regs + PL080_CH_DST_ADDR), readl(chan->regs + PL080_CH_LLI), readl(chan->regs + PL080_CH_CONTROL), readl(chan->regs + PL080S_CH_CONTROL2), readl(chan->regs + PL080S_CH_CONFIG)); } static void show_lli(struct pl080s_lli *lli) { pr_debug("LLI[%p] %08x->%08x, NL %08x C %08x,%08x\n", lli, lli->src_addr, lli->dst_addr, lli->next_lli, lli->control0, lli->control1); } static void dbg_showbuffs(struct s3c2410_dma_chan *chan) { struct s3c64xx_dma_buff *ptr; struct s3c64xx_dma_buff *end; pr_debug("DMA%d: buffs next %p, curr %p, end %p\n", chan->number, chan->next, chan->curr, chan->end); ptr = chan->next; end = chan->end; if (debug_show_buffs) { for (; ptr != NULL; ptr = ptr->next) { pr_debug("DMA%d: %08x ", chan->number, ptr->lli_dma); show_lli(ptr->lli); } } } /* End of Debug */ static struct s3c2410_dma_chan *s3c64xx_dma_map_channel(unsigned int channel) { struct s3c2410_dma_chan *chan; unsigned int start, offs; start = 0; if (channel >= DMACH_PCM1_TX) start = 8; for (offs = 0; offs < 8; offs++) { chan = &s3c2410_chans[start + offs]; if (!chan->in_use) goto found; } return NULL; found: s3c_dma_chan_map[channel] = chan; return chan; } int s3c2410_dma_config(enum dma_ch channel, int xferunit) { struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); if (chan == NULL) return -EINVAL; switch (xferunit) { case 1: chan->hw_width = 0; break;