summaryrefslogtreecommitdiff
path: root/arch/arm/plat-s3c24xx/dma.c
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2008-01-28 13:01:21 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-01-28 13:20:51 +0000
commitc58f7a1d36709e50398c05df9419386befef2c59 (patch)
treed42e95dc2d942073b198cbc2490aaccc91ed01b4 /arch/arm/plat-s3c24xx/dma.c
parentc6709e8ef5752314c22c75bc7575f9be390e215b (diff)
[ARM] 4781/1: S3C24XX: DMA suspend and resume support
If an DMA channel was active at suspend, then ensure that it is correctly reconfigured when the system resumes. Note, the previous policy was for each driver to handle their own reconfiguration on resume. The policy has been changed to make the individual driver's job easier. Signed-off-by: Ben Dooks <ben-linux@flfuf.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/plat-s3c24xx/dma.c')
-rw-r--r--arch/arm/plat-s3c24xx/dma.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index 10ef3995b114..68ce89db17db 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -1173,6 +1173,7 @@ int s3c2410_dma_devconfig(int channel,
chan->source = source;
chan->dev_addr = devaddr;
+ chan->hw_cfg = hwcfg;
switch (source) {
case S3C2410_DMASRC_HW:
@@ -1235,6 +1236,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 */
@@ -1242,7 +1247,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);
@@ -1264,6 +1269,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;
}
@@ -1453,6 +1476,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 */