vserver 1.9.3
[linux-2.6.git] / include / asm-arm / arch-s3c2410 / dma.h
index ea084c7..9cae382 100644 (file)
@@ -27,7 +27,7 @@
  *
  */
 #define MAX_DMA_ADDRESS                0x20000000
-#define MAX_DMA_TRANSFER_SIZE  0x100000 /* Data Unit is half word  */
+#define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
 
 
 /* according to the samsung port, we cannot use the regular
 
 
 /* we have 4 dma channels */
-#define S3C2410_DMA_CHANNELS       (4)
+#define S3C2410_DMA_CHANNELS        (4)
 
+/* types */
+
+typedef enum {
+       S3C2410_DMA_IDLE,
+       S3C2410_DMA_RUNNING,
+       S3C2410_DMA_PAUSED
+} s3c2410_dma_state_t;
+
+
+/* s3c2410_dma_loadst_t
+ *
+ * This represents the state of the DMA engine, wrt to the loaded / running
+ * transfers. Since we don't have any way of knowing exactly the state of
+ * the DMA transfers, we need to know the state to make decisions on wether
+ * we can
+ *
+ * S3C2410_DMA_NONE
+ *
+ * There are no buffers loaded (the channel should be inactive)
+ *
+ * S3C2410_DMA_1LOADED
+ *
+ * There is one buffer loaded, however it has not been confirmed to be
+ * loaded by the DMA engine. This may be because the channel is not
+ * yet running, or the DMA driver decided that it was too costly to
+ * sit and wait for it to happen.
+ *
+ * S3C2410_DMA_1RUNNING
+ *
+ * The buffer has been confirmed running, and not finisged
+ *
+ * S3C2410_DMA_1LOADED_1RUNNING
+ *
+ * There is a buffer waiting to be loaded by the DMA engine, and one
+ * currently running.
+*/
+
+typedef enum {
+       S3C2410_DMALOAD_NONE,
+       S3C2410_DMALOAD_1LOADED,
+       S3C2410_DMALOAD_1RUNNING,
+       S3C2410_DMALOAD_1LOADED_1RUNNING,
+} s3c2410_dma_loadst_t;
+
+typedef enum {
+       S3C2410_RES_OK,
+       S3C2410_RES_ERR,
+       S3C2410_RES_ABORT
+} s3c2410_dma_buffresult_t;
+
+
+typedef enum s3c2410_dmasrc_e s3c2410_dmasrc_t;
+
+enum s3c2410_dmasrc_e {
+       S3C2410_DMASRC_HW,      /* source is memory */
+       S3C2410_DMASRC_MEM      /* source is hardware */
+};
+
+/* enum s3c2410_chan_op_e
+ *
+ * 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_e {
+       S3C2410_DMAOP_START,
+       S3C2410_DMAOP_STOP,
+       S3C2410_DMAOP_PAUSE,
+       S3C2410_DMAOP_RESUME,
+       S3C2410_DMAOP_FLUSH,
+       S3C2410_DMAOP_TIMEOUT,           /* internal signal to handler */
+};
+
+typedef enum s3c2410_chan_op_e s3c2410_chan_op_t;
+
+/* flags */
+
+#define S3C2410_DMAF_SLOW         (1<<0)   /* slow, so don't worry about
+                                           * waiting for reloads */
+#define S3C2410_DMAF_AUTOSTART    (1<<1)   /* auto-start if buffer queued */
 
 /* dma buffer */
 
 typedef struct s3c2410_dma_buf_s s3c2410_dma_buf_t;
 
+struct s3c2410_dma_client {
+       char                *name;
+};
+
+typedef struct s3c2410_dma_client s3c2410_dma_client_t;
+
+/* s3c2410_dma_buf_s
+ *
+ * internally used buffer structure to describe a queued or running
+ * buffer.
+*/
+
 struct s3c2410_dma_buf_s {
        s3c2410_dma_buf_t   *next;
-       int                  magic;        /* magic */
-       int                  size;         /* buffer size in bytes */
-       dma_addr_t           data;         /* start of DMA data */
-       dma_addr_t           ptr;          /* where the DMA got to [1] */
-       int                  ref;
-       void                 *id;          /* client's id */
-       unsigned char        no_callback;  /* disable callback for buffer */
+       int                  magic;        /* magic */
+       int                  size;         /* buffer size in bytes */
+       dma_addr_t           data;         /* start of DMA data */
+       dma_addr_t           ptr;          /* where the DMA got to [1] */
+       void                *id;           /* client's id */
 };
 
 /* [1] is this updated for both recv/send modes? */
 
 typedef struct s3c2410_dma_chan_s s3c2410_dma_chan_t;
 
