1
#define _PCILIB_DMA_NWL_C
13
/* Common DMA registers */
14
#define REG_DMA_CTRL_STATUS 0x4000 /**< DMA Common Ctrl & Status */
16
/* These engine registers are applicable to both S2C and C2S channels.
17
* Register field mask and shift definitions are later in this file.
20
#define REG_DMA_ENG_CAP 0x00000000 /**< DMA Engine Capabilities */
21
#define REG_DMA_ENG_CTRL_STATUS 0x00000004 /**< DMA Engine Control */
22
#define REG_DMA_ENG_NEXT_BD 0x00000008 /**< HW Next desc pointer */
23
#define REG_SW_NEXT_BD 0x0000000C /**< SW Next desc pointer */
24
#define REG_DMA_ENG_LAST_BD 0x00000010 /**< HW Last completed pointer */
25
#define REG_DMA_ENG_ACTIVE_TIME 0x00000014 /**< DMA Engine Active Time */
26
#define REG_DMA_ENG_WAIT_TIME 0x00000018 /**< DMA Engine Wait Time */
27
#define REG_DMA_ENG_COMP_BYTES 0x0000001C /**< DMA Engine Completed Bytes */
29
/* Register masks. The following constants define bit locations of various
30
* control bits in the registers. For further information on the meaning of
31
* the various bit masks, refer to the hardware spec.
33
* Masks have been written assuming HW bits 0-31 correspond to SW bits 0-31
36
/** @name Bitmasks of REG_DMA_CTRL_STATUS register.
39
#define DMA_INT_ENABLE 0x00000001 /**< Enable global interrupts */
40
#define DMA_INT_DISABLE 0x00000000 /**< Disable interrupts */
41
#define DMA_INT_ACTIVE_MASK 0x00000002 /**< Interrupt active? */
42
#define DMA_INT_PENDING_MASK 0x00000004 /**< Engine interrupt pending */
43
#define DMA_INT_MSI_MODE 0x00000008 /**< MSI or Legacy mode? */
44
#define DMA_USER_INT_ENABLE 0x00000010 /**< Enable user interrupts */
45
#define DMA_USER_INT_ACTIVE_MASK 0x00000020 /**< Int - user interrupt */
46
#define DMA_USER_INT_ACK 0x00000020 /**< Acknowledge */
47
#define DMA_MPS_USED 0x00000700 /**< MPS Used */
48
#define DMA_MRRS_USED 0x00007000 /**< MRRS Used */
49
#define DMA_S2C_ENG_INT_VAL 0x00FF0000 /**< IRQ value of 1st 8 S2Cs */
50
#define DMA_C2S_ENG_INT_VAL 0xFF000000 /**< IRQ value of 1st 8 C2Ss */
52
/** @name Bitmasks of REG_DMA_ENG_CAP register.
55
/* DMA engine characteristics */
56
#define DMA_ENG_PRESENT_MASK 0x00000001 /**< DMA engine present? */
57
#define DMA_ENG_DIRECTION_MASK 0x00000002 /**< DMA engine direction */
58
#define DMA_ENG_C2S 0x00000002 /**< DMA engine - C2S */
59
#define DMA_ENG_S2C 0x00000000 /**< DMA engine - S2C */
60
#define DMA_ENG_TYPE_MASK 0x00000030 /**< DMA engine type */
61
#define DMA_ENG_BLOCK 0x00000000 /**< DMA engine - Block type */
62
#define DMA_ENG_PACKET 0x00000010 /**< DMA engine - Packet type */
63
#define DMA_ENG_NUMBER 0x0000FF00 /**< DMA engine number */
64
#define DMA_ENG_BD_MAX_BC 0x3F000000 /**< DMA engine max buffer size */
66
/* Shift constants for selected masks */
67
#define DMA_ENG_NUMBER_SHIFT 8
68
#define DMA_ENG_BD_MAX_BC_SHIFT 24
70
#define DMA_ENGINE_PER_SIZE 0x100 /**< Separation between engine regs */
71
#define DMA_OFFSET 0 /**< Starting register offset */
72
/**< Size of DMA engine reg space */
73
#define DMA_SIZE (MAX_DMA_ENGINES * DMA_ENGINE_PER_SIZE)
76
pcilib_register_bank_description_t ipecamera_register_banks[] = {
77
{ PCILIB_REGISTER_DMABANK0, PCILIB_BAR0, 128, PCILIB_DEFAULT_PROTOCOL, DMA_NWL_OFFSET, DMA_NWL_OFFSET, PCILIB_LITTLE_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "%lx", "dma", "NorthWest Logick DMA Engine" },
78
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
81
pcilib_register_description_t dma_nwl_registers[] = {
82
{0, 0, 32, 0, PCILIB_REGISTER_R , PCILIB_REGISTER_DMABANK, "dma_capabilities", ""},
83
{1, 0, 32, 0, PCILIB_REGISTER_RW, PCILIB_REGISTER_DMABANK, "dma_control", ""},
88
pcilib_dma_engine_description_t desc;
90
} pcilib_nwl_engine_description_t;
96
pcilib_register_bank_description_t *dma_bank;
99
pcilib_nwl_engine_description_t engines[PCILIB_MAX_DMA_ENGINES + 1];
102
#define nwl_read_register(var, ctx, base, reg) pcilib_datacpy(&var, base + reg, 4, 1, ctx->dma_bank->raw_endianess)
103
#define nwl_write_register(var, ctx, base, reg) pcilib_datacpy(base + reg, &var, 4, 1, ctx->dma_bank->raw_endianess)
105
static int nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base) {
108
nwl_read_register(val, ctx, base, REG_DMA_ENG_CAP);
110
if ((val & DMA_ENG_PRESENT_MASK) == 0) return PCILIB_ERROR_NOTAVAILABLE;
112
info->desc.addr = (val & DMA_ENG_NUMBER) >> DMA_ENG_NUMBER_SHIFT;
114
switch (val & DMA_ENG_DIRECTION_MASK) {
116
info->desc.direction = PCILIB_DMA_FROM_DEVICE;
119
info->desc.direction = PCILIB_DMA_TO_DEVICE;
122
switch (val & DMA_ENG_TYPE_MASK) {
124
info->desc.type = PCILIB_DMA_TYPE_BLOCK;
127
info->desc.type = PCILIB_DMA_TYPE_PACKET;
130
info->desc.type = PCILIB_DMA_TYPE_UNKNOWN;
133
info->desc.addr_bits = (val & DMA_ENG_BD_MAX_BC) >> DMA_ENG_BD_MAX_BC_SHIFT;
138
pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib) {
141
pcilib_dma_t n_engines;
143
pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib);
145
nwl_dma_t *ctx = malloc(sizeof(nwl_dma_t));
147
memset(ctx, 0, sizeof(nwl_dma_t));
148
ctx->pcilib = pcilib;
149
pcilib_register_bank_t dma_bank = pcilib_find_bank_by_addr(pcilib, PCILIB_REGISTER_BANK_DMA);
151
if (dma_bank == PCILIB_REGISTER_BANK_INVALID) {
152
pcilib_error("DMA Register Bank could not be found");
156
ctx->dma_bank = model_info->banks + dma_bank;
157
ctx->base_addr = pcilib_resolve_register_address(pcilib, ctx->dma_bank->bar, ctx->dma_bank->read_addr);
159
for (i = 0, n_engines = 0; i < 2 * PCILIB_MAX_DMA_ENGINES; i++) {
160
char *addr = ctx->base_addr + DMA_OFFSET + i * DMA_ENGINE_PER_SIZE;
161
err = nwl_read_engine_config(ctx, ctx->engines + n_engines, addr);
163
ctx->engines[n_engines].base_addr = addr;
164
pcilib_set_dma_engine_description(pcilib, n_engines, (pcilib_dma_engine_description_t*)(ctx->engines + n_engines));
168
pcilib_set_dma_engine_description(pcilib, n_engines, NULL);
170
return (pcilib_dma_context_t*)ctx;
173
void dma_nwl_free(pcilib_dma_context_t *vctx) {
174
nwl_dma_t *ctx = (nwl_dma_t*)vctx;