]> err.no Git - linux-2.6/blobdiff - arch/arm/plat-s3c24xx/dma.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
[linux-2.6] / arch / arm / plat-s3c24xx / dma.c
index aae1b9cbaf44b77a0e9f4ea7e9f37c04cd1a1191..8c5e656d5d8c8c346dd5f2d3c7740886a977f235 100644 (file)
@@ -130,8 +130,8 @@ dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
        dmadbg_dumpregs(fname, line, chan, &state);
 }
 
-#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
-#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
+#define dbg_showregs(chan) dmadbg_showregs(__func__, __LINE__, (chan))
+#define dbg_showchan(chan) dmadbg_showchan(__func__, __LINE__, (chan))
 #else
 #define dbg_showregs(chan) do { } while(0)
 #define dbg_showchan(chan) do { } while(0)
@@ -403,7 +403,7 @@ static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
 
                        if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
                                pr_debug("%s: buff not yet loaded, no more todo\n",
-                                        __FUNCTION__);
+                                        __func__);
                        } else {
                                chan->load_state = S3C2410_DMALOAD_1RUNNING;
                                s3c2410_dma_loadbuffer(chan, chan->next);
@@ -463,16 +463,16 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,
                return -EINVAL;
 
        pr_debug("%s: id=%p, data=%08x, size=%d\n",
-                __FUNCTION__, id, (unsigned int)data, size);
+                __func__, id, (unsigned int)data, size);
 
        buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
        if (buf == NULL) {
                pr_debug("%s: out of memory (%ld alloc)\n",
-                        __FUNCTION__, (long)sizeof(*buf));
+                        __func__, (long)sizeof(*buf));
                return -ENOMEM;
        }
 
-       //pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
+       //pr_debug("%s: new buffer %p\n", __func__, buf);
        //dbg_showchan(chan);
 
        buf->next  = NULL;
@@ -486,18 +486,18 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,
        if (chan->curr == NULL) {
                /* we've got nothing loaded... */
                pr_debug("%s: buffer %p queued onto empty channel\n",
-                        __FUNCTION__, buf);
+                        __func__, buf);
 
                chan->curr = buf;
                chan->end  = buf;
                chan->next = NULL;
        } else {
                pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
-                        chan->number, __FUNCTION__, buf);
+                        chan->number, __func__, buf);
 
                if (chan->end == NULL)
                        pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
-                                chan->number, __FUNCTION__, chan);
+                                chan->number, __func__, chan);
 
                chan->end->next = buf;
                chan->end = buf;
@@ -525,7 +525,8 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,
                }
        } else if (chan->state == S3C2410_DMA_IDLE) {
                if (chan->flags & S3C2410_DMAF_AUTOSTART) {
-                       s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
+                       s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
+                                        S3C2410_DMAOP_START);
                }
        }
 
@@ -571,7 +572,7 @@ s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
                if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
                                /* flag error? */
                        printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
-                              chan->number, __FUNCTION__);
+                              chan->number, __func__);
                        return;
                }
                break;
@@ -657,7 +658,7 @@ s3c2410_dma_irq(int irq, void *devpw)
 
                if (buf->magic != BUF_MAGIC) {
                        printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
-                              chan->number, __FUNCTION__, buf);
+                              chan->number, __func__, buf);
                        return IRQ_HANDLED;
                }
 
@@ -691,7 +692,7 @@ s3c2410_dma_irq(int irq, void *devpw)
                        if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
                                /* flag error? */
                                printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
-                                      chan->number, __FUNCTION__);
+                                      chan->number, __func__);
                                return IRQ_HANDLED;
                        }
 
