mirror of https://github.com/hak5/openwrt.git
1325 lines
37 KiB
Diff
1325 lines
37 KiB
Diff
--- a/arch/arm/mach-s3c2410/include/mach/dma.h
|
|
+++ b/arch/arm/mach-s3c2410/include/mach/dma.h
|
|
@@ -3,7 +3,7 @@
|
|
* Copyright (C) 2003,2004,2006 Simtec Electronics
|
|
* Ben Dooks <ben@simtec.co.uk>
|
|
*
|
|
- * Samsung S3C241XX DMA support
|
|
+ * Samsung S3C24XX DMA support
|
|
*
|
|
* 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
|
|
@@ -13,8 +13,8 @@
|
|
#ifndef __ASM_ARCH_DMA_H
|
|
#define __ASM_ARCH_DMA_H __FILE__
|
|
|
|
+#include <plat/dma.h>
|
|
#include <linux/sysdev.h>
|
|
-#include <mach/hardware.h>
|
|
|
|
#define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */
|
|
|
|
@@ -55,9 +55,9 @@ enum dma_ch {
|
|
|
|
/* we have 4 dma channels */
|
|
#ifndef CONFIG_CPU_S3C2443
|
|
-#define S3C2410_DMA_CHANNELS (4)
|
|
+#define S3C_DMA_CHANNELS (4)
|
|
#else
|
|
-#define S3C2410_DMA_CHANNELS (6)
|
|
+#define S3C_DMA_CHANNELS (6)
|
|
#endif
|
|
|
|
/* types */
|
|
@@ -68,7 +68,6 @@ enum s3c2410_dma_state {
|
|
S3C2410_DMA_PAUSED
|
|
};
|
|
|
|
-
|
|
/* enum s3c2410_dma_loadst
|
|
*
|
|
* This represents the state of the DMA engine, wrt to the loaded / running
|
|
@@ -104,32 +103,6 @@ enum s3c2410_dma_loadst {
|
|
S3C2410_DMALOAD_1LOADED_1RUNNING,
|
|
};
|
|
|
|
-enum s3c2410_dma_buffresult {
|
|
- S3C2410_RES_OK,
|
|
- S3C2410_RES_ERR,
|
|
- S3C2410_RES_ABORT
|
|
-};
|
|
-
|
|
-enum s3c2410_dmasrc {
|
|
- S3C2410_DMASRC_HW, /* source is memory */
|
|
- S3C2410_DMASRC_MEM /* source is hardware */
|
|
-};
|
|
-
|
|
-/* enum s3c2410_chan_op
|
|
- *
|
|
- * operation codes passed to the DMA code by the user, and also used
|
|
- * to inform the current channel owner of any changes to the system state
|
|
-*/
|
|
-
|
|
-enum s3c2410_chan_op {
|
|
- S3C2410_DMAOP_START,
|
|
- S3C2410_DMAOP_STOP,
|
|
- S3C2410_DMAOP_PAUSE,
|
|
- S3C2410_DMAOP_RESUME,
|
|
- S3C2410_DMAOP_FLUSH,
|
|
- S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */
|
|
- S3C2410_DMAOP_STARTED, /* indicate channel started */
|
|
-};
|
|
|
|
/* flags */
|
|
|
|
@@ -137,19 +110,18 @@ enum s3c2410_chan_op {
|
|
* waiting for reloads */
|
|
#define S3C2410_DMAF_AUTOSTART (1<<1) /* auto-start if buffer queued */
|
|
|
|
+#define S3C2410_DMAF_CIRCULAR (0x00) /* circular enqueue not supp. */
|
|
+
|
|
/* dma buffer */
|
|
|
|
-struct s3c2410_dma_client {
|
|
- char *name;
|
|
-};
|
|
+struct s3c2410_dma_buf;
|
|
|
|
-/* s3c2410_dma_buf_s
|
|
+/* s3c2410_dma_buf
|
|
*
|
|
* internally used buffer structure to describe a queued or running
|
|
* buffer.
|
|
*/
|
|
|
|
-struct s3c2410_dma_buf;
|
|
struct s3c2410_dma_buf {
|
|
struct s3c2410_dma_buf *next;
|
|
int magic; /* magic */
|
|
@@ -161,20 +133,6 @@ struct s3c2410_dma_buf {
|
|
|
|
/* [1] is this updated for both recv/send modes? */
|
|
|
|
-struct s3c2410_dma_chan;
|
|
-
|
|
-/* s3c2410_dma_cbfn_t
|
|
- *
|
|
- * buffer callback routine type
|
|
-*/
|
|
-
|
|
-typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
|
|
- void *buf, int size,
|
|
- enum s3c2410_dma_buffresult result);
|
|
-
|
|
-typedef int (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
|
|
- enum s3c2410_chan_op );
|
|
-
|
|
struct s3c2410_dma_stats {
|
|
unsigned long loads;
|
|
unsigned long timeout_longest;
|
|
@@ -206,10 +164,10 @@ struct s3c2410_dma_chan {
|
|
|
|
/* channel configuration */
|
|
enum s3c2410_dmasrc source;
|
|
+ enum dma_ch req_ch;
|
|
unsigned long dev_addr;
|
|
unsigned long load_timeout;
|
|
unsigned int flags; /* channel flags */
|
|
- unsigned int hw_cfg; /* last hw config */
|
|
|
|
struct s3c24xx_dma_map *map; /* channel hw maps */
|
|
|
|
@@ -236,213 +194,12 @@ struct s3c2410_dma_chan {
|
|
struct sys_device dev;
|
|
};
|
|
|
|
-/* the currently allocated channel information */
|
|
-extern struct s3c2410_dma_chan s3c2410_chans[];
|
|
-
|
|
-/* note, we don't really use dma_device_t at the moment */
|
|
typedef unsigned long dma_device_t;
|
|
|
|
-/* functions --------------------------------------------------------------- */
|
|
-
|
|
-/* s3c2410_dma_request
|
|
- *
|
|
- * request a dma channel exclusivley
|
|
-*/
|
|
-
|
|
-extern int s3c2410_dma_request(unsigned int channel,
|
|
- struct s3c2410_dma_client *, void *dev);
|
|
-
|
|
-
|
|
-/* s3c2410_dma_ctrl
|
|
- *
|
|
- * change the state of the dma channel
|
|
-*/
|
|
-
|
|
-extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op);
|
|
-
|
|
-/* s3c2410_dma_setflags
|
|
- *
|
|
- * set the channel's flags to a given state
|
|
-*/
|
|
-
|
|
-extern int s3c2410_dma_setflags(unsigned int channel,
|
|
- unsigned int flags);
|
|
-
|
|
-/* s3c2410_dma_free
|
|
- *
|
|
- * free the dma channel (will also abort any outstanding operations)
|
|
-*/
|
|
-
|
|
-extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *);
|
|
-
|
|
-/* s3c2410_dma_enqueue
|
|
- *
|
|
- * place the given buffer onto the queue of operations for the channel.
|
|
- * The buffer must be allocated from dma coherent memory, or the Dcache/WB
|
|
- * drained before the buffer is given to the DMA system.
|
|
-*/
|
|
-
|
|
-extern int s3c2410_dma_enqueue(unsigned int channel, void *id,
|
|
- dma_addr_t data, int size);
|
|
-
|
|
-/* s3c2410_dma_config
|
|
- *
|
|
- * configure the dma channel
|
|
-*/
|
|
-
|
|
-extern int s3c2410_dma_config(unsigned int channel, int xferunit, int dcon);
|
|
-
|
|
-/* s3c2410_dma_devconfig
|
|
- *
|
|
- * configure the device we're talking to
|
|
-*/
|
|
-
|
|
-extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
|
|
- int hwcfg, unsigned long devaddr);
|
|
-
|
|
-/* s3c2410_dma_getposition
|
|
- *
|
|
- * get the position that the dma transfer is currently at
|
|
-*/
|
|
-
|
|
-extern int s3c2410_dma_getposition(unsigned int channel,
|
|
- dma_addr_t *src, dma_addr_t *dest);
|
|
-
|
|
-extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn);
|
|
-extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn);
|
|
-
|
|
-/* DMA Register definitions */
|
|
-
|
|
-#define S3C2410_DMA_DISRC (0x00)
|
|
-#define S3C2410_DMA_DISRCC (0x04)
|
|
-#define S3C2410_DMA_DIDST (0x08)
|
|
-#define S3C2410_DMA_DIDSTC (0x0C)
|
|
-#define S3C2410_DMA_DCON (0x10)
|
|
-#define S3C2410_DMA_DSTAT (0x14)
|
|
-#define S3C2410_DMA_DCSRC (0x18)
|
|
-#define S3C2410_DMA_DCDST (0x1C)
|
|
-#define S3C2410_DMA_DMASKTRIG (0x20)
|
|
-#define S3C2412_DMA_DMAREQSEL (0x24)
|
|
-#define S3C2443_DMA_DMAREQSEL (0x24)
|
|
-
|
|
-#define S3C2410_DISRCC_INC (1<<0)
|
|
-#define S3C2410_DISRCC_APB (1<<1)
|
|
-
|
|
-#define S3C2410_DMASKTRIG_STOP (1<<2)
|
|
-#define S3C2410_DMASKTRIG_ON (1<<1)
|
|
-#define S3C2410_DMASKTRIG_SWTRIG (1<<0)
|
|
-
|
|
-#define S3C2410_DCON_DEMAND (0<<31)
|
|
-#define S3C2410_DCON_HANDSHAKE (1<<31)
|
|
-#define S3C2410_DCON_SYNC_PCLK (0<<30)
|
|
-#define S3C2410_DCON_SYNC_HCLK (1<<30)
|
|
-
|
|
-#define S3C2410_DCON_INTREQ (1<<29)
|
|
-
|
|
-#define S3C2410_DCON_CH0_XDREQ0 (0<<24)
|
|
-#define S3C2410_DCON_CH0_UART0 (1<<24)
|
|
-#define S3C2410_DCON_CH0_SDI (2<<24)
|
|
-#define S3C2410_DCON_CH0_TIMER (3<<24)
|
|
-#define S3C2410_DCON_CH0_USBEP1 (4<<24)
|
|
-
|
|
-#define S3C2410_DCON_CH1_XDREQ1 (0<<24)
|
|
-#define S3C2410_DCON_CH1_UART1 (1<<24)
|
|
-#define S3C2410_DCON_CH1_I2SSDI (2<<24)
|
|
-#define S3C2410_DCON_CH1_SPI (3<<24)
|
|
-#define S3C2410_DCON_CH1_USBEP2 (4<<24)
|
|
-
|
|
-#define S3C2410_DCON_CH2_I2SSDO (0<<24)
|
|
-#define S3C2410_DCON_CH2_I2SSDI (1<<24)
|
|
-#define S3C2410_DCON_CH2_SDI (2<<24)
|
|
-#define S3C2410_DCON_CH2_TIMER (3<<24)
|
|
-#define S3C2410_DCON_CH2_USBEP3 (4<<24)
|
|
-
|
|
-#define S3C2410_DCON_CH3_UART2 (0<<24)
|
|
-#define S3C2410_DCON_CH3_SDI (1<<24)
|
|
-#define S3C2410_DCON_CH3_SPI (2<<24)
|
|
-#define S3C2410_DCON_CH3_TIMER (3<<24)
|
|
-#define S3C2410_DCON_CH3_USBEP4 (4<<24)
|
|
-
|
|
-#define S3C2410_DCON_SRCSHIFT (24)
|
|
-#define S3C2410_DCON_SRCMASK (7<<24)
|
|
-
|
|
-#define S3C2410_DCON_BYTE (0<<20)
|
|
-#define S3C2410_DCON_HALFWORD (1<<20)
|
|
-#define S3C2410_DCON_WORD (2<<20)
|
|
-
|
|
-#define S3C2410_DCON_AUTORELOAD (0<<22)
|
|
-#define S3C2410_DCON_NORELOAD (1<<22)
|
|
-#define S3C2410_DCON_HWTRIG (1<<23)
|
|
-
|
|
-#ifdef CONFIG_CPU_S3C2440
|
|
-#define S3C2440_DIDSTC_CHKINT (1<<2)
|
|
-
|
|
-#define S3C2440_DCON_CH0_I2SSDO (5<<24)
|
|
-#define S3C2440_DCON_CH0_PCMIN (6<<24)
|
|
-
|
|
-#define S3C2440_DCON_CH1_PCMOUT (5<<24)
|
|
-#define S3C2440_DCON_CH1_SDI (6<<24)
|
|
-
|
|
-#define S3C2440_DCON_CH2_PCMIN (5<<24)
|
|
-#define S3C2440_DCON_CH2_MICIN (6<<24)
|
|
-
|
|
-#define S3C2440_DCON_CH3_MICIN (5<<24)
|
|
-#define S3C2440_DCON_CH3_PCMOUT (6<<24)
|
|
-#endif
|
|
-
|
|
-#ifdef CONFIG_CPU_S3C2412
|
|
-
|
|
-#define S3C2412_DMAREQSEL_SRC(x) ((x)<<1)
|
|
-
|
|
-#define S3C2412_DMAREQSEL_HW (1)
|
|
-
|
|
-#define S3C2412_DMAREQSEL_SPI0TX S3C2412_DMAREQSEL_SRC(0)
|
|
-#define S3C2412_DMAREQSEL_SPI0RX S3C2412_DMAREQSEL_SRC(1)
|
|
-#define S3C2412_DMAREQSEL_SPI1TX S3C2412_DMAREQSEL_SRC(2)
|
|
-#define S3C2412_DMAREQSEL_SPI1RX S3C2412_DMAREQSEL_SRC(3)
|
|
-#define S3C2412_DMAREQSEL_I2STX S3C2412_DMAREQSEL_SRC(4)
|
|
-#define S3C2412_DMAREQSEL_I2SRX S3C2412_DMAREQSEL_SRC(5)
|
|
-#define S3C2412_DMAREQSEL_TIMER S3C2412_DMAREQSEL_SRC(9)
|
|
-#define S3C2412_DMAREQSEL_SDI S3C2412_DMAREQSEL_SRC(10)
|
|
-#define S3C2412_DMAREQSEL_USBEP1 S3C2412_DMAREQSEL_SRC(13)
|
|
-#define S3C2412_DMAREQSEL_USBEP2 S3C2412_DMAREQSEL_SRC(14)
|
|
-#define S3C2412_DMAREQSEL_USBEP3 S3C2412_DMAREQSEL_SRC(15)
|
|
-#define S3C2412_DMAREQSEL_USBEP4 S3C2412_DMAREQSEL_SRC(16)
|
|
-#define S3C2412_DMAREQSEL_XDREQ0 S3C2412_DMAREQSEL_SRC(17)
|
|
-#define S3C2412_DMAREQSEL_XDREQ1 S3C2412_DMAREQSEL_SRC(18)
|
|
-#define S3C2412_DMAREQSEL_UART0_0 S3C2412_DMAREQSEL_SRC(19)
|
|
-#define S3C2412_DMAREQSEL_UART0_1 S3C2412_DMAREQSEL_SRC(20)
|
|
-#define S3C2412_DMAREQSEL_UART1_0 S3C2412_DMAREQSEL_SRC(21)
|
|
-#define S3C2412_DMAREQSEL_UART1_1 S3C2412_DMAREQSEL_SRC(22)
|
|
-#define S3C2412_DMAREQSEL_UART2_0 S3C2412_DMAREQSEL_SRC(23)
|
|
-#define S3C2412_DMAREQSEL_UART2_1 S3C2412_DMAREQSEL_SRC(24)
|
|
-
|
|
-#endif
|
|
-
|
|
-#define S3C2443_DMAREQSEL_SRC(x) ((x)<<1)
|
|
-
|
|
-#define S3C2443_DMAREQSEL_HW (1)
|
|
|
|
-#define S3C2443_DMAREQSEL_SPI0TX S3C2443_DMAREQSEL_SRC(0)
|
|
-#define S3C2443_DMAREQSEL_SPI0RX S3C2443_DMAREQSEL_SRC(1)
|
|
-#define S3C2443_DMAREQSEL_SPI1TX S3C2443_DMAREQSEL_SRC(2)
|
|
-#define S3C2443_DMAREQSEL_SPI1RX S3C2443_DMAREQSEL_SRC(3)
|
|
-#define S3C2443_DMAREQSEL_I2STX S3C2443_DMAREQSEL_SRC(4)
|
|
-#define S3C2443_DMAREQSEL_I2SRX S3C2443_DMAREQSEL_SRC(5)
|
|
-#define S3C2443_DMAREQSEL_TIMER S3C2443_DMAREQSEL_SRC(9)
|
|
-#define S3C2443_DMAREQSEL_SDI S3C2443_DMAREQSEL_SRC(10)
|
|
-#define S3C2443_DMAREQSEL_XDREQ0 S3C2443_DMAREQSEL_SRC(17)
|
|
-#define S3C2443_DMAREQSEL_XDREQ1 S3C2443_DMAREQSEL_SRC(18)
|
|
-#define S3C2443_DMAREQSEL_UART0_0 S3C2443_DMAREQSEL_SRC(19)
|
|
-#define S3C2443_DMAREQSEL_UART0_1 S3C2443_DMAREQSEL_SRC(20)
|
|
-#define S3C2443_DMAREQSEL_UART1_0 S3C2443_DMAREQSEL_SRC(21)
|
|
-#define S3C2443_DMAREQSEL_UART1_1 S3C2443_DMAREQSEL_SRC(22)
|
|
-#define S3C2443_DMAREQSEL_UART2_0 S3C2443_DMAREQSEL_SRC(23)
|
|
-#define S3C2443_DMAREQSEL_UART2_1 S3C2443_DMAREQSEL_SRC(24)
|
|
-#define S3C2443_DMAREQSEL_UART3_0 S3C2443_DMAREQSEL_SRC(25)
|
|
-#define S3C2443_DMAREQSEL_UART3_1 S3C2443_DMAREQSEL_SRC(26)
|
|
-#define S3C2443_DMAREQSEL_PCMOUT S3C2443_DMAREQSEL_SRC(27)
|
|
-#define S3C2443_DMAREQSEL_PCMIN S3C2443_DMAREQSEL_SRC(28)
|
|
-#define S3C2443_DMAREQSEL_MICIN S3C2443_DMAREQSEL_SRC(29)
|
|
+static int s3c_dma_has_circular(void)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
|
|
#endif /* __ASM_ARCH_DMA_H */
|
|
--- a/arch/arm/mach-s3c2442/Kconfig
|
|
+++ b/arch/arm/mach-s3c2442/Kconfig
|
|
@@ -11,6 +11,7 @@ config CPU_S3C2442
|
|
select S3C2410_CLOCK
|
|
select S3C2410_GPIO
|
|
select S3C2410_PM if PM
|
|
+ select S3C2440_DMA if S3C2410_DMA
|
|
select CPU_S3C244X
|
|
select CPU_LLSERIAL_S3C2440
|
|
help
|
|
--- /dev/null
|
|
+++ b/arch/arm/plat-s3c/dma.c
|
|
@@ -0,0 +1,86 @@
|
|
+/* linux/arch/arm/plat-s3c/dma.c
|
|
+ *
|
|
+ * Copyright (c) 2003-2005,2006,2009 Simtec Electronics
|
|
+ * Ben Dooks <ben@simtec.co.uk>
|
|
+ * http://armlinux.simtec.co.uk/
|
|
+ *
|
|
+ * S3C 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.
|
|
+*/
|
|
+
|
|
+struct s3c2410_dma_buf;
|
|
+
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/errno.h>
|
|
+
|
|
+#include <mach/dma.h>
|
|
+#include <mach/irqs.h>
|
|
+
|
|
+#include <plat/dma-plat.h>
|
|
+
|
|
+/* dma channel state information */
|
|
+struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
|
|
+struct s3c2410_dma_chan *s3c_dma_chan_map[DMACH_MAX];
|
|
+
|
|
+/* s3c_dma_lookup_channel
|
|
+ *
|
|
+ * change the dma channel number given into a real dma channel id
|
|
+*/
|
|
+
|
|
+struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel)
|
|
+{
|
|
+ if (channel & DMACH_LOW_LEVEL)
|
|
+ return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
|
|
+ else
|
|
+ return s3c_dma_chan_map[channel];
|
|
+}
|
|
+
|
|
+/* do we need to protect the settings of the fields from
|
|
+ * irq?
|
|
+*/
|
|
+
|
|
+int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn)
|
|
+{
|
|
+ struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
|
+
|
|
+ if (chan == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn);
|
|
+
|
|
+ chan->op_fn = rtn;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(s3c2410_dma_set_opfn);
|
|
+
|
|
+int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn)
|
|
+{
|
|
+ struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
|
+
|
|
+ if (chan == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn);
|
|
+
|
|
+ chan->callback_fn = rtn;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
|
|
+
|
|
+int s3c2410_dma_setflags(unsigned int channel, unsigned int flags)
|
|
+{
|
|
+ struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
|
+
|
|
+ if (chan == NULL)
|
|
+ return -EINVAL;
|
|
+
|
|
+ chan->flags = flags;
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(s3c2410_dma_setflags);
|
|
--- /dev/null
|
|
+++ b/arch/arm/plat-s3c/include/plat/dma-core.h
|
|
@@ -0,0 +1,22 @@
|
|
+/* arch/arm/plat-s3c/include/plat/dma.h
|
|
+ *
|
|
+ * Copyright 2008 Openmoko, Inc.
|
|
+ * Copyright 2008 Simtec Electronics
|
|
+ * Ben Dooks <ben@simtec.co.uk>
|
|
+ * http://armlinux.simtec.co.uk/
|
|
+ *
|
|
+ * Samsung S3C DMA core support
|
|
+ *
|
|
+ * 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.
|
|
+*/
|
|
+
|
|
+extern struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel);
|
|
+
|
|
+extern struct s3c2410_dma_chan *s3c_dma_chan_map[];
|
|
+
|
|
+/* the currently allocated channel information */
|
|
+extern struct s3c2410_dma_chan s3c2410_chans[];
|
|
+
|
|
+
|
|
--- /dev/null
|
|
+++ b/arch/arm/plat-s3c/include/plat/dma.h
|
|
@@ -0,0 +1,128 @@
|
|
+/* arch/arm/plat-s3c/include/plat/dma.h
|
|
+ *
|
|
+ * Copyright (C) 2003,2004,2006 Simtec Electronics
|
|
+ * Ben Dooks <ben@simtec.co.uk>
|
|
+ *
|
|
+ * Samsung S3C DMA support
|
|
+ *
|
|
+ * 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.
|
|
+*/
|
|
+
|
|
+enum s3c2410_dma_buffresult {
|
|
+ S3C2410_RES_OK,
|
|
+ S3C2410_RES_ERR,
|
|
+ S3C2410_RES_ABORT
|
|
+};
|
|
+
|
|
+enum s3c2410_dmasrc {
|
|
+ S3C2410_DMASRC_HW, /* source is memory */
|
|
+ S3C2410_DMASRC_MEM /* source is hardware */
|
|
+};
|
|
+
|
|
+/* enum s3c2410_chan_op
|
|
+ *
|
|
+ * operation codes passed to the DMA code by the user, and also used
|
|
+ * to inform the current channel owner of any changes to the system state
|
|
+*/
|
|
+
|
|
+enum s3c2410_chan_op {
|
|
+ S3C2410_DMAOP_START,
|
|
+ S3C2410_DMAOP_STOP,
|
|
+ S3C2410_DMAOP_PAUSE,
|
|
+ S3C2410_DMAOP_RESUME,
|
|
+ S3C2410_DMAOP_FLUSH,
|
|
+ S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */
|
|
+ S3C2410_DMAOP_STARTED, /* indicate channel started */
|
|
+};
|
|
+
|
|
+struct s3c2410_dma_client {
|
|
+ char *name;
|
|
+};
|
|
+
|
|
+struct s3c2410_dma_chan;
|
|
+
|
|
+/* s3c2410_dma_cbfn_t
|
|
+ *
|
|
+ * buffer callback routine type
|
|
+*/
|
|
+
|
|
+typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
|
|
+ void *buf, int size,
|
|
+ enum s3c2410_dma_buffresult result);
|
|
+
|
|
+typedef int (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
|
|
+ enum s3c2410_chan_op );
|
|
+
|
|
+
|
|
+
|
|
+/* s3c2410_dma_request
|
|
+ *
|
|
+ * request a dma channel exclusivley
|
|
+*/
|
|
+
|
|
+extern int s3c2410_dma_request(unsigned int channel,
|
|
+ struct s3c2410_dma_client *, void *dev);
|
|
+
|
|
+
|
|
+/* s3c2410_dma_ctrl
|
|
+ *
|
|
+ * change the state of the dma channel
|
|
+*/
|
|
+
|
|
+extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op);
|
|
+
|
|
+/* s3c2410_dma_setflags
|
|
+ *
|
|
+ * set the channel's flags to a given state
|
|
+*/
|
|
+
|
|
+extern int s3c2410_dma_setflags(unsigned int channel,
|
|
+ unsigned int flags);
|
|
+
|
|
+/* s3c2410_dma_free
|
|
+ *
|
|
+ * free the dma channel (will also abort any outstanding operations)
|
|
+*/
|
|
+
|
|
+extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *);
|
|
+
|
|
+/* s3c2410_dma_enqueue
|
|
+ *
|
|
+ * place the given buffer onto the queue of operations for the channel.
|
|
+ * The buffer must be allocated from dma coherent memory, or the Dcache/WB
|
|
+ * drained before the buffer is given to the DMA system.
|
|
+*/
|
|
+
|
|
+extern int s3c2410_dma_enqueue(unsigned int channel, void *id,
|
|
+ dma_addr_t data, int size);
|
|
+
|
|
+
|
|
+/* s3c2410_dma_config
|
|
+ *
|
|
+ * configure the dma channel
|
|
+*/
|
|
+
|
|
+extern int s3c2410_dma_config(unsigned int channel, int xferunit);
|
|
+
|
|
+/* s3c2410_dma_devconfig
|
|
+ *
|
|
+ * configure the device we're talking to
|
|
+*/
|
|
+
|
|
+extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
|
|
+ unsigned long devaddr);
|
|
+
|
|
+/* s3c2410_dma_getposition
|
|
+ *
|
|
+ * get the position that the dma transfer is currently at
|
|
+*/
|
|
+
|
|
+extern int s3c2410_dma_getposition(unsigned int channel,
|
|
+ dma_addr_t *src, dma_addr_t *dest);
|
|
+
|
|
+extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn);
|
|
+extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn);
|
|
+
|
|
+
|
|
--- a/arch/arm/plat-s3c/Kconfig
|
|
+++ b/arch/arm/plat-s3c/Kconfig
|
|
@@ -150,6 +150,13 @@ config S3C_GPIO_CFG_S3C64XX
|
|
Internal configuration to enable S3C64XX style GPIO configuration
|
|
functions.
|
|
|
|
+# DMA
|
|
+
|
|
+config S3C_DMA
|
|
+ bool
|
|
+ help
|
|
+ Internal configuration for S3C DMA core
|
|
+
|
|
# device definitions to compile in
|
|
|
|
config S3C_DEV_HSMMC
|
|
--- a/arch/arm/plat-s3c/Makefile
|
|
+++ b/arch/arm/plat-s3c/Makefile
|
|
@@ -18,6 +18,10 @@ obj-y += pwm-clock.o
|
|
obj-y += gpio.o
|
|
obj-y += gpio-config.o
|
|
|
|
+# DMA support
|
|
+
|
|
+obj-$(CONFIG_S3C_DMA) += dma.o
|
|
+
|
|
# PM support
|
|
|
|
obj-$(CONFIG_PM) += pm.o
|
|
@@ -31,3 +35,5 @@ obj-$(CONFIG_S3C_DEV_HSMMC1) += dev-hsmm
|
|
obj-y += dev-i2c0.o
|
|
obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o
|
|
obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o
|
|
+obj-$(CONFIG_S3C_DMA) += dma.o
|
|
+
|
|
--- a/arch/arm/plat-s3c24xx/dma.c
|
|
+++ b/arch/arm/plat-s3c24xx/dma.c
|
|
@@ -31,10 +31,11 @@
|
|
#include <asm/irq.h>
|
|
#include <mach/hardware.h>
|
|
#include <mach/dma.h>
|
|
-
|
|
#include <mach/map.h>
|
|
|
|
-#include <plat/dma.h>
|
|
+#include <plat/dma-core.h>
|
|
+#include <plat/regs-dma.h>
|
|
+#include <plat/dma-plat.h>
|
|
|
|
/* io map for dma */
|
|
static void __iomem *dma_base;
|
|
@@ -44,8 +45,6 @@ static int dma_channels;
|
|
|
|
static struct s3c24xx_dma_selection dma_sel;
|
|
|
|
-/* dma channel state information */
|
|
-struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
|
|
|
|
/* debugging functions */
|
|
|
|
@@ -135,21 +134,6 @@ dmadbg_showregs(const char *fname, int l
|
|
#define dbg_showchan(chan) do { } while(0)
|
|
#endif /* CONFIG_S3C2410_DMA_DEBUG */
|
|
|
|
-static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
|
|
-
|
|
-/* lookup_dma_channel
|
|
- *
|
|
- * change the dma channel number given into a real dma channel id
|
|
-*/
|
|
-
|
|
-static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
|
|
-{
|
|
- if (channel & DMACH_LOW_LEVEL)
|
|
- return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
|
|
- else
|
|
- return dma_chan_map[channel];
|
|
-}
|
|
-
|
|
/* s3c2410_dma_stats_timeout
|
|
*
|
|
* Update DMA stats from timeout info
|
|
@@ -214,8 +198,6 @@ s3c2410_dma_waitforload(struct s3c2410_d
|
|
return 0;
|
|
}
|
|
|
|
-
|
|
-
|
|
/* s3c2410_dma_loadbuffer
|
|
*
|
|
* load a buffer, and update the channel state
|
|
@@ -453,7 +435,7 @@ s3c2410_dma_canload(struct s3c2410_dma_c
|
|
int s3c2410_dma_enqueue(unsigned int channel, void *id,
|
|
dma_addr_t data, int size)
|
|
{
|
|
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
|
|
+ struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
|
struct s3c2410_dma_buf *buf;
|
|
unsigned long flags;
|
|
|
|
@@ -804,7 +786,7 @@ EXPORT_SYMBOL(s3c2410_dma_request);
|
|
|
|
int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)
|
|
{
|
|
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
|
|
+ struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
|
unsigned long flags;
|
|
|
|
if (chan == NULL)
|
|
@@ -836,7 +818,7 @@ int s3c2410_dma_free(unsigned int channe
|
|
chan->irq_claimed = 0;
|
|
|
|
if (!(channel & DMACH_LOW_LEVEL))
|
|
- dma_chan_map[channel] = NULL;
|
|
+ s3c_dma_chan_map[channel] = NULL;
|
|
|
|
local_irq_restore(flags);
|
|
|
|
@@ -995,7 +977,7 @@ static int s3c2410_dma_started(struct s3
|
|
int
|
|
s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
|
|
{
|
|
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
|
|
+ struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
|
|
|
if (chan == NULL)
|
|
return -EINVAL;
|
|
@@ -1038,14 +1020,13 @@ EXPORT_SYMBOL(s3c2410_dma_ctrl);
|
|
/* s3c2410_dma_config
|
|
*
|
|
* xfersize: size of unit in bytes (1,2,4)
|
|
- * dcon: base value of the DCONx register
|
|
*/
|
|
|
|
int s3c2410_dma_config(unsigned int channel,
|
|
- int xferunit,
|
|
- int dcon)
|
|
+ int xferunit)
|
|
{
|
|
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
|
|
+ struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
|
+ unsigned int dcon;
|
|
|
|
pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
|
|
__func__, channel, xferunit, dcon);
|
|
@@ -1055,10 +1036,33 @@ int s3c2410_dma_config(unsigned int chan
|
|
|
|
pr_debug("%s: Initial dcon is %08x\n", __func__, dcon);
|
|
|
|
- dcon |= chan->dcon & dma_sel.dcon_mask;
|
|
+ dcon = chan->dcon & dma_sel.dcon_mask;
|
|
|
|
pr_debug("%s: New dcon is %08x\n", __func__, dcon);
|
|
|
|
+ switch (chan->req_ch) {
|
|
+ case DMACH_I2S_IN:
|
|
+ case DMACH_I2S_OUT:
|
|
+ case DMACH_PCM_IN:
|
|
+ case DMACH_PCM_OUT:
|
|
+ case DMACH_MIC_IN:
|
|
+ default:
|
|
+ dcon |= S3C2410_DCON_HANDSHAKE;
|
|
+ dcon |= S3C2410_DCON_SYNC_PCLK;
|
|
+ break;
|
|
+
|
|
+ case DMACH_SDI:
|
|
+ /* note, ensure if need HANDSHAKE or not */
|
|
+ dcon |= S3C2410_DCON_SYNC_PCLK;
|
|
+ break;
|
|
+
|
|
+ case DMACH_XD0:
|
|
+ case DMACH_XD1:
|
|
+ dcon |= S3C2410_DCON_HANDSHAKE;
|
|
+ dcon |= S3C2410_DCON_SYNC_HCLK;
|
|
+ break;
|
|
+ }
|
|
+
|
|
switch (xferunit) {
|
|
case 1:
|
|
dcon |= S3C2410_DCON_BYTE;
|
|
@@ -1089,10 +1093,10 @@ int s3c2410_dma_config(unsigned int chan
|
|
}
|
|
|
|
EXPORT_SYMBOL(s3c2410_dma_config);
|
|
-
|
|
+#if 0 /* moved to plat-s3c? */
|
|
int s3c2410_dma_setflags(unsigned int channel, unsigned int flags)
|
|
{
|
|
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
|
|
+ struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
|
|
|
if (chan == NULL)
|
|
return -EINVAL;
|
|
@@ -1105,43 +1109,7 @@ int s3c2410_dma_setflags(unsigned int ch
|
|
}
|
|
|
|
EXPORT_SYMBOL(s3c2410_dma_setflags);
|
|
-
|
|
-
|
|
-/* do we need to protect the settings of the fields from
|
|
- * irq?
|
|
-*/
|
|
-
|
|
-int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn)
|
|
-{
|
|
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
|
|
-
|
|
- if (chan == NULL)
|
|
- return -EINVAL;
|
|
-
|
|
- pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn);
|
|
-
|
|
- chan->op_fn = rtn;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-EXPORT_SYMBOL(s3c2410_dma_set_opfn);
|
|
-
|
|
-int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn)
|
|
-{
|
|
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
|
|
-
|
|
- if (chan == NULL)
|
|
- return -EINVAL;
|
|
-
|
|
- pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn);
|
|
-
|
|
- chan->callback_fn = rtn;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
|
|
+#endif
|
|
|
|
/* s3c2410_dma_devconfig
|
|
*
|
|
@@ -1150,29 +1118,38 @@ EXPORT_SYMBOL(s3c2410_dma_set_buffdone_f
|
|
* source: S3C2410_DMASRC_HW: source is hardware
|
|
* S3C2410_DMASRC_MEM: source is memory
|
|
*
|
|
- * hwcfg: the value for xxxSTCn register,
|
|
- * bit 0: 0=increment pointer, 1=leave pointer
|
|
- * bit 1: 0=source is AHB, 1=source is APB
|
|
- *
|
|
* devaddr: physical address of the source
|
|
*/
|
|
|
|
int s3c2410_dma_devconfig(int channel,
|
|
enum s3c2410_dmasrc source,
|
|
- int hwcfg,
|
|
unsigned long devaddr)
|
|
{
|
|
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
|
|
+ struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
|
+ unsigned int hwcfg;
|
|
|
|
if (chan == NULL)
|
|
return -EINVAL;
|
|
|
|
- pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
|
|
- __func__, (int)source, hwcfg, devaddr);
|
|
+ pr_debug("%s: source=%d, devaddr=%08lx\n",
|
|
+ __func__, (int)source, devaddr);
|
|
|
|
chan->source = source;
|
|
chan->dev_addr = devaddr;
|
|
- chan->hw_cfg = hwcfg;
|
|
+
|
|
+ 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 S3C2410_DMASRC_HW:
|
|
@@ -1219,7 +1196,7 @@ EXPORT_SYMBOL(s3c2410_dma_devconfig);
|
|
|
|
int s3c2410_dma_getposition(unsigned int channel, dma_addr_t *src, dma_addr_t *dst)
|
|
{
|
|
- struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
|
|
+ struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
|
|
|
if (chan == NULL)
|
|
return -EINVAL;
|
|
@@ -1278,8 +1255,8 @@ static int s3c2410_dma_resume(struct sys
|
|
|
|
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);
|
|
+ s3c2410_dma_config(no, cp->xfer_unit);
|
|
+ s3c2410_dma_devconfig(no, cp->source, cp->dev_addr);
|
|
|
|
/* re-select the dma source for this channel */
|
|
|
|
@@ -1476,7 +1453,8 @@ static struct s3c2410_dma_chan *s3c2410_
|
|
found:
|
|
dmach = &s3c2410_chans[ch];
|
|
dmach->map = ch_map;
|
|
- dma_chan_map[channel] = dmach;
|
|
+ dmach->req_ch = channel;
|
|
+ s3c_dma_chan_map[channel] = dmach;
|
|
|
|
/* select the channel */
|
|
|
|
--- a/arch/arm/plat-s3c24xx/include/plat/dma.h
|
|
+++ /dev/null
|
|
@@ -1,82 +0,0 @@
|
|
-/* linux/include/asm-arm/plat-s3c24xx/dma.h
|
|
- *
|
|
- * Copyright (C) 2006 Simtec Electronics
|
|
- * Ben Dooks <ben@simtec.co.uk>
|
|
- *
|
|
- * Samsung S3C24XX DMA support
|
|
- *
|
|
- * 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.
|
|
-*/
|
|
-
|
|
-extern struct sysdev_class dma_sysclass;
|
|
-extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
|
|
-
|
|
-#define DMA_CH_VALID (1<<31)
|
|
-#define DMA_CH_NEVER (1<<30)
|
|
-
|
|
-struct s3c24xx_dma_addr {
|
|
- unsigned long from;
|
|
- unsigned long to;
|
|
-};
|
|
-
|
|
-/* struct s3c24xx_dma_map
|
|
- *
|
|
- * this holds the mapping information for the channel selected
|
|
- * to be connected to the specified device
|
|
-*/
|
|
-
|
|
-struct s3c24xx_dma_map {
|
|
- const char *name;
|
|
- struct s3c24xx_dma_addr hw_addr;
|
|
-
|
|
- unsigned long channels[S3C2410_DMA_CHANNELS];
|
|
- unsigned long channels_rx[S3C2410_DMA_CHANNELS];
|
|
-};
|
|
-
|
|
-struct s3c24xx_dma_selection {
|
|
- struct s3c24xx_dma_map *map;
|
|
- unsigned long map_size;
|
|
- unsigned long dcon_mask;
|
|
-
|
|
- void (*select)(struct s3c2410_dma_chan *chan,
|
|
- struct s3c24xx_dma_map *map);
|
|
-
|
|
- void (*direction)(struct s3c2410_dma_chan *chan,
|
|
- struct s3c24xx_dma_map *map,
|
|
- enum s3c2410_dmasrc dir);
|
|
-};
|
|
-
|
|
-extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
|
|
-
|
|
-/* struct s3c24xx_dma_order_ch
|
|
- *
|
|
- * channel map for one of the `enum dma_ch` dma channels. the list
|
|
- * entry contains a set of low-level channel numbers, orred with
|
|
- * DMA_CH_VALID, which are checked in the order in the array.
|
|
-*/
|
|
-
|
|
-struct s3c24xx_dma_order_ch {
|
|
- unsigned int list[S3C2410_DMA_CHANNELS]; /* list of channels */
|
|
- unsigned int flags; /* flags */
|
|
-};
|
|
-
|
|
-/* struct s3c24xx_dma_order
|
|
- *
|
|
- * information provided by either the core or the board to give the
|
|
- * dma system a hint on how to allocate channels
|
|
-*/
|
|
-
|
|
-struct s3c24xx_dma_order {
|
|
- struct s3c24xx_dma_order_ch channels[DMACH_MAX];
|
|
-};
|
|
-
|
|
-extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
|
|
-
|
|
-/* DMA init code, called from the cpu support code */
|
|
-
|
|
-extern int s3c2410_dma_init(void);
|
|
-
|
|
-extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
|
|
- unsigned int stride);
|
|
--- /dev/null
|
|
+++ b/arch/arm/plat-s3c24xx/include/plat/dma-plat.h
|
|
@@ -0,0 +1,84 @@
|
|
+/* linux/arch/arm/plat-s3c24xx/include/plat/dma-plat.h
|
|
+ *
|
|
+ * Copyright (C) 2006 Simtec Electronics
|
|
+ * Ben Dooks <ben@simtec.co.uk>
|
|
+ *
|
|
+ * Samsung S3C24XX DMA support
|
|
+ *
|
|
+ * 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 <plat/dma-core.h>
|
|
+
|
|
+extern struct sysdev_class dma_sysclass;
|
|
+extern struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
|
|
+
|
|
+#define DMA_CH_VALID (1<<31)
|
|
+#define DMA_CH_NEVER (1<<30)
|
|
+
|
|
+struct s3c24xx_dma_addr {
|
|
+ unsigned long from;
|
|
+ unsigned long to;
|
|
+};
|
|
+
|
|
+/* struct s3c24xx_dma_map
|
|
+ *
|
|
+ * this holds the mapping information for the channel selected
|
|
+ * to be connected to the specified device
|
|
+*/
|
|
+
|
|
+struct s3c24xx_dma_map {
|
|
+ const char *name;
|
|
+ struct s3c24xx_dma_addr hw_addr;
|
|
+
|
|
+ unsigned long channels[S3C_DMA_CHANNELS];
|
|
+ unsigned long channels_rx[S3C_DMA_CHANNELS];
|
|
+};
|
|
+
|
|
+struct s3c24xx_dma_selection {
|
|
+ struct s3c24xx_dma_map *map;
|
|
+ unsigned long map_size;
|
|
+ unsigned long dcon_mask;
|
|
+
|
|
+ void (*select)(struct s3c2410_dma_chan *chan,
|
|
+ struct s3c24xx_dma_map *map);
|
|
+
|
|
+ void (*direction)(struct s3c2410_dma_chan *chan,
|
|
+ struct s3c24xx_dma_map *map,
|
|
+ enum s3c2410_dmasrc dir);
|
|
+};
|
|
+
|
|
+extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
|
|
+
|
|
+/* struct s3c24xx_dma_order_ch
|
|
+ *
|
|
+ * channel map for one of the `enum dma_ch` dma channels. the list
|
|
+ * entry contains a set of low-level channel numbers, orred with
|
|
+ * DMA_CH_VALID, which are checked in the order in the array.
|
|
+*/
|
|
+
|
|
+struct s3c24xx_dma_order_ch {
|
|
+ unsigned int list[S3C_DMA_CHANNELS]; /* list of channels */
|
|
+ unsigned int flags; /* flags */
|
|
+};
|
|
+
|
|
+/* struct s3c24xx_dma_order
|
|
+ *
|
|
+ * information provided by either the core or the board to give the
|
|
+ * dma system a hint on how to allocate channels
|
|
+*/
|
|
+
|
|
+struct s3c24xx_dma_order {
|
|
+ struct s3c24xx_dma_order_ch channels[DMACH_MAX];
|
|
+};
|
|
+
|
|
+extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
|
|
+
|
|
+/* DMA init code, called from the cpu support code */
|
|
+
|
|
+extern int s3c2410_dma_init(void);
|
|
+
|
|
+extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
|
|
+ unsigned int stride);
|
|
--- /dev/null
|
|
+++ b/arch/arm/plat-s3c24xx/include/plat/regs-dma.h
|
|
@@ -0,0 +1,145 @@
|
|
+/* arch/arm/mach-s3c2410/include/mach/dma.h
|
|
+ *
|
|
+ * Copyright (C) 2003,2004,2006 Simtec Electronics
|
|
+ * Ben Dooks <ben@simtec.co.uk>
|
|
+ *
|
|
+ * Samsung S3C24XX DMA support
|
|
+ *
|
|
+ * 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.
|
|
+*/
|
|
+
|
|
+/* DMA Register definitions */
|
|
+
|
|
+#define S3C2410_DMA_DISRC (0x00)
|
|
+#define S3C2410_DMA_DISRCC (0x04)
|
|
+#define S3C2410_DMA_DIDST (0x08)
|
|
+#define S3C2410_DMA_DIDSTC (0x0C)
|
|
+#define S3C2410_DMA_DCON (0x10)
|
|
+#define S3C2410_DMA_DSTAT (0x14)
|
|
+#define S3C2410_DMA_DCSRC (0x18)
|
|
+#define S3C2410_DMA_DCDST (0x1C)
|
|
+#define S3C2410_DMA_DMASKTRIG (0x20)
|
|
+#define S3C2412_DMA_DMAREQSEL (0x24)
|
|
+#define S3C2443_DMA_DMAREQSEL (0x24)
|
|
+
|
|
+#define S3C2410_DISRCC_INC (1<<0)
|
|
+#define S3C2410_DISRCC_APB (1<<1)
|
|
+
|
|
+#define S3C2410_DMASKTRIG_STOP (1<<2)
|
|
+#define S3C2410_DMASKTRIG_ON (1<<1)
|
|
+#define S3C2410_DMASKTRIG_SWTRIG (1<<0)
|
|
+
|
|
+#define S3C2410_DCON_DEMAND (0<<31)
|
|
+#define S3C2410_DCON_HANDSHAKE (1<<31)
|
|
+#define S3C2410_DCON_SYNC_PCLK (0<<30)
|
|
+#define S3C2410_DCON_SYNC_HCLK (1<<30)
|
|
+
|
|
+#define S3C2410_DCON_INTREQ (1<<29)
|
|
+
|
|
+#define S3C2410_DCON_CH0_XDREQ0 (0<<24)
|
|
+#define S3C2410_DCON_CH0_UART0 (1<<24)
|
|
+#define S3C2410_DCON_CH0_SDI (2<<24)
|
|
+#define S3C2410_DCON_CH0_TIMER (3<<24)
|
|
+#define S3C2410_DCON_CH0_USBEP1 (4<<24)
|
|
+
|
|
+#define S3C2410_DCON_CH1_XDREQ1 (0<<24)
|
|
+#define S3C2410_DCON_CH1_UART1 (1<<24)
|
|
+#define S3C2410_DCON_CH1_I2SSDI (2<<24)
|
|
+#define S3C2410_DCON_CH1_SPI (3<<24)
|
|
+#define S3C2410_DCON_CH1_USBEP2 (4<<24)
|
|
+
|
|
+#define S3C2410_DCON_CH2_I2SSDO (0<<24)
|
|
+#define S3C2410_DCON_CH2_I2SSDI (1<<24)
|
|
+#define S3C2410_DCON_CH2_SDI (2<<24)
|
|
+#define S3C2410_DCON_CH2_TIMER (3<<24)
|
|
+#define S3C2410_DCON_CH2_USBEP3 (4<<24)
|
|
+
|
|
+#define S3C2410_DCON_CH3_UART2 (0<<24)
|
|
+#define S3C2410_DCON_CH3_SDI (1<<24)
|
|
+#define S3C2410_DCON_CH3_SPI (2<<24)
|
|
+#define S3C2410_DCON_CH3_TIMER (3<<24)
|
|
+#define S3C2410_DCON_CH3_USBEP4 (4<<24)
|
|
+
|
|
+#define S3C2410_DCON_SRCSHIFT (24)
|
|
+#define S3C2410_DCON_SRCMASK (7<<24)
|
|
+
|
|
+#define S3C2410_DCON_BYTE (0<<20)
|
|
+#define S3C2410_DCON_HALFWORD (1<<20)
|
|
+#define S3C2410_DCON_WORD (2<<20)
|
|
+
|
|
+#define S3C2410_DCON_AUTORELOAD (0<<22)
|
|
+#define S3C2410_DCON_NORELOAD (1<<22)
|
|
+#define S3C2410_DCON_HWTRIG (1<<23)
|
|
+
|
|
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
|
|
+#define S3C2440_DIDSTC_CHKINT (1<<2)
|
|
+
|
|
+#define S3C2440_DCON_CH0_I2SSDO (5<<24)
|
|
+#define S3C2440_DCON_CH0_PCMIN (6<<24)
|
|
+
|
|
+#define S3C2440_DCON_CH1_PCMOUT (5<<24)
|
|
+#define S3C2440_DCON_CH1_SDI (6<<24)
|
|
+
|
|
+#define S3C2440_DCON_CH2_PCMIN (5<<24)
|
|
+#define S3C2440_DCON_CH2_MICIN (6<<24)
|
|
+
|
|
+#define S3C2440_DCON_CH3_MICIN (5<<24)
|
|
+#define S3C2440_DCON_CH3_PCMOUT (6<<24)
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_CPU_S3C2412
|
|
+
|
|
+#define S3C2412_DMAREQSEL_SRC(x) ((x)<<1)
|
|
+
|
|
+#define S3C2412_DMAREQSEL_HW (1)
|
|
+
|
|
+#define S3C2412_DMAREQSEL_SPI0TX S3C2412_DMAREQSEL_SRC(0)
|
|
+#define S3C2412_DMAREQSEL_SPI0RX S3C2412_DMAREQSEL_SRC(1)
|
|
+#define S3C2412_DMAREQSEL_SPI1TX S3C2412_DMAREQSEL_SRC(2)
|
|
+#define S3C2412_DMAREQSEL_SPI1RX S3C2412_DMAREQSEL_SRC(3)
|
|
+#define S3C2412_DMAREQSEL_I2STX S3C2412_DMAREQSEL_SRC(4)
|
|
+#define S3C2412_DMAREQSEL_I2SRX S3C2412_DMAREQSEL_SRC(5)
|
|
+#define S3C2412_DMAREQSEL_TIMER S3C2412_DMAREQSEL_SRC(9)
|
|
+#define S3C2412_DMAREQSEL_SDI S3C2412_DMAREQSEL_SRC(10)
|
|
+#define S3C2412_DMAREQSEL_USBEP1 S3C2412_DMAREQSEL_SRC(13)
|
|
+#define S3C2412_DMAREQSEL_USBEP2 S3C2412_DMAREQSEL_SRC(14)
|
|
+#define S3C2412_DMAREQSEL_USBEP3 S3C2412_DMAREQSEL_SRC(15)
|
|
+#define S3C2412_DMAREQSEL_USBEP4 S3C2412_DMAREQSEL_SRC(16)
|
|
+#define S3C2412_DMAREQSEL_XDREQ0 S3C2412_DMAREQSEL_SRC(17)
|
|
+#define S3C2412_DMAREQSEL_XDREQ1 S3C2412_DMAREQSEL_SRC(18)
|
|
+#define S3C2412_DMAREQSEL_UART0_0 S3C2412_DMAREQSEL_SRC(19)
|
|
+#define S3C2412_DMAREQSEL_UART0_1 S3C2412_DMAREQSEL_SRC(20)
|
|
+#define S3C2412_DMAREQSEL_UART1_0 S3C2412_DMAREQSEL_SRC(21)
|
|
+#define S3C2412_DMAREQSEL_UART1_1 S3C2412_DMAREQSEL_SRC(22)
|
|
+#define S3C2412_DMAREQSEL_UART2_0 S3C2412_DMAREQSEL_SRC(23)
|
|
+#define S3C2412_DMAREQSEL_UART2_1 S3C2412_DMAREQSEL_SRC(24)
|
|
+
|
|
+#endif
|
|
+
|
|
+#define S3C2443_DMAREQSEL_SRC(x) ((x)<<1)
|
|
+
|
|
+#define S3C2443_DMAREQSEL_HW (1)
|
|
+
|
|
+#define S3C2443_DMAREQSEL_SPI0TX S3C2443_DMAREQSEL_SRC(0)
|
|
+#define S3C2443_DMAREQSEL_SPI0RX S3C2443_DMAREQSEL_SRC(1)
|
|
+#define S3C2443_DMAREQSEL_SPI1TX S3C2443_DMAREQSEL_SRC(2)
|
|
+#define S3C2443_DMAREQSEL_SPI1RX S3C2443_DMAREQSEL_SRC(3)
|
|
+#define S3C2443_DMAREQSEL_I2STX S3C2443_DMAREQSEL_SRC(4)
|
|
+#define S3C2443_DMAREQSEL_I2SRX S3C2443_DMAREQSEL_SRC(5)
|
|
+#define S3C2443_DMAREQSEL_TIMER S3C2443_DMAREQSEL_SRC(9)
|
|
+#define S3C2443_DMAREQSEL_SDI S3C2443_DMAREQSEL_SRC(10)
|
|
+#define S3C2443_DMAREQSEL_XDREQ0 S3C2443_DMAREQSEL_SRC(17)
|
|
+#define S3C2443_DMAREQSEL_XDREQ1 S3C2443_DMAREQSEL_SRC(18)
|
|
+#define S3C2443_DMAREQSEL_UART0_0 S3C2443_DMAREQSEL_SRC(19)
|
|
+#define S3C2443_DMAREQSEL_UART0_1 S3C2443_DMAREQSEL_SRC(20)
|
|
+#define S3C2443_DMAREQSEL_UART1_0 S3C2443_DMAREQSEL_SRC(21)
|
|
+#define S3C2443_DMAREQSEL_UART1_1 S3C2443_DMAREQSEL_SRC(22)
|
|
+#define S3C2443_DMAREQSEL_UART2_0 S3C2443_DMAREQSEL_SRC(23)
|
|
+#define S3C2443_DMAREQSEL_UART2_1 S3C2443_DMAREQSEL_SRC(24)
|
|
+#define S3C2443_DMAREQSEL_UART3_0 S3C2443_DMAREQSEL_SRC(25)
|
|
+#define S3C2443_DMAREQSEL_UART3_1 S3C2443_DMAREQSEL_SRC(26)
|
|
+#define S3C2443_DMAREQSEL_PCMOUT S3C2443_DMAREQSEL_SRC(27)
|
|
+#define S3C2443_DMAREQSEL_PCMIN S3C2443_DMAREQSEL_SRC(28)
|
|
+#define S3C2443_DMAREQSEL_MICIN S3C2443_DMAREQSEL_SRC(29)
|
|
--- a/arch/arm/plat-s3c24xx/Kconfig
|
|
+++ b/arch/arm/plat-s3c24xx/Kconfig
|
|
@@ -71,6 +71,7 @@ config PM_SIMTEC
|
|
config S3C2410_DMA
|
|
bool "S3C2410 DMA support"
|
|
depends on ARCH_S3C2410
|
|
+ select S3C_DMA
|
|
help
|
|
S3C2410 DMA support. This is needed for drivers like sound which
|
|
use the S3C2410's DMA system to move data to and from the
|
|
--- a/arch/arm/mach-s3c2410/dma.c
|
|
+++ b/arch/arm/mach-s3c2410/dma.c
|
|
@@ -17,14 +17,16 @@
|
|
#include <linux/sysdev.h>
|
|
#include <linux/serial_core.h>
|
|
|
|
+#include <mach/map.h>
|
|
#include <mach/dma.h>
|
|
|
|
#include <plat/cpu.h>
|
|
-#include <plat/dma.h>
|
|
+#include <plat/dma-plat.h>
|
|
|
|
#include <plat/regs-serial.h>
|
|
#include <mach/regs-gpio.h>
|
|
#include <plat/regs-ac97.h>
|
|
+#include <plat/regs-dma.h>
|
|
#include <mach/regs-mem.h>
|
|
#include <mach/regs-lcd.h>
|
|
#include <mach/regs-sdi.h>
|
|
--- a/arch/arm/mach-s3c2440/dma.c
|
|
+++ b/arch/arm/mach-s3c2440/dma.c
|
|
@@ -17,14 +17,16 @@
|
|
#include <linux/sysdev.h>
|
|
#include <linux/serial_core.h>
|
|
|
|
+#include <mach/map.h>
|
|
#include <mach/dma.h>
|
|
|
|
-#include <plat/dma.h>
|
|
+#include <plat/dma-plat.h>
|
|
#include <plat/cpu.h>
|
|
|
|
#include <plat/regs-serial.h>
|
|
#include <mach/regs-gpio.h>
|
|
#include <plat/regs-ac97.h>
|
|
+#include <plat/regs-dma.h>
|
|
#include <mach/regs-mem.h>
|
|
#include <mach/regs-lcd.h>
|
|
#include <mach/regs-sdi.h>
|
|
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
|
|
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
|
|
@@ -218,24 +218,17 @@ static int s3c24xx_pcm_prepare(struct sn
|
|
* sync to pclk, half-word transfers to the IIS-FIFO. */
|
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
s3c2410_dma_devconfig(prtd->params->channel,
|
|
- S3C2410_DMASRC_MEM, S3C2410_DISRCC_INC |
|
|
- S3C2410_DISRCC_APB, prtd->params->dma_addr);
|
|
-
|
|
- s3c2410_dma_config(prtd->params->channel,
|
|
- prtd->params->dma_size,
|
|
- S3C2410_DCON_SYNC_PCLK |
|
|
- S3C2410_DCON_HANDSHAKE);
|
|
+ S3C2410_DMASRC_MEM,
|
|
+ prtd->params->dma_addr);
|
|
} else {
|
|
- s3c2410_dma_config(prtd->params->channel,
|
|
- prtd->params->dma_size,
|
|
- S3C2410_DCON_HANDSHAKE |
|
|
- S3C2410_DCON_SYNC_PCLK);
|
|
-
|
|
s3c2410_dma_devconfig(prtd->params->channel,
|
|
- S3C2410_DMASRC_HW, 0x3,
|
|
- prtd->params->dma_addr);
|
|
+ S3C2410_DMASRC_HW,
|
|
+ prtd->params->dma_addr);
|
|
}
|
|
|
|
+ s3c2410_dma_config(prtd->params->channel,
|
|
+ prtd->params->dma_size);
|
|
+
|
|
/* flush the DMA channel */
|
|
s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
|
|
prtd->dma_loaded = 0;
|