-typedef void (*s3c2410_dma_cbfn_t)(s3c2410_dma_chan_t *, void *buf, int size);
-typedef void (*s3c2410_dma_enfn_t)(s3c2410_dma_chan_t *, int on);
-typedef void (*s3c2410_dma_pausefn_t)(s3c2410_dma_chan_t *, int on);
+/* s3c2410_dma_cbfn_t
+ *
+ * buffer callback routine type
+*/
+
+typedef void (*s3c2410_dma_cbfn_t)(s3c2410_dma_chan_t *, void *buf, int size,
+                                  s3c2410_dma_buffresult_t result);
+
+typedef int  (*s3c2410_dma_opfn_t)(s3c2410_dma_chan_t *,
+                                  s3c2410_chan_op_t );
+
+struct s3c2410_dma_stats_s {
+       unsigned long          loads;
+       unsigned long          timeout_longest;
+       unsigned long          timeout_shortest;
+       unsigned long          timeout_avg;
+       unsigned long          timeout_failed;
+};
+
+typedef struct s3c2410_dma_stats_s s3c2410_dma_stats_t;
+
+/* struct s3c2410_dma_chan_s
+ *
+ * full state information for each DMA channel
+*/
 
 struct s3c2410_dma_chan_s {
-       /* channel state flags */
-       unsigned char          number;        /* number of this dma channel */
-       unsigned char          in_use;        /* channel allocated */
-       unsigned char          started;       /* channel has been started */
-       unsigned char          stopped;       /* channel stopped */
-       unsigned char          sleeping;
-       unsigned char          xfer_unit;     /* size of an transfer */
-       unsigned char          irq_claimed;
+       /* channel state flags and information */
+       unsigned char          number;      /* number of this dma channel */
+       unsigned char          in_use;      /* channel allocated */
+       unsigned char          irq_claimed; /* irq claimed for channel */
+       unsigned char          irq_enabled; /* irq enabled for channel */
+       unsigned char          xfer_unit;   /* size of an transfer */
+
+       /* channel state */
+
+       s3c2410_dma_state_t    state;
+       s3c2410_dma_loadst_t   load_state;
+       s3c2410_dma_client_t  *client;
+
+       /* channel configuration */
+       s3c2410_dmasrc_t       source;
+       unsigned long          dev_addr;
+       unsigned long          load_timeout;
+       unsigned int           flags;        /* channel flags */
 
        /* channel's hardware position and configuration */
-       unsigned long          regs;          /* channels registers */
-       unsigned int           irq;           /* channel irq */
-       unsigned long          addr_reg;      /* data address register for buffs */
-       unsigned long          dcon;          /* default value of DCON */
+       unsigned long          regs;         /* channels registers */
+       unsigned int           irq;          /* channel irq */
+       unsigned long          addr_reg;     /* data address register */
+       unsigned long          dcon;         /* default value of DCON */
 
-       /* driver handlers for channel */
-       s3c2410_dma_cbfn_t     callback_fn;   /* callback function for buf-done */
-       s3c2410_dma_enfn_t     enable_fn;     /* channel enable function */
-       s3c2410_dma_pausefn_t  pause_fn;      /* channel pause function */
+       /* driver handles */
+       s3c2410_dma_cbfn_t     callback_fn;  /* buffer done callback */
+       s3c2410_dma_opfn_t     op_fn;        /* channel operation callback */
 
-       /* buffer list and information */
-       s3c2410_dma_buf_t      *curr;         /* current dma buffer */
-       s3c2410_dma_buf_t      *next;         /* next buffer to load */
-       s3c2410_dma_buf_t      *end;          /* end of queue */
+       /* stats gathering */
+       s3c2410_dma_stats_t   *stats;
+       s3c2410_dma_stats_t    stats_store;
 
-       int                    queue_count;   /* number of items in queue */
-       int                    loaded_count;  /* number of loaded buffers */
+       /* buffer list and information */
+       s3c2410_dma_buf_t      *curr;        /* current dma buffer */
+       s3c2410_dma_buf_t      *next;        /* next buffer to load */
+       s3c2410_dma_buf_t      *end;         /* end of queue */
 };
 