@@ -758,7 +759,7 @@ int s3c2410_dma_request(unsigned int channel,
 
        if (!chan->irq_claimed) {
                pr_debug("dma%d: %s : requesting irq %d\n",
-                        channel, __FUNCTION__, chan->irq);
+                        channel, __func__, chan->irq);
 
                chan->irq_claimed = 1;
                local_irq_restore(flags);
@@ -785,9 +786,9 @@ int s3c2410_dma_request(unsigned int channel,
 
        /* need to setup */
 
-       pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
+       pr_debug("%s: channel initialised, %p\n", __func__, chan);
 
-       return 0;
+       return chan->number | DMACH_LOW_LEVEL;
 }
 
 EXPORT_SYMBOL(s3c2410_dma_request);
@@ -822,7 +823,7 @@ int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
 
        if (chan->state != S3C2410_DMA_IDLE) {
                pr_debug("%s: need to stop dma channel %p\n",
-                      __FUNCTION__, chan);
+                      __func__, chan);
 
                /* possibly flush the channel */
                s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
@@ -851,7 +852,7 @@ static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
        unsigned long flags;
        unsigned long tmp;
 
-       pr_debug("%s:\n", __FUNCTION__);
+       pr_debug("%s:\n", __func__);
 
        dbg_showchan(chan);
 
@@ -906,14 +907,14 @@ static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
        struct s3c2410_dma_buf *buf, *next;
        unsigned long flags;
 
-       pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
+       pr_debug("%s: chan %p (%d)\n", __func__, chan, chan->number);
 
        dbg_showchan(chan);
 
        local_irq_save(flags);
 
        if (chan->state != S3C2410_DMA_IDLE) {
-               pr_debug("%s: stopping channel...\n", __FUNCTION__ );
+               pr_debug("%s: stopping channel...\n", __func__ );
                s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
        }
 
@@ -928,7 +929,7 @@ static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
                        next = buf->next;
 
                        pr_debug("%s: free buffer %p, next %p\n",
-                              __FUNCTION__, buf, buf->next);
+                              __func__, buf, buf->next);
 
                        s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
                        s3c2410_dma_freebuf(buf);
@@ -975,7 +976,7 @@ static int s3c2410_dma_started(struct s3c2410_dma_chan *chan)
 
                        if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
                                pr_debug("%s: buff not yet loaded, no more todo\n",
-                                        __FUNCTION__);
+                                        __func__);
                        } else {
                                chan->load_state = S3C2410_DMALOAD_1RUNNING;
                                s3c2410_dma_loadbuffer(chan, chan->next);
@@ -1049,16 +1050,16 @@ int s3c2410_dma_config(dmach_t channel,
        struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
 
        pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
-                __FUNCTION__, channel, xferunit, dcon);
+                __func__, channel, xferunit, dcon);
 
        if (chan == NULL)
                return -EINVAL;
 
-       pr_debug("%s: Initial dcon is %08x\n", __FUNCTION__, dcon);
+       pr_debug("%s: Initial dcon is %08x\n", __func__, dcon);
 
        dcon |= chan->dcon & dma_sel.dcon_mask;
 
-       pr_debug("%s: New dcon is %08x\n", __FUNCTION__, dcon);
+       pr_debug("%s: New dcon is %08x\n", __func__, dcon);
 
        switch (xferunit) {
        case 1:
@@ -1074,14 +1075,14 @@ int s3c2410_dma_config(dmach_t channel,
                break;
 
        default:
-               pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
+               pr_debug("%s: bad transfer size %d\n", __func__, xferunit);
                return -EINVAL;
        }
 
        dcon |= S3C2410_DCON_HWTRIG;
        dcon |= S3C2410_DCON_INTREQ;
 
-       pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
+       pr_debug("%s: dcon now %08x\n", __func__, dcon);
 
        chan->dcon = dcon;
        chan->xfer_unit = xferunit;
@@ -1098,7 +1099,7 @@ int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
        if (chan == NULL)
                return -EINVAL;
 
-       pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
+       pr_debug("%s: chan=%p, flags=%08x\n", __func__, chan, flags);
 
        chan->flags = flags;
 
@@ -1119,7 +1120,7 @@ int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
        if (chan == NULL)
                return -EINVAL;
 
-       pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
+       pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn);
 
        chan->op_fn = rtn;
 
