123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- /* linux/arch/arm/plat-s3c64xx/dma.c
- *
- * Copyright 2009 Openmoko, Inc.
- * Copyright 2009 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- * 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 <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/interrupt.h>
- #include <linux/dmapool.h>
- #include <linux/device.h>
- #include <linux/errno.h>
- #include <linux/slab.h>
- #include <linux/delay.h>
- #include <linux/clk.h>
- #include <linux/err.h>
- #include <linux/io.h>
- #include <mach/dma.h>
- #include <mach/map.h>
- #include <mach/irqs.h>
- #include <mach/regs-sys.h>
- #include <asm/hardware/pl080.h>
- /* 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;
|