-/* note, we don't really use dma_deivce_t at the moment */
+/* the currently allocated channel information */
+extern s3c2410_dma_chan_t s3c2410_chans[];
+
+/* note, we don't really use dma_device_t at the moment */
 typedef unsigned long dma_device_t;
 
-typedef enum s3c2410_dmasrc_e s3c2410_dmasrc_t;
+/* functions --------------------------------------------------------------- */
 
-/* these two defines control the source for the dma channel,
- * wether it is from memory or an device
+/* s3c2410_dma_request
+ *
+ * request a dma channel exclusivley
 */
 
-enum s3c2410_dmasrc_e {
-  S3C2410_DMASRC_HW,     /* source is memory */
-  S3C2410_DMASRC_MEM     /* source is hardware */
-};
+extern int s3c2410_dma_request(dmach_t channel,
+                              s3c2410_dma_client_t *, void *dev);
+
+
+/* s3c2410_dma_ctrl
+ *
+ * change the state of the dma channel
+*/
+
+extern int s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op);
+
+/* s3c2410_dma_setflags
+ *
+ * set the channel's flags to a given state
+*/
 
-/* dma control routines */
+extern int s3c2410_dma_setflags(dmach_t channel,
+                               unsigned int flags);
 
-extern int s3c2410_request_dma(dmach_t channel, const char *devid, void *dev);
-extern int s3c2410_free_dma(dmach_t channel);
-extern int s3c2410_dma_flush_all(dmach_t channel);
+/* s3c2410_dma_free
+ *
+ * free the dma channel (will also abort any outstanding operations)
+*/
 
-extern int s3c2410_dma_stop(dmach_t channel);
-extern int s3c2410_dma_resume(dmach_t channel);
+extern int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *);
 
-extern int s3c2410_dma_queue(dmach_t channel, void *id,
-                            dma_addr_t data, int size);
+/* 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.
+*/
 
-#define s3c2410_dma_queue_buffer s3c2410_dma_queue
+extern int s3c2410_dma_enqueue(dmach_t channel, void *id,
+                              dma_addr_t data, int size);
 
-/* channel configuration */
+/* s3c2410_dma_config
+ *
+ * configure the dma channel
+*/
 
 extern int s3c2410_dma_config(dmach_t channel, int xferunit, int dcon);
 
+/* s3c2410_dma_devconfig
+ *
+ * configure the device we're talking to
+*/
+
 extern int s3c2410_dma_devconfig(int channel, s3c2410_dmasrc_t source,
                                 int hwcfg, unsigned long devaddr);
 
-extern int s3c2410_dma_set_enablefn(dmach_t, s3c2410_dma_enfn_t rtn);
-extern int s3c2410_dma_set_pausefn(dmach_t, s3c2410_dma_pausefn_t rtn);
-extern int s3c2410_dma_set_callbackfn(dmach_t, s3c2410_dma_cbfn_t rtn);
+extern int s3c2410_dma_set_opfn(dmach_t, s3c2410_dma_opfn_t rtn);
+extern int s3c2410_dma_set_buffdone_fn(dmach_t, s3c2410_dma_cbfn_t rtn);
 
-#define s3c2410_dma_set_callback s3c2410_dma_set_callbackfn
+/* 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 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 S3C2410_DMASKTRIG_STOP  (1<<2)
-#define S3C2410_DMASKTRIG_ON    (1<<1)
+#define S3C2410_DMASKTRIG_STOP   (1<<2)
+#define S3C2410_DMASKTRIG_ON     (1<<1)
 #define S3C2410_DMASKTRIG_SWTRIG (1<<0)
 
-#define S3C2410_DCOM_DEMAND    (0<<31)
+#define S3C2410_DCOM_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_INTREQ     (1<<29)
 
-#define S3C2410_DCON_SRCSHIFT  (24)
+#define S3C2410_DCON_SRCSHIFT   (24)
 
-#define S3C2410_DCON_BYTE      (0<<20)
-#define S3C2410_DCON_HALFWORD  (1<<20)
-#define S3C2410_DCON_WORD      (2<<20)
+#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_HWTRIG    (1<<23)
+#define S3C2410_DCON_NORELOAD   (1<<22)
+#define S3C2410_DCON_HWTRIG     (1<<23)
 
 #endif /* __ASM_ARCH_DMA_H */