satip-axe/kernel/include/linux/stm/stm-dma.h
2015-03-26 17:24:57 +01:00

376 lines
9.6 KiB
C

/*
* Copyright (C) 2005,7 STMicroelectronics Limited
* Authors: Mark Glaisher <Mark.Glaisher@st.com>
* Stuart Menefy <stuart.menefy@st.com>
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*/
#ifndef STM_DMA_H
#define STM_DMA_H
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/string.h>
#include <linux/module.h>
/*DMA Modes */
#define MODE_FREERUNNING 0x01 /* FDMA, GPDMA */
#define MODE_PACED 0x02 /* FDMA */
#define MODE_SRC_SCATTER 0x04
#define MODE_DST_SCATTER 0x05
/* DMA dimensions */
#define DIM_SRC_SHIFT 0
#define DIM_DST_SHIFT 2
#define DIM_SRC(x) (((x) >> DIM_SRC_SHIFT) & 3)
#define DIM_DST(x) (((x) >> DIM_DST_SHIFT) & 3)
enum stm_dma_dimensions {
DIM_0_x_0 = (0 << DIM_SRC_SHIFT) | (0 << DIM_DST_SHIFT),
DIM_0_x_1 = (0 << DIM_SRC_SHIFT) | (1 << DIM_DST_SHIFT),
DIM_0_x_2 = (0 << DIM_SRC_SHIFT) | (2 << DIM_DST_SHIFT),
DIM_1_x_0 = (1 << DIM_SRC_SHIFT) | (0 << DIM_DST_SHIFT),
DIM_1_x_1 = (1 << DIM_SRC_SHIFT) | (1 << DIM_DST_SHIFT),
DIM_1_x_2 = (1 << DIM_SRC_SHIFT) | (2 << DIM_DST_SHIFT),
DIM_2_x_0 = (2 << DIM_SRC_SHIFT) | (0 << DIM_DST_SHIFT),
DIM_2_x_1 = (2 << DIM_SRC_SHIFT) | (1 << DIM_DST_SHIFT),
DIM_2_x_2 = (2 << DIM_SRC_SHIFT) | (2 << DIM_DST_SHIFT),
};
enum stm_dma_flags {
STM_DMA_INTER_NODE_PAUSE=0x800,
STM_DMA_NODE_COMP_INT=0x1000,
STM_DMA_CB_CONTEXT_ISR=0x2000,
STM_DMA_CB_CONTEXT_TASKLET=0x4000,
STM_DMA_CHANNEL_PAUSE_FLUSH=0x20000,
STM_DMA_CHANNEL_PAUSE_NOFLUSH=0x40000,
STM_DMA_NOBLOCK_MODE=0x80000,
STM_DMA_BLOCK_MODE=0x100000,
STM_DMA_LIST_CIRC=0x200000,
STM_DMA_LIST_OPEN=0x400000,
};
#define DMA_CHANNEL_STATUS_IDLE 0
#define DMA_CHANNEL_STATUS_RUNNING 2
#define DMA_CHANNEL_STATUS_PAUSED 3
/* Parameters to request_dma_bycap() */
#define STM_DMAC_ID "fdma_dmac"
#define STM_DMA_CAP_HIGH_BW "STM_DMA_HIGH_BANDWIDTH"
#define STM_DMA_CAP_LOW_BW "STM_DMA_LOW_BANDWIDTH"
#define STM_DMA_CAP_ETH_BUF "STM_DMA_ETH_BUFFER"
/* dma_extend() operations */
#define STM_DMA_OP_FLUSH 1
#define STM_DMA_OP_PAUSE 2
#define STM_DMA_OP_UNPAUSE 3
#define STM_DMA_OP_STOP 4
#define STM_DMA_OP_COMPILE 5
#define STM_DMA_OP_STATUS 6
#define STM_DMA_OP_REQ_CONFIG 7
#define STM_DMA_OP_REQ_FREE 8
/* Generic DMA request line configuration */
/* Read/Write */
#define REQ_CONFIG_READ 0
#define REQ_CONFIG_WRITE 1
/* Opcodes */
#define REQ_CONFIG_OPCODE_1 0x00
#define REQ_CONFIG_OPCODE_2 0x01
#define REQ_CONFIG_OPCODE_4 0x02
#define REQ_CONFIG_OPCODE_8 0x03
#define REQ_CONFIG_OPCODE_16 0x04
#define REQ_CONFIG_OPCODE_32 0x05
struct stm_dma_req_config
{
unsigned char req_line; /* Request line index number */
unsigned char rw; /* Access type: Read or Write */
unsigned char opcode; /* Size of word access */
unsigned char count; /* Number of transfers per request */
unsigned char increment; /* Whether to increment */
unsigned char hold_off; /* Holdoff value between req signal samples (in clock cycles)*/
unsigned char initiator; /* Which STBus initiatator to use */
};
struct stm_dma_req;
/* Generic STM DMA params */
struct stm_dma_params;
struct params_ops {
int (*free_params)(struct stm_dma_params* params);
};
struct stm_dma_params {
/* Transfer mode eg MODE_DST_SCATTER */
unsigned long mode;
/* a pointer to a callback function of type void foo(void*)
* which will be called on completion of the entire
* transaction or after each transfer suceeds if
* NODE_PAUSE_ISR is specifed */
void (*comp_cb)(unsigned long);
unsigned long comp_cb_parm;
/* a pointer to a callback function of type void foo(void*)
* which will be called upon failure of a transfer or
* transaction*/
void (*err_cb)(unsigned long);
unsigned long err_cb_parm;
/*Source location line stride for use in 0/1/2 x 2D modes*/
unsigned long sstride;
/*Source location line stride for use in 2D x 0/1/2 modes*/
unsigned long dstride;
/* Line length for any 2D modes */
unsigned long line_len;
/*source addr - given in phys*/
unsigned long sar;
/*dest addr - given in phys*/
unsigned long dar;
unsigned long node_bytes;
struct scatterlist * srcsg;
struct scatterlist * dstsg;
int sglen;
int err_cb_isr :1;
int comp_cb_isr :1;
int node_pause :1;
int node_interrupt :1;
int circular_llu :1;
unsigned long dim;
/* Parameters for paced transfers */
struct stm_dma_req *req;
/* Pointer to compiled parameters
* this includes the *template* llu node and
* its assoc'd memory */
void* priv;
/* Next pointer for linked list of params */
struct stm_dma_params *next;
/* Pointer to DMAC specific operators on the parameters.
* Filled in by dma_compile_list(). */
struct params_ops *params_ops;
void* params_ops_priv;
/* This is only used in the call to dma_compile_list(), so
* shouldn't really be here, but it saves us packing and unpacking
* the parameters into another struct. */
gfp_t context;
};
static inline void dma_params_init(struct stm_dma_params * p,
unsigned long mode,
unsigned long list_type)
{
memset(p,0,sizeof(struct stm_dma_params));
p->mode = mode;
p->circular_llu = (STM_DMA_LIST_CIRC ==list_type ?1:0);
};
static inline int dma_get_status(unsigned int vchan)
{
return dma_extend(vchan, STM_DMA_OP_STATUS, NULL);
}
/* Flush implies pause - I mean pause+flush */
static inline int dma_flush_channel(unsigned int vchan)
{
return dma_extend(vchan, STM_DMA_OP_FLUSH, NULL);
}
static inline int dma_pause_channel(unsigned int vchan)
{
return dma_extend(vchan, STM_DMA_OP_PAUSE, NULL);
}
static inline void dma_unpause_channel(unsigned int vchan)
{
dma_extend(vchan, STM_DMA_OP_UNPAUSE, NULL);
}
static inline int dma_stop_channel(unsigned int vchan)
{
return dma_extend(vchan, STM_DMA_OP_STOP, NULL);
}
static inline int dma_params_free(struct stm_dma_params *params)
{
return params->params_ops->free_params(params);
}
static inline int dma_compile_list(unsigned int vchan,
struct stm_dma_params *params,
gfp_t gfp_mask)
{
params->context = gfp_mask;
return dma_extend(vchan, STM_DMA_OP_COMPILE, params);
}
static inline int dma_xfer_list(unsigned int vchan, struct stm_dma_params *p)
{
/*TODO :- this is a bit 'orrible -
* should really extend arch/sh/drivers/dma/dma-api.c
* to include a 'set_dma_channel'*/
dma_configure_channel(vchan, (unsigned long)p);
return dma_xfer(vchan, 0, 0, 0, 0);
}
static inline struct stm_dma_req *dma_req_config(unsigned int vchan,
unsigned int req_line,
struct stm_dma_req_config* req_config)
{
req_config->req_line = req_line;
return (struct stm_dma_req *)
dma_extend(vchan, STM_DMA_OP_REQ_CONFIG, req_config);
}
static inline void dma_req_free(unsigned int vchan, struct stm_dma_req *req)
{
dma_extend(vchan, STM_DMA_OP_REQ_FREE, req);
}
static inline void dma_params_sg( struct stm_dma_params *p,
struct scatterlist * sg,
int nents)
{
if(MODE_SRC_SCATTER==p->mode)
p->srcsg=sg;
else if (MODE_DST_SCATTER==p->mode)
p->dstsg = sg;
else
BUG();
p->sglen = nents;
}
static inline void dma_params_link( struct stm_dma_params * parent,
struct stm_dma_params * child)
{
parent->next=child;
}
static inline void dma_params_req( struct stm_dma_params *p,
struct stm_dma_req *req)
{
p->req = req;
}
static inline void dma_params_addrs( struct stm_dma_params *p,
unsigned long src,
unsigned long dst,
unsigned long bytes)
{
p->sar = src;
p->dar = dst;
p->node_bytes = bytes;
}
static inline void dma_params_interrupts(struct stm_dma_params *p,
unsigned long isrflag)
{
if(isrflag & STM_DMA_INTER_NODE_PAUSE)
p->node_pause=1;
if(isrflag & STM_DMA_NODE_COMP_INT )
p->node_interrupt=1;
}
static inline void dma_params_comp_cb( struct stm_dma_params *p,
void (*fn)(unsigned long param),
unsigned long param,
int isr_context)
{
p->comp_cb = fn;
p->comp_cb_parm = param;
p->comp_cb_isr = (isr_context == STM_DMA_CB_CONTEXT_ISR ?1:0);
}
static inline void dma_params_err_cb( struct stm_dma_params *p,
void (*fn)(unsigned long param),
unsigned long param,
int isr_context)
{
p->err_cb = fn;
p->err_cb_parm = param;
p->err_cb_isr = (isr_context == STM_DMA_CB_CONTEXT_ISR ?1:0);
}
static inline void dma_params_dim( struct stm_dma_params *p,
unsigned long line_len,
unsigned long sstride,
unsigned long dstride,
unsigned long dim)
{
p->line_len = line_len;
p->sstride = sstride;
p->dstride = dstride;
p->dim =dim;
}
static inline void dma_params_DIM_0_x_0(struct stm_dma_params *p)
{
dma_params_dim(p, 0,0,0, DIM_0_x_0);
}
static inline void dma_params_DIM_0_x_1(struct stm_dma_params *p)
{
dma_params_dim(p, 0,0,0, DIM_0_x_1);
}
static inline void dma_params_DIM_0_x_2(struct stm_dma_params *p,
unsigned long line_len,
unsigned long dstride)
{
dma_params_dim(p, line_len, 0, dstride, DIM_0_x_2);
}
static inline void dma_params_DIM_1_x_0(struct stm_dma_params *p)
{
dma_params_dim(p, 0,0,0, DIM_1_x_0);
}
static inline void dma_params_DIM_1_x_1(struct stm_dma_params *p)
{
dma_params_dim(p, 0,0,0, DIM_1_x_1);
}
static inline void dma_params_DIM_1_x_2(struct stm_dma_params *p,
unsigned long line_len,
unsigned long dstride)
{
dma_params_dim(p, line_len, line_len, dstride, DIM_1_x_2);
}
static inline void dma_params_DIM_2_x_0(struct stm_dma_params *p,
unsigned long line_len,
unsigned long sstride)
{
dma_params_dim(p, line_len, sstride, 0, DIM_2_x_0);
}
static inline void dma_params_DIM_2_x_1(struct stm_dma_params *p,
unsigned long line_len,
unsigned long sstride)
{
dma_params_dim(p, line_len, sstride, line_len, DIM_2_x_1);
}
#endif