|
@@ -1308,3 +1308,88 @@ int __init s3c24xx_dma_init(unsigned int channels, unsigned int irq,
|
|
|
ret = -ENOMEM;
|
|
|
goto err;
|
|
|
}
|
|
|
+
|
|
|
+ for (channel = 0; channel < channels; channel++) {
|
|
|
+ cp = &s3c2410_chans[channel];
|
|
|
+
|
|
|
+ memset(cp, 0, sizeof(struct s3c2410_dma_chan));
|
|
|
+
|
|
|
+ /* dma channel irqs are in order.. */
|
|
|
+ cp->number = channel;
|
|
|
+ cp->irq = channel + irq;
|
|
|
+ cp->regs = dma_base + (channel * stride);
|
|
|
+
|
|
|
+ /* point current stats somewhere */
|
|
|
+ cp->stats = &cp->stats_store;
|
|
|
+ cp->stats_store.timeout_shortest = LONG_MAX;
|
|
|
+
|
|
|
+ /* basic channel configuration */
|
|
|
+
|
|
|
+ cp->load_timeout = 1<<18;
|
|
|
+
|
|
|
+ printk("DMA channel %d at %p, irq %d\n",
|
|
|
+ cp->number, cp->regs, cp->irq);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ err:
|
|
|
+ kmem_cache_destroy(dma_kmem);
|
|
|
+ iounmap(dma_base);
|
|
|
+ dma_base = NULL;
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+int __init s3c2410_dma_init(void)
|
|
|
+{
|
|
|
+ return s3c24xx_dma_init(4, IRQ_DMA0, 0x40);
|
|
|
+}
|
|
|
+
|
|
|
+static inline int is_channel_valid(unsigned int channel)
|
|
|
+{
|
|
|
+ return (channel & DMA_CH_VALID);
|
|
|
+}
|
|
|
+
|
|
|
+static struct s3c24xx_dma_order *dma_order;
|
|
|
+
|
|
|
+
|
|
|
+/* s3c2410_dma_map_channel()
|
|
|
+ *
|
|
|
+ * turn the virtual channel number into a real, and un-used hardware
|
|
|
+ * channel.
|
|
|
+ *
|
|
|
+ * first, try the dma ordering given to us by either the relevant
|
|
|
+ * dma code, or the board. Then just find the first usable free
|
|
|
+ * channel
|
|
|
+*/
|
|
|
+
|
|
|
+static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
|
|
|
+{
|
|
|
+ struct s3c24xx_dma_order_ch *ord = NULL;
|
|
|
+ struct s3c24xx_dma_map *ch_map;
|
|
|
+ struct s3c2410_dma_chan *dmach;
|
|
|
+ int ch;
|
|
|
+
|
|
|
+ if (dma_sel.map == NULL || channel > dma_sel.map_size)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ ch_map = dma_sel.map + channel;
|
|
|
+
|
|
|
+ /* first, try the board mapping */
|
|
|
+
|
|
|
+ if (dma_order) {
|
|
|
+ ord = &dma_order->channels[channel];
|
|
|
+
|
|
|
+ for (ch = 0; ch < dma_channels; ch++) {
|
|
|
+ int tmp;
|
|
|
+ if (!is_channel_valid(ord->list[ch]))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ tmp = ord->list[ch] & ~DMA_CH_VALID;
|
|
|
+ if (s3c2410_chans[tmp].in_use == 0) {
|
|
|
+ ch = tmp;
|
|
|
+ goto found;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ord->flags & DMA_CH_NEVER)
|