@@ -1135,7 +1136,7 @@ int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
        if (chan == NULL)
                return -EINVAL;
 
-       pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
+       pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn);
 
        chan->callback_fn = rtn;
 
@@ -1169,37 +1170,46 @@ int s3c2410_dma_devconfig(int channel,
                return -EINVAL;
 
        pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
-                __FUNCTION__, (int)source, hwcfg, devaddr);
+                __func__, (int)source, hwcfg, devaddr);
 
        chan->source = source;
        chan->dev_addr = devaddr;
+       chan->hw_cfg = hwcfg;
 
        switch (source) {
        case S3C2410_DMASRC_HW:
                /* source is hardware */
                pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
-                        __FUNCTION__, devaddr, hwcfg);
+                        __func__, devaddr, hwcfg);
                dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
                dma_wrreg(chan, S3C2410_DMA_DISRC,  devaddr);
                dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
 
                chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
-               return 0;
+               break;
 
        case S3C2410_DMASRC_MEM:
                /* source is memory */
-               pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
-                         __FUNCTION__, devaddr, hwcfg);
+               pr_debug("%s: mem source, devaddr=%08lx, hwcfg=%d\n",
+                        __func__, devaddr, hwcfg);
                dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
                dma_wrreg(chan, S3C2410_DMA_DIDST,  devaddr);
                dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
 
                chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
-               return 0;
+               break;
+
+       default:
+               printk(KERN_ERR "dma%d: invalid source type (%d)\n",
+                      channel, source);
+
+               return -EINVAL;
        }
 
-       printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
-       return -EINVAL;
+       if (dma_sel.direction != NULL)
+               (dma_sel.direction)(chan, chan->map, source);
+
+       return 0;
 }
 
 EXPORT_SYMBOL(s3c2410_dma_devconfig);
@@ -1227,6 +1237,10 @@ int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
 
 EXPORT_SYMBOL(s3c2410_dma_getposition);
 
+static struct s3c2410_dma_chan *to_dma_chan(struct sys_device *dev)
+{
+       return container_of(dev, struct s3c2410_dma_chan, dev);
+}
 
 /* system device class */
 
@@ -1234,7 +1248,7 @@ EXPORT_SYMBOL(s3c2410_dma_getposition);
 
 static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
 {
-       struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev);
+       struct s3c2410_dma_chan *cp = to_dma_chan(dev);
 
        printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
 
@@ -1256,6 +1270,24 @@ static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
 
 static int s3c2410_dma_resume(struct sys_device *dev)
 {
+       struct s3c2410_dma_chan *cp = to_dma_chan(dev);
+       unsigned int no = cp->number | DMACH_LOW_LEVEL;
+
+       /* restore channel's hardware configuration */
+
+       if (!cp->in_use)
+               return 0;
+
+       printk(KERN_INFO "dma%d: restoring configuration\n", cp->number);
+
+       s3c2410_dma_config(no, cp->xfer_unit, cp->dcon);
+       s3c2410_dma_devconfig(no, cp->source, cp->hw_cfg, cp->dev_addr);
+
+       /* re-select the dma source for this channel */
+
+       if (cp->map != NULL)
+               dma_sel.select(cp, cp->map);
+
        return 0;
 }
 
@@ -1272,7 +1304,7 @@ struct sysdev_class dma_sysclass = {
 
 /* kmem cache implementation */
 
-static void s3c2410_dma_cache_ctor(struct kmem_cache *c, void *p)
+static void s3c2410_dma_cache_ctor(void *p)
 {
        memset(p, 0, sizeof(struct s3c2410_dma_buf));
 }
@@ -1445,6 +1477,7 @@ static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
 
  found:
        dmach = &s3c2410_chans[ch];
+       dmach->map = ch_map;
        dma_chan_map[channel] = dmach;
 
        /* select the channel */