|
@@ -1065,3 +1065,123 @@ int s3c2410_dma_config(enum dma_ch channel,
|
|
|
|
|
|
case 2:
|
|
|
dcon |= S3C2410_DCON_HALFWORD;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 4:
|
|
|
+ dcon |= S3C2410_DCON_WORD;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ 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", __func__, dcon);
|
|
|
+
|
|
|
+ chan->dcon = dcon;
|
|
|
+ chan->xfer_unit = xferunit;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+EXPORT_SYMBOL(s3c2410_dma_config);
|
|
|
+
|
|
|
+
|
|
|
+/* s3c2410_dma_devconfig
|
|
|
+ *
|
|
|
+ * configure the dma source/destination hardware type and address
|
|
|
+ *
|
|
|
+ * source: DMA_FROM_DEVICE: source is hardware
|
|
|
+ * DMA_TO_DEVICE: source is memory
|
|
|
+ *
|
|
|
+ * devaddr: physical address of the source
|
|
|
+*/
|
|
|
+
|
|
|
+int s3c2410_dma_devconfig(enum dma_ch channel,
|
|
|
+ enum dma_data_direction source,
|
|
|
+ unsigned long devaddr)
|
|
|
+{
|
|
|
+ struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
|
|
+ unsigned int hwcfg;
|
|
|
+
|
|
|
+ if (chan == NULL)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ pr_debug("%s: source=%d, devaddr=%08lx\n",
|
|
|
+ __func__, (int)source, devaddr);
|
|
|
+
|
|
|
+ chan->source = source;
|
|
|
+ chan->dev_addr = devaddr;
|
|
|
+
|
|
|
+ switch (chan->req_ch) {
|
|
|
+ case DMACH_XD0:
|
|
|
+ case DMACH_XD1:
|
|
|
+ hwcfg = 0; /* AHB */
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ hwcfg = S3C2410_DISRCC_APB;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* always assume our peripheral desintation is a fixed
|
|
|
+ * address in memory. */
|
|
|
+ hwcfg |= S3C2410_DISRCC_INC;
|
|
|
+
|
|
|
+ switch (source) {
|
|
|
+ case DMA_FROM_DEVICE:
|
|
|
+ /* source is hardware */
|
|
|
+ pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
|
|
|
+ __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);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case DMA_TO_DEVICE:
|
|
|
+ /* source is memory */
|
|
|
+ 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);
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ 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);
|
|
|
+
|
|
|
+/* s3c2410_dma_getposition
|
|
|
+ *
|
|
|
+ * returns the current transfer points for the dma source and destination
|
|
|
+*/
|
|
|
+
|
|
|
+int s3c2410_dma_getposition(enum dma_ch channel, dma_addr_t *src, dma_addr_t *dst)
|
|
|
+{
|
|
|
+ struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
|
|
+
|
|
|
+ if (chan == NULL)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (src != NULL)
|
|
|
+ *src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
|
|
|
+
|
|
|
+ if (dst != NULL)
|
|
|
+ *dst = dma_rdreg(chan, S3C2410_DMA_DCDST);
|